[gnome-panel] add geoclue location to the ui



commit 5e9bba77bf99c6c0fb14255a9958e0235c325a30
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Jun 29 13:34:36 2009 -0400

    add geoclue location to the ui
    
    Also add manual provider for test purposes

 applets/clock/clock.c |  265 ++++++++++++++++++++++++++++++++++++++++++++++---
 configure.in          |    2 +-
 2 files changed, 254 insertions(+), 13 deletions(-)
---
diff --git a/applets/clock/clock.c b/applets/clock/clock.c
index 2523c0c..2978dee 100644
--- a/applets/clock/clock.c
+++ b/applets/clock/clock.c
@@ -56,6 +56,7 @@
 #include <libgweather/gweather-xml.h>
 #include <libgweather/location-entry.h>
 #include <libgweather/timezone-menu.h>
+#include <libnotify/notify.h> /* for geoclue-started notifications */
 
 #ifdef HAVE_LIBECAL
 #include <libedataserverui/e-passwords.h>
@@ -177,7 +178,9 @@ struct _ClockData {
         GList *locations;
         GList *location_tiles;
 
+        GtkWidget *geo_city_section;
 	ClockGeoclue *clock_geo; /* geoclue abstraction */
+        ClockLocation *current_geo_location; /* also in locations */
 
 	/* runtime data */
         time_t             current_time;
@@ -239,8 +242,228 @@ static void applet_change_orient (PanelApplet       *applet,
 
 static void edit_hide (GtkWidget *unused, ClockData *cd);
 static gboolean edit_delete (GtkWidget *unused, GdkEvent *event, ClockData *cd);
+static void ensure_prefs_window_is_created (ClockData *cd);
+static void fill_location_tree (ClockData *cd);
 static void save_cities_store (ClockData *cd);
 
+static void location_tile_pressed_cb (ClockLocationTile *tile, gpointer data);
+static ClockFormat location_tile_need_clock_format_cb(ClockLocationTile *tile, gpointer data);
+
+static GWeatherLocation *
+find_gweather_location_by_country (GWeatherLocation *loc,
+                                   const char *country,
+                                   const char *country_code)
+{
+	GWeatherLocation *result;
+
+	if (gweather_location_get_level (loc) < GWEATHER_LOCATION_COUNTRY) {
+		GWeatherLocation **children;
+		int i;
+		children = gweather_location_get_children (loc);
+		for (i = 0; children[i]; i++) {
+			result = find_gweather_location_by_country (children[i], country, country_code);
+			if (result)
+				return result;
+		}
+	}
+	else if (gweather_location_get_level (loc) == GWEATHER_LOCATION_COUNTRY) {
+                const char *name;
+		const char *code;
+		code = gweather_location_get_country (loc);
+		name = gweather_location_get_name (loc);
+		if (country_code && g_strcmp0 (country_code, code) == 0)
+			return loc;
+		if (country && g_strcmp0 (country, name) == 0)
+			return loc;
+	}
+
+	return NULL;
+}
+
+static const char *
+find_gweather_location_code (GWeatherLocation *location)
+{
+	if (gweather_location_get_level (location) == GWEATHER_LOCATION_WEATHER_STATION) {
+		return gweather_location_get_code (location);
+	}
+	else {
+		GWeatherLocation **children;
+		children = gweather_location_get_children (location);
+	 	return find_gweather_location_code (children[0]);
+	}
+}
+
+static ClockLocation *
+create_new_geoclue_location (ClockData *cd, 
+                             char *locality, 
+                             char *country, 
+                             char *country_code)
+{
+        WeatherPrefs prefs;
+        GtkTreeModel *model;
+        char *weather_code;
+        ClockLocation *loc;
+        gdouble lat, lon;
+        char *zone_name;
+        char *location_name;
+        GWeatherLocation *location, *world;
+	GWeatherTimezone *zone;
+       
+	if (!country && !country_code)
+		return NULL;
+
+	world = gweather_location_new_world (FALSE);
+	location = find_gweather_location_by_country (world, country, country_code);
+	if (location)
+		gweather_location_ref (location);
+	gweather_location_unref (world);
+        if (!location) {
+                /* TODO: use geoclue coordinates to figure out the location */ 
+		g_debug ("New geoclue location was not usable");
+                return NULL;
+        }
+
+        if (locality) {
+                location_name = g_strdup_printf ("%s (geoclue)", locality);
+        } else {
+                /* TODO use names from zone? */
+                location_name = g_strdup_printf ("%s (geoclue)", gweather_location_get_name (location));
+        }
+        /* TODO: get coordinates from geoclue instead of using zoneinfo coords ? */ 
+       
+	zone = gweather_location_get_timezone (location);
+        zone_name = g_strdup (gweather_timezone_get_tzid (zone));
+	if (gweather_location_has_coords (location)) {
+		gweather_location_get_coords (location, &lat, &lon);
+	}
+	else {
+		/* FIXME use geoclue coordinates */
+	}
+	/* FIXME use coords to find a better location */
+	weather_code = g_strdup (find_gweather_location_code (location));
+ 
+       prefs.temperature_unit = cd->temperature_unit;
+       prefs.speed_unit = cd->speed_unit;
+       
+       loc = clock_location_new (location_name, 
+                                 zone_name, (gfloat)lat, (gfloat)lon, 
+                                 weather_code, &prefs);
+
+	g_free (location_name);
+	gweather_location_unref (location);
+	g_free (zone_name);
+	g_free (weather_code);
+
+        return loc;
+}
+
+typedef struct {
+       ClockData *cd;
+       ClockLocation *loc;
+} ClockNotifyData;
+
+
+static void
+set_geoclue_location_as_current (ClockData *cd, ClockLocation *loc)
+{
+       g_debug ("setting geoclue location as current");
+       
+       /* TODO: make sure current_loc is not same as loc */
+       
+       /* TODO: free current_geo_location if needed and remove from list */
+       
+       cd->current_geo_location = loc;
+       cd->locations = g_list_append (cd->locations, loc);
+       /* do something to trigger update ? */
+}
+
+static void
+edit_notify_callback (NotifyNotification *n, const char *action, ClockNotifyData *data) 
+{
+       g_debug ("'edit geoclue location' clicked");
+}
+
+static void
+set_notify_callback (NotifyNotification *n, const char *action, ClockNotifyData *data) 
+{
+       set_geoclue_location_as_current (data->cd, data->loc);
+       /*TODO save? */
+}
+
+static void
+show_new_timezone_notification (ClockData *cd, ClockLocation *loc) 
+{
+       ClockNotifyData *data;
+       NotifyNotification *notification;
+       gboolean notify_init_ok = FALSE;
+       char *body;
+       
+       notify_init_ok = notify_is_initted () ? TRUE : notify_init ("Clock Applet");
+       if (!notify_init_ok) {
+               g_warning ("Could not initialize libnotify\n");
+               return;
+       }
+       
+       data = g_new0 (ClockNotifyData, 1);
+       data->cd = cd;
+       data->loc = loc;
+       
+       body =  g_strdup_printf ("New location '%s', in timezone '%s'", 
+                                clock_location_get_name (loc),
+                                clock_location_get_timezone (loc));
+       
+       /*this ends up in wrong places, maybe button size/location is not available yet? */
+       notification = notify_notification_new ("Timezone change detected",
+                                               body,
+                                               NULL, 
+                                               cd->panel_button);
+       notify_notification_add_action(notification, 
+                                      "set", "Set as current location",
+                                      (NotifyActionCallback)set_notify_callback,
+                                      data, NULL); /* TODO free function */
+       notify_notification_add_action(notification,
+                                      "edit", "Edit location",
+                                      (NotifyActionCallback)edit_notify_callback,
+                                      data, NULL);
+       if (!notify_notification_show (notification, NULL)) {
+               g_warning ("Failed to send notification\n");
+               g_free (data);
+       }
+       
+       g_free (body);
+}
+
+static void
+on_location_changed (ClockGeoclue *clock_geo,
+                     char *locality,
+                     char *country,
+                     char *country_code,
+                     ClockData *cd)
+{
+       ClockLocation *geo_loc;
+       geo_loc = create_new_geoclue_location (cd, locality, country, country_code);
+       if (!geo_loc) {
+               g_debug ("New geoclue location was not usable");
+               return;
+       }
+       /* we now know the timezone we're in */
+       
+       /* TODO: if timezone is different from current, popup
+        *       if timezone is same as current, change current location to geoclue location */
+       
+       if (strcmp (system_timezone_get (cd->systz),
+                   clock_location_get_timezone (geo_loc)) == 0) {
+               g_debug ("new geoclue location (%s), same as system tz",
+                        clock_location_get_name (geo_loc));
+               set_geoclue_location_as_current (cd, geo_loc);
+       } else {
+               g_debug ("new geoclue location (%s) on new timezone, showing notification",
+                        clock_location_get_name (geo_loc));
+               show_new_timezone_notification (cd, geo_loc);
+       }
+}
+
+
 /* ClockBox, an instantiable GtkBox */
 
 typedef GtkBox      ClockBox;
@@ -779,10 +1002,14 @@ destroy_clock (GtkWidget * widget, ClockData *cd)
         g_list_free (cd->location_tiles);
         cd->location_tiles = NULL;
 
-	if (cd->clock_geo)
+	if (cd->clock_geo) {
 		g_object_unref (cd->clock_geo);
-	cd->clock_geo = NULL;
-
+		cd->clock_geo = NULL;
+	}
+	if (cd->current_geo_location) {
+               g_object_unref (cd->current_geo_location);
+               cd->current_geo_location = NULL;
+	}
 	if (cd->systz) {
 		g_object_unref (cd->systz);
 		cd->systz = NULL;
@@ -1026,14 +1253,15 @@ create_cities_store (ClockData *cd)
 	while (list) {
 		ClockLocation *loc = CLOCK_LOCATION (list->data);
 
-		gtk_list_store_append (cd->cities_store, &iter);
-		gtk_list_store_set (cd->cities_store, &iter,
-				    COL_CITY_NAME, clock_location_get_name (loc),
-				    /* FIXME: translate the timezone */
-				    COL_CITY_TZ, clock_location_get_timezone (loc),
-                                    COL_CITY_LOC, loc,
-				    -1);
-
+		if (loc != cd->current_geo_location) {
+			gtk_list_store_append (cd->cities_store, &iter);
+			gtk_list_store_set (cd->cities_store, &iter,
+					    COL_CITY_NAME, clock_location_get_name (loc),
+					    /* FIXME: translate the timezone */
+					    COL_CITY_TZ, clock_location_get_timezone (loc),
+       	                             	    COL_CITY_LOC, loc,
+					    -1);
+		}
                 list = list->next;
 	}
 
@@ -1213,6 +1441,7 @@ update_calendar_popup (ClockData *cd)
                         gtk_widget_destroy (cd->calendar_popup);
                         cd->calendar_popup = NULL;
                         cd->cities_section = NULL;
+			cd->geo_city_section = NULL;
                         cd->map_section = NULL;
                         cd->map_widget = NULL;
 			cd->clock_vbox = NULL;
@@ -2080,6 +2309,11 @@ set_locations (ClockData *cd, GList *locations)
 {
         free_locations (cd);
         cd->locations = locations;
+
+	if (cd->current_geo_location) {
+		cd->locations = g_list_append (cd->locations, cd->current_geo_location);
+	}
+
 	locations_changed (cd);
 }
 
@@ -2645,7 +2879,12 @@ fill_clock_applet (PanelApplet *applet)
 					      NULL);
 	}
 
+	cd->current_geo_location = NULL;
+
 	cd->clock_geo = clock_geoclue_new ();
+        g_signal_connect (cd->clock_geo, "location-changed", 
+                          G_CALLBACK (on_location_changed), cd);
+        clock_geoclue_force_location_changed (cd->clock_geo);
 
 	cd->systz = system_timezone_new ();
 	g_signal_connect (cd->systz, "changed",
@@ -2882,7 +3121,9 @@ save_cities_store (ClockData *cd)
 
         while (node) {
                 loc = CLOCK_LOCATION (node->data);
-                list = g_slist_prepend (list, loc_to_string (loc));
+		if (loc != cd->current_geo_location) {
+               		list = g_slist_prepend (list, loc_to_string (loc));
+		}
                 node = node->next;
         }
 
diff --git a/configure.in b/configure.in
index ee0548c..3424b7d 100644
--- a/configure.in
+++ b/configure.in
@@ -122,7 +122,7 @@ fi
 AM_CONDITIONAL(HAVE_LIBECAL, test -n "$LIBECAL_REQUIREMENT")
 AC_SUBST(CLOCK_EDS_ICONDIR)
 
-PKG_CHECK_MODULES(CLOCK, pango >= $PANGO_REQUIRED gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED gio-2.0 >= $GLIB_REQUIRED $LIBECAL_REQUIREMENT libglade-2.0 >= $LIBGLADE_REQUIRED librsvg-2.0 dbus-glib-1 gweather >= $GWEATHER_REQUIRED geoclue >= $GEOCLUE_REQUIRED libnm_glib)
+PKG_CHECK_MODULES(CLOCK, pango >= $PANGO_REQUIRED gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED gio-2.0 >= $GLIB_REQUIRED $LIBECAL_REQUIREMENT libglade-2.0 >= $LIBGLADE_REQUIRED librsvg-2.0 dbus-glib-1 gweather >= $GWEATHER_REQUIRED geoclue >= $GEOCLUE_REQUIRED libnm_glib libnotify)
 AC_SUBST(CLOCK_CFLAGS)
 AC_SUBST(CLOCK_LIBS)
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]