Search on geo-position
[geeqie.git] / src / bar_gps.c
index a8d08d2..d21b824 100644 (file)
@@ -1,13 +1,22 @@
 /*
- * Geeqie
- * (C) 2004 John Ellis
- * Copyright (C) 2008 - 2012 The Geeqie Team
+ * Copyright (C) 2004 John Ellis
+ * Copyright (C) 2008 - 2016 The Geeqie Team
  *
  * Author: Colin Clark
  *
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include "main.h"
@@ -34,6 +43,8 @@
 #define THUMB_COLOUR 0xff, 0xff, 0xff, 0xff
 #define THUMB_SIZE 100
 
+#define DIRECTION_SIZE 300
+
 /*
  *-------------------------------------------------------------------
  * GPS Map utils
@@ -63,6 +74,20 @@ struct _PaneGPSData
        gboolean enable_markers_checked;
 };
 
+static gboolean bar_gps_draw_direction (ClutterCanvas *canvas,
+                               cairo_t *cr, gpointer data)
+{
+       cairo_set_source_rgb(cr, 255, 0, 0);
+
+       cairo_set_line_width(cr, 2);
+       cairo_move_to(cr, 0, 1);
+       cairo_line_to(cr, DIRECTION_SIZE, 1);
+
+       cairo_stroke(cr);
+
+       return TRUE;
+}
+
 static void bar_pane_gps_thumb_done_cb(ThumbLoader *tl, gpointer data)
 {
        FileData *fd;
@@ -89,12 +114,12 @@ static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButton
 {
        //PaneGPSData *pgd = data;
        FileData *fd;
-       ClutterActor *marker;
+       ClutterActor *label_marker, *parent_marker;
        ClutterColor marker_colour = { MARKER_COLOUR };
        ClutterColor text_colour = { TEXT_COLOUR };
        ClutterColor thumb_colour = { THUMB_COLOUR };
        gchar *current_text;
-       ClutterActor *actor;
+       ClutterActor *actor, *direction;
        ClutterActor *current_image;
        GString *text;
        gint height, width, rotate;
@@ -103,19 +128,19 @@ static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButton
 
        if (bevent->button == MOUSE_BUTTON_LEFT)
                {
-               marker = CLUTTER_ACTOR(widget);
-               fd = g_object_get_data(G_OBJECT(marker), "file_fd");
+               label_marker = CLUTTER_ACTOR(widget);
+               fd = g_object_get_data(G_OBJECT(label_marker), "file_fd");
 
                /* If the marker is showing a thumbnail, delete it
                 */
-               current_image = champlain_label_get_image(CHAMPLAIN_LABEL(marker));
+               current_image = champlain_label_get_image(CHAMPLAIN_LABEL(label_marker));
                if (current_image != NULL)
                        {
                        clutter_actor_destroy(CLUTTER_ACTOR(current_image));
-                       champlain_label_set_image(CHAMPLAIN_LABEL(marker), NULL);
+                       champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), NULL);
                        }
 
-               current_text = g_strdup(champlain_label_get_text(CHAMPLAIN_LABEL(marker)));
+               current_text = g_strdup(champlain_label_get_text(CHAMPLAIN_LABEL(label_marker)));
 
                /* If the marker is showing only the text character, replace it with a
                 * thumbnail and date and altitude
@@ -130,7 +155,7 @@ static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButton
                                {
                                actor = gtk_clutter_texture_new();
                                gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor), fd->thumb_pixbuf, NULL);
-                               champlain_label_set_image(CHAMPLAIN_LABEL(marker), actor);
+                               champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), actor);
                                }
                        else if (fd->pixbuf != NULL)
                                {
@@ -155,7 +180,7 @@ static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButton
                                        gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor),
                                                                                gdk_pixbuf_rotate_simple(gdk_pixbuf_scale_simple(fd->pixbuf, THUMB_SIZE, height * THUMB_SIZE / width,
                                                                                GDK_INTERP_NEAREST), rotate), NULL);
-                                       champlain_label_set_image(CHAMPLAIN_LABEL(marker), actor);
+                                       champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), actor);
                                }
                        else
                                {
@@ -164,7 +189,7 @@ static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButton
                                                                                        bar_pane_gps_thumb_done_cb,
                                                                                        bar_pane_gps_thumb_error_cb,
                                                                                        NULL,
-                                                                                       marker);
+                                                                                       label_marker);
                                thumb_loader_start(tl, fd);
                                }
 
@@ -178,22 +203,30 @@ static gboolean bar_pane_gps_marker_keypress_cb(GtkWidget *widget, ClutterButton
                                g_string_append(text, altitude);
                                }
 
-                       champlain_label_set_text(CHAMPLAIN_LABEL(marker), text->str);
-                       champlain_label_set_color(CHAMPLAIN_LABEL(marker), &thumb_colour);
-                       champlain_label_set_text_color(CHAMPLAIN_LABEL(marker), &text_colour);
-                       champlain_label_set_font_name(CHAMPLAIN_LABEL(marker), "sans 8");
+                       champlain_label_set_text(CHAMPLAIN_LABEL(label_marker), text->str);
+                       champlain_label_set_font_name(CHAMPLAIN_LABEL(label_marker), "sans 8");
+                       champlain_marker_set_selection_color(&thumb_colour);
+                       champlain_marker_set_selection_text_color(&text_colour);
 
                        g_free(altitude);
                        g_string_free(text, TRUE);
+
+                       parent_marker = clutter_actor_get_parent(label_marker);
+                       direction = clutter_actor_get_child_at_index(parent_marker, 0);
+                       clutter_actor_set_opacity(direction, 255);
                        }
                /* otherwise, revert to the hidden text marker
                 */
                else
                        {
-                       champlain_label_set_text(CHAMPLAIN_LABEL(marker), "i");
-                       champlain_label_set_color(CHAMPLAIN_LABEL(marker), &marker_colour);
-                       champlain_label_set_text_color(CHAMPLAIN_LABEL(marker), &marker_colour);
-                       champlain_label_set_font_name(CHAMPLAIN_LABEL(marker), "courier 5");
+                       champlain_label_set_text(CHAMPLAIN_LABEL(label_marker), "i");
+                       champlain_label_set_font_name(CHAMPLAIN_LABEL(label_marker), "courier 5");
+                       champlain_marker_set_selection_color(&marker_colour);
+                       champlain_marker_set_selection_text_color(&marker_colour);
+
+                       parent_marker = clutter_actor_get_parent(label_marker);
+                       direction = clutter_actor_get_child_at_index(parent_marker, 0);
+                       clutter_actor_set_opacity(direction, 0);
                        }
 
                g_free(current_text);
@@ -208,11 +241,14 @@ static gboolean bar_pane_gps_create_markers_cb(gpointer data)
        PaneGPSData *pgd = data;
        gdouble latitude;
        gdouble longitude;
-       GList *work;
-       ClutterActor *marker;
+       gdouble compass;
        FileData *fd;
+       ClutterActor *parent_marker, *label_marker;
+       ClutterActor *direction;
        ClutterColor marker_colour = { MARKER_COLOUR };
+       ClutterColor thumb_colour = { THUMB_COLOUR };
        GString *message;
+       ClutterContent *canvas;
 
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pgd->progress),
                                                        (gdouble)(pgd->selection_count - g_list_length(pgd->not_added)) /
@@ -229,25 +265,49 @@ static gboolean bar_pane_gps_create_markers_cb(gpointer data)
                fd = pgd->not_added->data;
                pgd->not_added = pgd->not_added->next;
 
-               latitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLatitude", 1000);
-               longitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLongitude", 1000);
+               latitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLatitude", 0);
+               longitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLongitude", 0);
+               compass = metadata_read_GPS_direction(fd, "Xmp.exif.GPSImgDirection", 1000);
 
-               if ((latitude != 1000) && (longitude != 1000))
+               if (!(latitude == 0 && longitude == 0))
                        {
                        pgd->num_added++;
 
-                       marker = champlain_label_new_with_text("i","courier 5", &marker_colour, &marker_colour);
+                       parent_marker = champlain_marker_new();
+                       clutter_actor_set_reactive(parent_marker, FALSE);
+                       label_marker = champlain_label_new_with_text("i","courier 5", &marker_colour, &marker_colour);
+                       clutter_actor_set_reactive(label_marker, TRUE);
+                       champlain_marker_set_selection_color(&thumb_colour);
+
+                       if (compass != 1000)
+                               {
+                               canvas = clutter_canvas_new();
+                               clutter_canvas_set_size(CLUTTER_CANVAS (canvas), DIRECTION_SIZE, 3);
+                               g_signal_connect(canvas, "draw", G_CALLBACK(bar_gps_draw_direction), NULL);
+                               direction = clutter_actor_new();
+                               clutter_actor_set_size(direction, DIRECTION_SIZE, 3);
+                               clutter_actor_set_position(direction, 0, 0);
+                               clutter_actor_set_rotation_angle(direction, CLUTTER_Z_AXIS, compass -90.00);
+                               clutter_actor_set_content(direction, canvas);
+                               clutter_content_invalidate(canvas);
+                               g_object_unref(canvas);
+
+                               clutter_actor_add_child(parent_marker, direction);
+                               clutter_actor_set_opacity(direction, 0);
+                               }
 
-                       champlain_location_set_location(CHAMPLAIN_LOCATION(marker), latitude, longitude);
-                       champlain_marker_layer_add_marker(pgd->icon_layer, CHAMPLAIN_MARKER(marker));
-                       clutter_actor_set_reactive(marker, TRUE);
+                       clutter_actor_add_child(parent_marker, label_marker);
 
-                       g_signal_connect(G_OBJECT(marker), "button_release_event",
+                       champlain_location_set_location(CHAMPLAIN_LOCATION(parent_marker), latitude, longitude);
+                       champlain_marker_layer_add_marker(pgd->icon_layer, CHAMPLAIN_MARKER(parent_marker));
+
+                       g_signal_connect(G_OBJECT(label_marker), "button_release_event",
                                        G_CALLBACK(bar_pane_gps_marker_keypress_cb), pgd);
 
-                       g_object_set_data(G_OBJECT(marker), "file_fd", fd);
+                       g_object_set_data(G_OBJECT(label_marker), "file_fd", fd);
 
                        champlain_bounding_box_extend(pgd->bbox, latitude, longitude);
+
                        }
                return TRUE;
                }
@@ -337,7 +397,6 @@ void bar_pane_gps_set_map_source(PaneGPSData *pgd, const gchar *map_id)
        if (map_source != NULL)
                {
                g_object_set(G_OBJECT(pgd->gps_view), "map-source", map_source, NULL);
-               //g_object_unref(map_source);
                }
 
        g_object_unref(map_factory);
@@ -546,7 +605,6 @@ static GtkWidget *bar_pane_gps_menu(PaneGPSData *pgd)
 {
        GtkWidget *menu;
        GtkWidget *map_centre;
-       GtkWidget *parent;
        ChamplainMapSourceFactory *map_factory;
        GSList *map_list;
        ChamplainMapSourceDesc *map_desc;
@@ -583,7 +641,6 @@ static GtkWidget *bar_pane_gps_menu(PaneGPSData *pgd)
 
        g_slist_free(map_list);
        g_object_unref(map_factory);
-       //g_object_unref(map_centre);
 
        return menu;
 }
@@ -623,6 +680,8 @@ static gboolean bar_pane_gps_map_keypress_cb(GtkWidget *widget, GdkEventButton *
 {
        PaneGPSData *pgd = data;
        GtkWidget *menu;
+       GtkClipboard *clipboard;
+       gchar *geo_coords;
 
        if (bevent->button == MOUSE_BUTTON_RIGHT)
                {
@@ -637,7 +696,17 @@ static gboolean bar_pane_gps_map_keypress_cb(GtkWidget *widget, GdkEventButton *
                }
        else if (bevent->button == MOUSE_BUTTON_LEFT)
                {
-               return FALSE;
+               clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
+               geo_coords = g_strdup_printf("%lf %lf",
+                                                       champlain_view_y_to_latitude(
+                                                               CHAMPLAIN_VIEW(pgd->gps_view),bevent->y),
+                                                       champlain_view_x_to_longitude(
+                                                               CHAMPLAIN_VIEW(pgd->gps_view),bevent->x));
+               gtk_clipboard_set_text(clipboard, geo_coords, -1);
+
+               g_free(geo_coords);
+
+               return TRUE;
                }
        else
                {
@@ -670,11 +739,11 @@ GtkWidget *bar_pane_gps_new(const gchar *id, const gchar *title, const gchar *ma
 {
        PaneGPSData *pgd;
        GtkWidget *vbox, *frame;
-       GtkWidget *gpswidget, *viewport;
+       GtkWidget *gpswidget;
        GtkWidget *status, *state, *progress, *slider;
        ChamplainMarkerLayer *layer;
        ChamplainView *view;
-       const gchar *slider_list[] = {GTK_STOCK_ZOOM_IN, GTK_STOCK_ZOOM_OUT, NULL};
+       const gchar *slider_list[] = {"zoom-in", "zoom-out", NULL};
        const gchar **slider_icons = slider_list;
 
        pgd = g_new0(PaneGPSData, 1);
@@ -690,7 +759,7 @@ GtkWidget *bar_pane_gps_new(const gchar *id, const gchar *title, const gchar *ma
        pgd->height = height;
 
        frame = gtk_frame_new(NULL);
-       vbox = gtk_vbox_new(FALSE, 0);
+       vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
 
        gpswidget = gtk_champlain_embed_new();
        view = gtk_champlain_embed_get_view(GTK_CHAMPLAIN_EMBED(gpswidget));
@@ -698,12 +767,16 @@ GtkWidget *bar_pane_gps_new(const gchar *id, const gchar *title, const gchar *ma
        gtk_box_pack_start(GTK_BOX(vbox), gpswidget, TRUE, TRUE, 0);
        gtk_container_add(GTK_CONTAINER(frame), vbox);
 
-       status = gtk_hbox_new(FALSE,0);
+       status = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
        slider = gtk_scale_button_new(GTK_ICON_SIZE_SMALL_TOOLBAR, 1, 17, 1, slider_icons);
        gtk_widget_set_tooltip_text(slider, "Zoom");
        gtk_scale_button_set_value(GTK_SCALE_BUTTON(slider), (gdouble)zoom);
 
        progress = gtk_progress_bar_new();
+#if GTK_CHECK_VERSION(3,0,0)
+       gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "");
+       gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(progress), TRUE);
+#endif
        state = gtk_label_new("");
        gtk_label_set_justify(GTK_LABEL(state), GTK_JUSTIFY_CENTER);
 
@@ -727,9 +800,7 @@ GtkWidget *bar_pane_gps_new(const gchar *id, const gchar *title, const gchar *ma
        g_object_set(G_OBJECT(view), "kinetic-mode", TRUE,
                                     "zoom-level", zoom,
                                     "keep-center-on-resize", TRUE,
-/* This seems to be broken, https://bugzilla.gnome.org/show_bug.cgi?id=596419
-                                    "decel-rate", 1.0,
-*/
+                                    "deceleration", 1.1,
                                     "zoom-on-double-click", FALSE,
                                     "max-zoom-level", 17,
                                     "min-zoom-level", 1,
@@ -743,7 +814,6 @@ GtkWidget *bar_pane_gps_new(const gchar *id, const gchar *title, const gchar *ma
 
        gtk_widget_set_size_request(pgd->widget, -1, height);
 
-       clutter_set_motion_events_enabled(TRUE);
        g_signal_connect(G_OBJECT(gpswidget), "button_press_event", G_CALLBACK(bar_pane_gps_map_keypress_cb), pgd);
        g_signal_connect(pgd->gps_view, "notify::state", G_CALLBACK(bar_pane_gps_view_state_changed_cb), pgd);
        g_signal_connect(pgd->gps_view, "notify::zoom-level", G_CALLBACK(bar_pane_gps_view_state_changed_cb), pgd);
@@ -784,10 +854,7 @@ GtkWidget *bar_pane_gps_new_from_config(const gchar **attribute_names, const gch
                        continue;
                if (READ_CHAR_FULL("map-id", map_id))
                        continue;
-               /* There is a bug in the libchamplain libraries which prevents correct
-                * initialisation if the zoom level starts higher than 8
-                */
-               if (READ_INT_CLAMP_FULL("zoom-level", zoom, 1, 8))
+               if (READ_INT_CLAMP_FULL("zoom-level", zoom, 1, 20))
                        continue;
                if (READ_INT_CLAMP_FULL("latitude", int_latitude, -90000000, +90000000))
                        continue;