2 * Copyright (C) 2004 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #ifdef HAVE_LIBCHAMPLAIN
24 #ifdef HAVE_LIBCHAMPLAIN_GTK
37 #include <clutter-gtk/clutter-gtk.h>
38 #include <champlain/champlain.h>
39 #include <champlain-gtk/champlain-gtk.h>
41 #define MARKER_COLOUR 0x00, 0x00, 0xff, 0xff
42 #define TEXT_COLOUR 0x00, 0x00, 0x00, 0xff
43 #define THUMB_COLOUR 0xff, 0xff, 0xff, 0xff
44 #define THUMB_SIZE 100
46 #define DIRECTION_SIZE 300
49 *-------------------------------------------------------------------
51 *-------------------------------------------------------------------
54 typedef struct _PaneGPSData PaneGPSData;
62 ClutterActor *gps_view;
63 ChamplainMarkerLayer *icon_layer;
64 GList *selection_list;
66 ChamplainBoundingBox *bbox;
68 guint create_markers_id;
73 gboolean centre_map_checked;
74 gboolean enable_markers_checked;
77 static gboolean bar_gps_draw_direction (ClutterCanvas *canvas,
78 cairo_t *cr, gpointer data)
80 cairo_set_source_rgb(cr, 255, 0, 0);
82 cairo_set_line_width(cr, 2);
83 cairo_move_to(cr, 0, 1);
84 cairo_line_to(cr, DIRECTION_SIZE, 1);
91 static void bar_pane_gps_thumb_done_cb(ThumbLoader *tl, gpointer data)
97 marker = CLUTTER_ACTOR(data);
98 fd = g_object_get_data(G_OBJECT(marker), "file_fd");
99 if (fd->thumb_pixbuf != NULL)
101 actor = gtk_clutter_texture_new();
102 gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor), fd->thumb_pixbuf, NULL);
103 champlain_label_set_image(CHAMPLAIN_LABEL(marker), actor);
105 thumb_loader_free(tl);
108 static void bar_pane_gps_thumb_error_cb(ThumbLoader *tl, gpointer data)
110 thumb_loader_free(tl);
113 static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButtonEvent *bevent, gpointer data)
115 //PaneGPSData *pgd = data;
117 ClutterActor *label_marker, *parent_marker;
118 ClutterColor marker_colour = { MARKER_COLOUR };
119 ClutterColor text_colour = { TEXT_COLOUR };
120 ClutterColor thumb_colour = { THUMB_COLOUR };
122 ClutterActor *actor, *direction;
123 ClutterActor *current_image;
125 gint height, width, rotate;
126 gchar *altitude = NULL;
129 if (bevent->button == MOUSE_BUTTON_LEFT)
131 label_marker = CLUTTER_ACTOR(widget);
132 fd = g_object_get_data(G_OBJECT(label_marker), "file_fd");
134 /* If the marker is showing a thumbnail, delete it
136 current_image = champlain_label_get_image(CHAMPLAIN_LABEL(label_marker));
137 if (current_image != NULL)
139 clutter_actor_destroy(CLUTTER_ACTOR(current_image));
140 champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), NULL);
143 current_text = g_strdup(champlain_label_get_text(CHAMPLAIN_LABEL(label_marker)));
145 /* If the marker is showing only the text character, replace it with a
146 * thumbnail and date and altitude
148 if (g_strcmp0(current_text, "i") == 0)
150 /* If a thumbail has already been generated, use that. If not try the pixbuf of the full image.
151 * If not, call the thumb_loader to generate a thumbnail and update the marker later in the
152 * thumb_loader callback
154 if (fd->thumb_pixbuf != NULL)
156 actor = gtk_clutter_texture_new();
157 gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor), fd->thumb_pixbuf, NULL);
158 champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), actor);
160 else if (fd->pixbuf != NULL)
162 actor = gtk_clutter_texture_new();
163 width = gdk_pixbuf_get_width (fd->pixbuf);
164 height = gdk_pixbuf_get_height (fd->pixbuf);
165 switch (fd->exif_orientation)
168 rotate = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
171 rotate = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
174 rotate = GDK_PIXBUF_ROTATE_CLOCKWISE;
177 rotate = GDK_PIXBUF_ROTATE_NONE;
180 gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor),
181 gdk_pixbuf_rotate_simple(gdk_pixbuf_scale_simple(fd->pixbuf, THUMB_SIZE, height * THUMB_SIZE / width,
182 GDK_INTERP_NEAREST), rotate), NULL);
183 champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), actor);
187 tl = thumb_loader_new(THUMB_SIZE, THUMB_SIZE);
188 thumb_loader_set_callbacks(tl,
189 bar_pane_gps_thumb_done_cb,
190 bar_pane_gps_thumb_error_cb,
193 thumb_loader_start(tl, fd);
196 text = g_string_new(fd->name);
197 g_string_append(text, "\n");
198 g_string_append(text, text_from_time(fd->date));
199 g_string_append(text, "\n");
200 altitude = metadata_read_string(fd, "formatted.GPSAltitude", METADATA_FORMATTED);
201 if (altitude != NULL)
203 g_string_append(text, altitude);
206 champlain_label_set_text(CHAMPLAIN_LABEL(label_marker), text->str);
207 champlain_label_set_font_name(CHAMPLAIN_LABEL(label_marker), "sans 8");
208 champlain_marker_set_selection_color(&thumb_colour);
209 champlain_marker_set_selection_text_color(&text_colour);
212 g_string_free(text, TRUE);
214 parent_marker = clutter_actor_get_parent(label_marker);
215 direction = clutter_actor_get_child_at_index(parent_marker, 0);
216 clutter_actor_set_opacity(direction, 255);
218 /* otherwise, revert to the hidden text marker
222 champlain_label_set_text(CHAMPLAIN_LABEL(label_marker), "i");
223 champlain_label_set_font_name(CHAMPLAIN_LABEL(label_marker), "courier 5");
224 champlain_marker_set_selection_color(&marker_colour);
225 champlain_marker_set_selection_text_color(&marker_colour);
227 parent_marker = clutter_actor_get_parent(label_marker);
228 direction = clutter_actor_get_child_at_index(parent_marker, 0);
229 clutter_actor_set_opacity(direction, 0);
232 g_free(current_text);
239 static gboolean bar_pane_gps_create_markers_cb(gpointer data)
241 PaneGPSData *pgd = data;
246 ClutterActor *parent_marker, *label_marker;
247 ClutterActor *direction;
248 ClutterColor marker_colour = { MARKER_COLOUR };
249 ClutterColor thumb_colour = { THUMB_COLOUR };
251 ClutterContent *canvas;
253 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pgd->progress),
254 (gdouble)(pgd->selection_count - g_list_length(pgd->not_added)) /
255 (gdouble)pgd->selection_count);
257 message = g_string_new("");
258 g_string_printf(message, "%i/%i", (pgd->selection_count - g_list_length(pgd->not_added)),
259 pgd->selection_count);
260 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pgd->progress), message->str);
261 g_string_free(message, TRUE);
265 fd = pgd->not_added->data;
266 pgd->not_added = pgd->not_added->next;
268 latitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLatitude", 0);
269 longitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLongitude", 0);
270 compass = metadata_read_GPS_direction(fd, "Xmp.exif.GPSImgDirection", 1000);
272 if (!(latitude == 0 && longitude == 0))
276 parent_marker = champlain_marker_new();
277 clutter_actor_set_reactive(parent_marker, FALSE);
278 label_marker = champlain_label_new_with_text("i","courier 5", &marker_colour, &marker_colour);
279 clutter_actor_set_reactive(label_marker, TRUE);
280 champlain_marker_set_selection_color(&thumb_colour);
284 canvas = clutter_canvas_new();
285 clutter_canvas_set_size(CLUTTER_CANVAS (canvas), DIRECTION_SIZE, 3);
286 g_signal_connect(canvas, "draw", G_CALLBACK(bar_gps_draw_direction), NULL);
287 direction = clutter_actor_new();
288 clutter_actor_set_size(direction, DIRECTION_SIZE, 3);
289 clutter_actor_set_position(direction, 0, 0);
290 clutter_actor_set_rotation_angle(direction, CLUTTER_Z_AXIS, compass -90.00);
291 clutter_actor_set_content(direction, canvas);
292 clutter_content_invalidate(canvas);
293 g_object_unref(canvas);
295 clutter_actor_add_child(parent_marker, direction);
296 clutter_actor_set_opacity(direction, 0);
299 clutter_actor_add_child(parent_marker, label_marker);
301 champlain_location_set_location(CHAMPLAIN_LOCATION(parent_marker), latitude, longitude);
302 champlain_marker_layer_add_marker(pgd->icon_layer, CHAMPLAIN_MARKER(parent_marker));
304 g_signal_connect(G_OBJECT(label_marker), "button_release_event",
305 G_CALLBACK(bar_pane_gps_marker_keypress_cb), pgd);
307 g_object_set_data(G_OBJECT(label_marker), "file_fd", fd);
309 champlain_bounding_box_extend(pgd->bbox, latitude, longitude);
315 if (pgd->centre_map_checked)
317 if (pgd->num_added == 1)
319 champlain_bounding_box_get_center(pgd->bbox, &latitude, &longitude);
320 champlain_view_go_to(CHAMPLAIN_VIEW(pgd->gps_view), latitude, longitude);
322 else if (pgd->num_added > 1)
324 champlain_view_ensure_visible(CHAMPLAIN_VIEW(pgd->gps_view), pgd->bbox, TRUE);
327 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pgd->progress), 0);
328 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pgd->progress), NULL);
329 pgd->create_markers_id = 0;
334 static void bar_pane_gps_update(PaneGPSData *pgd)
338 /* The widget does not have a parent during bar_pane_gps_new, so calling gtk_widget_show_all there gives a
339 * "Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed"
340 * error. gtk_widget_show_all can be given after it has been added to the bar.
342 if (gtk_widget_get_parent(pgd->widget) != NULL)
343 gtk_widget_show_all(pgd->widget);
345 /* If a create-marker background process is running, kill it
348 if (pgd->create_markers_id != 0)
350 if (g_idle_remove_by_data(pgd))
352 pgd->create_markers_id = 0;
360 /* Delete any markers currently displayed
363 champlain_marker_layer_remove_all(pgd->icon_layer);
365 if (!pgd->enable_markers_checked)
370 /* For each selected photo that has GPS data, create a marker containing
371 * a single, small text character the same colour as the marker background.
372 * Use a background process in case the user selects a large number of files.
374 filelist_free(pgd->selection_list);
375 if (pgd->bbox) champlain_bounding_box_free(pgd->bbox);
377 list = layout_selection_list(pgd->pane.lw);
378 list = file_data_process_groups_in_selection(list, FALSE, NULL);
380 pgd->selection_list = list;
381 pgd->not_added = list;
383 pgd->bbox = champlain_bounding_box_new();
384 pgd->selection_count = g_list_length(pgd->selection_list);
385 pgd->create_markers_id = g_idle_add(bar_pane_gps_create_markers_cb, pgd);
389 void bar_pane_gps_set_map_source(PaneGPSData *pgd, const gchar *map_id)
391 ChamplainMapSource *map_source;
392 ChamplainMapSourceFactory *map_factory;
394 map_factory = champlain_map_source_factory_dup_default();
395 map_source = champlain_map_source_factory_create(map_factory, map_id);
397 if (map_source != NULL)
399 g_object_set(G_OBJECT(pgd->gps_view), "map-source", map_source, NULL);
402 g_object_unref(map_factory);
405 void bar_pane_gps_enable_markers_checked_toggle_cb(GtkWidget *menu_widget, gpointer data)
407 PaneGPSData *pgd = data;
409 if (pgd->enable_markers_checked)
411 pgd->enable_markers_checked = FALSE;
415 pgd->enable_markers_checked = TRUE;
419 static void bar_pane_gps_centre_map_checked_toggle_cb(GtkWidget *menu_widget, gpointer data)
421 PaneGPSData *pgd = data;
423 if (pgd->centre_map_checked)
425 pgd->centre_map_checked = FALSE;
429 pgd->centre_map_checked = TRUE;
433 static void bar_pane_gps_change_map_cb(GtkWidget *widget, gpointer data)
435 PaneGPSData *pgd = data;
438 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
443 mapsource = g_object_get_data(G_OBJECT(widget), "menu_item_radio_data");
444 bar_pane_gps_set_map_source(pgd, mapsource);
447 static void bar_pane_gps_notify_selection(GtkWidget *bar, gint count)
451 if (count == 0) return;
453 pgd = g_object_get_data(G_OBJECT(bar), "pane_data");
456 bar_pane_gps_update(pgd);
459 static void bar_pane_gps_set_fd(GtkWidget *bar, FileData *fd)
463 pgd = g_object_get_data(G_OBJECT(bar), "pane_data");
466 file_data_unref(pgd->fd);
467 pgd->fd = file_data_ref(fd);
469 bar_pane_gps_update(pgd);
472 static gint bar_pane_gps_event(GtkWidget *bar, GdkEvent *event)
476 pgd = g_object_get_data(G_OBJECT(bar), "pane_data");
477 if (!pgd) return FALSE;
479 if (gtk_widget_has_focus(pgd->widget)) return gtk_widget_event(GTK_WIDGET(pgd->widget), event);
484 static void bar_pane_gps_write_config(GtkWidget *pane, GString *outstr, gint indent)
488 ChamplainMapSource *mapsource;
491 GString *buffer = g_string_new(str);
495 pgd = g_object_get_data(G_OBJECT(pane), "pane_data");
499 WRITE_STRING("<pane_gps ");
500 write_char_option(outstr, indent, "id", pgd->pane.id);
501 write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(pgd->pane.title)));
502 WRITE_BOOL(pgd->pane, expanded);
503 WRITE_INT(*pgd, height);
506 g_object_get(G_OBJECT(pgd->gps_view), "map-source", &mapsource, NULL);
507 map_id = champlain_map_source_get_id(mapsource);
509 write_char_option(outstr, indent, "map-id", map_id);
511 g_object_get(G_OBJECT(pgd->gps_view), "zoom-level", &zoom, NULL);
512 g_string_printf(buffer, "%d", zoom);
514 write_char_option(outstr, indent, "zoom-level", buffer->str);
516 g_object_get(G_OBJECT(pgd->gps_view), "latitude", &position, NULL);
517 int_position = position * 1000000;
518 g_string_printf(buffer, "%i", int_position);
520 write_char_option(outstr, indent, "latitude", buffer->str);
522 g_object_get(G_OBJECT(pgd->gps_view), "longitude", &position, NULL);
523 int_position = position * 1000000;
524 g_string_printf(buffer, "%i", int_position);
526 write_char_option(outstr, indent, "longitude", buffer->str);
532 g_object_unref(mapsource);
536 static void bar_pane_gps_slider_changed_cb(GtkScaleButton *slider,
540 PaneGPSData *pgd = data;
543 message = g_string_new("");
544 g_string_printf(message, _("Zoom %i"), (gint)zoom);
546 g_object_set(G_OBJECT(CHAMPLAIN_VIEW(pgd->gps_view)), "zoom-level", (gint)zoom, NULL);
547 gtk_widget_set_tooltip_text(GTK_WIDGET(slider), message->str);
548 g_string_free(message, TRUE);
551 static void bar_pane_gps_view_state_changed_cb(ChamplainView *view,
555 PaneGPSData *pgd = data;
556 ChamplainState status;
560 g_object_get(G_OBJECT(view), "zoom-level", &zoom, NULL);
561 message = g_string_new("");
562 g_string_printf(message, _("Zoom level %i"), zoom);
564 g_object_get(G_OBJECT(view), "state", &status, NULL);
565 if (status == CHAMPLAIN_STATE_LOADING)
567 gtk_label_set_text(GTK_LABEL(pgd->state), _("Loading map"));
571 gtk_label_set_text(GTK_LABEL(pgd->state), message->str);
574 gtk_widget_set_tooltip_text(GTK_WIDGET(pgd->slider), message->str);
575 gtk_scale_button_set_value(GTK_SCALE_BUTTON(pgd->slider), (gdouble)zoom);
577 g_string_free(message, TRUE);
580 static void bar_pane_gps_notify_cb(FileData *fd, NotifyType type, gpointer data)
582 PaneGPSData *pgd = data;
584 if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE | NOTIFY_METADATA)) &&
585 g_list_find(pgd->selection_list, fd))
587 bar_pane_gps_update(pgd);
591 const gchar *bar_pane_gps_get_map_id(PaneGPSData *pgd)
594 ChamplainMapSource *mapsource;
596 g_object_get(G_OBJECT(pgd->gps_view), "map-source", &mapsource, NULL);
597 map_id = champlain_map_source_get_id(mapsource);
599 g_object_unref(mapsource);
604 static GtkWidget *bar_pane_gps_menu(PaneGPSData *pgd)
607 GtkWidget *map_centre;
608 ChamplainMapSourceFactory *map_factory;
610 ChamplainMapSourceDesc *map_desc;
611 const gchar *current;
613 menu = popup_menu_short_lived();
615 map_factory = champlain_map_source_factory_dup_default();
616 map_list = champlain_map_source_factory_get_registered(map_factory);
617 current = bar_pane_gps_get_map_id(pgd);
621 map_desc = (ChamplainMapSourceDesc *)(map_list->data);
623 menu_item_add_radio(menu,
624 champlain_map_source_desc_get_name(map_desc),
625 (gpointer)champlain_map_source_desc_get_id(map_desc),
626 strcmp(champlain_map_source_desc_get_id(map_desc), current) == 0,
627 G_CALLBACK(bar_pane_gps_change_map_cb), pgd);
629 map_list = g_slist_next(map_list);
632 menu_item_add_divider(menu);
633 menu_item_add_check(menu, _("Enable markers"), pgd->enable_markers_checked,
634 G_CALLBACK(bar_pane_gps_enable_markers_checked_toggle_cb), pgd);
635 map_centre = menu_item_add_check(menu, _("Centre map on marker"), pgd->centre_map_checked,
636 G_CALLBACK(bar_pane_gps_centre_map_checked_toggle_cb), pgd);
637 if (!pgd->enable_markers_checked)
639 gtk_widget_set_sensitive(map_centre, FALSE);
642 g_slist_free(map_list);
643 g_object_unref(map_factory);
648 /* Determine if the map is to be re-centred on the marker when another photo is selected
650 void bar_pane_gps_map_centreing(PaneGPSData *pgd)
653 GString *message = g_string_new("");
655 if (pgd->centre_map_checked)
657 message = g_string_append(message, _("Move map centre to marker\n is disabled"));
658 pgd->centre_map_checked = FALSE;
662 message = g_string_append(message, _("Move map centre to marker\n is enabled"));
663 pgd->centre_map_checked = TRUE;
666 dialog = gtk_message_dialog_new(NULL,
667 GTK_DIALOG_DESTROY_WITH_PARENT,
671 gtk_window_set_title(GTK_WINDOW(dialog), _("Map Centreing"));
672 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
673 gtk_dialog_run(GTK_DIALOG(dialog));
675 gtk_widget_destroy(dialog);
676 g_string_free(message, TRUE);
679 static gboolean bar_pane_gps_map_keypress_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
681 PaneGPSData *pgd = data;
684 if (bevent->button == MOUSE_BUTTON_RIGHT)
686 menu = bar_pane_gps_menu(pgd);
687 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
690 else if (bevent->button == MOUSE_BUTTON_MIDDLE)
692 bar_pane_gps_map_centreing(pgd);
695 else if (bevent->button == MOUSE_BUTTON_LEFT)
705 static void bar_pane_gps_destroy(GtkWidget *widget, gpointer data)
707 PaneGPSData *pgd = data;
709 file_data_unregister_notify_func(bar_pane_gps_notify_cb, pgd);
711 g_idle_remove_by_data(pgd);
713 filelist_free(pgd->selection_list);
714 if (pgd->bbox) champlain_bounding_box_free(pgd->bbox);
716 file_data_unref(pgd->fd);
717 g_free(pgd->map_source);
718 g_free(pgd->pane.id);
719 clutter_actor_destroy(pgd->gps_view);
724 GtkWidget *bar_pane_gps_new(const gchar *id, const gchar *title, const gchar *map_id,
725 const gint zoom, const gdouble latitude, const gdouble longitude,
726 gboolean expanded, gint height)
729 GtkWidget *vbox, *frame;
730 GtkWidget *gpswidget;
731 GtkWidget *status, *state, *progress, *slider;
732 ChamplainMarkerLayer *layer;
734 const gchar *slider_list[] = {"zoom-in", "zoom-out", NULL};
735 const gchar **slider_icons = slider_list;
737 pgd = g_new0(PaneGPSData, 1);
739 pgd->pane.pane_set_fd = bar_pane_gps_set_fd;
740 pgd->pane.pane_notify_selection = bar_pane_gps_notify_selection;
741 pgd->pane.pane_event = bar_pane_gps_event;
742 pgd->pane.pane_write_config = bar_pane_gps_write_config;
743 pgd->pane.title = bar_pane_expander_title(title);
744 pgd->pane.id = g_strdup(id);
745 pgd->pane.type = PANE_GPS;
746 pgd->pane.expanded = expanded;
747 pgd->height = height;
749 frame = gtk_frame_new(NULL);
750 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
752 gpswidget = gtk_champlain_embed_new();
753 view = gtk_champlain_embed_get_view(GTK_CHAMPLAIN_EMBED(gpswidget));
755 gtk_box_pack_start(GTK_BOX(vbox), gpswidget, TRUE, TRUE, 0);
756 gtk_container_add(GTK_CONTAINER(frame), vbox);
758 status = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
759 slider = gtk_scale_button_new(GTK_ICON_SIZE_SMALL_TOOLBAR, 1, 17, 1, slider_icons);
760 gtk_widget_set_tooltip_text(slider, "Zoom");
761 gtk_scale_button_set_value(GTK_SCALE_BUTTON(slider), (gdouble)zoom);
763 progress = gtk_progress_bar_new();
764 state = gtk_label_new("");
765 gtk_label_set_justify(GTK_LABEL(state), GTK_JUSTIFY_CENTER);
767 gtk_box_pack_start(GTK_BOX(status), GTK_WIDGET(slider), FALSE, FALSE, 0);
768 gtk_box_pack_start(GTK_BOX(status), GTK_WIDGET(state), FALSE, FALSE, 5);
769 gtk_box_pack_end(GTK_BOX(status), GTK_WIDGET(progress), FALSE, FALSE, 0);
770 gtk_box_pack_end(GTK_BOX(vbox),GTK_WIDGET(status), FALSE, FALSE, 0);
772 layer = champlain_marker_layer_new();
773 champlain_view_add_layer(view, CHAMPLAIN_LAYER(layer));
775 pgd->icon_layer = layer;
776 pgd->gps_view = CLUTTER_ACTOR(view);
778 pgd->progress = progress;
779 pgd->slider = slider;
782 bar_pane_gps_set_map_source(pgd, map_id);
784 g_object_set(G_OBJECT(view), "kinetic-mode", TRUE,
786 "keep-center-on-resize", TRUE,
788 "zoom-on-double-click", FALSE,
789 "max-zoom-level", 17,
792 champlain_view_center_on(view, latitude, longitude);
793 pgd->centre_map_checked = TRUE;
794 g_object_set_data(G_OBJECT(pgd->widget), "pane_data", pgd);
795 g_signal_connect(G_OBJECT(pgd->widget), "destroy", G_CALLBACK(bar_pane_gps_destroy), pgd);
797 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
799 gtk_widget_set_size_request(pgd->widget, -1, height);
801 g_signal_connect(G_OBJECT(gpswidget), "button_press_event", G_CALLBACK(bar_pane_gps_map_keypress_cb), pgd);
802 g_signal_connect(pgd->gps_view, "notify::state", G_CALLBACK(bar_pane_gps_view_state_changed_cb), pgd);
803 g_signal_connect(pgd->gps_view, "notify::zoom-level", G_CALLBACK(bar_pane_gps_view_state_changed_cb), pgd);
804 g_signal_connect(G_OBJECT(slider), "value-changed", G_CALLBACK(bar_pane_gps_slider_changed_cb), pgd);
806 file_data_register_notify_func(bar_pane_gps_notify_cb, pgd, NOTIFY_PRIORITY_LOW);
808 pgd->create_markers_id = 0;
809 pgd->enable_markers_checked = TRUE;
810 pgd->centre_map_checked = TRUE;
815 GtkWidget *bar_pane_gps_new_from_config(const gchar **attribute_names, const gchar **attribute_values)
817 gchar *title = g_strdup(_("GPS Map"));
818 gchar *map_id = NULL;
819 gboolean expanded = TRUE;
824 /* Latitude and longitude are stored in the config file as an integer of
825 * (actual value * 1,000,000). There is no READ_DOUBLE utilty function.
827 gint int_latitude = 54000000;
828 gint int_longitude = -4000000;
829 gchar *id = g_strdup("gps");
832 while (*attribute_names)
834 const gchar *option = *attribute_names++;
835 const gchar *value = *attribute_values++;
837 if (READ_CHAR_FULL("title", title))
839 if (READ_CHAR_FULL("map-id", map_id))
841 if (READ_INT_CLAMP_FULL("zoom-level", zoom, 1, 20))
843 if (READ_INT_CLAMP_FULL("latitude", int_latitude, -90000000, +90000000))
845 if (READ_INT_CLAMP_FULL("longitude", int_longitude, -90000000, +90000000))
847 if (READ_BOOL_FULL("expanded", expanded))
849 if (READ_INT_FULL("height", height))
851 if (READ_CHAR_FULL("id", id))
854 log_printf("unknown attribute %s = %s\n", option, value);
857 bar_pane_translate_title(PANE_COMMENT, id, &title);
858 latitude = int_latitude / 1000000;
859 longitude = int_longitude / 1000000;
860 ret = bar_pane_gps_new(id, title, map_id, zoom, latitude, longitude, expanded, height);
867 void bar_pane_gps_update_from_config(GtkWidget *pane, const gchar **attribute_names,
868 const gchar **attribute_values)
872 gint int_longitude, int_latitude;
873 gdouble longitude, latitude;
875 pgd = g_object_get_data(G_OBJECT(pane), "pane_data");
881 while (*attribute_names)
883 const gchar *option = *attribute_names++;
884 const gchar *value = *attribute_values++;
886 if (READ_CHAR_FULL("title", title))
888 if (READ_CHAR_FULL("map-id", pgd->map_source))
890 if (READ_BOOL_FULL("expanded", pgd->pane.expanded))
892 if (READ_INT_FULL("height", pgd->height))
894 if (READ_CHAR_FULL("id", pgd->pane.id))
896 if (READ_INT_CLAMP_FULL("zoom-level", zoom, 1, 8))
898 g_object_set(G_OBJECT(CHAMPLAIN_VIEW(pgd->gps_view)), "zoom-level", zoom, NULL);
901 if (READ_INT_CLAMP_FULL("longitude", int_longitude, -90000000, +90000000))
903 longitude = int_longitude / 1000000;
904 g_object_set(G_OBJECT(CHAMPLAIN_VIEW(pgd->gps_view)), "longitude", longitude, NULL);
907 if (READ_INT_CLAMP_FULL("latitude", int_latitude, -90000000, +90000000))
909 latitude = int_latitude / 1000000;
910 g_object_set(G_OBJECT(CHAMPLAIN_VIEW(pgd->gps_view)), "latitude", latitude, NULL);
913 log_printf("unknown attribute %s = %s\n", option, value);
918 bar_pane_translate_title(PANE_COMMENT, pgd->pane.id, &title);
919 gtk_label_set_text(GTK_LABEL(pgd->pane.title), title);
923 gtk_widget_set_size_request(pgd->widget, -1, pgd->height);
924 bar_update_expander(pane);
930 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */