From a10f207618976b59a0cc43c01befbf67128c92a5 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Thu, 17 Feb 2011 14:30:43 -0500 Subject: first pass at preferences dialog --- configure.ac | 18 + data/Makefile.am | 3 + data/com.canonical.indicator.datetime.gschema.xml | 53 +- data/datetime-dialog.ui | 808 ++++++++++++++++++++++ src/Makefile.am | 20 +- src/datetime-prefs.c | 211 ++++++ src/datetime-service.c | 14 +- src/indicator-datetime.c | 31 +- src/settings-shared.h | 39 ++ src/utils.c | 45 ++ src/utils.h | 34 + 11 files changed, 1229 insertions(+), 47 deletions(-) create mode 100644 data/datetime-dialog.ui create mode 100644 src/datetime-prefs.c create mode 100644 src/settings-shared.h create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/configure.ac b/configure.ac index 4f35d38..3cf45ef 100644 --- a/configure.ac +++ b/configure.ac @@ -64,6 +64,8 @@ EDS_REQUIRED_VERSION=2.30 ICAL_REQUIRED_VERSION=0.44 CAIRO_REQUIRED_VERSION=1.10 GDK_REQUIRED_VERSION=2.22 +GTK_REQUIRED_VERSION=2.12 +GTK3_REQUIRED_VERSION=3.0 AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION @@ -110,12 +112,28 @@ AS_IF([test "x$with_gtk" = x3], ], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) + +AS_IF([test "x$with_gtk" = x3], + [PKG_CHECK_MODULES(PREF, gio-2.0 >= $GIO_REQUIRED_VERSION + gtk+-3.0 >= $GTK3_REQUIRED_VERSION + unique-3.0) + ], + [test "x$with_gtk" = x2], + [PKG_CHECK_MODULES(PREF, gio-2.0 >= $GIO_REQUIRED_VERSION + gtk+-2.0 >= $GTK_REQUIRED_VERSION + unique-1.0) + ], + [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] +) AC_SUBST(INDICATOR_CFLAGS) AC_SUBST(INDICATOR_LIBS) AC_SUBST(SERVICE_CFLAGS) AC_SUBST(SERVICE_LIBS) +AC_SUBST(PREF_CFLAGS) +AC_SUBST(PREF_LIBS) + ########################### # Grab the GSettings Macros ########################### diff --git a/data/Makefile.am b/data/Makefile.am index de417b2..669db77 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -10,8 +10,11 @@ dbus_services_DATA = indicator-datetime.service %.service: %.service.in sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ +pkgdata_DATA = datetime-dialog.ui + EXTRA_DIST = \ $(gsettings_SCHEMAS) \ + datetime-dialog.ui \ indicator-datetime.service.in CLEANFILES = indicator-datetime.service diff --git a/data/com.canonical.indicator.datetime.gschema.xml b/data/com.canonical.indicator.datetime.gschema.xml index 117f965..b33f34e 100644 --- a/data/com.canonical.indicator.datetime.gschema.xml +++ b/data/com.canonical.indicator.datetime.gschema.xml @@ -6,6 +6,13 @@ + + true + Show the clock in the panel + + Controls whether the clock indicator appears in the panel or not. + + 'locale-default' What the time format should be @@ -18,6 +25,17 @@ string and set the custom-time-format setting. + + "%l:%M %p" + The format string passed to strftime + + The format of the time and/or date that is visible on the panel when using + the indicator. For most users this will be a set of predefined values as + determined by the configuration utility, but advanced users can change it + to anything strftime can accept. Look at the man page on strftime for + more information. + + false Show the number of seconds in the indicator @@ -46,19 +64,36 @@ time-format value is set to custom. - - "%l:%M %p" - The format string passed to strftime + + true + Show the monthly calendar in the indicator - The format of the time and/or date that is visible on the panel when using - the indicator. For most users this will be a set of predefined values as - determined by the configuration utility, but advanced users can change it - to anything strftime can accept. Look at the man page on strftime for - more information. + Puts the monthly calendar in indicator-datetime's menu. + + + + false + Show week numbers in calendar + + Shows the week numbers in the monthly calendar in indicator-datetime's menu. + + + + true + Show events in the indicator + + Shows events from Evolution in indicator-datetime's menu. + + + + false + Show locations in the indicator + + Shows custom defined locations in indicator-datetime's menu. - [] + ['UTC'] A List of locations Adds the list of locations the user has configured to display in the diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui new file mode 100644 index 0000000..42f3bb6 --- /dev/null +++ b/data/datetime-dialog.ui @@ -0,0 +1,808 @@ + + + + + + False + Locations + time-admin + + + True + False + + + True + True + locationsStore + + + True + True + 0 + + + + + True + False + + + True + True + True + False + + + True + False + gtk-add + + + + + False + True + 0 + + + + + True + True + True + False + + + True + False + gtk-remove + + + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + + + + + + + False + 5 + Time & Date + time-admin + dialog + + + True + False + + + False + True + end + + + gtk-close + True + True + True + False + True + + + False + False + 0 + + + + + False + True + end + 0 + + + + + True + True + + + True + False + 12 + 6 + + + + + + + + + True + False + 12 + True + + + True + False + 6 + + + True + False + 0 + _Region: + True + regionCombo + + + False + True + 0 + + + + + True + False + + + True + True + 1 + + + + + True + True + 0 + + + + + True + False + 6 + + + True + False + 0 + Time_zone: + True + timezoneCombo + + + False + True + 0 + + + + + True + False + + + True + True + 1 + + + + + False + True + 1 + + + + + False + True + 2 + + + + + True + False + 2 + 2 + 6 + 6 + + + True + False + 6 + + + _Manually + True + True + False + False + True + 0 + True + True + + + False + True + 0 + + + + + _Automatically from the Internet + True + True + False + False + True + 0 + True + manualTimeRadio + + + False + True + 1 + + + + + 1 + 2 + + + + + True + False + 0 + Set the time: + + + GTK_FILL + GTK_FILL + + + + + True + False + 12 + + + True + False + 6 + + + True + False + 0 + Tim_e: + True + timeSpinner + + + False + True + 0 + + + + + True + True + + True + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + 6 + + + True + False + 0 + _Date: + True + dateSpinner + + + False + True + 0 + + + + + True + True + + True + + + False + True + 1 + + + + + False + True + 1 + + + + + 1 + 2 + 1 + 2 + + + + + + + + False + True + 3 + + + + + + + True + False + 1 + _Time & Date + True + + + False + + + + + True + False + 12 + 12 + + + _Show a clock in the panel + True + True + False + False + True + 0 + True + + + True + True + 0 + + + + + True + False + True + + + True + False + + + True + False + 0 + In the clock, show: + + + False + True + 0 + + + + + _Weekday + True + True + False + False + True + 0 + True + + + False + True + 1 + + + + + _Date and time + True + True + False + False + True + 0 + True + + + False + True + 2 + + + + + _12-hour time + True + True + False + False + True + 0 + True + True + + + False + True + 3 + + + + + _24-hour time + True + True + False + False + True + 0 + True + True + show12HourRadio + + + False + True + 4 + + + + + Seco_nds + True + True + False + False + True + 0 + True + + + False + True + 5 + + + + + True + True + 0 + + + + + True + False + + + True + False + 0 + In the clock’s menu, show: + + + True + True + 0 + + + + + _Monthly calendar + True + True + False + False + True + 0 + True + + + False + True + 1 + + + + + True + False + 0 + 0 + 0 + 0 + 12 + + + True + False + + + Include week num_bers + True + True + False + False + True + 0 + True + + + True + True + 0 + + + + + False + True + 0 + Week begins on: + + + True + True + 1 + + + + + False + True + True + + + S_unday + True + True + False + False + True + 0 + True + True + + + True + True + 0 + + + + + Monda_y + True + True + False + False + True + 0 + True + True + startOnSundayRadio + + + True + True + 1 + + + + + True + True + 2 + + + + + + + False + True + 2 + + + + + True + True + False + False + True + 0 + True + + + True + False + 0 + Coming _events from Evolution Calendar + True + True + showEventsCheck + + + + + False + True + 3 + + + + + Time in _other locations + True + True + False + False + True + 0 + True + + + False + True + 4 + + + + + True + False + 0 + 0 + 0 + 0 + 12 + + + Choose _Locations… + True + True + True + False + True + 0 + + + + + True + True + 5 + + + + + True + True + 1 + + + + + True + True + 1 + + + + + 1 + False + + + + + True + False + _Clock + True + + + 1 + False + + + + + True + True + 1 + + + + + + + + + closeButton + + + diff --git a/src/Makefile.am b/src/Makefile.am index 7a290c6..150c87d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,5 @@ +bin_PROGRAMS = indicator-datetime-preferences libexec_PROGRAMS = indicator-datetime-service indicator_datetime_service_SOURCES = \ @@ -8,7 +9,8 @@ indicator_datetime_service_SOURCES = \ calendar-menu-item.c \ calendar-menu-item.h \ datetime-service.c \ - dbus-shared.h + dbus-shared.h \ + settings-shared.h indicator_datetime_service_CFLAGS = \ -Wall \ -Werror \ @@ -23,6 +25,9 @@ datetimelib_LTLIBRARIES = libdatetime.la libdatetime_la_SOURCES = \ gen-datetime-service.xml.h \ dbus-shared.h \ + settings-shared.h \ + utils.c \ + utils.h \ indicator-datetime.c libdatetime_la_CFLAGS = \ $(INDICATOR_CFLAGS) \ @@ -34,6 +39,19 @@ libdatetime_la_LDFLAGS = \ -module \ -avoid-version +indicator_datetime_preferences_SOURCES =\ + datetime-prefs.c \ + utils.c \ + utils.h \ + settings-shared.h +indicator_datetime_preferences_CFLAGS = \ + -Wall \ + -Werror \ + $(PREF_CFLAGS) \ + -DPKGDATADIR="\"$(pkgdatadir)\"" +indicator_datetime_preferences_LDADD = \ + $(PREF_LIBS) + gen-%.xml.c: %.xml @echo "Building $@ from $<" @echo "const char * _$(subst -,_,$(subst .,_,$(basename $<))) = " > $@ diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c new file mode 100644 index 0000000..1957b7f --- /dev/null +++ b/src/datetime-prefs.c @@ -0,0 +1,211 @@ +/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*- + +A dialog for setting time and date preferences. + +Copyright 2011 Canonical Ltd. + +Authors: + Ted Gould + Michael Terry + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "settings-shared.h" +#include "utils.h" + +#define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui" + +/* Turns the boolean property into a string gsettings */ +static GVariant * +bind_hours_set (const GValue * value, const GVariantType * type, gpointer user_data) +{ + const gchar * output = NULL; + gboolean is_12hour_button = (gboolean)GPOINTER_TO_INT(user_data); + + if (g_value_get_boolean(value)) { + /* Only do anything if we're setting active = true */ + output = is_12hour_button ? "12-hour" : "24-hour"; + } else { + return NULL; + } + + return g_variant_new_string (output); +} + +/* Turns a string gsettings into a boolean property */ +static gboolean +bind_hours_get (GValue * value, GVariant * variant, gpointer user_data) +{ + const gchar * str = g_variant_get_string(variant, NULL); + gboolean output = FALSE; + gboolean is_12hour_button = (gboolean)GPOINTER_TO_INT(user_data); + + if (g_strcmp0(str, "locale-default") == 0) { + output = (is_12hour_button == is_locale_12h ()); + } else if (g_strcmp0(str, "12-hour") == 0) { + output = is_12hour_button; + } else if (g_strcmp0(str, "24-hour") == 0) { + output = !is_12hour_button; + } else { + return FALSE; + } + + g_value_set_boolean (value, output); + return TRUE; +} + +static void +widget_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent) +{ + gboolean active, sensitive; + g_object_get (G_OBJECT (parent), + "active", &active, + "sensitive", &sensitive, NULL); + gtk_widget_set_sensitive (dependent, active && sensitive); +} + +static void +add_widget_dependency (GtkWidget * parent, GtkWidget * dependent) +{ + g_signal_connect (parent, "notify::active", G_CALLBACK(widget_dependency_cb), + dependent); + g_signal_connect (parent, "notify::sensitive", G_CALLBACK(widget_dependency_cb), + dependent); + widget_dependency_cb (parent, NULL, dependent); +} + +static GtkWidget * +create_dialog (void) +{ + GError * error = NULL; + + GtkBuilder * builder = gtk_builder_new (); + gtk_builder_add_from_file (builder, DATETIME_DIALOG_UI_FILE, &error); + if (error != NULL) { + /* We have to abort, we can't continue without the ui file */ + g_error ("Could not load ui file %s: %s", DATETIME_DIALOG_UI_FILE, error->message); + g_error_free (error); + return NULL; + } + + gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); + + GSettings * conf = g_settings_new (SETTINGS_INTERFACE); + +#define WIG(name) GTK_WIDGET (gtk_builder_get_object (builder, name)) + + /* Set up settings bindings */ + + g_settings_bind (conf, SETTINGS_SHOW_CLOCK_S, WIG ("showClockCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + g_settings_bind (conf, SETTINGS_SHOW_DAY_S, WIG ("showWeekdayCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + g_settings_bind (conf, SETTINGS_SHOW_DATE_S, WIG ("showDateTimeCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + g_settings_bind (conf, SETTINGS_SHOW_SECONDS_S, WIG ("showSecondsCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + g_settings_bind_with_mapping (conf, SETTINGS_TIME_FORMAT_S, + WIG ("show12HourRadio"), "active", + G_SETTINGS_BIND_DEFAULT, + bind_hours_get, bind_hours_set, + GINT_TO_POINTER(TRUE), NULL); + g_settings_bind_with_mapping (conf, SETTINGS_TIME_FORMAT_S, + WIG ("show24HourRadio"), "active", + G_SETTINGS_BIND_DEFAULT, + bind_hours_get, bind_hours_set, + GINT_TO_POINTER(FALSE), NULL); + g_settings_bind (conf, SETTINGS_SHOW_CALENDAR_S, WIG ("showCalendarCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + g_settings_bind (conf, SETTINGS_SHOW_WEEK_NUMBERS_S, WIG ("includeWeekNumbersCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + /*g_settings_bind_(conf, SETTINGS_WEEK_BEGINS_SUNDAY_S, WIG ("startOnSundayRadio"), + "active", G_SETTINGS_BIND_DEFAULT);*/ + g_settings_bind (conf, SETTINGS_SHOW_EVENTS_S, WIG ("showEventsCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + g_settings_bind (conf, SETTINGS_SHOW_LOCATIONS_S, WIG ("showLocationsCheck"), + "active", G_SETTINGS_BIND_DEFAULT); + + /* Set up sensitivities */ + add_widget_dependency (WIG ("showCalendarCheck"), WIG ("calendarOptions")); + add_widget_dependency (WIG ("showClockCheck"), WIG ("clockOptions")); + add_widget_dependency (WIG ("showLocationsCheck"), WIG ("locationsButton")); + add_widget_dependency (WIG ("manualTimeRadio"), WIG ("manualOptions")); + + /* Hacky proxy test for whether evolution-data-server is installed */ + gchar * evo_path = g_find_program_in_path ("evolution"); + gtk_widget_set_sensitive (WIG ("showEventsCheck"), (evo_path != NULL)); + g_free (evo_path); + + GtkWidget * dlg = WIG ("timeDateDialog"); + +#undef WIG + + g_object_unref (conf); + g_object_unref (builder); + + return dlg; +} + +static UniqueResponse +message_received (UniqueApp * app, gint command, UniqueMessageData *message_data, + guint time, gpointer user_data) +{ + if (command == UNIQUE_ACTIVATE) { + gtk_window_present_with_time (GTK_WINDOW (user_data), time); + return UNIQUE_RESPONSE_OK; + } + return UNIQUE_RESPONSE_PASSTHROUGH; +} + +int +main (int argc, char ** argv) +{ + g_type_init (); + + /* Setting up i18n and gettext. Apparently, we need + all of these. */ + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + textdomain (GETTEXT_PACKAGE); + + gtk_init (&argc, &argv); + + UniqueApp * app = unique_app_new ("com.canonical.indicator.datetime.preferences", NULL); + + if (unique_app_is_running (app)) { + unique_app_send_message (app, UNIQUE_ACTIVATE, NULL); + } else { + // We're first instance. Yay! + GtkWidget * dlg = create_dialog (); + + g_signal_connect (app, "message-received", G_CALLBACK(message_received), dlg); + unique_app_watch_window (app, GTK_WINDOW (dlg)); + + gtk_widget_show_all (dlg); + g_signal_connect (dlg, "response", G_CALLBACK(gtk_main_quit), NULL); + gtk_main (); + } + + return 0; +} + diff --git a/src/datetime-service.c b/src/datetime-service.c index 0894e83..cc6c9d5 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -51,11 +51,9 @@ with this program. If not, see . #include "datetime-interface.h" #include "dbus-shared.h" +#include "settings-shared.h" -#define SETTINGS_INTERFACE "com.canonical.indicator.datetime" -#define SETTINGS_LOCATIONS "locations" - static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data); static gboolean update_appointment_menu_items (gpointer user_data); static gboolean update_timezone_menu_items(gpointer user_data); @@ -363,7 +361,7 @@ check_for_calendar (gpointer user_data) static gboolean update_timezone_menu_items(gpointer user_data) { g_debug("Updating timezone menu items"); - gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS); + gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS_S); if (locations == NULL) { g_debug("No locations configured (NULL)"); return FALSE; @@ -648,13 +646,13 @@ check_for_timeadmin (gpointer user_data) { g_return_val_if_fail (settings != NULL, FALSE); - gchar * timeadmin = g_find_program_in_path("time-admin"); + gchar * timeadmin = g_find_program_in_path("indicator-datetime-preferences"); if (timeadmin != NULL) { - g_debug("Found the time-admin application: %s", timeadmin); + g_debug("Found the indicator-datetime-preferences application: %s", timeadmin); dbusmenu_menuitem_property_set_bool(settings, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); g_free(timeadmin); } else { - g_debug("Unable to find time-admin app."); + g_debug("Unable to find indicator-datetime-preferences app."); dbusmenu_menuitem_property_set_bool(settings, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); } @@ -721,7 +719,7 @@ build_menus (DbusmenuMenuitem * root) dbusmenu_menuitem_property_set (settings, DBUSMENU_MENUITEM_PROP_LABEL, _("Time & Date Settings...")); /* insensitive until we check for available apps */ dbusmenu_menuitem_property_set_bool(settings, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - g_signal_connect(G_OBJECT(settings), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "time-admin"); + g_signal_connect(G_OBJECT(settings), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "indicator-datetime-preferences"); dbusmenu_menuitem_child_append(root, settings); g_idle_add(check_for_timeadmin, NULL); diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 0f60428..e27158c 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -23,10 +23,6 @@ with this program. If not, see . #include "config.h" #endif -#include -#include -#include - /* GStuff */ #include #include @@ -43,7 +39,9 @@ with this program. If not, see . #include #include +#include "utils.h" #include "dbus-shared.h" +#include "settings-shared.h" #define INDICATOR_DATETIME_TYPE (indicator_datetime_get_type ()) @@ -117,13 +115,6 @@ struct _indicator_item_t { #define PROP_SHOW_DATE_S "show-date" #define PROP_CUSTOM_TIME_FORMAT_S "custom-time-format" -#define SETTINGS_INTERFACE "com.canonical.indicator.datetime" -#define SETTINGS_TIME_FORMAT_S "time-format" -#define SETTINGS_SHOW_SECONDS_S "show-seconds" -#define SETTINGS_SHOW_DAY_S "show-day" -#define SETTINGS_SHOW_DATE_S "show-date" -#define SETTINGS_CUSTOM_TIME_FORMAT_S "custom-time-format" - enum { SETTINGS_TIME_LOCALE = 0, SETTINGS_TIME_12_HOUR = 1, @@ -964,24 +955,6 @@ T_(const char *msg) return rv; } -/* Check the system locale setting to see if the format is 24-hour - time or 12-hour time */ -static gboolean -is_locale_12h() -{ - static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", NULL}; - const char *t_fmt = nl_langinfo(T_FMT); - int i; - - for (i = 0; formats_24h[i]; ++i) { - if (strstr(t_fmt, formats_24h[i])) { - return FALSE; - } - } - - return TRUE; -} - /* Respond to changes in the screen to update the text gravity */ static void update_text_gravity (GtkWidget *widget, GdkScreen *previous_screen, gpointer data) diff --git a/src/settings-shared.h b/src/settings-shared.h new file mode 100644 index 0000000..1a66688 --- /dev/null +++ b/src/settings-shared.h @@ -0,0 +1,39 @@ +/* +An indicator to show date and time information. + +Copyright 2010 Canonical Ltd. + +Authors: + Ted Gould + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . +*/ + +#ifndef __DATETIME_SETTINGS_SHARED_H__ +#define __DATETIME_SETTINGS_SHARED_H__ + +#define SETTINGS_INTERFACE "com.canonical.indicator.datetime" +#define SETTINGS_SHOW_CLOCK_S "show-clock" +#define SETTINGS_TIME_FORMAT_S "time-format" +#define SETTINGS_SHOW_SECONDS_S "show-seconds" +#define SETTINGS_SHOW_DAY_S "show-day" +#define SETTINGS_SHOW_DATE_S "show-date" +#define SETTINGS_CUSTOM_TIME_FORMAT_S "custom-time-format" +#define SETTINGS_SHOW_CALENDAR_S "show-calendar" +#define SETTINGS_SHOW_WEEK_NUMBERS_S "show-week-numbers" +#define SETTINGS_WEEK_BEGINS_SUNDAY_S "week-begins-sunday" +#define SETTINGS_SHOW_EVENTS_S "show-events" +#define SETTINGS_SHOW_LOCATIONS_S "show-locations" +#define SETTINGS_LOCATIONS_S "locations" + +#endif diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..69143b9 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,45 @@ +/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*- + +A dialog for setting time and date preferences. + +Copyright 2010 Canonical Ltd. + +Authors: + Michael Terry + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . +*/ + +#include +#include +#include +#include "utils.h" + +/* Check the system locale setting to see if the format is 24-hour + time or 12-hour time */ +gboolean +is_locale_12h (void) +{ + static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", NULL}; + const char *t_fmt = nl_langinfo (T_FMT); + int i; + + for (i = 0; formats_24h[i]; ++i) { + if (strstr (t_fmt, formats_24h[i])) { + return FALSE; + } + } + + return TRUE; +} + diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..f6305c8 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*- + +A dialog for setting time and date preferences. + +Copyright 2010 Canonical Ltd. + +Authors: + Michael Terry + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . +*/ + +#ifndef __DATETIME_UTILS_H__ +#define __DATETIME_UTILS_H__ + +#include + +G_BEGIN_DECLS + +gboolean is_locale_12h (void); + +G_END_DECLS + +#endif -- cgit v1.2.3 From 354fc2c05e901b65f4a0516473632a4df3878ed6 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Fri, 18 Feb 2011 10:50:49 -0500 Subject: add polkit support and use new gnome-settings-daemon ntp-setting support --- configure.ac | 7 +- data/datetime-dialog.ui | 354 +++++++++++++++++++++++++----------------------- src/datetime-prefs.c | 223 ++++++++++++++++++++++++++---- 3 files changed, 387 insertions(+), 197 deletions(-) diff --git a/configure.ac b/configure.ac index 3cf45ef..2418f12 100644 --- a/configure.ac +++ b/configure.ac @@ -113,15 +113,18 @@ AS_IF([test "x$with_gtk" = x3], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) +# FIXME: polkit-gtk-1 isn't gtk3-compatible AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(PREF, gio-2.0 >= $GIO_REQUIRED_VERSION gtk+-3.0 >= $GTK3_REQUIRED_VERSION - unique-3.0) + unique-3.0 + polkit-gtk-1) ], [test "x$with_gtk" = x2], [PKG_CHECK_MODULES(PREF, gio-2.0 >= $GIO_REQUIRED_VERSION gtk+-2.0 >= $GTK_REQUIRED_VERSION - unique-1.0) + unique-1.0 + polkit-gtk-1) ], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui index 42f3bb6..f2a5938 100644 --- a/data/datetime-dialog.ui +++ b/data/datetime-dialog.ui @@ -133,82 +133,91 @@ 12 6 - - - - - - - + True False - 12 - True + 6 - - True - False - 6 - - - True - False - 0 - _Region: - True - regionCombo - - - False - True - 0 - - - - - True - False - - - True - True - 1 - - - - - True - True - 0 - + - + True False - 6 + 12 + True - + True False - 0 - Time_zone: - True - timezoneCombo + 6 + + + True + False + 0 + _Region: + True + regionCombo + + + False + True + 0 + + + + + True + False + + + True + True + 1 + + - False + True True 0 - + True False + 6 + + + True + False + 0 + Time_zone: + True + timezoneCombo + + + False + True + 0 + + + + + True + False + + + True + True + 1 + + - True + False True 1 @@ -220,98 +229,30 @@ 1 - - - False - True - 2 - - - - - True - False - 2 - 2 - 6 - 6 - + True False - 6 + 2 + 2 + 6 + 6 - - _Manually - True - True - False - False - True - 0 - True - True - - - False - True - 0 - - - - - _Automatically from the Internet - True - True - False - False - True - 0 - True - manualTimeRadio - - - False - True - 1 - - - - - 1 - 2 - - - - - True - False - 0 - Set the time: - - - GTK_FILL - GTK_FILL - - - - - True - False - 12 - - + True False 6 - + + _Manually True - False - 0 - Tim_e: + True + False + False True - timeSpinner + 0 + True + True False @@ -320,11 +261,16 @@ - + + _Automatically from the Internet True True - - True + False + False + True + 0 + True + manualTimeRadio False @@ -334,24 +280,62 @@ - False - True - 0 + 1 + 2 - + True False - 6 + 0 + Set the time: + + + GTK_FILL + GTK_FILL + + + + + True + False + 12 - + True False - 0 - _Date: - True - dateSpinner + 6 + + + True + False + 0 + Tim_e: + True + timeSpinner + + + False + True + 0 + + + + + True + True + + 11 + 1 + True + + + False + True + 1 + + False @@ -360,11 +344,40 @@ - + True - True - - True + False + 6 + + + True + False + 0 + _Date: + True + dateSpinner + + + False + True + 0 + + + + + True + True + + 11 + 1 + True + + + False + True + 1 + + False @@ -374,29 +387,33 @@ - False - True - 1 + 1 + 2 + 1 + 2 + + + - 1 - 2 - 1 - 2 + False + True + 2 - - - - False + True True - 3 + end + 0 + + + @@ -443,6 +460,7 @@ True False + 6 True @@ -555,6 +573,7 @@ True False + 6 True @@ -796,9 +815,6 @@ 1 - - - diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index 1957b7f..87eec94 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -27,8 +27,10 @@ with this program. If not, see . #include #include +#include #include #include +#include #include "settings-shared.h" #include "utils.h" @@ -42,36 +44,36 @@ bind_hours_set (const GValue * value, const GVariantType * type, gpointer user_d const gchar * output = NULL; gboolean is_12hour_button = (gboolean)GPOINTER_TO_INT(user_data); - if (g_value_get_boolean(value)) { + if (g_value_get_boolean(value)) { /* Only do anything if we're setting active = true */ - output = is_12hour_button ? "12-hour" : "24-hour"; - } else { + output = is_12hour_button ? "12-hour" : "24-hour"; + } else { return NULL; } - return g_variant_new_string (output); + return g_variant_new_string (output); } /* Turns a string gsettings into a boolean property */ static gboolean bind_hours_get (GValue * value, GVariant * variant, gpointer user_data) { - const gchar * str = g_variant_get_string(variant, NULL); - gboolean output = FALSE; + const gchar * str = g_variant_get_string(variant, NULL); + gboolean output = FALSE; gboolean is_12hour_button = (gboolean)GPOINTER_TO_INT(user_data); - if (g_strcmp0(str, "locale-default") == 0) { - output = (is_12hour_button == is_locale_12h ()); - } else if (g_strcmp0(str, "12-hour") == 0) { - output = is_12hour_button; - } else if (g_strcmp0(str, "24-hour") == 0) { - output = !is_12hour_button; - } else { - return FALSE; - } + if (g_strcmp0(str, "locale-default") == 0) { + output = (is_12hour_button == is_locale_12h ()); + } else if (g_strcmp0(str, "12-hour") == 0) { + output = is_12hour_button; + } else if (g_strcmp0(str, "24-hour") == 0) { + output = !is_12hour_button; + } else { + return FALSE; + } - g_value_set_boolean (value, output); - return TRUE; + g_value_set_boolean (value, output); + return TRUE; } static void @@ -94,6 +96,163 @@ add_widget_dependency (GtkWidget * parent, GtkWidget * dependent) widget_dependency_cb (parent, NULL, dependent); } +static void +polkit_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent) +{ + gboolean authorized, sensitive; + g_object_get (G_OBJECT (parent), + "is-authorized", &authorized, + "sensitive", &sensitive, NULL); + gtk_widget_set_sensitive (dependent, authorized && sensitive); +} + +static void +add_polkit_dependency (GtkWidget * parent, GtkWidget * dependent) +{ + g_signal_connect (parent, "notify::is-authorized", G_CALLBACK(polkit_dependency_cb), + dependent); + g_signal_connect (parent, "notify::sensitive", G_CALLBACK(polkit_dependency_cb), + dependent); + polkit_dependency_cb (parent, NULL, dependent); +} + +void ntp_set_answered (GObject *object, GAsyncResult *res, gpointer autoRadio) +{ + GError * error = NULL; + GDBusProxy * proxy = G_DBUS_PROXY (object); + GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error); + + if (error != NULL) { + g_warning("Could not set 'using_ntp' for SettingsDaemon: %s", error->message); + g_error_free(error); + return; + } + + g_variant_unref (answers); +} + +static void +toggle_ntp (GtkWidget * autoRadio, GParamSpec * pspec, gpointer user_data) +{ + gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (autoRadio)); + GDBusProxy * proxy = G_DBUS_PROXY (g_object_get_data (G_OBJECT (autoRadio), "proxy")); + + g_dbus_proxy_call (proxy, "SetUsingNtp", g_variant_new ("(b)", active), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, ntp_set_answered, autoRadio); +} + +void ntp_query_answered (GObject *object, GAsyncResult *res, gpointer autoRadio) +{ + GError * error = NULL; + GDBusProxy * proxy = G_DBUS_PROXY (object); + GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error); + + if (error != NULL) { + g_warning("Could not query DBus proxy for SettingsDaemon: %s", error->message); + g_error_free(error); + return; + } + + gboolean can_use_ntp, is_using_ntp; + g_variant_get (answers, "(bb)", &can_use_ntp, &is_using_ntp); + + gtk_widget_set_sensitive (GTK_WIDGET (autoRadio), can_use_ntp); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (autoRadio), is_using_ntp); + + g_signal_connect (autoRadio, "notify::active", G_CALLBACK(toggle_ntp), NULL); + + g_variant_unref (answers); +} + +void ntp_proxy_ready (GObject *object, GAsyncResult *res, gpointer autoRadio) +{ + GError * error = NULL; + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (error != NULL) { + g_critical("Could not grab DBus proxy for SettingsDaemon: %s", error->message); + g_error_free(error); + return; + } + + /* Now attach proxy to button so we can use it later */ + g_object_set_data_full (G_OBJECT (autoRadio), "proxy", proxy, g_object_unref); + + /* And finally ask it what is up */ + g_dbus_proxy_call (proxy, "GetUsingNtp", NULL, G_DBUS_CALL_FLAGS_NONE, -1, + NULL, ntp_query_answered, autoRadio); +} + +static void +setup_ntp (GtkWidget * autoRadio) +{ + /* Do some quick checks to see if ntp is running or installed */ + + /* Start with assumption ntp is unusable until we prove otherwise */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (autoRadio), FALSE); + gtk_widget_set_sensitive (autoRadio, FALSE); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, + "org.gnome.SettingsDaemon.DateTimeMechanism", + "/", + "org.gnome.SettingsDaemon.DateTimeMechanism", + NULL, ntp_proxy_ready, autoRadio); +} + +/*static int +input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) +{ + //const gchar * text = gtk_entry_get_text (GTK_ENTRY (spinner)); + + return TRUE; +}*/ + +static gboolean +format_time_text (GtkWidget * spinner, gpointer user_data) +{ + GDateTime * datetime = (GDateTime *)g_object_get_data (G_OBJECT (spinner), "datetime"); + + const gchar * format; + if (is_locale_12h ()) { + format = "%I:%M:%S %p"; + } else { + format = "%H:%M:%S"; + } + + gchar * formatted = g_date_time_format (datetime, format); + gtk_entry_set_text (GTK_ENTRY (spinner), formatted); + + return TRUE; +} + +static gboolean +update_spinner (GtkWidget * spinner) +{ + /* Add datetime object to spinner, which will hold the real time value, rather + then using the value of the spinner itself. */ + GDateTime * datetime = g_date_time_new_now_local (); + g_object_set_data_full (G_OBJECT (spinner), "datetime", datetime, (GDestroyNotify)g_date_time_unref); + + format_time_text (spinner, NULL); + + return TRUE; +} + +static void +setup_time_spinner (GtkWidget * spinner) +{ + /* Set up spinner to have reasonable behavior */ + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), FALSE); + //g_signal_connect (spinner, "input", G_CALLBACK (input_time_text), NULL); + g_signal_connect (spinner, "output", G_CALLBACK (format_time_text), NULL); + + /* 2 seconds is what the indicator itself uses */ + guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_spinner, spinner); + g_signal_connect_swapped (spinner, "destroy", G_CALLBACK (g_source_remove), GINT_TO_POINTER(time_id)); + + update_spinner (spinner); +} + static GtkWidget * create_dialog (void) { @@ -110,10 +269,16 @@ create_dialog (void) gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); - GSettings * conf = g_settings_new (SETTINGS_INTERFACE); + GSettings * conf = g_settings_new (SETTINGS_INTERFACE); #define WIG(name) GTK_WIDGET (gtk_builder_get_object (builder, name)) + /* Add policykit button */ + GtkWidget * polkit_button = polkit_lock_button_new ("org.gnome.settingsdaemon.datetimemechanism.configure"); + polkit_lock_button_set_unlock_text (POLKIT_LOCK_BUTTON (polkit_button), _("Unlock to change these settings")); + polkit_lock_button_set_lock_text (POLKIT_LOCK_BUTTON (polkit_button), _("Lock to prevent further changes")); + gtk_box_pack_start (GTK_BOX (WIG ("timeDateBox")), polkit_button, FALSE, TRUE, 0); + /* Set up settings bindings */ g_settings_bind (conf, SETTINGS_SHOW_CLOCK_S, WIG ("showClockCheck"), @@ -150,12 +315,18 @@ create_dialog (void) add_widget_dependency (WIG ("showClockCheck"), WIG ("clockOptions")); add_widget_dependency (WIG ("showLocationsCheck"), WIG ("locationsButton")); add_widget_dependency (WIG ("manualTimeRadio"), WIG ("manualOptions")); + add_polkit_dependency (polkit_button, WIG ("timeDateOptions")); /* Hacky proxy test for whether evolution-data-server is installed */ gchar * evo_path = g_find_program_in_path ("evolution"); gtk_widget_set_sensitive (WIG ("showEventsCheck"), (evo_path != NULL)); g_free (evo_path); + /* Check if ntp is usable and enabled */ + setup_ntp (WIG ("automaticTimeRadio")); + + setup_time_spinner (WIG ("timeSpinner")); + GtkWidget * dlg = WIG ("timeDateDialog"); #undef WIG @@ -180,17 +351,17 @@ message_received (UniqueApp * app, gint command, UniqueMessageData *message_data int main (int argc, char ** argv) { - g_type_init (); + g_type_init (); - /* Setting up i18n and gettext. Apparently, we need - all of these. */ - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain (GETTEXT_PACKAGE); + /* Setting up i18n and gettext. Apparently, we need + all of these. */ + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + textdomain (GETTEXT_PACKAGE); - gtk_init (&argc, &argv); + gtk_init (&argc, &argv); - UniqueApp * app = unique_app_new ("com.canonical.indicator.datetime.preferences", NULL); + UniqueApp * app = unique_app_new ("com.canonical.indicator.datetime.preferences", NULL); if (unique_app_is_running (app)) { unique_app_send_message (app, UNIQUE_ACTIVATE, NULL); -- cgit v1.2.3 From da3962a55e4e7fab374d1cbbd2401000ed67fe07 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Fri, 18 Feb 2011 01:51:56 -0500 Subject: make manual date/time fields work --- data/datetime-dialog.ui | 546 ++++++++++++++++++++++++------------------------ src/datetime-prefs.c | 158 ++++++++++---- 2 files changed, 394 insertions(+), 310 deletions(-) diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui index f2a5938..1e0f726 100644 --- a/data/datetime-dialog.ui +++ b/data/datetime-dialog.ui @@ -88,6 +88,7 @@ False 5 Time & Date + False time-admin dialog @@ -264,6 +265,7 @@ _Automatically from the Internet True + False True False False @@ -429,139 +431,27 @@ - + True False - 12 - 12 - - - _Show a clock in the panel - True - True - False - False - True - 0 - True - - - True - True - 0 - - + 0 + 0 - + True False - True + 12 + 12 - + + _Show a clock in the panel True - False - 6 - - - True - False - 0 - In the clock, show: - - - False - True - 0 - - - - - _Weekday - True - True - False - False - True - 0 - True - - - False - True - 1 - - - - - _Date and time - True - True - False - False - True - 0 - True - - - False - True - 2 - - - - - _12-hour time - True - True - False - False - True - 0 - True - True - - - False - True - 3 - - - - - _24-hour time - True - True - False - False - True - 0 - True - True - show12HourRadio - - - False - True - 4 - - - - - Seco_nds - True - True - False - False - True - 0 - True - - - False - True - 5 - - + True + False + False + True + 0 + True True @@ -570,16 +460,115 @@ - + True False - 6 + True - + True False - 0 - In the clock’s menu, show: + 6 + + + True + False + 0 + In the clock, show: + + + False + True + 0 + + + + + _Weekday + True + True + False + False + True + 0 + True + + + False + True + 1 + + + + + _Date and time + True + True + False + False + True + 0 + True + + + False + True + 2 + + + + + _12-hour time + True + True + False + False + True + 0 + True + True + + + False + True + 3 + + + + + _24-hour time + True + True + False + False + True + 0 + True + show12HourRadio + + + False + True + 4 + + + + + Seco_nds + True + True + False + False + True + 0 + True + + + False + True + 5 + + True @@ -588,80 +577,62 @@ - - _Monthly calendar - True - True - False - False - True - 0 - True - - - False - True - 1 - - - - + True False - 0 - 0 - 0 - 0 - 12 + 6 - + True False + 0 + In the clock’s menu, show: + + + True + True + 0 + + + + + _Monthly calendar + True + True + False + False + True + 0 + True + + + False + True + 1 + + + + + True + False + 0 + 0 + 0 + 0 + 12 - - Include week num_bers + True - True - False - False - True - 0 - True - - - True - True - 0 - - - - - False - True - 0 - Week begins on: - - - True - True - 1 - - - - False - True - True - - S_unday + + Include week num_bers True True False False True 0 - True True @@ -671,17 +642,11 @@ - - Monda_y - True - True - False - False - True + + False + True 0 - True - True - startOnSundayRadio + Week begins on: True @@ -689,91 +654,139 @@ 1 + + + False + True + True + + + S_unday + True + True + False + False + True + 0 + True + True + + + True + True + 0 + + + + + Monda_y + True + True + False + False + True + 0 + True + startOnSundayRadio + + + True + True + 1 + + + + + True + True + 2 + + - - True - True - 2 - + + False + True + 2 + - - - False - True - 2 - - - - - True - True - False - False - True - 0 - True - + True - False - 0 - Coming _events from Evolution Calendar + True + False + False True - True - showEventsCheck + 0 + True + + + True + False + 0 + Coming _events from Evolution Calendar + True + True + showEventsCheck + + + + False + True + 3 + - - - False - True - 3 - - - - - Time in _other locations - True - True - False - False - True - 0 - True - - - False - True - 4 - - - - - True - False - 0 - 0 - 0 - 0 - 12 - - Choose _Locations… + + Time in _other locations True True - True + False False True 0 + True + + + False + True + 4 + + + + + True + False + 0 + 0 + 0 + 0 + 12 + + + Choose _Locations… + True + True + True + False + True + 0 + + + + True + True + 5 + True True - 5 + 1 @@ -784,11 +797,6 @@ - - True - True - 1 - diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index 87eec94..a42c46b 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -27,6 +27,7 @@ with this program. If not, see . #include #include +#include #include #include #include @@ -37,6 +38,8 @@ with this program. If not, see . #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui" +GDBusProxy * proxy = NULL; + /* Turns the boolean property into a string gsettings */ static GVariant * bind_hours_set (const GValue * value, const GVariantType * type, gpointer user_data) @@ -116,14 +119,13 @@ add_polkit_dependency (GtkWidget * parent, GtkWidget * dependent) polkit_dependency_cb (parent, NULL, dependent); } -void ntp_set_answered (GObject *object, GAsyncResult *res, gpointer autoRadio) +void dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command) { GError * error = NULL; - GDBusProxy * proxy = G_DBUS_PROXY (object); GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error); if (error != NULL) { - g_warning("Could not set 'using_ntp' for SettingsDaemon: %s", error->message); + g_warning("Could not set '%s' for SettingsDaemon: %s", (gchar *)command, error->message); g_error_free(error); return; } @@ -135,16 +137,14 @@ static void toggle_ntp (GtkWidget * autoRadio, GParamSpec * pspec, gpointer user_data) { gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (autoRadio)); - GDBusProxy * proxy = G_DBUS_PROXY (g_object_get_data (G_OBJECT (autoRadio), "proxy")); g_dbus_proxy_call (proxy, "SetUsingNtp", g_variant_new ("(b)", active), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, ntp_set_answered, autoRadio); + G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "using_ntp"); } void ntp_query_answered (GObject *object, GAsyncResult *res, gpointer autoRadio) { GError * error = NULL; - GDBusProxy * proxy = G_DBUS_PROXY (object); GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error); if (error != NULL) { @@ -164,10 +164,11 @@ void ntp_query_answered (GObject *object, GAsyncResult *res, gpointer autoRadio) g_variant_unref (answers); } -void ntp_proxy_ready (GObject *object, GAsyncResult *res, gpointer autoRadio) +void proxy_ready (GObject *object, GAsyncResult *res, gpointer autoRadio) { GError * error = NULL; - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (error != NULL) { g_critical("Could not grab DBus proxy for SettingsDaemon: %s", error->message); @@ -175,48 +176,117 @@ void ntp_proxy_ready (GObject *object, GAsyncResult *res, gpointer autoRadio) return; } - /* Now attach proxy to button so we can use it later */ - g_object_set_data_full (G_OBJECT (autoRadio), "proxy", proxy, g_object_unref); - - /* And finally ask it what is up */ + /* And now, do initial proxy configuration */ g_dbus_proxy_call (proxy, "GetUsingNtp", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, ntp_query_answered, autoRadio); } -static void -setup_ntp (GtkWidget * autoRadio) +static int +input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) { - /* Do some quick checks to see if ntp is running or installed */ + gboolean is_time = (gboolean)GPOINTER_TO_INT (g_object_get_data (G_OBJECT (spinner), "is-time")); + const gchar * text = gtk_entry_get_text (GTK_ENTRY (spinner)); + + GDateTime * now = g_date_time_new_now_local (); + gint year, month, day, hour, minute, second; + year = g_date_time_get_year (now); + month = g_date_time_get_month (now); + day = g_date_time_get_day_of_month (now); + hour = g_date_time_get_hour (now); + minute = g_date_time_get_minute (now); + second = g_date_time_get_second (now); + g_date_time_unref (now); + + /* Parse this string as if it were in the output format */ + gint scanned = 0; + gboolean passed = TRUE, skip = FALSE; + if (is_time) { + gint hour_in, minute_in, second_in; + + if (is_locale_12h ()) { // TODO: make this look-at/watch gsettings? + char ampm[51]; + + scanned = sscanf (text, "%u:%u:%u %50s", &hour_in, &minute_in, &second_in, ampm); + passed = (scanned == 4); + + if (passed) { + const char *pm_str = nl_langinfo (PM_STR); + if (g_ascii_strcasecmp (pm_str, ampm) == 0) { + hour_in += 12; + } + } + } else { + scanned = sscanf (text, "%u:%u:%u", &hour_in, &minute_in, &second_in); + passed = (scanned == 3); + } + + if (passed && (hour_in > 23 || minute_in > 59 || second_in > 59)) { + passed = FALSE; + } + if (passed && hour == hour_in && minute == minute_in && second == second_in) { + skip = TRUE; // no change + } else { + hour = hour_in; + minute = minute_in; + second = second_in; + } + } + else { + gint year_in, month_in, day_in; + + scanned = sscanf (text, "%u-%u-%u", &year_in, &month_in, &day_in); + + if (scanned != 3 || year_in < 1 || year_in > 9999 || + month_in < 1 || month_in > 12 || day_in < 1 || day_in > 31) { + passed = FALSE; + } + if (passed && year == year_in && month == month_in && day == day_in) { + skip = TRUE; // no change + } else { + year = year_in; + month = month_in; + day = day_in; + } + } - /* Start with assumption ntp is unusable until we prove otherwise */ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (autoRadio), FALSE); - gtk_widget_set_sensitive (autoRadio, FALSE); + if (!passed) { + g_warning ("Could not understand %s", text); + return TRUE; + } - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, - "org.gnome.SettingsDaemon.DateTimeMechanism", - "/", - "org.gnome.SettingsDaemon.DateTimeMechanism", - NULL, ntp_proxy_ready, autoRadio); -} + if (skip) { + return TRUE; + } -/*static int -input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) -{ - //const gchar * text = gtk_entry_get_text (GTK_ENTRY (spinner)); + GDateTime * datetime = g_date_time_new_local (year, month, day, hour, minute, second); + + g_dbus_proxy_call (proxy, "SetTime", g_variant_new ("(x)", g_date_time_to_unix (datetime)), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "time"); return TRUE; -}*/ +} static gboolean format_time_text (GtkWidget * spinner, gpointer user_data) { + if (gtk_widget_has_focus (spinner)) { + /* Don't do anything if we have focus, user is likely editing us */ + return TRUE; + } + GDateTime * datetime = (GDateTime *)g_object_get_data (G_OBJECT (spinner), "datetime"); + gboolean is_time = (gboolean)GPOINTER_TO_INT (g_object_get_data (G_OBJECT (spinner), "is-time")); const gchar * format; - if (is_locale_12h ()) { - format = "%I:%M:%S %p"; - } else { - format = "%H:%M:%S"; + if (is_time) { + if (is_locale_12h ()) { // TODO: make this look-at/watch gsettings? + format = "%I:%M:%S %p"; + } else { + format = "%H:%M:%S"; + } + } + else { + format = "%Y-%m-%d"; } gchar * formatted = g_date_time_format (datetime, format); @@ -239,16 +309,17 @@ update_spinner (GtkWidget * spinner) } static void -setup_time_spinner (GtkWidget * spinner) +setup_time_spinner (GtkWidget * spinner, GtkWidget * other, gboolean is_time) { /* Set up spinner to have reasonable behavior */ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), FALSE); - //g_signal_connect (spinner, "input", G_CALLBACK (input_time_text), NULL); - g_signal_connect (spinner, "output", G_CALLBACK (format_time_text), NULL); + g_signal_connect (spinner, "input", G_CALLBACK (input_time_text), other); + g_signal_connect (spinner, "output", G_CALLBACK (format_time_text), other); + g_object_set_data (G_OBJECT (spinner), "is-time", GINT_TO_POINTER (is_time)); /* 2 seconds is what the indicator itself uses */ guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_spinner, spinner); - g_signal_connect_swapped (spinner, "destroy", G_CALLBACK (g_source_remove), GINT_TO_POINTER(time_id)); + g_signal_connect_swapped (spinner, "destroy", G_CALLBACK (g_source_remove), GINT_TO_POINTER (time_id)); update_spinner (spinner); } @@ -322,13 +393,18 @@ create_dialog (void) gtk_widget_set_sensitive (WIG ("showEventsCheck"), (evo_path != NULL)); g_free (evo_path); - /* Check if ntp is usable and enabled */ - setup_ntp (WIG ("automaticTimeRadio")); - - setup_time_spinner (WIG ("timeSpinner")); + setup_time_spinner (WIG ("timeSpinner"), WIG ("dateSpinner"), TRUE); + setup_time_spinner (WIG ("dateSpinner"), WIG ("timeSpinner"), FALSE); GtkWidget * dlg = WIG ("timeDateDialog"); + /* Grab proxy for settings daemon */ + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, + "org.gnome.SettingsDaemon.DateTimeMechanism", + "/", + "org.gnome.SettingsDaemon.DateTimeMechanism", + NULL, proxy_ready, WIG ("automaticTimeRadio")); + #undef WIG g_object_unref (conf); -- cgit v1.2.3 From 6dda4370c9cc94bb25c1cd388adce14f1c0e9f19 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Fri, 18 Feb 2011 14:47:14 -0500 Subject: mark prefs dialog as translatable --- po/POTFILES.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 41324a7..2eb7ec1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,2 +1,4 @@ src/indicator-datetime.c src/datetime-service.c +src/datetime-prefs.c +[type: gettext/glade]data/datetime-dialog.ui -- cgit v1.2.3 From 1e274bb18d9936c39d4c22e00ec895dc79178390 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Fri, 18 Feb 2011 16:31:17 -0500 Subject: start of locations dialog --- data/datetime-dialog.ui | 22 +++++-- po/POTFILES.in | 1 + src/Makefile.am | 2 + src/datetime-prefs-locations.c | 137 +++++++++++++++++++++++++++++++++++++++++ src/datetime-prefs-locations.h | 34 ++++++++++ src/datetime-prefs.c | 11 +++- 6 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 src/datetime-prefs-locations.c create mode 100644 src/datetime-prefs-locations.h diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui index 1e0f726..a849107 100644 --- a/data/datetime-dialog.ui +++ b/data/datetime-dialog.ui @@ -5,16 +5,28 @@ False Locations + True + True time-admin True False - + True True - locationsStore + automatic + automatic + + + True + True + locationsStore + True + 0 + + True @@ -27,10 +39,11 @@ True False - + True True True + Add a Location… False @@ -47,10 +60,11 @@ - + True True True + Remove This Location False diff --git a/po/POTFILES.in b/po/POTFILES.in index 2eb7ec1..0fa22d4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,5 @@ src/indicator-datetime.c src/datetime-service.c src/datetime-prefs.c +src/datetime-prefs-locations.c [type: gettext/glade]data/datetime-dialog.ui diff --git a/src/Makefile.am b/src/Makefile.am index 150c87d..94d179d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,8 @@ libdatetime_la_LDFLAGS = \ indicator_datetime_preferences_SOURCES =\ datetime-prefs.c \ + datetime-prefs-locations.c \ + datetime-prefs-locations.h \ utils.c \ utils.h \ settings-shared.h diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c new file mode 100644 index 0000000..24efd04 --- /dev/null +++ b/src/datetime-prefs-locations.c @@ -0,0 +1,137 @@ +/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*- + +A dialog for setting time and date preferences. + +Copyright 2011 Canonical Ltd. + +Authors: + Michael Terry + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "datetime-prefs-locations.h" +#include "settings-shared.h" + +#define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui" + +static void +handle_add (GtkWidget * button, gpointer user_data) +{ +} + +static void +handle_remove (GtkWidget * button, gpointer user_data) +{ +} + +static void +fill_from_settings (GObject * store, GSettings * conf) +{ + gchar ** locations = g_settings_get_strv (conf, SETTINGS_LOCATIONS_S); + + gtk_list_store_clear (GTK_LIST_STORE (store)); + + gchar ** striter; + GtkTreeIter iter; + for (striter = locations; *striter; ++striter) { + gtk_list_store_append (GTK_LIST_STORE (store), &iter); + gtk_list_store_set (GTK_LIST_STORE (store), &iter, 0, *striter, -1); + } + + g_strfreev (locations); +} + +static void +save_to_settings (GtkWidget * dlg, GObject * store) +{ + GVariantBuilder builder; + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) { + do { + GValue value = {0}; + gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 0, &value); + g_variant_builder_add (&builder, "s", g_value_get_string (&value)); + g_value_unset (&value); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); + } + + GVariant * locations = g_variant_builder_end (&builder); + + GSettings * conf = G_SETTINGS (g_object_get_data (G_OBJECT (dlg), "conf")); + g_settings_set_strv (conf, SETTINGS_LOCATIONS_S, g_variant_get_strv (locations, NULL)); + + g_variant_unref (locations); +} + +GtkWidget * +datetime_setup_locations_dialog (GtkWindow * parent) +{ + GError * error = NULL; + GtkBuilder * builder = gtk_builder_new (); + gtk_builder_add_from_file (builder, DATETIME_DIALOG_UI_FILE, &error); + if (error != NULL) { + /* We have to abort, we can't continue without the ui file */ + g_error ("Could not load ui file %s: %s", DATETIME_DIALOG_UI_FILE, error->message); + g_error_free (error); + return NULL; + } + + gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); + + GSettings * conf = g_settings_new (SETTINGS_INTERFACE); + +#define WIG(name) GTK_WIDGET (gtk_builder_get_object (builder, name)) + + GtkWidget * dlg = WIG ("locationsDialog"); + GtkWidget * tree = WIG ("locationsView"); + GObject * store = gtk_builder_get_object (builder, "locationsStore"); + + /* Configure tree */ + GtkCellRenderer * cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", TRUE, NULL); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1, + _("Location"), cell, + "text", 0, NULL); + cell = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1, + _("Time"), cell, + "text", 1, NULL); + gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)), GTK_SELECTION_MULTIPLE); + + g_signal_connect (WIG ("addButton"), "clicked", G_CALLBACK (handle_add), NULL); + g_signal_connect (WIG ("removeButton"), "clicked", G_CALLBACK (handle_remove), NULL); + + fill_from_settings (store, conf); + g_object_set_data_full (G_OBJECT (dlg), "conf", g_object_ref (conf), g_object_unref); + g_signal_connect (dlg, "destroy", G_CALLBACK (save_to_settings), store); + + gtk_window_set_transient_for (GTK_WINDOW (dlg), parent); + +#undef WIG + + g_object_unref (conf); + g_object_unref (builder); + + return dlg; +} + diff --git a/src/datetime-prefs-locations.h b/src/datetime-prefs-locations.h new file mode 100644 index 0000000..d5dd534 --- /dev/null +++ b/src/datetime-prefs-locations.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*- + +A dialog for setting time and date preferences. + +Copyright 2011 Canonical Ltd. + +Authors: + Michael Terry + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . +*/ + +#ifndef __DATETIME_PREFS_LOCATIONS_H__ +#define __DATETIME_PREFS_LOCATIONS_H__ + +#include + +G_BEGIN_DECLS + +GtkWidget * datetime_setup_locations_dialog (GtkWindow * parent); + +G_END_DECLS + +#endif diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index a42c46b..97b106d 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -35,6 +35,7 @@ with this program. If not, see . #include "settings-shared.h" #include "utils.h" +#include "datetime-prefs-locations.h" #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui" @@ -324,6 +325,13 @@ setup_time_spinner (GtkWidget * spinner, GtkWidget * other, gboolean is_time) update_spinner (spinner); } +static void +show_locations (GtkWidget * button, GtkWidget * dlg) +{ + GtkWidget * locationsDlg = datetime_setup_locations_dialog (GTK_WINDOW (dlg)); + gtk_widget_show_all (locationsDlg); +} + static GtkWidget * create_dialog (void) { @@ -351,7 +359,6 @@ create_dialog (void) gtk_box_pack_start (GTK_BOX (WIG ("timeDateBox")), polkit_button, FALSE, TRUE, 0); /* Set up settings bindings */ - g_settings_bind (conf, SETTINGS_SHOW_CLOCK_S, WIG ("showClockCheck"), "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind (conf, SETTINGS_SHOW_DAY_S, WIG ("showWeekdayCheck"), @@ -398,6 +405,8 @@ create_dialog (void) GtkWidget * dlg = WIG ("timeDateDialog"); + g_signal_connect (WIG ("locationsButton"), "clicked", G_CALLBACK (show_locations), dlg); + /* Grab proxy for settings daemon */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.gnome.SettingsDaemon.DateTimeMechanism", -- cgit v1.2.3 From 45b1165f77cab0ac8dc40ce7d605e32c697fb22d Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 22 Feb 2011 11:20:34 -0500 Subject: add initial timezone map implementation, borrowed from gnome-control-center --- Makefile.am | 1 + configure.ac | 16 + data/datetime-dialog.ui | 15 +- libmap/Makefile.am | 76 +++++ libmap/Makefile.in | 732 +++++++++++++++++++++++++++++++++++++++++ libmap/README | 5 + libmap/backward | 118 +++++++ libmap/cc-timezone-map.c | 711 +++++++++++++++++++++++++++++++++++++++ libmap/cc-timezone-map.h | 79 +++++ libmap/data/bg.png | Bin 0 -> 213448 bytes libmap/data/cc.png | Bin 0 -> 53948 bytes libmap/data/pin.png | Bin 0 -> 561 bytes libmap/data/timezone_-1.png | Bin 0 -> 8012 bytes libmap/data/timezone_-10.png | Bin 0 -> 7783 bytes libmap/data/timezone_-11.png | Bin 0 -> 7406 bytes libmap/data/timezone_-2.png | Bin 0 -> 4333 bytes libmap/data/timezone_-3.5.png | Bin 0 -> 740 bytes libmap/data/timezone_-3.png | Bin 0 -> 13615 bytes libmap/data/timezone_-4.5.png | Bin 0 -> 1900 bytes libmap/data/timezone_-4.png | Bin 0 -> 15084 bytes libmap/data/timezone_-5.5.png | Bin 0 -> 437 bytes libmap/data/timezone_-5.png | Bin 0 -> 19166 bytes libmap/data/timezone_-6.png | Bin 0 -> 13764 bytes libmap/data/timezone_-7.png | Bin 0 -> 11977 bytes libmap/data/timezone_-8.png | Bin 0 -> 6801 bytes libmap/data/timezone_-9.5.png | Bin 0 -> 437 bytes libmap/data/timezone_-9.png | Bin 0 -> 7908 bytes libmap/data/timezone_0.png | Bin 0 -> 11074 bytes libmap/data/timezone_1.png | Bin 0 -> 15458 bytes libmap/data/timezone_10.5.png | Bin 0 -> 421 bytes libmap/data/timezone_10.png | Bin 0 -> 12829 bytes libmap/data/timezone_11.5.png | Bin 0 -> 446 bytes libmap/data/timezone_11.png | Bin 0 -> 12113 bytes libmap/data/timezone_12.75.png | Bin 0 -> 409 bytes libmap/data/timezone_12.png | Bin 0 -> 7130 bytes libmap/data/timezone_13.png | Bin 0 -> 621 bytes libmap/data/timezone_2.png | Bin 0 -> 12854 bytes libmap/data/timezone_3.5.png | Bin 0 -> 2142 bytes libmap/data/timezone_3.png | Bin 0 -> 17475 bytes libmap/data/timezone_4.5.png | Bin 0 -> 1773 bytes libmap/data/timezone_4.png | Bin 0 -> 4954 bytes libmap/data/timezone_5.5.png | Bin 0 -> 6099 bytes libmap/data/timezone_5.75.png | Bin 0 -> 2885 bytes libmap/data/timezone_5.png | Bin 0 -> 14539 bytes libmap/data/timezone_6.5.png | Bin 0 -> 1609 bytes libmap/data/timezone_6.png | Bin 0 -> 8441 bytes libmap/data/timezone_7.png | Bin 0 -> 14412 bytes libmap/data/timezone_8.png | Bin 0 -> 16725 bytes libmap/data/timezone_9.5.png | Bin 0 -> 1959 bytes libmap/data/timezone_9.png | Bin 0 -> 12608 bytes libmap/datetime-module.c | 46 +++ libmap/dt-lockbutton.c | 627 +++++++++++++++++++++++++++++++++++ libmap/dt-lockbutton.h | 68 ++++ libmap/set-timezone.c | 481 +++++++++++++++++++++++++++ libmap/set-timezone.h | 57 ++++ libmap/test-timezone.c | 55 ++++ libmap/tz.c | 350 ++++++++++++++++++++ libmap/tz.h | 86 +++++ src/Makefile.am | 2 + src/datetime-prefs.c | 58 +++- 60 files changed, 3575 insertions(+), 8 deletions(-) create mode 100644 libmap/Makefile.am create mode 100644 libmap/Makefile.in create mode 100644 libmap/README create mode 100644 libmap/backward create mode 100644 libmap/cc-timezone-map.c create mode 100644 libmap/cc-timezone-map.h create mode 100644 libmap/data/bg.png create mode 100644 libmap/data/cc.png create mode 100644 libmap/data/pin.png create mode 100644 libmap/data/timezone_-1.png create mode 100644 libmap/data/timezone_-10.png create mode 100644 libmap/data/timezone_-11.png create mode 100644 libmap/data/timezone_-2.png create mode 100644 libmap/data/timezone_-3.5.png create mode 100644 libmap/data/timezone_-3.png create mode 100644 libmap/data/timezone_-4.5.png create mode 100644 libmap/data/timezone_-4.png create mode 100644 libmap/data/timezone_-5.5.png create mode 100644 libmap/data/timezone_-5.png create mode 100644 libmap/data/timezone_-6.png create mode 100644 libmap/data/timezone_-7.png create mode 100644 libmap/data/timezone_-8.png create mode 100644 libmap/data/timezone_-9.5.png create mode 100644 libmap/data/timezone_-9.png create mode 100644 libmap/data/timezone_0.png create mode 100644 libmap/data/timezone_1.png create mode 100644 libmap/data/timezone_10.5.png create mode 100644 libmap/data/timezone_10.png create mode 100644 libmap/data/timezone_11.5.png create mode 100644 libmap/data/timezone_11.png create mode 100644 libmap/data/timezone_12.75.png create mode 100644 libmap/data/timezone_12.png create mode 100644 libmap/data/timezone_13.png create mode 100644 libmap/data/timezone_2.png create mode 100644 libmap/data/timezone_3.5.png create mode 100644 libmap/data/timezone_3.png create mode 100644 libmap/data/timezone_4.5.png create mode 100644 libmap/data/timezone_4.png create mode 100644 libmap/data/timezone_5.5.png create mode 100644 libmap/data/timezone_5.75.png create mode 100644 libmap/data/timezone_5.png create mode 100644 libmap/data/timezone_6.5.png create mode 100644 libmap/data/timezone_6.png create mode 100644 libmap/data/timezone_7.png create mode 100644 libmap/data/timezone_8.png create mode 100644 libmap/data/timezone_9.5.png create mode 100644 libmap/data/timezone_9.png create mode 100644 libmap/datetime-module.c create mode 100644 libmap/dt-lockbutton.c create mode 100644 libmap/dt-lockbutton.h create mode 100644 libmap/set-timezone.c create mode 100644 libmap/set-timezone.h create mode 100644 libmap/test-timezone.c create mode 100644 libmap/tz.c create mode 100644 libmap/tz.h diff --git a/Makefile.am b/Makefile.am index a692889..4de650a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,6 @@ SUBDIRS = \ + libmap \ src \ data \ tests \ diff --git a/configure.ac b/configure.ac index 242033e..bcedddc 100644 --- a/configure.ac +++ b/configure.ac @@ -135,6 +135,17 @@ AS_IF([test "x$with_gtk" = x3], ], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) + +AS_IF([test "x$with_gtk" = x3], + [PKG_CHECK_MODULES(LIBMAP, gio-2.0 >= $GIO_REQUIRED_VERSION + gtk+-3.0 >= $GTK3_REQUIRED_VERSION) + ], + [test "x$with_gtk" = x2], + [PKG_CHECK_MODULES(LIBMAP, gio-2.0 >= $GIO_REQUIRED_VERSION + gtk+-2.0 >= $GTK_REQUIRED_VERSION) + ], + [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] +) AC_SUBST(INDICATOR_CFLAGS) AC_SUBST(INDICATOR_LIBS) @@ -144,6 +155,10 @@ AC_SUBST(SERVICE_LIBS) AC_SUBST(PREF_CFLAGS) AC_SUBST(PREF_LIBS) +AC_SUBST(LIBMAP_CFLAGS) +AC_SUBST(LIBMAP_LIBS) +AC_SUBST(LIBMAP_LDFLAGS) + ########################### # Grab the GSettings Macros ########################### @@ -223,6 +238,7 @@ AM_GLIB_GNU_GETTEXT AC_OUTPUT([ Makefile +libmap/Makefile src/Makefile data/Makefile tests/Makefile diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui index a849107..b5eba54 100644 --- a/data/datetime-dialog.ui +++ b/data/datetime-dialog.ui @@ -153,7 +153,20 @@ False 6 - + + True + False + 0 + none + + + + + + True + True + 0 + diff --git a/libmap/Makefile.am b/libmap/Makefile.am new file mode 100644 index 0000000..0cdeb34 --- /dev/null +++ b/libmap/Makefile.am @@ -0,0 +1,76 @@ +uidir = $(pkgdatadir)/libmap/ui +dist_ui_DATA = \ + data/bg.png \ + data/cc.png \ + data/pin.png \ + data/timezone_0.png \ + data/timezone_-10.png \ + data/timezone_10.png \ + data/timezone_10.5.png \ + data/timezone_-1.png \ + data/timezone_1.png \ + data/timezone_-11.png \ + data/timezone_11.png \ + data/timezone_11.5.png \ + data/timezone_12.png \ + data/timezone_12.75.png \ + data/timezone_13.png \ + data/timezone_-2.png \ + data/timezone_2.png \ + data/timezone_-3.png \ + data/timezone_3.png \ + data/timezone_-3.5.png \ + data/timezone_3.5.png \ + data/timezone_-4.png \ + data/timezone_4.png \ + data/timezone_-4.5.png \ + data/timezone_4.5.png \ + data/timezone_-5.png \ + data/timezone_5.png \ + data/timezone_-5.5.png \ + data/timezone_5.5.png \ + data/timezone_5.75.png \ + data/timezone_-6.png \ + data/timezone_6.png \ + data/timezone_6.5.png \ + data/timezone_-7.png \ + data/timezone_7.png \ + data/timezone_-8.png \ + data/timezone_8.png \ + data/timezone_-9.png \ + data/timezone_9.png \ + data/timezone_-9.5.png \ + data/timezone_9.5.png + +tzdatadir = $(pkgdatadir)/libmap/datetime +dist_tzdata_DATA = backward + +AM_CPPFLAGS = \ + $(LIBMAP_CFLAGS) \ + -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ + -DGNOMECC_DATA_DIR="\"$(pkgdatadir)/libmap\"" \ + -DDATADIR="\"$(uidir)\"" \ + $(NULL) + +noinst_PROGRAMS = test-timezone + +test_timezone_SOURCES = test-timezone.c tz.c tz.h +test_timezone_LDADD = $(LIBMAP_LIBS) +test_timezone_CFLAGS = $(LIBMAP_CFLAGS) + +all-local: check-local + +# FIXME remove "|| :" when we have all the necessary pixmaps +check-local: test-timezone + $(builddir)/test-timezone $(srcdir)/data || : + +noinst_LTLIBRARIES = libmap.la + +libmap_la_SOURCES = \ + cc-timezone-map.c \ + cc-timezone-map.h \ + tz.c tz.h + +libmap_la_LIBADD = $(LIBMAP_LIBS) +libmap_la_LDFLAGS = $(LIBMAP_LDFLAGS) + diff --git a/libmap/Makefile.in b/libmap/Makefile.in new file mode 100644 index 0000000..b4ae6df --- /dev/null +++ b/libmap/Makefile.in @@ -0,0 +1,732 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-timezone$(EXEEXT) +subdir = libmap +DIST_COMMON = README $(dist_tzdata_DATA) $(dist_ui_DATA) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libmap_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libmap_la_OBJECTS = cc-timezone-map.lo tz.lo +libmap_la_OBJECTS = $(am_libmap_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +libmap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libmap_la_LDFLAGS) $(LDFLAGS) -o $@ +PROGRAMS = $(noinst_PROGRAMS) +am_test_timezone_OBJECTS = test_timezone-test-timezone.$(OBJEXT) \ + test_timezone-tz.$(OBJEXT) +test_timezone_OBJECTS = $(am_test_timezone_OBJECTS) +test_timezone_DEPENDENCIES = $(am__DEPENDENCIES_1) +test_timezone_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_timezone_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libmap_la_SOURCES) $(test_timezone_SOURCES) +DIST_SOURCES = $(libmap_la_SOURCES) $(test_timezone_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(tzdatadir)" "$(DESTDIR)$(uidir)" +DATA = $(dist_tzdata_DATA) $(dist_ui_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUSSERVICEDIR = @DBUSSERVICEDIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GNOMELOCALEDIR = @GNOMELOCALEDIR@ +GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ +INDICATORDIR = @INDICATORDIR@ +INDICATORICONSDIR = @INDICATORICONSDIR@ +INDICATOR_CFLAGS = @INDICATOR_CFLAGS@ +INDICATOR_LIBS = @INDICATOR_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBMAP_CFLAGS = @LIBMAP_CFLAGS@ +LIBMAP_LDFLAGS = @LIBMAP_LDFLAGS@ +LIBMAP_LIBS = @LIBMAP_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PREF_CFLAGS = @PREF_CFLAGS@ +PREF_LIBS = @PREF_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVICE_CFLAGS = @SERVICE_CFLAGS@ +SERVICE_LIBS = @SERVICE_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +uidir = $(pkgdatadir)/libmap/ui +dist_ui_DATA = \ + data/bg.png \ + data/cc.png \ + data/pin.png \ + data/timezone_0.png \ + data/timezone_-10.png \ + data/timezone_10.png \ + data/timezone_10.5.png \ + data/timezone_-1.png \ + data/timezone_1.png \ + data/timezone_-11.png \ + data/timezone_11.png \ + data/timezone_11.5.png \ + data/timezone_12.png \ + data/timezone_12.75.png \ + data/timezone_13.png \ + data/timezone_-2.png \ + data/timezone_2.png \ + data/timezone_-3.png \ + data/timezone_3.png \ + data/timezone_-3.5.png \ + data/timezone_3.5.png \ + data/timezone_-4.png \ + data/timezone_4.png \ + data/timezone_-4.5.png \ + data/timezone_4.5.png \ + data/timezone_-5.png \ + data/timezone_5.png \ + data/timezone_-5.5.png \ + data/timezone_5.5.png \ + data/timezone_5.75.png \ + data/timezone_-6.png \ + data/timezone_6.png \ + data/timezone_6.5.png \ + data/timezone_-7.png \ + data/timezone_7.png \ + data/timezone_-8.png \ + data/timezone_8.png \ + data/timezone_-9.png \ + data/timezone_9.png \ + data/timezone_-9.5.png \ + data/timezone_9.5.png + +tzdatadir = $(pkgdatadir)/libmap/datetime +dist_tzdata_DATA = backward +AM_CPPFLAGS = \ + $(LIBMAP_CFLAGS) \ + -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ + -DGNOMECC_DATA_DIR="\"$(pkgdatadir)/libmap\"" \ + -DDATADIR="\"$(uidir)\"" \ + $(NULL) + +test_timezone_SOURCES = test-timezone.c tz.c tz.h +test_timezone_LDADD = $(LIBMAP_LIBS) +test_timezone_CFLAGS = $(LIBMAP_CFLAGS) +noinst_LTLIBRARIES = libmap.la +libmap_la_SOURCES = \ + cc-timezone-map.c \ + cc-timezone-map.h \ + tz.c tz.h + +libmap_la_LIBADD = $(LIBMAP_LIBS) +libmap_la_LDFLAGS = $(LIBMAP_LDFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libmap/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libmap/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libmap.la: $(libmap_la_OBJECTS) $(libmap_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmap_la_LINK) $(libmap_la_OBJECTS) $(libmap_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +test-timezone$(EXEEXT): $(test_timezone_OBJECTS) $(test_timezone_DEPENDENCIES) + @rm -f test-timezone$(EXEEXT) + $(AM_V_CCLD)$(test_timezone_LINK) $(test_timezone_OBJECTS) $(test_timezone_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cc-timezone-map.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_timezone-test-timezone.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_timezone-tz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tz.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +test_timezone-test-timezone.o: test-timezone.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -MT test_timezone-test-timezone.o -MD -MP -MF $(DEPDIR)/test_timezone-test-timezone.Tpo -c -o test_timezone-test-timezone.o `test -f 'test-timezone.c' || echo '$(srcdir)/'`test-timezone.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_timezone-test-timezone.Tpo $(DEPDIR)/test_timezone-test-timezone.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-timezone.c' object='test_timezone-test-timezone.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -c -o test_timezone-test-timezone.o `test -f 'test-timezone.c' || echo '$(srcdir)/'`test-timezone.c + +test_timezone-test-timezone.obj: test-timezone.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -MT test_timezone-test-timezone.obj -MD -MP -MF $(DEPDIR)/test_timezone-test-timezone.Tpo -c -o test_timezone-test-timezone.obj `if test -f 'test-timezone.c'; then $(CYGPATH_W) 'test-timezone.c'; else $(CYGPATH_W) '$(srcdir)/test-timezone.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_timezone-test-timezone.Tpo $(DEPDIR)/test_timezone-test-timezone.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-timezone.c' object='test_timezone-test-timezone.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -c -o test_timezone-test-timezone.obj `if test -f 'test-timezone.c'; then $(CYGPATH_W) 'test-timezone.c'; else $(CYGPATH_W) '$(srcdir)/test-timezone.c'; fi` + +test_timezone-tz.o: tz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -MT test_timezone-tz.o -MD -MP -MF $(DEPDIR)/test_timezone-tz.Tpo -c -o test_timezone-tz.o `test -f 'tz.c' || echo '$(srcdir)/'`tz.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_timezone-tz.Tpo $(DEPDIR)/test_timezone-tz.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tz.c' object='test_timezone-tz.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -c -o test_timezone-tz.o `test -f 'tz.c' || echo '$(srcdir)/'`tz.c + +test_timezone-tz.obj: tz.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -MT test_timezone-tz.obj -MD -MP -MF $(DEPDIR)/test_timezone-tz.Tpo -c -o test_timezone-tz.obj `if test -f 'tz.c'; then $(CYGPATH_W) 'tz.c'; else $(CYGPATH_W) '$(srcdir)/tz.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_timezone-tz.Tpo $(DEPDIR)/test_timezone-tz.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tz.c' object='test_timezone-tz.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_timezone_CFLAGS) $(CFLAGS) -c -o test_timezone-tz.obj `if test -f 'tz.c'; then $(CYGPATH_W) 'tz.c'; else $(CYGPATH_W) '$(srcdir)/tz.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_tzdataDATA: $(dist_tzdata_DATA) + @$(NORMAL_INSTALL) + test -z "$(tzdatadir)" || $(MKDIR_P) "$(DESTDIR)$(tzdatadir)" + @list='$(dist_tzdata_DATA)'; test -n "$(tzdatadir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(tzdatadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(tzdatadir)" || exit $$?; \ + done + +uninstall-dist_tzdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_tzdata_DATA)'; test -n "$(tzdatadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(tzdatadir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(tzdatadir)" && rm -f $$files +install-dist_uiDATA: $(dist_ui_DATA) + @$(NORMAL_INSTALL) + test -z "$(uidir)" || $(MKDIR_P) "$(DESTDIR)$(uidir)" + @list='$(dist_ui_DATA)'; test -n "$(uidir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(uidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(uidir)" || exit $$?; \ + done + +uninstall-dist_uiDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_ui_DATA)'; test -n "$(uidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(uidir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(uidir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) all-local +installdirs: + for dir in "$(DESTDIR)$(tzdatadir)" "$(DESTDIR)$(uidir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_tzdataDATA install-dist_uiDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_tzdataDATA uninstall-dist_uiDATA + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am all-local check check-am check-local \ + clean clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dist_tzdataDATA \ + install-dist_uiDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-dist_tzdataDATA \ + uninstall-dist_uiDATA + + +all-local: check-local + +# FIXME remove "|| :" when we have all the necessary pixmaps +check-local: test-timezone + $(builddir)/test-timezone $(srcdir)/data || : + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libmap/README b/libmap/README new file mode 100644 index 0000000..70d6f6c --- /dev/null +++ b/libmap/README @@ -0,0 +1,5 @@ +This static library is a copied version of the code in GNOME 3.0's control center panel 'datetime', which itself is a version of Ubiquity's map ported to C. + +Ideally in the future, we can have all three packages using the same code. But for now, for time reasons (hah), it's just a copy. + +To update this copy, put newer versions of the code and data files in place; then fix up any GTK3-isms. diff --git a/libmap/backward b/libmap/backward new file mode 100644 index 0000000..f1f95a8 --- /dev/null +++ b/libmap/backward @@ -0,0 +1,118 @@ +#
+# @(#)backward	8.9
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
+
+# This file provides links between current names for time zones
+# and their old names.  Many names changed in late 1993.
+
+Link	Africa/Asmara		Africa/Asmera
+Link	Africa/Bamako		Africa/Timbuktu
+Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
+Link	America/Adak		America/Atka
+Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
+Link	America/Argentina/Catamarca	America/Catamarca
+Link	America/Atikokan	America/Coral_Harbour
+Link	America/Argentina/Cordoba	America/Cordoba
+Link	America/Tijuana		America/Ensenada
+Link	America/Indiana/Indianapolis	America/Fort_Wayne
+Link	America/Indiana/Indianapolis	America/Indianapolis
+Link	America/Argentina/Jujuy	America/Jujuy
+Link	America/Indiana/Knox	America/Knox_IN
+Link	America/Kentucky/Louisville	America/Louisville
+Link	America/Argentina/Mendoza	America/Mendoza
+Link	America/Rio_Branco	America/Porto_Acre
+Link	America/Argentina/Cordoba	America/Rosario
+Link	America/St_Thomas	America/Virgin
+Link	Asia/Ashgabat		Asia/Ashkhabad
+Link	Asia/Chongqing		Asia/Chungking
+Link	Asia/Dhaka		Asia/Dacca
+Link	Asia/Kathmandu		Asia/Katmandu
+Link	Asia/Kolkata		Asia/Calcutta
+Link	Asia/Macau		Asia/Macao
+Link	Asia/Jerusalem		Asia/Tel_Aviv
+Link	Asia/Ho_Chi_Minh	Asia/Saigon
+Link	Asia/Thimphu		Asia/Thimbu
+Link	Asia/Makassar		Asia/Ujung_Pandang
+Link	Asia/Ulaanbaatar	Asia/Ulan_Bator
+Link	Atlantic/Faroe		Atlantic/Faeroe
+Link	Europe/Oslo		Atlantic/Jan_Mayen
+Link	Australia/Sydney	Australia/ACT
+Link	Australia/Sydney	Australia/Canberra
+Link	Australia/Lord_Howe	Australia/LHI
+Link	Australia/Sydney	Australia/NSW
+Link	Australia/Darwin	Australia/North
+Link	Australia/Brisbane	Australia/Queensland
+Link	Australia/Adelaide	Australia/South
+Link	Australia/Hobart	Australia/Tasmania
+Link	Australia/Melbourne	Australia/Victoria
+Link	Australia/Perth		Australia/West
+Link	Australia/Broken_Hill	Australia/Yancowinna
+Link	America/Rio_Branco	Brazil/Acre
+Link	America/Noronha		Brazil/DeNoronha
+Link	America/Sao_Paulo	Brazil/East
+Link	America/Manaus		Brazil/West
+Link	America/Halifax		Canada/Atlantic
+Link	America/Winnipeg	Canada/Central
+Link	America/Regina		Canada/East-Saskatchewan
+Link	America/Toronto		Canada/Eastern
+Link	America/Edmonton	Canada/Mountain
+Link	America/St_Johns	Canada/Newfoundland
+Link	America/Vancouver	Canada/Pacific
+Link	America/Regina		Canada/Saskatchewan
+Link	America/Whitehorse	Canada/Yukon
+Link	America/Santiago	Chile/Continental
+Link	Pacific/Easter		Chile/EasterIsland
+Link	America/Havana		Cuba
+Link	Africa/Cairo		Egypt
+Link	Europe/Dublin		Eire
+Link	Europe/London		Europe/Belfast
+Link	Europe/Chisinau		Europe/Tiraspol
+Link	Europe/London		GB
+Link	Europe/London		GB-Eire
+Link	Etc/GMT			GMT+0
+Link	Etc/GMT			GMT-0
+Link	Etc/GMT			GMT0
+Link	Etc/GMT			Greenwich
+Link	Asia/Hong_Kong		Hongkong
+Link	Atlantic/Reykjavik	Iceland
+Link	Asia/Tehran		Iran
+Link	Asia/Jerusalem		Israel
+Link	America/Jamaica		Jamaica
+Link	Asia/Tokyo		Japan
+Link	Pacific/Kwajalein	Kwajalein
+Link	Africa/Tripoli		Libya
+Link	America/Tijuana		Mexico/BajaNorte
+Link	America/Mazatlan	Mexico/BajaSur
+Link	America/Mexico_City	Mexico/General
+Link	Pacific/Auckland	NZ
+Link	Pacific/Chatham		NZ-CHAT
+Link	America/Denver		Navajo
+Link	Asia/Shanghai		PRC
+Link	Pacific/Pago_Pago	Pacific/Samoa
+Link	Pacific/Chuuk		Pacific/Yap
+Link	Pacific/Chuuk		Pacific/Truk
+Link	Pacific/Pohnpei		Pacific/Ponape
+Link	Europe/Warsaw		Poland
+Link	Europe/Lisbon		Portugal
+Link	Asia/Taipei		ROC
+Link	Asia/Seoul		ROK
+Link	Asia/Singapore		Singapore
+Link	Europe/Istanbul		Turkey
+Link	Etc/UCT			UCT
+Link	America/Anchorage	US/Alaska
+Link	America/Adak		US/Aleutian
+Link	America/Phoenix		US/Arizona
+Link	America/Chicago		US/Central
+Link	America/Indiana/Indianapolis	US/East-Indiana
+Link	America/New_York	US/Eastern
+Link	Pacific/Honolulu	US/Hawaii
+Link	America/Indiana/Knox	US/Indiana-Starke
+Link	America/Detroit		US/Michigan
+Link	America/Denver		US/Mountain
+Link	America/Los_Angeles	US/Pacific
+Link	Pacific/Pago_Pago	US/Samoa
+Link	Etc/UTC			UTC
+Link	Etc/UTC			Universal
+Link	Europe/Moscow		W-SU
+Link	Etc/UTC			Zulu
diff --git a/libmap/cc-timezone-map.c b/libmap/cc-timezone-map.c
new file mode 100644
index 0000000..960a049
--- /dev/null
+++ b/libmap/cc-timezone-map.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * Portions from Ubiquity, Copyright (C) 2009 Canonical Ltd.
+ * Written by Evan Dandrea 
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood 
+ *
+ */
+
+#include "cc-timezone-map.h"
+#include 
+#include "tz.h"
+
+G_DEFINE_TYPE (CcTimezoneMap, cc_timezone_map, GTK_TYPE_WIDGET)
+
+#define TIMEZONE_MAP_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_TIMEZONE_MAP, CcTimezoneMapPrivate))
+
+
+typedef struct
+{
+  gdouble offset;
+  guchar red;
+  guchar green;
+  guchar blue;
+  guchar alpha;
+} CcTimezoneMapOffset;
+
+struct _CcTimezoneMapPrivate
+{
+  GdkPixbuf *orig_background;
+  GdkPixbuf *orig_color_map;
+
+  GdkPixbuf *background;
+  GdkPixbuf *color_map;
+
+  guchar *visible_map_pixels;
+  gint visible_map_rowstride;
+
+  gdouble selected_offset;
+
+  TzDB *tzdb;
+  TzLocation *location;
+  GHashTable *alias_db;
+};
+
+enum
+{
+  LOCATION_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+
+static CcTimezoneMapOffset color_codes[] =
+{
+    {-11.0, 43, 0, 0, 255 },
+    {-10.0, 85, 0, 0, 255 },
+    {-9.5, 102, 255, 0, 255 },
+    {-9.0, 128, 0, 0, 255 },
+    {-8.0, 170, 0, 0, 255 },
+    {-7.0, 212, 0, 0, 255 },
+    {-6.0, 255, 0, 1, 255 }, // north
+    {-6.0, 255, 0, 0, 255 }, // south
+    {-5.0, 255, 42, 42, 255 },
+    {-4.5, 192, 255, 0, 255 },
+    {-4.0, 255, 85, 85, 255 },
+    {-3.5, 0, 255, 0, 255 },
+    {-3.0, 255, 128, 128, 255 },
+    {-2.0, 255, 170, 170, 255 },
+    {-1.0, 255, 213, 213, 255 },
+    {0.0, 43, 17, 0, 255 },
+    {1.0, 85, 34, 0, 255 },
+    {2.0, 128, 51, 0, 255 },
+    {3.0, 170, 68, 0, 255 },
+    {3.5, 0, 255, 102, 255 },
+    {4.0, 212, 85, 0, 255 },
+    {4.5, 0, 204, 255, 255 },
+    {5.0, 255, 102, 0, 255 },
+    {5.5, 0, 102, 255, 255 },
+    {5.75, 0, 238, 207, 247 },
+    {6.0, 255, 127, 42, 255 },
+    {6.5, 204, 0, 254, 254 },
+    {7.0, 255, 153, 85, 255 },
+    {8.0, 255, 179, 128, 255 },
+    {9.0, 255, 204, 170, 255 },
+    {9.5, 170, 0, 68, 250 },
+    {10.0, 255, 230, 213, 255 },
+    {10.5, 212, 124, 21, 250 },
+    {11.0, 212, 170, 0, 255 },
+    {11.5, 249, 25, 87, 253 },
+    {12.0, 255, 204, 0, 255 },
+    {12.75, 254, 74, 100, 248 },
+    {13.0, 255, 85, 153, 250 },
+    {-100, 0, 0, 0, 0 }
+};
+
+
+static void
+cc_timezone_map_get_property (GObject    *object,
+                              guint       property_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_timezone_map_set_property (GObject      *object,
+                              guint         property_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_timezone_map_dispose (GObject *object)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (object)->priv;
+
+  if (priv->orig_background)
+    {
+      g_object_unref (priv->orig_background);
+      priv->orig_background = NULL;
+    }
+
+  if (priv->orig_color_map)
+    {
+      g_object_unref (priv->orig_color_map);
+      priv->orig_color_map = NULL;
+    }
+
+  if (priv->background)
+    {
+      g_object_unref (priv->background);
+      priv->background = NULL;
+    }
+
+  if (priv->color_map)
+    {
+      g_object_unref (priv->color_map);
+      priv->color_map = NULL;
+
+      priv->visible_map_pixels = NULL;
+      priv->visible_map_rowstride = 0;
+    }
+
+  if (priv->alias_db)
+    {
+      g_hash_table_destroy (priv->alias_db);
+      priv->alias_db = NULL;
+    }
+
+  G_OBJECT_CLASS (cc_timezone_map_parent_class)->dispose (object);
+}
+
+static void
+cc_timezone_map_finalize (GObject *object)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (object)->priv;
+
+  if (priv->tzdb)
+    {
+      tz_db_free (priv->tzdb);
+      priv->tzdb = NULL;
+    }
+
+
+  G_OBJECT_CLASS (cc_timezone_map_parent_class)->finalize (object);
+}
+
+/* GtkWidget functions */
+#ifdef CCGTK3
+static void
+cc_timezone_map_get_preferred_width (GtkWidget *widget,
+                                     gint      *minimum,
+                                     gint      *natural)
+{
+  /* choose a minimum size small enough to prevent the window
+   * from growing horizontally
+   */
+  if (minimum != NULL)
+    *minimum = 300;
+  if (natural != NULL)
+    *natural = 300;
+}
+
+static void
+cc_timezone_map_get_preferred_height (GtkWidget *widget,
+                                      gint      *minimum,
+                                      gint      *natural)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
+  gint size;
+
+  /* The + 20 here is a slight tweak to make the map fill the
+   * panel better without causing horizontal growing
+   */
+  size = 300 * gdk_pixbuf_get_height (priv->orig_background) / gdk_pixbuf_get_width (priv->orig_background) + 20;
+  if (minimum != NULL)
+    *minimum = size;
+  if (natural != NULL)
+    *natural = size;
+}
+
+#else
+
+static void
+cc_timezone_map_size_request (GtkWidget *widget,
+                              GtkRequisition *requisition)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
+
+  if (!requisition)
+    return;
+
+  /* The + 20 here is a slight tweak to make the map fill the
+   * panel better without causing horizontal growing
+   */
+  requisition->height = 300 * gdk_pixbuf_get_height (priv->orig_background) / gdk_pixbuf_get_width (priv->orig_background) + 20;
+  requisition->width = 300;
+}
+#endif
+
+static void
+cc_timezone_map_size_allocate (GtkWidget     *widget,
+                               GtkAllocation *allocation)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
+
+  if (priv->background)
+    g_object_unref (priv->background);
+
+  priv->background = gdk_pixbuf_scale_simple (priv->orig_background,
+                                              allocation->width,
+                                              allocation->height,
+                                              GDK_INTERP_BILINEAR);
+
+  if (priv->color_map)
+    g_object_unref (priv->color_map);
+
+  priv->color_map = gdk_pixbuf_scale_simple (priv->orig_color_map,
+                                             allocation->width,
+                                             allocation->height,
+                                             GDK_INTERP_BILINEAR);
+
+  priv->visible_map_pixels = gdk_pixbuf_get_pixels (priv->color_map);
+  priv->visible_map_rowstride = gdk_pixbuf_get_rowstride (priv->color_map);
+
+  GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->size_allocate (widget,
+                                                                  allocation);
+}
+
+static void
+cc_timezone_map_realize (GtkWidget *widget)
+{
+  GdkWindowAttr attr = { 0, };
+  GtkAllocation allocation;
+  GdkCursor *cursor;
+  GdkWindow *window;
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  gtk_widget_set_realized (widget, TRUE);
+
+  attr.window_type = GDK_WINDOW_CHILD;
+  attr.wclass = GDK_INPUT_OUTPUT;
+  attr.width = allocation.width;
+  attr.height = allocation.height;
+  attr.x = allocation.x;
+  attr.y = allocation.y;
+  attr.event_mask = gtk_widget_get_events (widget)
+                                 | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
+
+  window = gdk_window_new (gtk_widget_get_parent_window (widget), &attr,
+                           GDK_WA_X | GDK_WA_Y);
+
+  gtk_widget_set_style (widget,
+                        gtk_style_attach (gtk_widget_get_style (widget),
+                                          window));
+
+  gdk_window_set_user_data (window, widget);
+
+  cursor = gdk_cursor_new (GDK_HAND2);
+  gdk_window_set_cursor (window, cursor);
+
+  gtk_widget_set_window (widget, window);
+}
+
+
+static gdouble
+convert_longtitude_to_x (gdouble longitude, gint map_width)
+{
+  const gdouble xdeg_offset = -6;
+  gdouble x;
+
+  x = (map_width * (180.0 + longitude) / 360.0)
+    + (map_width * xdeg_offset / 180.0);
+
+  return x;
+}
+
+static gdouble
+radians (gdouble degrees)
+{
+  return (degrees / 360.0) * G_PI * 2;
+}
+
+static gdouble
+convert_latitude_to_y (gdouble latitude, gdouble map_height)
+{
+  gdouble bottom_lat = -59;
+  gdouble top_lat = 81;
+  gdouble top_per, y, full_range, top_offset, map_range;
+
+  top_per = top_lat / 180.0;
+  y = 1.25 * log (tan (G_PI_4 + 0.4 * radians (latitude)));
+  full_range = 4.6068250867599998;
+  top_offset = full_range * top_per;
+  map_range = fabs (1.25 * log (tan (G_PI_4 + 0.4 * radians (bottom_lat))) - top_offset);
+  y = fabs (y - top_offset);
+  y = y / map_range;
+  y = y * map_height;
+  return y;
+}
+
+
+static gboolean
+cc_timezone_map_draw (GtkWidget *widget,
+                      cairo_t   *cr)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
+  GdkPixbuf *hilight, *orig_hilight, *pin;
+  GtkAllocation alloc;
+  gchar *file;
+  GError *err = NULL;
+  gdouble pointx, pointy;
+  char buf[16];
+
+  gtk_widget_get_allocation (widget, &alloc);
+
+  /* paint background */
+  gdk_cairo_set_source_pixbuf (cr, priv->background, 0, 0);
+  cairo_paint (cr);
+
+  /* paint hilight */
+  file = g_strdup_printf (DATADIR "/timezone_%s.png",
+                          g_ascii_formatd (buf, sizeof (buf),
+                                           "%g", priv->selected_offset));
+  orig_hilight = gdk_pixbuf_new_from_file (file, &err);
+  g_free (file);
+  file = NULL;
+
+  if (!orig_hilight)
+    {
+      g_warning ("Could not load hilight: %s",
+                 (err) ? err->message : "Unknown Error");
+      if (err)
+        g_clear_error (&err);
+    }
+  else
+    {
+
+      hilight = gdk_pixbuf_scale_simple (orig_hilight, alloc.width,
+                                         alloc.height, GDK_INTERP_BILINEAR);
+      gdk_cairo_set_source_pixbuf (cr, hilight, 0, 0);
+
+      cairo_paint (cr);
+      g_object_unref (hilight);
+      g_object_unref (orig_hilight);
+    }
+
+  /* load pin icon */
+  pin = gdk_pixbuf_new_from_file (DATADIR "/pin.png", &err);
+
+  if (err)
+    {
+      g_warning ("Could not load pin icon: %s", err->message);
+      g_clear_error (&err);
+    }
+
+  if (priv->location)
+    {
+      pointx = convert_longtitude_to_x (priv->location->longitude, alloc.width);
+      pointy = convert_latitude_to_y (priv->location->latitude, alloc.height);
+
+      if (pointy > alloc.height)
+        pointy = alloc.height;
+
+      if (pin)
+        {
+          gdk_cairo_set_source_pixbuf (cr, pin, pointx - 8, pointy - 14);
+          cairo_paint (cr);
+        }
+    }
+
+  if (pin)
+    {
+      g_object_unref (pin);
+    }
+
+  return TRUE;
+}
+
+#ifndef CCGTK3
+static gboolean
+cc_timezone_map_expose_event (GtkWidget *widget,
+                              GdkEventExpose  *event)
+{
+  gboolean   rv;
+  cairo_t   *cr;
+  cr = gdk_cairo_create (widget->window);
+  rv = cc_timezone_map_draw (widget, cr);
+  cairo_destroy (cr);
+  return rv;
+}
+#endif
+
+
+static void
+cc_timezone_map_class_init (CcTimezoneMapClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (CcTimezoneMapPrivate));
+
+  object_class->get_property = cc_timezone_map_get_property;
+  object_class->set_property = cc_timezone_map_set_property;
+  object_class->dispose = cc_timezone_map_dispose;
+  object_class->finalize = cc_timezone_map_finalize;
+
+#ifdef CCGTK3
+  widget_class->get_preferred_width = cc_timezone_map_get_preferred_width;
+  widget_class->get_preferred_height = cc_timezone_map_get_preferred_height;
+#else
+  widget_class->size_request = cc_timezone_map_size_request;
+#endif
+  widget_class->size_allocate = cc_timezone_map_size_allocate;
+  widget_class->realize = cc_timezone_map_realize;
+#ifdef CCGTK3
+  widget_class->draw = cc_timezone_map_draw;
+#else
+  widget_class->expose_event = cc_timezone_map_expose_event;
+#endif
+
+  signals[LOCATION_CHANGED] = g_signal_new ("location-changed",
+                                            CC_TYPE_TIMEZONE_MAP,
+                                            G_SIGNAL_RUN_FIRST,
+                                            0,
+                                            NULL,
+                                            NULL,
+                                            g_cclosure_marshal_VOID__POINTER,
+                                            G_TYPE_NONE, 1,
+                                            G_TYPE_POINTER);
+}
+
+
+static gint
+sort_locations (TzLocation *a,
+                TzLocation *b)
+{
+  if (a->dist > b->dist)
+    return 1;
+
+  if (a->dist < b->dist)
+    return -1;
+
+  return 0;
+}
+
+static void
+set_location (CcTimezoneMap *map,
+              TzLocation    *location)
+{
+  CcTimezoneMapPrivate *priv = map->priv;
+  TzInfo *info;
+
+  priv->location = location;
+
+  info = tz_info_from_location (priv->location);
+
+  priv->selected_offset = tz_location_get_utc_offset (priv->location)
+    / (60.0*60.0) + ((info->daylight) ? -1.0 : 0.0);
+
+  g_signal_emit (map, signals[LOCATION_CHANGED], 0, priv->location);
+
+  tz_info_free (info);
+}
+
+static gboolean
+button_press_event (GtkWidget      *widget,
+                    GdkEventButton *event)
+{
+  CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
+  gint x, y;
+  guchar r, g, b, a;
+  guchar *pixels;
+  gint rowstride;
+  gint i;
+
+  const GPtrArray *array;
+  gint width, height;
+  GList *distances = NULL;
+  GtkAllocation alloc;
+
+  x = event->x;
+  y = event->y;
+
+
+  rowstride = priv->visible_map_rowstride;
+  pixels = priv->visible_map_pixels;
+
+  r = pixels[(rowstride * y + x * 4)];
+  g = pixels[(rowstride * y + x * 4) + 1];
+  b = pixels[(rowstride * y + x * 4) + 2];
+  a = pixels[(rowstride * y + x * 4) + 3];
+
+
+  for (i = 0; color_codes[i].offset != -100; i++)
+    {
+       if (color_codes[i].red == r && color_codes[i].green == g
+           && color_codes[i].blue == b && color_codes[i].alpha == a)
+         {
+           priv->selected_offset = color_codes[i].offset;
+         }
+    }
+
+  gtk_widget_queue_draw (widget);
+
+  /* work out the co-ordinates */
+
+  array = tz_get_locations (priv->tzdb);
+
+  gtk_widget_get_allocation (widget, &alloc);
+  width = alloc.width;
+  height = alloc.height;
+
+  for (i = 0; i < array->len; i++)
+    {
+      gdouble pointx, pointy, dx, dy;
+      TzLocation *loc = array->pdata[i];
+
+      pointx = convert_longtitude_to_x (loc->longitude, width);
+      pointy = convert_latitude_to_y (loc->latitude, height);
+
+      dx = pointx - x;
+      dy = pointy - y;
+
+      loc->dist = dx * dx + dy * dy;
+      distances = g_list_prepend (distances, loc);
+
+    }
+  distances = g_list_sort (distances, (GCompareFunc) sort_locations);
+
+
+  set_location (CC_TIMEZONE_MAP (widget), (TzLocation*) distances->data);
+
+  g_list_free (distances);
+
+  return TRUE;
+}
+
+static void
+load_backward_tz (CcTimezoneMap *self)
+{
+  GError *error = NULL;
+  char **lines, *contents;
+  guint i;
+
+  self->priv->alias_db = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+  if (g_file_get_contents (GNOMECC_DATA_DIR "/datetime/backward", &contents, NULL, &error) == FALSE)
+    {
+      g_warning ("Failed to load 'backward' file: %s", error->message);
+      return;
+    }
+  lines = g_strsplit (contents, "\n", -1);
+  g_free (contents);
+  for (i = 0; lines[i] != NULL; i++)
+    {
+      char **items;
+      guint j;
+      char *real, *alias;
+
+      if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0)
+        continue;
+
+      items = g_strsplit (lines[i], "\t", -1);
+      real = NULL;
+      alias = NULL;
+      /* Skip the "Link" part */
+      for (j = 1; items[j] != NULL; j++)
+        {
+          if (items[j][0] == '\0')
+            continue;
+          if (real == NULL)
+            {
+              real = items[j];
+              continue;
+            }
+          alias = items[j];
+          break;
+        }
+
+      if (real == NULL || alias == NULL)
+        g_warning ("Could not parse line: %s", lines[i]);
+
+      g_hash_table_insert (self->priv->alias_db, g_strdup (alias), g_strdup (real));
+      g_strfreev (items);
+    }
+  g_strfreev (lines);
+}
+
+static void
+cc_timezone_map_init (CcTimezoneMap *self)
+{
+  CcTimezoneMapPrivate *priv;
+  GError *err = NULL;
+
+  priv = self->priv = TIMEZONE_MAP_PRIVATE (self);
+
+  priv->orig_background = gdk_pixbuf_new_from_file (DATADIR "/bg.png",
+                                                    &err);
+
+  if (!priv->orig_background)
+    {
+      g_warning ("Could not load background image: %s",
+                 (err) ? err->message : "Unknown error");
+      g_clear_error (&err);
+    }
+
+  priv->orig_color_map = gdk_pixbuf_new_from_file (DATADIR "/cc.png",
+                                                   &err);
+  if (!priv->orig_color_map)
+    {
+      g_warning ("Could not load background image: %s",
+                 (err) ? err->message : "Unknown error");
+      g_clear_error (&err);
+    }
+
+  priv->tzdb = tz_load_db ();
+
+  g_signal_connect (self, "button-press-event", G_CALLBACK (button_press_event),
+                    NULL);
+
+  load_backward_tz (self);
+}
+
+CcTimezoneMap *
+cc_timezone_map_new (void)
+{
+  return g_object_new (CC_TYPE_TIMEZONE_MAP, NULL);
+}
+
+void
+cc_timezone_map_set_timezone (CcTimezoneMap *map,
+                              const gchar   *timezone)
+{
+  GPtrArray *locations;
+  guint i;
+  char *real_tz;
+
+  real_tz = g_hash_table_lookup (map->priv->alias_db, timezone);
+
+  locations = tz_get_locations (map->priv->tzdb);
+
+  for (i = 0; i < locations->len; i++)
+    {
+      TzLocation *loc = locations->pdata[i];
+
+      if (!g_strcmp0 (loc->zone, real_tz ? real_tz : timezone))
+        {
+          set_location (map, loc);
+          break;
+        }
+    }
+
+  gtk_widget_queue_draw (GTK_WIDGET (map));
+}
+
+TzLocation *
+cc_timezone_map_get_location (CcTimezoneMap *map)
+{
+  return map->priv->location;
+}
diff --git a/libmap/cc-timezone-map.h b/libmap/cc-timezone-map.h
new file mode 100644
index 0000000..3c57b27
--- /dev/null
+++ b/libmap/cc-timezone-map.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood 
+ *
+ */
+
+
+#ifndef _CC_TIMEZONE_MAP_H
+#define _CC_TIMEZONE_MAP_H
+
+#include 
+#include "tz.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_TIMEZONE_MAP cc_timezone_map_get_type()
+
+#define CC_TIMEZONE_MAP(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  CC_TYPE_TIMEZONE_MAP, CcTimezoneMap))
+
+#define CC_TIMEZONE_MAP_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  CC_TYPE_TIMEZONE_MAP, CcTimezoneMapClass))
+
+#define CC_IS_TIMEZONE_MAP(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  CC_TYPE_TIMEZONE_MAP))
+
+#define CC_IS_TIMEZONE_MAP_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  CC_TYPE_TIMEZONE_MAP))
+
+#define CC_TIMEZONE_MAP_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  CC_TYPE_TIMEZONE_MAP, CcTimezoneMapClass))
+
+typedef struct _CcTimezoneMap CcTimezoneMap;
+typedef struct _CcTimezoneMapClass CcTimezoneMapClass;
+typedef struct _CcTimezoneMapPrivate CcTimezoneMapPrivate;
+
+struct _CcTimezoneMap
+{
+  GtkWidget parent;
+
+  CcTimezoneMapPrivate *priv;
+};
+
+struct _CcTimezoneMapClass
+{
+  GtkWidgetClass parent_class;
+};
+
+GType cc_timezone_map_get_type (void) G_GNUC_CONST;
+
+CcTimezoneMap *cc_timezone_map_new (void);
+
+void cc_timezone_map_set_timezone (CcTimezoneMap *map,
+                                   const gchar   *timezone);
+TzLocation * cc_timezone_map_get_location (CcTimezoneMap *map);
+
+G_END_DECLS
+
+#endif /* _CC_TIMEZONE_MAP_H */
diff --git a/libmap/data/bg.png b/libmap/data/bg.png
new file mode 100644
index 0000000..4180ee8
Binary files /dev/null and b/libmap/data/bg.png differ
diff --git a/libmap/data/cc.png b/libmap/data/cc.png
new file mode 100644
index 0000000..54fb668
Binary files /dev/null and b/libmap/data/cc.png differ
diff --git a/libmap/data/pin.png b/libmap/data/pin.png
new file mode 100644
index 0000000..599a751
Binary files /dev/null and b/libmap/data/pin.png differ
diff --git a/libmap/data/timezone_-1.png b/libmap/data/timezone_-1.png
new file mode 100644
index 0000000..fb00d83
Binary files /dev/null and b/libmap/data/timezone_-1.png differ
diff --git a/libmap/data/timezone_-10.png b/libmap/data/timezone_-10.png
new file mode 100644
index 0000000..472eb88
Binary files /dev/null and b/libmap/data/timezone_-10.png differ
diff --git a/libmap/data/timezone_-11.png b/libmap/data/timezone_-11.png
new file mode 100644
index 0000000..5f8c5d6
Binary files /dev/null and b/libmap/data/timezone_-11.png differ
diff --git a/libmap/data/timezone_-2.png b/libmap/data/timezone_-2.png
new file mode 100644
index 0000000..30a1ec7
Binary files /dev/null and b/libmap/data/timezone_-2.png differ
diff --git a/libmap/data/timezone_-3.5.png b/libmap/data/timezone_-3.5.png
new file mode 100644
index 0000000..c1df00b
Binary files /dev/null and b/libmap/data/timezone_-3.5.png differ
diff --git a/libmap/data/timezone_-3.png b/libmap/data/timezone_-3.png
new file mode 100644
index 0000000..c22dbb6
Binary files /dev/null and b/libmap/data/timezone_-3.png differ
diff --git a/libmap/data/timezone_-4.5.png b/libmap/data/timezone_-4.5.png
new file mode 100644
index 0000000..9e3c134
Binary files /dev/null and b/libmap/data/timezone_-4.5.png differ
diff --git a/libmap/data/timezone_-4.png b/libmap/data/timezone_-4.png
new file mode 100644
index 0000000..4b5a431
Binary files /dev/null and b/libmap/data/timezone_-4.png differ
diff --git a/libmap/data/timezone_-5.5.png b/libmap/data/timezone_-5.5.png
new file mode 100644
index 0000000..b1c788d
Binary files /dev/null and b/libmap/data/timezone_-5.5.png differ
diff --git a/libmap/data/timezone_-5.png b/libmap/data/timezone_-5.png
new file mode 100644
index 0000000..06c15e6
Binary files /dev/null and b/libmap/data/timezone_-5.png differ
diff --git a/libmap/data/timezone_-6.png b/libmap/data/timezone_-6.png
new file mode 100644
index 0000000..8505fb1
Binary files /dev/null and b/libmap/data/timezone_-6.png differ
diff --git a/libmap/data/timezone_-7.png b/libmap/data/timezone_-7.png
new file mode 100644
index 0000000..fec235d
Binary files /dev/null and b/libmap/data/timezone_-7.png differ
diff --git a/libmap/data/timezone_-8.png b/libmap/data/timezone_-8.png
new file mode 100644
index 0000000..bdad7bf
Binary files /dev/null and b/libmap/data/timezone_-8.png differ
diff --git a/libmap/data/timezone_-9.5.png b/libmap/data/timezone_-9.5.png
new file mode 100644
index 0000000..b1c788d
Binary files /dev/null and b/libmap/data/timezone_-9.5.png differ
diff --git a/libmap/data/timezone_-9.png b/libmap/data/timezone_-9.png
new file mode 100644
index 0000000..04cb3cb
Binary files /dev/null and b/libmap/data/timezone_-9.png differ
diff --git a/libmap/data/timezone_0.png b/libmap/data/timezone_0.png
new file mode 100644
index 0000000..e59b773
Binary files /dev/null and b/libmap/data/timezone_0.png differ
diff --git a/libmap/data/timezone_1.png b/libmap/data/timezone_1.png
new file mode 100644
index 0000000..2053b7e
Binary files /dev/null and b/libmap/data/timezone_1.png differ
diff --git a/libmap/data/timezone_10.5.png b/libmap/data/timezone_10.5.png
new file mode 100644
index 0000000..6ec7f9f
Binary files /dev/null and b/libmap/data/timezone_10.5.png differ
diff --git a/libmap/data/timezone_10.png b/libmap/data/timezone_10.png
new file mode 100644
index 0000000..475dcf4
Binary files /dev/null and b/libmap/data/timezone_10.png differ
diff --git a/libmap/data/timezone_11.5.png b/libmap/data/timezone_11.5.png
new file mode 100644
index 0000000..afdedd7
Binary files /dev/null and b/libmap/data/timezone_11.5.png differ
diff --git a/libmap/data/timezone_11.png b/libmap/data/timezone_11.png
new file mode 100644
index 0000000..6168aa2
Binary files /dev/null and b/libmap/data/timezone_11.png differ
diff --git a/libmap/data/timezone_12.75.png b/libmap/data/timezone_12.75.png
new file mode 100644
index 0000000..4f74a85
Binary files /dev/null and b/libmap/data/timezone_12.75.png differ
diff --git a/libmap/data/timezone_12.png b/libmap/data/timezone_12.png
new file mode 100644
index 0000000..d0b3531
Binary files /dev/null and b/libmap/data/timezone_12.png differ
diff --git a/libmap/data/timezone_13.png b/libmap/data/timezone_13.png
new file mode 100644
index 0000000..fe2f134
Binary files /dev/null and b/libmap/data/timezone_13.png differ
diff --git a/libmap/data/timezone_2.png b/libmap/data/timezone_2.png
new file mode 100644
index 0000000..ec1e874
Binary files /dev/null and b/libmap/data/timezone_2.png differ
diff --git a/libmap/data/timezone_3.5.png b/libmap/data/timezone_3.5.png
new file mode 100644
index 0000000..2dc7399
Binary files /dev/null and b/libmap/data/timezone_3.5.png differ
diff --git a/libmap/data/timezone_3.png b/libmap/data/timezone_3.png
new file mode 100644
index 0000000..eda59dc
Binary files /dev/null and b/libmap/data/timezone_3.png differ
diff --git a/libmap/data/timezone_4.5.png b/libmap/data/timezone_4.5.png
new file mode 100644
index 0000000..e09ed90
Binary files /dev/null and b/libmap/data/timezone_4.5.png differ
diff --git a/libmap/data/timezone_4.png b/libmap/data/timezone_4.png
new file mode 100644
index 0000000..483dc53
Binary files /dev/null and b/libmap/data/timezone_4.png differ
diff --git a/libmap/data/timezone_5.5.png b/libmap/data/timezone_5.5.png
new file mode 100644
index 0000000..f904cc2
Binary files /dev/null and b/libmap/data/timezone_5.5.png differ
diff --git a/libmap/data/timezone_5.75.png b/libmap/data/timezone_5.75.png
new file mode 100644
index 0000000..827ce1a
Binary files /dev/null and b/libmap/data/timezone_5.75.png differ
diff --git a/libmap/data/timezone_5.png b/libmap/data/timezone_5.png
new file mode 100644
index 0000000..1bb6d20
Binary files /dev/null and b/libmap/data/timezone_5.png differ
diff --git a/libmap/data/timezone_6.5.png b/libmap/data/timezone_6.5.png
new file mode 100644
index 0000000..d307bf3
Binary files /dev/null and b/libmap/data/timezone_6.5.png differ
diff --git a/libmap/data/timezone_6.png b/libmap/data/timezone_6.png
new file mode 100644
index 0000000..460f9cf
Binary files /dev/null and b/libmap/data/timezone_6.png differ
diff --git a/libmap/data/timezone_7.png b/libmap/data/timezone_7.png
new file mode 100644
index 0000000..239115a
Binary files /dev/null and b/libmap/data/timezone_7.png differ
diff --git a/libmap/data/timezone_8.png b/libmap/data/timezone_8.png
new file mode 100644
index 0000000..3627686
Binary files /dev/null and b/libmap/data/timezone_8.png differ
diff --git a/libmap/data/timezone_9.5.png b/libmap/data/timezone_9.5.png
new file mode 100644
index 0000000..1c3290c
Binary files /dev/null and b/libmap/data/timezone_9.5.png differ
diff --git a/libmap/data/timezone_9.png b/libmap/data/timezone_9.png
new file mode 100644
index 0000000..65d2e46
Binary files /dev/null and b/libmap/data/timezone_9.png differ
diff --git a/libmap/datetime-module.c b/libmap/datetime-module.c
new file mode 100644
index 0000000..8217dc3
--- /dev/null
+++ b/libmap/datetime-module.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood 
+ *
+ */
+
+#include 
+
+#include "cc-datetime-panel.h"
+
+#include 
+
+#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
+
+void
+g_io_module_load (GIOModule *module)
+{
+  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+  bindtextdomain (GETTEXT_PACKAGE_TIMEZONES, GNOMELOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE_TIMEZONES, "UTF-8");
+
+  /* register the panel */
+  cc_date_time_panel_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/libmap/dt-lockbutton.c b/libmap/dt-lockbutton.c
new file mode 100644
index 0000000..ecf4c12
--- /dev/null
+++ b/libmap/dt-lockbutton.c
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Author: Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "dt-lockbutton.h"
+
+#include 
+#include 
+
+#define P_(s) s
+
+struct _DtLockButtonPrivate
+{
+  GPermission *permission;
+
+  gchar *text_lock;
+  gchar *text_unlock;
+  gchar *text_not_authorized;
+
+  gchar *tooltip_lock;
+  gchar *tooltip_unlock;
+  gchar *tooltip_not_authorized;
+
+  GtkWidget *box;
+  GtkWidget *eventbox;
+  GtkWidget *image;
+  GtkWidget *button;
+  GtkWidget *notebook;
+
+  GtkWidget *label_lock;
+  GtkWidget *label_unlock;
+  GtkWidget *label_not_authorized;
+
+  GCancellable *cancellable;
+
+  gboolean constructed;
+};
+
+enum
+{
+  PROP_0,
+  PROP_PERMISSION,
+  PROP_TEXT_LOCK,
+  PROP_TEXT_UNLOCK,
+  PROP_TEXT_NOT_AUTHORIZED,
+  PROP_TOOLTIP_LOCK,
+  PROP_TOOLTIP_UNLOCK,
+  PROP_TOOLTIP_NOT_AUTHORIZED
+};
+
+static void update_state (DtLockButton *button);
+
+static void on_permission_changed (GPermission *permission,
+                                   GParamSpec  *pspec,
+                                   gpointer     user_data);
+
+static void on_clicked (GtkButton *button,
+                        gpointer   user_data);
+
+static void on_button_press (GtkWidget      *widget,
+                             GdkEventButton *event,
+                             gpointer        user_data);
+
+G_DEFINE_TYPE (DtLockButton, dt_lock_button, GTK_TYPE_BIN);
+
+static void
+dt_lock_button_finalize (GObject *object)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (object);
+  DtLockButtonPrivate *priv = button->priv;
+
+  g_free (priv->text_lock);
+  g_free (priv->text_unlock);
+  g_free (priv->text_not_authorized);
+
+  g_free (priv->tooltip_lock);
+  g_free (priv->tooltip_unlock);
+  g_free (priv->tooltip_not_authorized);
+
+  if (priv->cancellable != NULL)
+    {
+      g_cancellable_cancel (priv->cancellable);
+      g_object_unref (priv->cancellable);
+    }
+
+  g_signal_handlers_disconnect_by_func (priv->permission,
+                                        on_permission_changed,
+                                        button);
+
+  g_object_unref (priv->permission);
+
+  G_OBJECT_CLASS (dt_lock_button_parent_class)->finalize (object);
+}
+
+static void
+dt_lock_button_get_property (GObject    *object,
+                             guint       property_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (object);
+  DtLockButtonPrivate *priv = button->priv;
+
+  switch (property_id)
+    {
+    case PROP_PERMISSION:
+      g_value_set_object (value, priv->permission);
+      break;
+
+    case PROP_TEXT_LOCK:
+      g_value_set_string (value, priv->text_lock);
+      break;
+
+    case PROP_TEXT_UNLOCK:
+      g_value_set_string (value, priv->text_unlock);
+      break;
+
+    case PROP_TEXT_NOT_AUTHORIZED:
+      g_value_set_string (value, priv->text_not_authorized);
+      break;
+
+    case PROP_TOOLTIP_LOCK:
+      g_value_set_string (value, priv->tooltip_lock);
+      break;
+
+    case PROP_TOOLTIP_UNLOCK:
+      g_value_set_string (value, priv->tooltip_unlock);
+      break;
+
+    case PROP_TOOLTIP_NOT_AUTHORIZED:
+      g_value_set_string (value, priv->tooltip_not_authorized);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+dt_lock_button_set_property (GObject      *object,
+                             guint         property_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (object);
+  DtLockButtonPrivate *priv = button->priv;
+
+  switch (property_id)
+    {
+    case PROP_PERMISSION:
+      priv->permission = g_value_get_object (value);
+      break;
+
+    case PROP_TEXT_LOCK:
+      g_free (priv->text_lock);
+      priv->text_lock = g_value_dup_string (value);
+      break;
+
+    case PROP_TEXT_UNLOCK:
+      g_free (priv->text_unlock);
+      priv->text_unlock = g_value_dup_string (value);
+      break;
+
+    case PROP_TEXT_NOT_AUTHORIZED:
+      g_free (priv->text_not_authorized);
+      priv->text_not_authorized = g_value_dup_string (value);
+      break;
+
+    case PROP_TOOLTIP_LOCK:
+      g_free (priv->tooltip_lock);
+      priv->tooltip_lock = g_value_dup_string (value);
+      break;
+
+    case PROP_TOOLTIP_UNLOCK:
+      g_free (priv->tooltip_unlock);
+      priv->tooltip_unlock = g_value_dup_string (value);
+      break;
+
+    case PROP_TOOLTIP_NOT_AUTHORIZED:
+      g_free (priv->tooltip_not_authorized);
+      priv->tooltip_not_authorized = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+
+  if (priv->constructed)
+    update_state (button);
+}
+
+static void
+dt_lock_button_init (DtLockButton *button)
+{
+  button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
+                                              DT_TYPE_LOCK_BUTTON,
+                                              DtLockButtonPrivate);
+}
+
+static void
+dt_lock_button_constructed (GObject *object)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (object);
+  DtLockButtonPrivate *priv = button->priv;
+
+  priv->constructed = TRUE;
+
+  g_signal_connect (priv->permission, "notify",
+                    G_CALLBACK (on_permission_changed), button);
+
+  priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_container_add (GTK_CONTAINER (button), priv->box);
+
+  priv->eventbox = gtk_event_box_new ();
+  gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->eventbox), FALSE);
+  gtk_container_add (GTK_CONTAINER (priv->box), priv->eventbox);
+  gtk_widget_show (priv->eventbox);
+
+  priv->image = gtk_image_new (); /* image is set in update_state() */
+  gtk_container_add (GTK_CONTAINER (priv->eventbox), priv->image);
+  gtk_widget_show (priv->image);
+
+  priv->notebook = gtk_notebook_new ();
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
+  gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
+  gtk_widget_show (priv->notebook);
+
+  priv->button = gtk_button_new ();
+  gtk_container_add (GTK_CONTAINER (priv->button), priv->notebook);
+  gtk_widget_show (priv->button);
+
+  priv->label_lock = gtk_label_new (""); /* text is set in update_state */
+  gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->label_lock, NULL);
+  gtk_widget_show (priv->label_lock);
+
+  priv->label_unlock = gtk_label_new ("");
+  gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->label_unlock, NULL);
+  gtk_widget_show (priv->label_unlock);
+
+  priv->label_not_authorized = gtk_label_new ("");
+  gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->label_not_authorized, NULL);
+  gtk_widget_show (priv->label_not_authorized);
+
+  gtk_box_pack_start (GTK_BOX (priv->box), priv->button, FALSE, FALSE, 0);
+  gtk_widget_show (priv->button);
+
+  g_signal_connect (priv->eventbox, "button-press-event",
+                    G_CALLBACK (on_button_press), button);
+  g_signal_connect (priv->button, "clicked",
+                    G_CALLBACK (on_clicked), button);
+
+  gtk_widget_set_no_show_all (priv->box, TRUE);
+
+  update_state (button);
+
+  if (G_OBJECT_CLASS (dt_lock_button_parent_class)->constructed != NULL)
+    G_OBJECT_CLASS (dt_lock_button_parent_class)->constructed (object);
+}
+
+static void
+dt_lock_button_get_preferred_width (GtkWidget *widget,
+                                    gint      *minimum,
+                                    gint      *natural)
+{
+  DtLockButtonPrivate *priv = DT_LOCK_BUTTON (widget)->priv;
+
+  gtk_widget_get_preferred_width (priv->box, minimum, natural);
+}
+
+static void
+dt_lock_button_get_preferred_height (GtkWidget *widget,
+                                     gint      *minimum,
+                                     gint      *natural)
+{
+  DtLockButtonPrivate *priv = DT_LOCK_BUTTON (widget)->priv;
+
+  gtk_widget_get_preferred_height (priv->box, minimum, natural);
+}
+
+static void
+dt_lock_button_size_allocate (GtkWidget     *widget,
+                              GtkAllocation *allocation)
+{
+  DtLockButtonPrivate *priv = DT_LOCK_BUTTON (widget)->priv;
+  GtkRequisition requisition;
+  GtkAllocation child_allocation;
+
+  gtk_widget_set_allocation (widget, allocation);
+  gtk_widget_get_preferred_size (priv->box, &requisition, NULL);
+  child_allocation.x = allocation->x;
+  child_allocation.y = allocation->y;
+  child_allocation.width = requisition.width;
+  child_allocation.height = requisition.height;
+  gtk_widget_size_allocate (priv->box, &child_allocation);
+}
+
+static void
+dt_lock_button_class_init (DtLockButtonClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gobject_class->finalize     = dt_lock_button_finalize;
+  gobject_class->get_property = dt_lock_button_get_property;
+  gobject_class->set_property = dt_lock_button_set_property;
+  gobject_class->constructed  = dt_lock_button_constructed;
+
+  widget_class->get_preferred_width = dt_lock_button_get_preferred_width;
+  widget_class->get_preferred_height = dt_lock_button_get_preferred_height;
+  widget_class->size_allocate = dt_lock_button_size_allocate;
+
+  g_type_class_add_private (klass, sizeof (DtLockButtonPrivate));
+
+  g_object_class_install_property (gobject_class, PROP_PERMISSION,
+    g_param_spec_object ("permission",
+                         P_("Permission"),
+                         P_("The GPermission object controlling this button"),
+                         G_TYPE_PERMISSION,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TEXT_LOCK,
+    g_param_spec_string ("text-lock",
+                         P_("Lock Text"),
+                         P_("The text to display when prompting the user to lock"),
+                         _("Lock"),
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TEXT_UNLOCK,
+    g_param_spec_string ("text-unlock",
+                         P_("Unlock Text"),
+                         P_("The text to display when prompting the user to unlock"),
+                         _("Unlock"),
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TEXT_NOT_AUTHORIZED,
+    g_param_spec_string ("text-not-authorized",
+                         P_("Not Authorized Text"),
+                         P_("The text to display when prompting the user cannot obtain authorization"),
+                         _("Locked"),
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TOOLTIP_LOCK,
+    g_param_spec_string ("tooltip-lock",
+                         P_("Lock Tooltip"),
+                         P_("The tooltip to display when prompting the user to lock"),
+                         _("Dialog is unlocked.\nClick to prevent further changes"),
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TOOLTIP_UNLOCK,
+    g_param_spec_string ("tooltip-unlock",
+                         P_("Unlock Tooltip"),
+                         P_("The tooltip to display when prompting the user to unlock"),
+                         _("Dialog is locked.\nClick to make changes"),
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TOOLTIP_NOT_AUTHORIZED,
+    g_param_spec_string ("tooltip-not-authorized",
+                         P_("Not Authorized Tooltip"),
+                         P_("The tooltip to display when prompting the user cannot obtain authorization"),
+                         _("System policy prevents changes.\nContact your system administrator"),
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * dt_lock_button_new:
+ * @permission: a #GPermission
+ *
+ * Creates a new lock button which reflects the @permission.
+ *
+ * Returns: a new #DtLockButton
+ *
+ * Since: 3.0
+ */
+GtkWidget *
+dt_lock_button_new (GPermission *permission)
+{
+  g_return_val_if_fail (permission != NULL, NULL);
+
+  return GTK_WIDGET (g_object_new (DT_TYPE_LOCK_BUTTON,
+                                   "permission", permission,
+                                   NULL));
+}
+
+static void
+update_state (DtLockButton *button)
+{
+  DtLockButtonPrivate *priv = button->priv;
+  gint page;
+  const gchar *tooltip;
+  gboolean sensitive;
+  gboolean visible;
+  GIcon *icon;
+
+  visible = TRUE;
+  sensitive = TRUE;
+
+  gtk_label_set_text (GTK_LABEL (priv->label_lock), priv->text_lock);
+  gtk_label_set_text (GTK_LABEL (priv->label_unlock), priv->text_unlock);
+  gtk_label_set_text (GTK_LABEL (priv->label_not_authorized), priv->text_not_authorized);
+
+  if (g_permission_get_allowed (priv->permission))
+    {
+      if (g_permission_get_can_release (priv->permission))
+        {
+          page = 0;
+          tooltip = priv->tooltip_lock;
+          sensitive = TRUE;
+        }
+      else
+        {
+          page = 0;
+          tooltip = "";
+          visible = FALSE;
+        }
+    }
+  else
+    {
+      if (g_permission_get_can_acquire (priv->permission))
+        {
+          page = 1;
+          tooltip = button->priv->tooltip_unlock;
+          sensitive = TRUE;
+        }
+      else
+        {
+          page = 2;
+          tooltip = button->priv->tooltip_not_authorized;
+          sensitive = FALSE;
+        }
+    }
+
+  if (g_permission_get_allowed (priv->permission))
+    {
+      gchar *names[3];
+
+      names[0] = "changes-allow-symbolic";
+      names[1] = "changes-allow";
+      names[2] = NULL;
+      icon = g_themed_icon_new_from_names (names, -1);
+    }
+  else
+    {
+      gchar *names[3];
+
+      names[0] = "changes-prevent-symbolic";
+      names[1] = "changes-prevent";
+      names[2] = NULL;
+      icon = g_themed_icon_new_from_names (names, -1);
+    }
+
+  gtk_image_set_from_gicon (GTK_IMAGE (priv->image), icon, GTK_ICON_SIZE_BUTTON);
+  g_object_unref (icon);
+
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), page);
+  gtk_widget_set_tooltip_markup (priv->box, tooltip);
+
+  gtk_widget_set_sensitive (priv->box, sensitive);
+
+  if (visible)
+    gtk_widget_show (priv->box);
+  else
+    gtk_widget_hide (priv->box);
+}
+
+static void
+on_permission_changed (GPermission *permission,
+                       GParamSpec  *pspec,
+                       gpointer     user_data)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (user_data);
+
+  update_state (button);
+}
+
+static void
+acquire_cb (GObject      *source,
+            GAsyncResult *result,
+            gpointer      user_data)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (user_data);
+  DtLockButtonPrivate *priv = button->priv;
+  GError *error;
+
+  error = NULL;
+  g_permission_acquire_finish (priv->permission, result, &error);
+
+  if (error)
+    {
+      g_warning ("Error acquiring permission: %s", error->message);
+      g_error_free (error);
+    }
+
+  g_object_unref (priv->cancellable);
+  priv->cancellable = NULL;
+
+  update_state (button);
+}
+
+static void
+release_cb (GObject      *source,
+            GAsyncResult *result,
+            gpointer      user_data)
+{
+  DtLockButton *button = DT_LOCK_BUTTON (user_data);
+  DtLockButtonPrivate *priv = button->priv;
+  GError *error;
+
+  error = NULL;
+  g_permission_release_finish (priv->permission, result, &error);
+
+  if (error)
+    {
+      g_warning ("Error releasing permission: %s", error->message);
+      g_error_free (error);
+    }
+
+  g_object_unref (priv->cancellable);
+  priv->cancellable = NULL;
+
+  update_state (button);
+}
+
+static void
+handle_click (DtLockButton *button)
+{
+  DtLockButtonPrivate *priv = button->priv;
+
+  if (!g_permission_get_allowed (priv->permission) &&
+       g_permission_get_can_acquire (priv->permission))
+    {
+      /* if we already have a pending interactive check, then do nothing */
+      if (priv->cancellable != NULL)
+        goto out;
+
+      priv->cancellable = g_cancellable_new ();
+
+      g_permission_acquire_async (priv->permission,
+                                  priv->cancellable,
+                                  acquire_cb,
+                                  button);
+    }
+  else if (g_permission_get_allowed (priv->permission) &&
+           g_permission_get_can_release (priv->permission))
+    {
+      /* if we already have a pending interactive check, then do nothing */
+      if (priv->cancellable != NULL)
+        goto out;
+
+      priv->cancellable = g_cancellable_new ();
+
+      g_permission_release_async (priv->permission,
+                                  priv->cancellable,
+                                  release_cb,
+                                  button);
+    }
+
+ out: ;
+}
+
+static void
+on_clicked (GtkButton *_button,
+            gpointer   user_data)
+
+{
+  handle_click (DT_LOCK_BUTTON (user_data));
+}
+
+static void
+on_button_press (GtkWidget      *widget,
+                 GdkEventButton *event,
+                 gpointer        user_data)
+{
+  handle_click (DT_LOCK_BUTTON (user_data));
+}
+
+/**
+ * dt_lock_button_get_permission:
+ * @button: a #DtLockButton
+ *
+ * Obtains the #GPermission object that controls @button.
+ *
+ * Returns: the #GPermission of @button
+ *
+ * Since: 3.0
+ */
+GPermission *
+dt_lock_button_get_permission (DtLockButton *button)
+{
+  g_return_val_if_fail (DT_IS_LOCK_BUTTON (button), NULL);
+
+  return button->priv->permission;
+}
+
diff --git a/libmap/dt-lockbutton.h b/libmap/dt-lockbutton.h
new file mode 100644
index 0000000..adab0a7
--- /dev/null
+++ b/libmap/dt-lockbutton.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Author: Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DT_LOCK_BUTTON_H__
+#define __DT_LOCK_BUTTON_H__
+
+#include 
+#include 
+
+G_BEGIN_DECLS
+
+#define DT_TYPE_LOCK_BUTTON         (dt_lock_button_get_type ())
+#define DT_LOCK_BUTTON(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), DT_TYPE_LOCK_BUTTON, DtLockButton))
+#define DT_LOCK_BUTTON_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), DT_LOCK_BUTTON,  DtLockButtonClass))
+#define DT_IS_LOCK_BUTTON(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), DT_TYPE_LOCK_BUTTON))
+#define DT_IS_LOCK_BUTTON_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), DT_TYPE_LOCK_BUTTON))
+#define DT_LOCK_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DT_TYPE_LOCK_BUTTON, DtLockButtonClass))
+
+typedef struct _DtLockButton        DtLockButton;
+typedef struct _DtLockButtonClass   DtLockButtonClass;
+typedef struct _DtLockButtonPrivate DtLockButtonPrivate;
+
+struct _DtLockButton
+{
+  GtkBin parent;
+
+  DtLockButtonPrivate *priv;
+};
+
+struct _DtLockButtonClass
+{
+  GtkBinClass parent_class;
+
+  void (*reserved0) (void);
+  void (*reserved1) (void);
+  void (*reserved2) (void);
+  void (*reserved3) (void);
+  void (*reserved4) (void);
+  void (*reserved5) (void);
+  void (*reserved6) (void);
+  void (*reserved7) (void);
+};
+
+GType        dt_lock_button_get_type       (void) G_GNUC_CONST;
+GtkWidget   *dt_lock_button_new            (GPermission   *permission);
+GPermission *dt_lock_button_get_permission (DtLockButton *button);
+
+
+G_END_DECLS
+
+#endif  /* __DT_LOCK_BUTTON_H__ */
diff --git a/libmap/set-timezone.c b/libmap/set-timezone.c
new file mode 100644
index 0000000..5aafced
--- /dev/null
+++ b/libmap/set-timezone.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen 
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "set-timezone.h"
+
+
+static DBusGConnection *
+get_system_bus (GError **err)
+{
+        GError          *error;
+        static DBusGConnection *bus = NULL;
+
+	if (bus == NULL) {
+        	error = NULL;
+        	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        	if (bus == NULL) {
+			g_propagate_error (err, error);
+		}
+        }
+
+        return bus;
+}
+
+#define CACHE_VALIDITY_SEC 2
+
+typedef  void (*CanDoFunc) (gint value);
+
+static void
+notify_can_do (DBusGProxy     *proxy,
+	       DBusGProxyCall *call,
+	       void           *user_data)
+{
+	CanDoFunc callback = user_data;
+	GError *error = NULL;
+	gint value;
+
+	if (dbus_g_proxy_end_call (proxy, call,
+				   &error,
+				   G_TYPE_INT, &value,
+				   G_TYPE_INVALID)) {
+		callback (value);
+	}
+}
+
+static void
+refresh_can_do (const gchar *action, CanDoFunc callback)
+{
+        DBusGConnection *bus;
+        DBusGProxy      *proxy;
+
+        bus = get_system_bus (NULL);
+        if (bus == NULL)
+                return;
+
+	proxy = dbus_g_proxy_new_for_name (bus,
+					   "org.gnome.SettingsDaemon.DateTimeMechanism",
+					   "/",
+					   "org.gnome.SettingsDaemon.DateTimeMechanism");
+
+	dbus_g_proxy_begin_call_with_timeout (proxy,
+					      action,
+					      notify_can_do,
+					      callback, NULL,
+					      INT_MAX,
+					      G_TYPE_INVALID);
+}
+
+static gint   settimezone_cache = 0;
+static time_t settimezone_stamp = 0;
+
+static void
+update_can_settimezone (gint res)
+{
+	settimezone_cache = res;
+	time (&settimezone_stamp);
+}
+
+gint
+can_set_system_timezone (void)
+{
+	time_t          now;
+
+	time (&now);
+	if (ABS (now - settimezone_stamp) > CACHE_VALIDITY_SEC) {
+		refresh_can_do ("CanSetTimezone", update_can_settimezone);
+		settimezone_stamp = now;
+	}
+
+	return settimezone_cache;
+}
+
+static gint   settime_cache = 0;
+static time_t settime_stamp = 0;
+
+static void
+update_can_settime (gint res)
+{
+	settime_cache = res;
+	time (&settime_stamp);
+}
+
+gint
+can_set_system_time (void)
+{
+	time_t now;
+
+	time (&now);
+	if (ABS (now - settime_stamp) > CACHE_VALIDITY_SEC) {
+		refresh_can_do ("CanSetTime", update_can_settime);
+		settime_stamp = now;
+	}
+
+	return settime_cache;
+}
+
+static gint   usingntp_cache = 0;
+static time_t usingntp_stamp = 0;
+
+static void
+update_can_usingntp (gint res)
+{
+	usingntp_cache = res;
+	time (&usingntp_stamp);
+}
+
+gint
+can_set_using_ntp (void)
+{
+	time_t now;
+
+	time (&now);
+	if (ABS (now - usingntp_stamp) > CACHE_VALIDITY_SEC) {
+		refresh_can_do ("CanSetUsingNtp", update_can_usingntp);
+		settime_stamp = now;
+	}
+
+	return usingntp_cache;
+}
+
+typedef struct {
+	gint ref_count;
+        gchar *call;
+	gint64 time;
+	gchar *tz;
+	gboolean using_ntp;
+	GFunc callback;
+	gpointer data;
+	GDestroyNotify notify;
+} SetTimeCallbackData;
+
+static void
+free_data (gpointer d)
+{
+	SetTimeCallbackData *data = d;
+
+	data->ref_count--;
+	if (data->ref_count == 0) {
+		if (data->notify)
+			data->notify (data->data);
+		g_free (data->tz);
+		g_free (data);
+	}
+}
+
+static void
+set_time_notify (DBusGProxy     *proxy,
+		 DBusGProxyCall *call,
+		 void           *user_data)
+{
+	SetTimeCallbackData *data = user_data;
+	GError *error = NULL;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) {
+		if (data->callback)
+			data->callback (data->data, NULL);
+	}
+	else {
+		if (error->domain == DBUS_GERROR &&
+		    error->code == DBUS_GERROR_NO_REPLY) {
+			/* these errors happen because dbus doesn't
+			 * use monotonic clocks
+			 */	
+			g_warning ("ignoring no-reply error when setting time");
+			g_error_free (error);
+			if (data->callback)
+				data->callback (data->data, NULL);
+		}
+		else {
+			if (data->callback)
+				data->callback (data->data, error);
+			else
+				g_error_free (error);
+		}		
+	}
+}
+
+static void
+set_time_async (SetTimeCallbackData *data)
+{
+        DBusGConnection *bus;
+        DBusGProxy      *proxy;
+	GError          *err = NULL;
+
+        bus = get_system_bus (&err);
+        if (bus == NULL) {
+		if (err) {
+			if (data->callback)
+				data->callback (data->data, err);
+			g_clear_error (&err);
+		}
+		return;
+	}
+
+	proxy = dbus_g_proxy_new_for_name (bus,
+					   "org.gnome.SettingsDaemon.DateTimeMechanism",
+					   "/",
+					   "org.gnome.SettingsDaemon.DateTimeMechanism");
+
+	data->ref_count++;
+	if (strcmp (data->call, "SetTime") == 0)
+		dbus_g_proxy_begin_call_with_timeout (proxy,
+						      "SetTime",
+						      set_time_notify,
+						      data, free_data,
+						      INT_MAX,
+						      /* parameters: */
+						      G_TYPE_INT64, data->time,
+						      G_TYPE_INVALID,
+						      /* return values: */
+						      G_TYPE_INVALID);
+	else if (strcmp (data->call, "SetTimezone") == 0)
+		dbus_g_proxy_begin_call_with_timeout (proxy,
+						      "SetTimezone",
+						      set_time_notify,
+						      data, free_data,
+						      INT_MAX,
+						      /* parameters: */
+						      G_TYPE_STRING, data->tz,
+						      G_TYPE_INVALID,
+						      /* return values: */
+						      G_TYPE_INVALID);
+	else if (strcmp (data->call, "SetUsingNtp") == 0)
+		dbus_g_proxy_begin_call_with_timeout (proxy,
+						      "SetUsingNtp",
+						      set_time_notify,
+						      data, free_data,
+						      INT_MAX,
+						      /* parameters: */
+						      G_TYPE_BOOLEAN, data->using_ntp,
+						      G_TYPE_INVALID,
+						      /* return values: */
+						      G_TYPE_INVALID);
+}
+
+void
+set_system_time_async (gint64         time,
+		       GFunc          callback,
+		       gpointer       d,
+		       GDestroyNotify notify)
+{
+	SetTimeCallbackData *data;
+
+	if (time == -1)
+		return;
+
+	data = g_new0 (SetTimeCallbackData, 1);
+	data->ref_count = 1;
+	data->call = "SetTime";
+	data->time = time;
+	data->tz = NULL;
+	data->callback = callback;
+	data->data = d;
+	data->notify = notify;
+
+	set_time_async (data);
+	free_data (data);
+}
+
+void
+set_system_timezone_async (const gchar    *tz,
+			   GFunc           callback,
+			   gpointer        d,
+			   GDestroyNotify  notify)
+{
+	SetTimeCallbackData *data;
+
+	g_return_if_fail (tz != NULL);
+
+	data = g_new0 (SetTimeCallbackData, 1);
+	data->ref_count = 1;
+	data->call = "SetTimezone";
+	data->time = -1;
+	data->tz = g_strdup (tz);
+	data->callback = callback;
+	data->data = d;
+	data->notify = notify;
+
+	set_time_async (data);
+	free_data (data);
+}
+
+/* get timezone */
+
+typedef struct
+{
+  GetTimezoneFunc callback;
+  GDestroyNotify notify;
+
+  gpointer data;
+
+} GetTimezoneData;
+
+static void
+get_timezone_destroy_notify (GetTimezoneData *data)
+{
+	if (data->notify && data->data)
+		data->notify (data);
+
+	g_free (data);
+}
+
+static void
+get_timezone_notify (DBusGProxy     *proxy,
+		     DBusGProxyCall *call,
+		     void           *user_data)
+{
+	GError *error = NULL;
+	gboolean retval;
+	gchar *string = NULL;
+	GetTimezoneData *data = user_data;
+
+	retval = dbus_g_proxy_end_call (proxy, call, &error,
+					G_TYPE_STRING, &string,
+					G_TYPE_INVALID);
+
+	if (data->callback) {
+		if (!retval) {
+			data->callback (data->data, NULL, error);
+			g_error_free (error);
+		}
+		else {
+			data->callback (data->data, string, NULL);
+			g_free (string);
+		}
+	}
+}
+
+void
+get_system_timezone_async (GetTimezoneFunc callback,
+			   gpointer        user_data,
+			   GDestroyNotify  notify)
+{
+	DBusGConnection *bus;
+	DBusGProxy      *proxy;
+	GetTimezoneData *data;
+	GError          *error = NULL;
+
+	bus = get_system_bus (&error);
+	if (bus == NULL) {
+		if (error) {
+			if (callback)
+				callback (user_data, NULL, error);
+			g_clear_error (&error);
+		}
+		return;
+
+        }
+
+	data = g_new0 (GetTimezoneData, 1);
+	data->data = user_data;
+	data->notify = notify;
+	data->callback = callback;
+
+	proxy = dbus_g_proxy_new_for_name (bus,
+					   "org.gnome.SettingsDaemon.DateTimeMechanism",
+					   "/",
+					   "org.gnome.SettingsDaemon.DateTimeMechanism");
+
+	dbus_g_proxy_begin_call (proxy,
+				 "GetTimezone",
+				 get_timezone_notify,
+				 data,
+				 (GDestroyNotify) get_timezone_destroy_notify,
+				 /* parameters: */
+				 G_TYPE_INVALID,
+				 /* return values: */
+				 G_TYPE_STRING,
+				 G_TYPE_INVALID);
+
+}
+
+gboolean
+get_using_ntp (void)
+{
+	static gboolean can_use_cache = FALSE;
+	static gboolean is_using_cache = FALSE;
+	static time_t   last_refreshed = 0;
+	time_t          now;
+        DBusGConnection *bus;
+        DBusGProxy      *proxy;
+
+	time (&now);
+	if (ABS (now - last_refreshed) > CACHE_VALIDITY_SEC) {
+		gboolean cu, iu;
+		bus = get_system_bus (NULL);
+		if (bus == NULL)
+			return FALSE;
+
+		proxy = dbus_g_proxy_new_for_name (bus,
+						   "org.gnome.SettingsDaemon.DateTimeMechanism",
+						   "/",
+						   "org.gnome.SettingsDaemon.DateTimeMechanism");
+
+
+		if (dbus_g_proxy_call (proxy,
+				       "GetUsingNtp",
+				       NULL,
+				       G_TYPE_INVALID,
+				       G_TYPE_BOOLEAN, &cu,
+				       G_TYPE_BOOLEAN, &iu,
+				       G_TYPE_INVALID)) {
+			can_use_cache = cu;
+			is_using_cache = iu;
+			last_refreshed = now;
+		}
+	}
+
+	return is_using_cache;
+}
+
+void
+set_using_ntp_async (gboolean        using_ntp,
+	             GFunc           callback,
+	             gpointer        d,
+	             GDestroyNotify  notify)
+{
+	SetTimeCallbackData *data;
+
+	data = g_new0 (SetTimeCallbackData, 1);
+	data->ref_count = 1;
+	data->call = "SetUsingNtp";
+	data->time = -1;
+	data->using_ntp = using_ntp;
+	data->callback = callback;
+	data->data = d;
+	data->notify = notify;
+
+	set_time_async (data);
+	free_data (data);
+}
diff --git a/libmap/set-timezone.h b/libmap/set-timezone.h
new file mode 100644
index 0000000..5e657e3
--- /dev/null
+++ b/libmap/set-timezone.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen 
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __SET_SYSTEM_TIMEZONE_H__
+
+#include 
+
+#include 
+#include 
+
+typedef void (*GetTimezoneFunc) (gpointer     data,
+                                 const gchar *timezone,
+                                 GError      *error);
+void     get_system_timezone_async   (GetTimezoneFunc callback,
+                                      gpointer        data,
+                                      GDestroyNotify  notify);
+
+gint     can_set_system_timezone (void);
+
+gint     can_set_system_time     (void);
+
+gint     can_set_using_ntp       (void);
+
+void     set_system_time_async   (gint64         time,
+                                  GFunc          callback,
+                                  gpointer       data,
+                                  GDestroyNotify notify);
+
+void     set_system_timezone_async   (const gchar    *tz,
+                                      GFunc           callback,
+                                      gpointer        data,
+                                      GDestroyNotify  notify);
+
+gboolean get_using_ntp               (void);
+
+void     set_using_ntp_async         (gboolean        using_ntp,
+                                      GFunc           callback,
+                                      gpointer        data,
+                                      GDestroyNotify  notify);
+#endif
diff --git a/libmap/test-timezone.c b/libmap/test-timezone.c
new file mode 100644
index 0000000..d667c42
--- /dev/null
+++ b/libmap/test-timezone.c
@@ -0,0 +1,55 @@
+#include 
+#include 
+
+#include "tz.h"
+
+int main (int argc, char **argv)
+{
+	TzDB *db;
+	GPtrArray *locs;
+	guint i;
+	char *pixmap_dir;
+	int retval = 0;
+
+        setlocale (LC_ALL, "");
+
+	if (argc == 2) {
+		pixmap_dir = g_strdup (argv[1]);
+	} else if (argc == 1) {
+		pixmap_dir = g_strdup ("data/");
+	} else {
+		g_message ("Usage: %s [PIXMAP DIRECTORY]", argv[0]);
+		return 1;
+	}
+
+	db = tz_load_db ();
+	locs = tz_get_locations (db);
+	for (i = 0; i < locs->len ; i++) {
+		TzLocation *loc = locs->pdata[i];
+		TzInfo *info;
+		char *filename, *path;
+		gdouble selected_offset;
+                char buf[16];
+
+		info = tz_info_from_location (loc);
+		selected_offset = tz_location_get_utc_offset (loc)
+			/ (60.0*60.0) + ((info->daylight) ? -1.0 : 0.0);
+
+		filename = g_strdup_printf ("timezone_%s.png",
+                                            g_ascii_formatd (buf, sizeof (buf),
+                                                             "%g", selected_offset));
+		path = g_build_filename (pixmap_dir, filename, NULL);
+
+		if (g_file_test (path, G_FILE_TEST_IS_REGULAR) == FALSE) {
+			g_message ("File '%s' missing for zone '%s'", filename, loc->zone);
+			retval = 1;
+		}
+
+		g_free (filename);
+		g_free (path);
+	}
+	tz_db_free (db);
+	g_free (pixmap_dir);
+
+	return retval;
+}
diff --git a/libmap/tz.c b/libmap/tz.c
new file mode 100644
index 0000000..3e6c8ae
--- /dev/null
+++ b/libmap/tz.c
@@ -0,0 +1,350 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Generic timezone utilities.
+ *
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Authors: Hans Petter Jansson 
+ * 
+ * Largely based on Michael Fulbright's work on Anaconda.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tz.h"
+
+
+/* Forward declarations for private functions */
+
+static float convert_pos (gchar *pos, int digits);
+static int compare_country_names (const void *a, const void *b);
+static void sort_locations_by_country (GPtrArray *locations);
+static gchar * tz_data_file_get (void);
+
+
+/* ---------------- *
+ * Public interface *
+ * ---------------- */
+TzDB *
+tz_load_db (void)
+{
+	gchar *tz_data_file;
+	TzDB *tz_db;
+	FILE *tzfile;
+	char buf[4096];
+
+	tz_data_file = tz_data_file_get ();
+	if (!tz_data_file) {
+		g_warning ("Could not get the TimeZone data file name");
+		return NULL;
+	}
+	tzfile = fopen (tz_data_file, "r");
+	if (!tzfile) {
+		g_warning ("Could not open *%s*\n", tz_data_file);
+		g_free (tz_data_file);
+		return NULL;
+	}
+
+	tz_db = g_new0 (TzDB, 1);
+	tz_db->locations = g_ptr_array_new ();
+
+	while (fgets (buf, sizeof(buf), tzfile))
+	{
+		gchar **tmpstrarr;
+		gchar *latstr, *lngstr, *p;
+		TzLocation *loc;
+
+		if (*buf == '#') continue;
+
+		g_strchomp(buf);
+		tmpstrarr = g_strsplit(buf,"\t", 6);
+		
+		latstr = g_strdup (tmpstrarr[1]);
+		p = latstr + 1;
+		while (*p != '-' && *p != '+') p++;
+		lngstr = g_strdup (p);
+		*p = '\0';
+		
+		loc = g_new0 (TzLocation, 1);
+		loc->country = g_strdup (tmpstrarr[0]);
+		loc->zone = g_strdup (tmpstrarr[2]);
+		loc->latitude  = convert_pos (latstr, 2);
+		loc->longitude = convert_pos (lngstr, 3);
+		
+#ifdef __sun
+		if (tmpstrarr[3] && *tmpstrarr[3] == '-' && tmpstrarr[4])
+			loc->comment = g_strdup (tmpstrarr[4]);
+
+		if (tmpstrarr[3] && *tmpstrarr[3] != '-' && !islower(loc->zone)) {
+			TzLocation *locgrp;
+
+			/* duplicate entry */
+			locgrp = g_new0 (TzLocation, 1);
+			locgrp->country = g_strdup (tmpstrarr[0]);
+			locgrp->zone = g_strdup (tmpstrarr[3]);
+			locgrp->latitude  = convert_pos (latstr, 2);
+			locgrp->longitude = convert_pos (lngstr, 3);
+			locgrp->comment = (tmpstrarr[4]) ? g_strdup (tmpstrarr[4]) : NULL;
+
+			g_ptr_array_add (tz_db->locations, (gpointer) locgrp);
+		}
+#else
+		loc->comment = (tmpstrarr[3]) ? g_strdup(tmpstrarr[3]) : NULL;
+#endif
+
+		g_ptr_array_add (tz_db->locations, (gpointer) loc);
+
+		g_free (latstr);
+		g_free (lngstr);
+		g_strfreev (tmpstrarr);
+	}
+	
+	fclose (tzfile);
+	
+	/* now sort by country */
+	sort_locations_by_country (tz_db->locations);
+	
+	g_free (tz_data_file);
+	
+	return tz_db;
+}    
+
+static void
+tz_location_free (TzLocation *loc)
+{
+	g_free (loc->country);
+	g_free (loc->zone);
+	g_free (loc->comment);
+
+	g_free (loc);
+}
+
+void
+tz_db_free (TzDB *db)
+{
+	g_ptr_array_foreach (db->locations, (GFunc) tz_location_free, NULL);
+	g_ptr_array_free (db->locations, TRUE);
+	g_free (db);
+}
+
+GPtrArray *
+tz_get_locations (TzDB *db)
+{
+	return db->locations;
+}
+
+
+gchar *
+tz_location_get_country (TzLocation *loc)
+{
+	return loc->country;
+}
+
+
+gchar *
+tz_location_get_zone (TzLocation *loc)
+{
+	return loc->zone;
+}
+
+
+gchar *
+tz_location_get_comment (TzLocation *loc)
+{
+	return loc->comment;
+}
+
+
+void
+tz_location_get_position (TzLocation *loc, double *longitude, double *latitude)
+{
+	*longitude = loc->longitude;
+	*latitude = loc->latitude;
+}
+
+glong
+tz_location_get_utc_offset (TzLocation *loc)
+{
+	TzInfo *tz_info;
+	glong offset;
+
+	tz_info = tz_info_from_location (loc);
+	offset = tz_info->utc_offset;
+	tz_info_free (tz_info);
+	return offset;
+}
+
+gint
+tz_location_set_locally (TzLocation *loc)
+{
+	time_t curtime;
+	struct tm *curzone;
+	gboolean is_dst = FALSE;
+	gint correction = 0;
+
+	g_return_val_if_fail (loc != NULL, 0);
+	g_return_val_if_fail (loc->zone != NULL, 0);
+	
+	curtime = time (NULL);
+	curzone = localtime (&curtime);
+	is_dst = curzone->tm_isdst;
+
+	setenv ("TZ", loc->zone, 1);
+#if 0
+	curtime = time (NULL);
+	curzone = localtime (&curtime);
+
+	if (!is_dst && curzone->tm_isdst) {
+		correction = (60 * 60);
+	}
+	else if (is_dst && !curzone->tm_isdst) {
+		correction = 0;
+	}
+#endif
+
+	return correction;
+}
+
+TzInfo *
+tz_info_from_location (TzLocation *loc)
+{
+	TzInfo *tzinfo;
+	time_t curtime;
+	struct tm *curzone;
+	
+	g_return_val_if_fail (loc != NULL, NULL);
+	g_return_val_if_fail (loc->zone != NULL, NULL);
+	
+	setenv ("TZ", loc->zone, 1);
+	
+#if 0
+	tzset ();
+#endif
+	tzinfo = g_new0 (TzInfo, 1);
+
+	curtime = time (NULL);
+	curzone = localtime (&curtime);
+
+#ifndef __sun
+	/* Currently this solution doesnt seem to work - I get that */
+	/* America/Phoenix uses daylight savings, which is wrong    */
+	tzinfo->tzname_normal = g_strdup (curzone->tm_zone);
+	if (curzone->tm_isdst) 
+		tzinfo->tzname_daylight =
+			g_strdup (&curzone->tm_zone[curzone->tm_isdst]);
+	else
+		tzinfo->tzname_daylight = NULL;
+
+	tzinfo->utc_offset = curzone->tm_gmtoff;
+#else
+	tzinfo->tzname_normal = NULL;
+	tzinfo->tzname_daylight = NULL;
+	tzinfo->utc_offset = 0;
+#endif
+
+	tzinfo->daylight = curzone->tm_isdst;
+	
+	return tzinfo;
+}
+
+
+void
+tz_info_free (TzInfo *tzinfo)
+{
+	g_return_if_fail (tzinfo != NULL);
+	
+	if (tzinfo->tzname_normal) g_free (tzinfo->tzname_normal);
+	if (tzinfo->tzname_daylight) g_free (tzinfo->tzname_daylight);
+	g_free (tzinfo);
+}
+
+/* ----------------- *
+ * Private functions *
+ * ----------------- */
+
+static gchar *
+tz_data_file_get (void)
+{
+	gchar *file;
+
+	file = g_strdup (TZ_DATA_FILE);
+
+	return file;
+}
+
+static float
+convert_pos (gchar *pos, int digits)
+{
+	gchar whole[10];
+	gchar *fraction;
+	gint i;
+	float t1, t2;
+	
+	if (!pos || strlen(pos) < 4 || digits > 9) return 0.0;
+	
+	for (i = 0; i < digits + 1; i++) whole[i] = pos[i];
+	whole[i] = '\0';
+	fraction = pos + digits + 1;
+
+	t1 = g_strtod (whole, NULL);
+	t2 = g_strtod (fraction, NULL);
+
+	if (t1 >= 0.0) return t1 + t2/pow (10.0, strlen(fraction));
+	else return t1 - t2/pow (10.0, strlen(fraction));
+}
+
+
+#if 0
+
+/* Currently not working */
+static void
+free_tzdata (TzLocation *tz)
+{
+	
+	if (tz->country)
+	  g_free(tz->country);
+	if (tz->zone)
+	  g_free(tz->zone);
+	if (tz->comment)
+	  g_free(tz->comment);
+	
+	g_free(tz);
+}
+#endif
+
+
+static int
+compare_country_names (const void *a, const void *b)
+{
+	const TzLocation *tza = * (TzLocation **) a;
+	const TzLocation *tzb = * (TzLocation **) b;
+	
+	return strcmp (tza->zone, tzb->zone);
+}
+
+
+static void
+sort_locations_by_country (GPtrArray *locations)
+{
+	qsort (locations->pdata, locations->len, sizeof (gpointer),
+	       compare_country_names);
+}
diff --git a/libmap/tz.h b/libmap/tz.h
new file mode 100644
index 0000000..91281a5
--- /dev/null
+++ b/libmap/tz.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Generic timezone utilities.
+ *
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Authors: Hans Petter Jansson 
+ * 
+ * Largely based on Michael Fulbright's work on Anaconda.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _E_TZ_H
+#define _E_TZ_H
+
+#include 
+
+#ifndef __sun
+#  define TZ_DATA_FILE "/usr/share/zoneinfo/zone.tab"
+#else
+#  define TZ_DATA_FILE "/usr/share/lib/zoneinfo/tab/zone_sun.tab"
+#endif
+
+typedef struct _TzDB TzDB;
+typedef struct _TzLocation TzLocation;
+typedef struct _TzInfo TzInfo;
+
+
+struct _TzDB
+{
+	GPtrArray *locations;
+};
+
+struct _TzLocation
+{
+	gchar *country;
+	gdouble latitude;
+	gdouble longitude;
+	gchar *zone;
+	gchar *comment;
+
+	gdouble dist; /* distance to clicked point for comparison */
+};
+
+/* see the glibc info page information on time zone information */
+/*  tzname_normal    is the default name for the timezone */
+/*  tzname_daylight  is the name of the zone when in daylight savings */
+/*  utc_offset       is offset in seconds from utc */
+/*  daylight         if non-zero then location obeys daylight savings */
+
+struct _TzInfo
+{
+	gchar *tzname_normal;
+	gchar *tzname_daylight;
+	glong utc_offset;
+	gint daylight;
+};
+
+
+TzDB      *tz_load_db                 (void);
+void       tz_db_free                 (TzDB *db);
+GPtrArray *tz_get_locations           (TzDB *db);
+void       tz_location_get_position   (TzLocation *loc,
+				       double *longitude, double *latitude);
+char      *tz_location_get_country    (TzLocation *loc);
+gchar     *tz_location_get_zone       (TzLocation *loc);
+gchar     *tz_location_get_comment    (TzLocation *loc);
+glong      tz_location_get_utc_offset (TzLocation *loc);
+gint       tz_location_set_locally    (TzLocation *loc);
+TzInfo    *tz_info_from_location      (TzLocation *loc);
+void       tz_info_free               (TzInfo *tz_info);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 94d179d..4c94f7c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,9 +49,11 @@ indicator_datetime_preferences_SOURCES =\
 indicator_datetime_preferences_CFLAGS = \
 	-Wall \
 	-Werror \
+	-I$(top_srcdir)/libmap \
 	$(PREF_CFLAGS) \
 	-DPKGDATADIR="\"$(pkgdatadir)\""
 indicator_datetime_preferences_LDADD = \
+	 $(top_builddir)/libmap/libmap.la \
 	$(PREF_LIBS)
 
 gen-%.xml.c: %.xml
diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index 97b106d..ee4b26a 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -36,10 +36,13 @@ with this program.  If not, see .
 #include "settings-shared.h"
 #include "utils.h"
 #include "datetime-prefs-locations.h"
+#include "cc-timezone-map.h"
 
 #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
 
 GDBusProxy * proxy = NULL;
+GtkWidget * autoRadio = NULL;
+CcTimezoneMap * tzmap = NULL;
 
 /* Turns the boolean property into a string gsettings */
 static GVariant *
@@ -120,7 +123,8 @@ add_polkit_dependency (GtkWidget * parent, GtkWidget * dependent)
   polkit_dependency_cb (parent, NULL, dependent);
 }
 
-void dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command)
+static void
+dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command)
 {
   GError * error = NULL;
   GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error);
@@ -135,15 +139,16 @@ void dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command)
 }
 
 static void
-toggle_ntp (GtkWidget * autoRadio, GParamSpec * pspec, gpointer user_data)
+toggle_ntp (GtkWidget * radio, GParamSpec * pspec, gpointer user_data)
 {
-  gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (autoRadio));
+  gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio));
 
   g_dbus_proxy_call (proxy, "SetUsingNtp", g_variant_new ("(b)", active),
                      G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "using_ntp");
 }
 
-void ntp_query_answered (GObject *object, GAsyncResult *res, gpointer autoRadio)
+static void
+ntp_query_answered (GObject *object, GAsyncResult *res, gpointer user_data)
 {
   GError * error = NULL;
   GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error);
@@ -160,12 +165,44 @@ void ntp_query_answered (GObject *object, GAsyncResult *res, gpointer autoRadio)
   gtk_widget_set_sensitive (GTK_WIDGET (autoRadio), can_use_ntp);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (autoRadio), is_using_ntp);
 
-  g_signal_connect (autoRadio, "notify::active", G_CALLBACK(toggle_ntp), NULL);
+  g_signal_connect (autoRadio, "notify::active", G_CALLBACK (toggle_ntp), NULL);
+
+  g_variant_unref (answers);
+}
+
+static void
+tz_changed (CcTimezoneMap * map, TzLocation * location)
+{
+  if (location == NULL)
+    return;
+
+  g_dbus_proxy_call (proxy, "SetTimezone", g_variant_new ("(s)", location->zone),
+                     G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "timezone");
+}
+
+static void
+tz_query_answered (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  GError * error = NULL;
+  GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error);
+
+  if (error != NULL) {
+    g_warning("Could not query DBus proxy for SettingsDaemon: %s", error->message);
+    g_error_free(error);
+    return;
+  }
+
+  const gchar * timezone;
+  g_variant_get (answers, "(&s)", &timezone);
+
+  cc_timezone_map_set_timezone (tzmap, timezone);
+
+  g_signal_connect (tzmap, "location-changed", G_CALLBACK (tz_changed), NULL);
 
   g_variant_unref (answers);
 }
 
-void proxy_ready (GObject *object, GAsyncResult *res, gpointer autoRadio)
+void proxy_ready (GObject *object, GAsyncResult *res, gpointer user_data)
 {
   GError * error = NULL;
 
@@ -180,6 +217,8 @@ void proxy_ready (GObject *object, GAsyncResult *res, gpointer autoRadio)
   /* And now, do initial proxy configuration */
   g_dbus_proxy_call (proxy, "GetUsingNtp", NULL, G_DBUS_CALL_FLAGS_NONE, -1,
                      NULL, ntp_query_answered, autoRadio);
+  g_dbus_proxy_call (proxy, "GetTimezone", NULL, G_DBUS_CALL_FLAGS_NONE, -1,
+                     NULL, tz_query_answered, NULL);
 }
 
 static int
@@ -358,6 +397,10 @@ create_dialog (void)
   polkit_lock_button_set_lock_text (POLKIT_LOCK_BUTTON (polkit_button), _("Lock to prevent further changes"));
   gtk_box_pack_start (GTK_BOX (WIG ("timeDateBox")), polkit_button, FALSE, TRUE, 0);
 
+  /* Add map */
+  tzmap = cc_timezone_map_new ();
+  gtk_container_add (GTK_CONTAINER (WIG ("mapBox")), GTK_WIDGET (tzmap));
+
   /* Set up settings bindings */
   g_settings_bind (conf, SETTINGS_SHOW_CLOCK_S, WIG ("showClockCheck"),
                    "active", G_SETTINGS_BIND_DEFAULT);
@@ -404,6 +447,7 @@ create_dialog (void)
   setup_time_spinner (WIG ("dateSpinner"), WIG ("timeSpinner"), FALSE);
 
   GtkWidget * dlg = WIG ("timeDateDialog");
+  autoRadio = WIG ("automaticTimeRadio");
 
   g_signal_connect (WIG ("locationsButton"), "clicked", G_CALLBACK (show_locations), dlg);
 
@@ -412,7 +456,7 @@ create_dialog (void)
                             "org.gnome.SettingsDaemon.DateTimeMechanism",
                             "/",                            
                             "org.gnome.SettingsDaemon.DateTimeMechanism",
-                            NULL, proxy_ready, WIG ("automaticTimeRadio"));
+                            NULL, proxy_ready, NULL);
 
 #undef WIG
 
-- 
cgit v1.2.3


From 9265799709d7c1090ffef4082f4485c0d9a5c363 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Tue, 22 Feb 2011 11:22:17 -0500
Subject: drop some unused code from libmap

---
 libmap/datetime-module.c |  46 ----
 libmap/dt-lockbutton.c   | 627 -----------------------------------------------
 libmap/dt-lockbutton.h   |  68 -----
 libmap/set-timezone.c    | 481 ------------------------------------
 libmap/set-timezone.h    |  57 -----
 5 files changed, 1279 deletions(-)
 delete mode 100644 libmap/datetime-module.c
 delete mode 100644 libmap/dt-lockbutton.c
 delete mode 100644 libmap/dt-lockbutton.h
 delete mode 100644 libmap/set-timezone.c
 delete mode 100644 libmap/set-timezone.h

diff --git a/libmap/datetime-module.c b/libmap/datetime-module.c
deleted file mode 100644
index 8217dc3..0000000
--- a/libmap/datetime-module.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2010 Intel, Inc
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Author: Thomas Wood 
- *
- */
-
-#include 
-
-#include "cc-datetime-panel.h"
-
-#include 
-
-#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
-
-void
-g_io_module_load (GIOModule *module)
-{
-  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-
-  bindtextdomain (GETTEXT_PACKAGE_TIMEZONES, GNOMELOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE_TIMEZONES, "UTF-8");
-
-  /* register the panel */
-  cc_date_time_panel_register (module);
-}
-
-void
-g_io_module_unload (GIOModule *module)
-{
-}
diff --git a/libmap/dt-lockbutton.c b/libmap/dt-lockbutton.c
deleted file mode 100644
index ecf4c12..0000000
--- a/libmap/dt-lockbutton.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- * Author: Matthias Clasen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include "dt-lockbutton.h"
-
-#include 
-#include 
-
-#define P_(s) s
-
-struct _DtLockButtonPrivate
-{
-  GPermission *permission;
-
-  gchar *text_lock;
-  gchar *text_unlock;
-  gchar *text_not_authorized;
-
-  gchar *tooltip_lock;
-  gchar *tooltip_unlock;
-  gchar *tooltip_not_authorized;
-
-  GtkWidget *box;
-  GtkWidget *eventbox;
-  GtkWidget *image;
-  GtkWidget *button;
-  GtkWidget *notebook;
-
-  GtkWidget *label_lock;
-  GtkWidget *label_unlock;
-  GtkWidget *label_not_authorized;
-
-  GCancellable *cancellable;
-
-  gboolean constructed;
-};
-
-enum
-{
-  PROP_0,
-  PROP_PERMISSION,
-  PROP_TEXT_LOCK,
-  PROP_TEXT_UNLOCK,
-  PROP_TEXT_NOT_AUTHORIZED,
-  PROP_TOOLTIP_LOCK,
-  PROP_TOOLTIP_UNLOCK,
-  PROP_TOOLTIP_NOT_AUTHORIZED
-};
-
-static void update_state (DtLockButton *button);
-
-static void on_permission_changed (GPermission *permission,
-                                   GParamSpec  *pspec,
-                                   gpointer     user_data);
-
-static void on_clicked (GtkButton *button,
-                        gpointer   user_data);
-
-static void on_button_press (GtkWidget      *widget,
-                             GdkEventButton *event,
-                             gpointer        user_data);
-
-G_DEFINE_TYPE (DtLockButton, dt_lock_button, GTK_TYPE_BIN);
-
-static void
-dt_lock_button_finalize (GObject *object)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (object);
-  DtLockButtonPrivate *priv = button->priv;
-
-  g_free (priv->text_lock);
-  g_free (priv->text_unlock);
-  g_free (priv->text_not_authorized);
-
-  g_free (priv->tooltip_lock);
-  g_free (priv->tooltip_unlock);
-  g_free (priv->tooltip_not_authorized);
-
-  if (priv->cancellable != NULL)
-    {
-      g_cancellable_cancel (priv->cancellable);
-      g_object_unref (priv->cancellable);
-    }
-
-  g_signal_handlers_disconnect_by_func (priv->permission,
-                                        on_permission_changed,
-                                        button);
-
-  g_object_unref (priv->permission);
-
-  G_OBJECT_CLASS (dt_lock_button_parent_class)->finalize (object);
-}
-
-static void
-dt_lock_button_get_property (GObject    *object,
-                             guint       property_id,
-                             GValue     *value,
-                             GParamSpec *pspec)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (object);
-  DtLockButtonPrivate *priv = button->priv;
-
-  switch (property_id)
-    {
-    case PROP_PERMISSION:
-      g_value_set_object (value, priv->permission);
-      break;
-
-    case PROP_TEXT_LOCK:
-      g_value_set_string (value, priv->text_lock);
-      break;
-
-    case PROP_TEXT_UNLOCK:
-      g_value_set_string (value, priv->text_unlock);
-      break;
-
-    case PROP_TEXT_NOT_AUTHORIZED:
-      g_value_set_string (value, priv->text_not_authorized);
-      break;
-
-    case PROP_TOOLTIP_LOCK:
-      g_value_set_string (value, priv->tooltip_lock);
-      break;
-
-    case PROP_TOOLTIP_UNLOCK:
-      g_value_set_string (value, priv->tooltip_unlock);
-      break;
-
-    case PROP_TOOLTIP_NOT_AUTHORIZED:
-      g_value_set_string (value, priv->tooltip_not_authorized);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-    }
-}
-
-static void
-dt_lock_button_set_property (GObject      *object,
-                             guint         property_id,
-                             const GValue *value,
-                             GParamSpec   *pspec)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (object);
-  DtLockButtonPrivate *priv = button->priv;
-
-  switch (property_id)
-    {
-    case PROP_PERMISSION:
-      priv->permission = g_value_get_object (value);
-      break;
-
-    case PROP_TEXT_LOCK:
-      g_free (priv->text_lock);
-      priv->text_lock = g_value_dup_string (value);
-      break;
-
-    case PROP_TEXT_UNLOCK:
-      g_free (priv->text_unlock);
-      priv->text_unlock = g_value_dup_string (value);
-      break;
-
-    case PROP_TEXT_NOT_AUTHORIZED:
-      g_free (priv->text_not_authorized);
-      priv->text_not_authorized = g_value_dup_string (value);
-      break;
-
-    case PROP_TOOLTIP_LOCK:
-      g_free (priv->tooltip_lock);
-      priv->tooltip_lock = g_value_dup_string (value);
-      break;
-
-    case PROP_TOOLTIP_UNLOCK:
-      g_free (priv->tooltip_unlock);
-      priv->tooltip_unlock = g_value_dup_string (value);
-      break;
-
-    case PROP_TOOLTIP_NOT_AUTHORIZED:
-      g_free (priv->tooltip_not_authorized);
-      priv->tooltip_not_authorized = g_value_dup_string (value);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-    }
-
-  if (priv->constructed)
-    update_state (button);
-}
-
-static void
-dt_lock_button_init (DtLockButton *button)
-{
-  button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
-                                              DT_TYPE_LOCK_BUTTON,
-                                              DtLockButtonPrivate);
-}
-
-static void
-dt_lock_button_constructed (GObject *object)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (object);
-  DtLockButtonPrivate *priv = button->priv;
-
-  priv->constructed = TRUE;
-
-  g_signal_connect (priv->permission, "notify",
-                    G_CALLBACK (on_permission_changed), button);
-
-  priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-  gtk_container_add (GTK_CONTAINER (button), priv->box);
-
-  priv->eventbox = gtk_event_box_new ();
-  gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->eventbox), FALSE);
-  gtk_container_add (GTK_CONTAINER (priv->box), priv->eventbox);
-  gtk_widget_show (priv->eventbox);
-
-  priv->image = gtk_image_new (); /* image is set in update_state() */
-  gtk_container_add (GTK_CONTAINER (priv->eventbox), priv->image);
-  gtk_widget_show (priv->image);
-
-  priv->notebook = gtk_notebook_new ();
-  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
-  gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
-  gtk_widget_show (priv->notebook);
-
-  priv->button = gtk_button_new ();
-  gtk_container_add (GTK_CONTAINER (priv->button), priv->notebook);
-  gtk_widget_show (priv->button);
-
-  priv->label_lock = gtk_label_new (""); /* text is set in update_state */
-  gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->label_lock, NULL);
-  gtk_widget_show (priv->label_lock);
-
-  priv->label_unlock = gtk_label_new ("");
-  gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->label_unlock, NULL);
-  gtk_widget_show (priv->label_unlock);
-
-  priv->label_not_authorized = gtk_label_new ("");
-  gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->label_not_authorized, NULL);
-  gtk_widget_show (priv->label_not_authorized);
-
-  gtk_box_pack_start (GTK_BOX (priv->box), priv->button, FALSE, FALSE, 0);
-  gtk_widget_show (priv->button);
-
-  g_signal_connect (priv->eventbox, "button-press-event",
-                    G_CALLBACK (on_button_press), button);
-  g_signal_connect (priv->button, "clicked",
-                    G_CALLBACK (on_clicked), button);
-
-  gtk_widget_set_no_show_all (priv->box, TRUE);
-
-  update_state (button);
-
-  if (G_OBJECT_CLASS (dt_lock_button_parent_class)->constructed != NULL)
-    G_OBJECT_CLASS (dt_lock_button_parent_class)->constructed (object);
-}
-
-static void
-dt_lock_button_get_preferred_width (GtkWidget *widget,
-                                    gint      *minimum,
-                                    gint      *natural)
-{
-  DtLockButtonPrivate *priv = DT_LOCK_BUTTON (widget)->priv;
-
-  gtk_widget_get_preferred_width (priv->box, minimum, natural);
-}
-
-static void
-dt_lock_button_get_preferred_height (GtkWidget *widget,
-                                     gint      *minimum,
-                                     gint      *natural)
-{
-  DtLockButtonPrivate *priv = DT_LOCK_BUTTON (widget)->priv;
-
-  gtk_widget_get_preferred_height (priv->box, minimum, natural);
-}
-
-static void
-dt_lock_button_size_allocate (GtkWidget     *widget,
-                              GtkAllocation *allocation)
-{
-  DtLockButtonPrivate *priv = DT_LOCK_BUTTON (widget)->priv;
-  GtkRequisition requisition;
-  GtkAllocation child_allocation;
-
-  gtk_widget_set_allocation (widget, allocation);
-  gtk_widget_get_preferred_size (priv->box, &requisition, NULL);
-  child_allocation.x = allocation->x;
-  child_allocation.y = allocation->y;
-  child_allocation.width = requisition.width;
-  child_allocation.height = requisition.height;
-  gtk_widget_size_allocate (priv->box, &child_allocation);
-}
-
-static void
-dt_lock_button_class_init (DtLockButtonClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
-  gobject_class->finalize     = dt_lock_button_finalize;
-  gobject_class->get_property = dt_lock_button_get_property;
-  gobject_class->set_property = dt_lock_button_set_property;
-  gobject_class->constructed  = dt_lock_button_constructed;
-
-  widget_class->get_preferred_width = dt_lock_button_get_preferred_width;
-  widget_class->get_preferred_height = dt_lock_button_get_preferred_height;
-  widget_class->size_allocate = dt_lock_button_size_allocate;
-
-  g_type_class_add_private (klass, sizeof (DtLockButtonPrivate));
-
-  g_object_class_install_property (gobject_class, PROP_PERMISSION,
-    g_param_spec_object ("permission",
-                         P_("Permission"),
-                         P_("The GPermission object controlling this button"),
-                         G_TYPE_PERMISSION,
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT_ONLY |
-                         G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TEXT_LOCK,
-    g_param_spec_string ("text-lock",
-                         P_("Lock Text"),
-                         P_("The text to display when prompting the user to lock"),
-                         _("Lock"),
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT |
-                         G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TEXT_UNLOCK,
-    g_param_spec_string ("text-unlock",
-                         P_("Unlock Text"),
-                         P_("The text to display when prompting the user to unlock"),
-                         _("Unlock"),
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT |
-                         G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TEXT_NOT_AUTHORIZED,
-    g_param_spec_string ("text-not-authorized",
-                         P_("Not Authorized Text"),
-                         P_("The text to display when prompting the user cannot obtain authorization"),
-                         _("Locked"),
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT |
-                         G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TOOLTIP_LOCK,
-    g_param_spec_string ("tooltip-lock",
-                         P_("Lock Tooltip"),
-                         P_("The tooltip to display when prompting the user to lock"),
-                         _("Dialog is unlocked.\nClick to prevent further changes"),
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT |
-                         G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TOOLTIP_UNLOCK,
-    g_param_spec_string ("tooltip-unlock",
-                         P_("Unlock Tooltip"),
-                         P_("The tooltip to display when prompting the user to unlock"),
-                         _("Dialog is locked.\nClick to make changes"),
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT |
-                         G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TOOLTIP_NOT_AUTHORIZED,
-    g_param_spec_string ("tooltip-not-authorized",
-                         P_("Not Authorized Tooltip"),
-                         P_("The tooltip to display when prompting the user cannot obtain authorization"),
-                         _("System policy prevents changes.\nContact your system administrator"),
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT |
-                         G_PARAM_STATIC_STRINGS));
-}
-
-/**
- * dt_lock_button_new:
- * @permission: a #GPermission
- *
- * Creates a new lock button which reflects the @permission.
- *
- * Returns: a new #DtLockButton
- *
- * Since: 3.0
- */
-GtkWidget *
-dt_lock_button_new (GPermission *permission)
-{
-  g_return_val_if_fail (permission != NULL, NULL);
-
-  return GTK_WIDGET (g_object_new (DT_TYPE_LOCK_BUTTON,
-                                   "permission", permission,
-                                   NULL));
-}
-
-static void
-update_state (DtLockButton *button)
-{
-  DtLockButtonPrivate *priv = button->priv;
-  gint page;
-  const gchar *tooltip;
-  gboolean sensitive;
-  gboolean visible;
-  GIcon *icon;
-
-  visible = TRUE;
-  sensitive = TRUE;
-
-  gtk_label_set_text (GTK_LABEL (priv->label_lock), priv->text_lock);
-  gtk_label_set_text (GTK_LABEL (priv->label_unlock), priv->text_unlock);
-  gtk_label_set_text (GTK_LABEL (priv->label_not_authorized), priv->text_not_authorized);
-
-  if (g_permission_get_allowed (priv->permission))
-    {
-      if (g_permission_get_can_release (priv->permission))
-        {
-          page = 0;
-          tooltip = priv->tooltip_lock;
-          sensitive = TRUE;
-        }
-      else
-        {
-          page = 0;
-          tooltip = "";
-          visible = FALSE;
-        }
-    }
-  else
-    {
-      if (g_permission_get_can_acquire (priv->permission))
-        {
-          page = 1;
-          tooltip = button->priv->tooltip_unlock;
-          sensitive = TRUE;
-        }
-      else
-        {
-          page = 2;
-          tooltip = button->priv->tooltip_not_authorized;
-          sensitive = FALSE;
-        }
-    }
-
-  if (g_permission_get_allowed (priv->permission))
-    {
-      gchar *names[3];
-
-      names[0] = "changes-allow-symbolic";
-      names[1] = "changes-allow";
-      names[2] = NULL;
-      icon = g_themed_icon_new_from_names (names, -1);
-    }
-  else
-    {
-      gchar *names[3];
-
-      names[0] = "changes-prevent-symbolic";
-      names[1] = "changes-prevent";
-      names[2] = NULL;
-      icon = g_themed_icon_new_from_names (names, -1);
-    }
-
-  gtk_image_set_from_gicon (GTK_IMAGE (priv->image), icon, GTK_ICON_SIZE_BUTTON);
-  g_object_unref (icon);
-
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), page);
-  gtk_widget_set_tooltip_markup (priv->box, tooltip);
-
-  gtk_widget_set_sensitive (priv->box, sensitive);
-
-  if (visible)
-    gtk_widget_show (priv->box);
-  else
-    gtk_widget_hide (priv->box);
-}
-
-static void
-on_permission_changed (GPermission *permission,
-                       GParamSpec  *pspec,
-                       gpointer     user_data)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (user_data);
-
-  update_state (button);
-}
-
-static void
-acquire_cb (GObject      *source,
-            GAsyncResult *result,
-            gpointer      user_data)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (user_data);
-  DtLockButtonPrivate *priv = button->priv;
-  GError *error;
-
-  error = NULL;
-  g_permission_acquire_finish (priv->permission, result, &error);
-
-  if (error)
-    {
-      g_warning ("Error acquiring permission: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_object_unref (priv->cancellable);
-  priv->cancellable = NULL;
-
-  update_state (button);
-}
-
-static void
-release_cb (GObject      *source,
-            GAsyncResult *result,
-            gpointer      user_data)
-{
-  DtLockButton *button = DT_LOCK_BUTTON (user_data);
-  DtLockButtonPrivate *priv = button->priv;
-  GError *error;
-
-  error = NULL;
-  g_permission_release_finish (priv->permission, result, &error);
-
-  if (error)
-    {
-      g_warning ("Error releasing permission: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_object_unref (priv->cancellable);
-  priv->cancellable = NULL;
-
-  update_state (button);
-}
-
-static void
-handle_click (DtLockButton *button)
-{
-  DtLockButtonPrivate *priv = button->priv;
-
-  if (!g_permission_get_allowed (priv->permission) &&
-       g_permission_get_can_acquire (priv->permission))
-    {
-      /* if we already have a pending interactive check, then do nothing */
-      if (priv->cancellable != NULL)
-        goto out;
-
-      priv->cancellable = g_cancellable_new ();
-
-      g_permission_acquire_async (priv->permission,
-                                  priv->cancellable,
-                                  acquire_cb,
-                                  button);
-    }
-  else if (g_permission_get_allowed (priv->permission) &&
-           g_permission_get_can_release (priv->permission))
-    {
-      /* if we already have a pending interactive check, then do nothing */
-      if (priv->cancellable != NULL)
-        goto out;
-
-      priv->cancellable = g_cancellable_new ();
-
-      g_permission_release_async (priv->permission,
-                                  priv->cancellable,
-                                  release_cb,
-                                  button);
-    }
-
- out: ;
-}
-
-static void
-on_clicked (GtkButton *_button,
-            gpointer   user_data)
-
-{
-  handle_click (DT_LOCK_BUTTON (user_data));
-}
-
-static void
-on_button_press (GtkWidget      *widget,
-                 GdkEventButton *event,
-                 gpointer        user_data)
-{
-  handle_click (DT_LOCK_BUTTON (user_data));
-}
-
-/**
- * dt_lock_button_get_permission:
- * @button: a #DtLockButton
- *
- * Obtains the #GPermission object that controls @button.
- *
- * Returns: the #GPermission of @button
- *
- * Since: 3.0
- */
-GPermission *
-dt_lock_button_get_permission (DtLockButton *button)
-{
-  g_return_val_if_fail (DT_IS_LOCK_BUTTON (button), NULL);
-
-  return button->priv->permission;
-}
-
diff --git a/libmap/dt-lockbutton.h b/libmap/dt-lockbutton.h
deleted file mode 100644
index adab0a7..0000000
--- a/libmap/dt-lockbutton.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- * Author: Matthias Clasen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __DT_LOCK_BUTTON_H__
-#define __DT_LOCK_BUTTON_H__
-
-#include 
-#include 
-
-G_BEGIN_DECLS
-
-#define DT_TYPE_LOCK_BUTTON         (dt_lock_button_get_type ())
-#define DT_LOCK_BUTTON(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), DT_TYPE_LOCK_BUTTON, DtLockButton))
-#define DT_LOCK_BUTTON_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), DT_LOCK_BUTTON,  DtLockButtonClass))
-#define DT_IS_LOCK_BUTTON(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), DT_TYPE_LOCK_BUTTON))
-#define DT_IS_LOCK_BUTTON_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), DT_TYPE_LOCK_BUTTON))
-#define DT_LOCK_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DT_TYPE_LOCK_BUTTON, DtLockButtonClass))
-
-typedef struct _DtLockButton        DtLockButton;
-typedef struct _DtLockButtonClass   DtLockButtonClass;
-typedef struct _DtLockButtonPrivate DtLockButtonPrivate;
-
-struct _DtLockButton
-{
-  GtkBin parent;
-
-  DtLockButtonPrivate *priv;
-};
-
-struct _DtLockButtonClass
-{
-  GtkBinClass parent_class;
-
-  void (*reserved0) (void);
-  void (*reserved1) (void);
-  void (*reserved2) (void);
-  void (*reserved3) (void);
-  void (*reserved4) (void);
-  void (*reserved5) (void);
-  void (*reserved6) (void);
-  void (*reserved7) (void);
-};
-
-GType        dt_lock_button_get_type       (void) G_GNUC_CONST;
-GtkWidget   *dt_lock_button_new            (GPermission   *permission);
-GPermission *dt_lock_button_get_permission (DtLockButton *button);
-
-
-G_END_DECLS
-
-#endif  /* __DT_LOCK_BUTTON_H__ */
diff --git a/libmap/set-timezone.c b/libmap/set-timezone.c
deleted file mode 100644
index 5aafced..0000000
--- a/libmap/set-timezone.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007 David Zeuthen 
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "set-timezone.h"
-
-
-static DBusGConnection *
-get_system_bus (GError **err)
-{
-        GError          *error;
-        static DBusGConnection *bus = NULL;
-
-	if (bus == NULL) {
-        	error = NULL;
-        	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-        	if (bus == NULL) {
-			g_propagate_error (err, error);
-		}
-        }
-
-        return bus;
-}
-
-#define CACHE_VALIDITY_SEC 2
-
-typedef  void (*CanDoFunc) (gint value);
-
-static void
-notify_can_do (DBusGProxy     *proxy,
-	       DBusGProxyCall *call,
-	       void           *user_data)
-{
-	CanDoFunc callback = user_data;
-	GError *error = NULL;
-	gint value;
-
-	if (dbus_g_proxy_end_call (proxy, call,
-				   &error,
-				   G_TYPE_INT, &value,
-				   G_TYPE_INVALID)) {
-		callback (value);
-	}
-}
-
-static void
-refresh_can_do (const gchar *action, CanDoFunc callback)
-{
-        DBusGConnection *bus;
-        DBusGProxy      *proxy;
-
-        bus = get_system_bus (NULL);
-        if (bus == NULL)
-                return;
-
-	proxy = dbus_g_proxy_new_for_name (bus,
-					   "org.gnome.SettingsDaemon.DateTimeMechanism",
-					   "/",
-					   "org.gnome.SettingsDaemon.DateTimeMechanism");
-
-	dbus_g_proxy_begin_call_with_timeout (proxy,
-					      action,
-					      notify_can_do,
-					      callback, NULL,
-					      INT_MAX,
-					      G_TYPE_INVALID);
-}
-
-static gint   settimezone_cache = 0;
-static time_t settimezone_stamp = 0;
-
-static void
-update_can_settimezone (gint res)
-{
-	settimezone_cache = res;
-	time (&settimezone_stamp);
-}
-
-gint
-can_set_system_timezone (void)
-{
-	time_t          now;
-
-	time (&now);
-	if (ABS (now - settimezone_stamp) > CACHE_VALIDITY_SEC) {
-		refresh_can_do ("CanSetTimezone", update_can_settimezone);
-		settimezone_stamp = now;
-	}
-
-	return settimezone_cache;
-}
-
-static gint   settime_cache = 0;
-static time_t settime_stamp = 0;
-
-static void
-update_can_settime (gint res)
-{
-	settime_cache = res;
-	time (&settime_stamp);
-}
-
-gint
-can_set_system_time (void)
-{
-	time_t now;
-
-	time (&now);
-	if (ABS (now - settime_stamp) > CACHE_VALIDITY_SEC) {
-		refresh_can_do ("CanSetTime", update_can_settime);
-		settime_stamp = now;
-	}
-
-	return settime_cache;
-}
-
-static gint   usingntp_cache = 0;
-static time_t usingntp_stamp = 0;
-
-static void
-update_can_usingntp (gint res)
-{
-	usingntp_cache = res;
-	time (&usingntp_stamp);
-}
-
-gint
-can_set_using_ntp (void)
-{
-	time_t now;
-
-	time (&now);
-	if (ABS (now - usingntp_stamp) > CACHE_VALIDITY_SEC) {
-		refresh_can_do ("CanSetUsingNtp", update_can_usingntp);
-		settime_stamp = now;
-	}
-
-	return usingntp_cache;
-}
-
-typedef struct {
-	gint ref_count;
-        gchar *call;
-	gint64 time;
-	gchar *tz;
-	gboolean using_ntp;
-	GFunc callback;
-	gpointer data;
-	GDestroyNotify notify;
-} SetTimeCallbackData;
-
-static void
-free_data (gpointer d)
-{
-	SetTimeCallbackData *data = d;
-
-	data->ref_count--;
-	if (data->ref_count == 0) {
-		if (data->notify)
-			data->notify (data->data);
-		g_free (data->tz);
-		g_free (data);
-	}
-}
-
-static void
-set_time_notify (DBusGProxy     *proxy,
-		 DBusGProxyCall *call,
-		 void           *user_data)
-{
-	SetTimeCallbackData *data = user_data;
-	GError *error = NULL;
-
-	if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) {
-		if (data->callback)
-			data->callback (data->data, NULL);
-	}
-	else {
-		if (error->domain == DBUS_GERROR &&
-		    error->code == DBUS_GERROR_NO_REPLY) {
-			/* these errors happen because dbus doesn't
-			 * use monotonic clocks
-			 */	
-			g_warning ("ignoring no-reply error when setting time");
-			g_error_free (error);
-			if (data->callback)
-				data->callback (data->data, NULL);
-		}
-		else {
-			if (data->callback)
-				data->callback (data->data, error);
-			else
-				g_error_free (error);
-		}		
-	}
-}
-
-static void
-set_time_async (SetTimeCallbackData *data)
-{
-        DBusGConnection *bus;
-        DBusGProxy      *proxy;
-	GError          *err = NULL;
-
-        bus = get_system_bus (&err);
-        if (bus == NULL) {
-		if (err) {
-			if (data->callback)
-				data->callback (data->data, err);
-			g_clear_error (&err);
-		}
-		return;
-	}
-
-	proxy = dbus_g_proxy_new_for_name (bus,
-					   "org.gnome.SettingsDaemon.DateTimeMechanism",
-					   "/",
-					   "org.gnome.SettingsDaemon.DateTimeMechanism");
-
-	data->ref_count++;
-	if (strcmp (data->call, "SetTime") == 0)
-		dbus_g_proxy_begin_call_with_timeout (proxy,
-						      "SetTime",
-						      set_time_notify,
-						      data, free_data,
-						      INT_MAX,
-						      /* parameters: */
-						      G_TYPE_INT64, data->time,
-						      G_TYPE_INVALID,
-						      /* return values: */
-						      G_TYPE_INVALID);
-	else if (strcmp (data->call, "SetTimezone") == 0)
-		dbus_g_proxy_begin_call_with_timeout (proxy,
-						      "SetTimezone",
-						      set_time_notify,
-						      data, free_data,
-						      INT_MAX,
-						      /* parameters: */
-						      G_TYPE_STRING, data->tz,
-						      G_TYPE_INVALID,
-						      /* return values: */
-						      G_TYPE_INVALID);
-	else if (strcmp (data->call, "SetUsingNtp") == 0)
-		dbus_g_proxy_begin_call_with_timeout (proxy,
-						      "SetUsingNtp",
-						      set_time_notify,
-						      data, free_data,
-						      INT_MAX,
-						      /* parameters: */
-						      G_TYPE_BOOLEAN, data->using_ntp,
-						      G_TYPE_INVALID,
-						      /* return values: */
-						      G_TYPE_INVALID);
-}
-
-void
-set_system_time_async (gint64         time,
-		       GFunc          callback,
-		       gpointer       d,
-		       GDestroyNotify notify)
-{
-	SetTimeCallbackData *data;
-
-	if (time == -1)
-		return;
-
-	data = g_new0 (SetTimeCallbackData, 1);
-	data->ref_count = 1;
-	data->call = "SetTime";
-	data->time = time;
-	data->tz = NULL;
-	data->callback = callback;
-	data->data = d;
-	data->notify = notify;
-
-	set_time_async (data);
-	free_data (data);
-}
-
-void
-set_system_timezone_async (const gchar    *tz,
-			   GFunc           callback,
-			   gpointer        d,
-			   GDestroyNotify  notify)
-{
-	SetTimeCallbackData *data;
-
-	g_return_if_fail (tz != NULL);
-
-	data = g_new0 (SetTimeCallbackData, 1);
-	data->ref_count = 1;
-	data->call = "SetTimezone";
-	data->time = -1;
-	data->tz = g_strdup (tz);
-	data->callback = callback;
-	data->data = d;
-	data->notify = notify;
-
-	set_time_async (data);
-	free_data (data);
-}
-
-/* get timezone */
-
-typedef struct
-{
-  GetTimezoneFunc callback;
-  GDestroyNotify notify;
-
-  gpointer data;
-
-} GetTimezoneData;
-
-static void
-get_timezone_destroy_notify (GetTimezoneData *data)
-{
-	if (data->notify && data->data)
-		data->notify (data);
-
-	g_free (data);
-}
-
-static void
-get_timezone_notify (DBusGProxy     *proxy,
-		     DBusGProxyCall *call,
-		     void           *user_data)
-{
-	GError *error = NULL;
-	gboolean retval;
-	gchar *string = NULL;
-	GetTimezoneData *data = user_data;
-
-	retval = dbus_g_proxy_end_call (proxy, call, &error,
-					G_TYPE_STRING, &string,
-					G_TYPE_INVALID);
-
-	if (data->callback) {
-		if (!retval) {
-			data->callback (data->data, NULL, error);
-			g_error_free (error);
-		}
-		else {
-			data->callback (data->data, string, NULL);
-			g_free (string);
-		}
-	}
-}
-
-void
-get_system_timezone_async (GetTimezoneFunc callback,
-			   gpointer        user_data,
-			   GDestroyNotify  notify)
-{
-	DBusGConnection *bus;
-	DBusGProxy      *proxy;
-	GetTimezoneData *data;
-	GError          *error = NULL;
-
-	bus = get_system_bus (&error);
-	if (bus == NULL) {
-		if (error) {
-			if (callback)
-				callback (user_data, NULL, error);
-			g_clear_error (&error);
-		}
-		return;
-
-        }
-
-	data = g_new0 (GetTimezoneData, 1);
-	data->data = user_data;
-	data->notify = notify;
-	data->callback = callback;
-
-	proxy = dbus_g_proxy_new_for_name (bus,
-					   "org.gnome.SettingsDaemon.DateTimeMechanism",
-					   "/",
-					   "org.gnome.SettingsDaemon.DateTimeMechanism");
-
-	dbus_g_proxy_begin_call (proxy,
-				 "GetTimezone",
-				 get_timezone_notify,
-				 data,
-				 (GDestroyNotify) get_timezone_destroy_notify,
-				 /* parameters: */
-				 G_TYPE_INVALID,
-				 /* return values: */
-				 G_TYPE_STRING,
-				 G_TYPE_INVALID);
-
-}
-
-gboolean
-get_using_ntp (void)
-{
-	static gboolean can_use_cache = FALSE;
-	static gboolean is_using_cache = FALSE;
-	static time_t   last_refreshed = 0;
-	time_t          now;
-        DBusGConnection *bus;
-        DBusGProxy      *proxy;
-
-	time (&now);
-	if (ABS (now - last_refreshed) > CACHE_VALIDITY_SEC) {
-		gboolean cu, iu;
-		bus = get_system_bus (NULL);
-		if (bus == NULL)
-			return FALSE;
-
-		proxy = dbus_g_proxy_new_for_name (bus,
-						   "org.gnome.SettingsDaemon.DateTimeMechanism",
-						   "/",
-						   "org.gnome.SettingsDaemon.DateTimeMechanism");
-
-
-		if (dbus_g_proxy_call (proxy,
-				       "GetUsingNtp",
-				       NULL,
-				       G_TYPE_INVALID,
-				       G_TYPE_BOOLEAN, &cu,
-				       G_TYPE_BOOLEAN, &iu,
-				       G_TYPE_INVALID)) {
-			can_use_cache = cu;
-			is_using_cache = iu;
-			last_refreshed = now;
-		}
-	}
-
-	return is_using_cache;
-}
-
-void
-set_using_ntp_async (gboolean        using_ntp,
-	             GFunc           callback,
-	             gpointer        d,
-	             GDestroyNotify  notify)
-{
-	SetTimeCallbackData *data;
-
-	data = g_new0 (SetTimeCallbackData, 1);
-	data->ref_count = 1;
-	data->call = "SetUsingNtp";
-	data->time = -1;
-	data->using_ntp = using_ntp;
-	data->callback = callback;
-	data->data = d;
-	data->notify = notify;
-
-	set_time_async (data);
-	free_data (data);
-}
diff --git a/libmap/set-timezone.h b/libmap/set-timezone.h
deleted file mode 100644
index 5e657e3..0000000
--- a/libmap/set-timezone.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007 David Zeuthen 
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef __SET_SYSTEM_TIMEZONE_H__
-
-#include 
-
-#include 
-#include 
-
-typedef void (*GetTimezoneFunc) (gpointer     data,
-                                 const gchar *timezone,
-                                 GError      *error);
-void     get_system_timezone_async   (GetTimezoneFunc callback,
-                                      gpointer        data,
-                                      GDestroyNotify  notify);
-
-gint     can_set_system_timezone (void);
-
-gint     can_set_system_time     (void);
-
-gint     can_set_using_ntp       (void);
-
-void     set_system_time_async   (gint64         time,
-                                  GFunc          callback,
-                                  gpointer       data,
-                                  GDestroyNotify notify);
-
-void     set_system_timezone_async   (const gchar    *tz,
-                                      GFunc           callback,
-                                      gpointer        data,
-                                      GDestroyNotify  notify);
-
-gboolean get_using_ntp               (void);
-
-void     set_using_ntp_async         (gboolean        using_ntp,
-                                      GFunc           callback,
-                                      gpointer        data,
-                                      GDestroyNotify  notify);
-#endif
-- 
cgit v1.2.3


From 74cf8fa3465f955fc01fd3ac9b826079b0f5cdb6 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Tue, 22 Feb 2011 13:49:07 -0500
Subject: make locations dialog editable

---
 src/datetime-prefs-locations.c | 58 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c
index 24efd04..90b6f97 100644
--- a/src/datetime-prefs-locations.c
+++ b/src/datetime-prefs-locations.c
@@ -33,13 +33,56 @@ with this program.  If not, see .
 #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
 
 static void
-handle_add (GtkWidget * button, gpointer user_data)
+handle_add (GtkWidget * button, GtkTreeView * tree)
 {
+  GtkListStore * store = GTK_LIST_STORE (gtk_tree_view_get_model (tree));
+
+  GtkTreeIter iter;
+  gtk_list_store_append (store, &iter);
+
+  GtkTreePath * path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+  gtk_tree_view_set_cursor (tree, path, gtk_tree_view_get_column (tree, 0), TRUE);
+  gtk_tree_path_free (path);
 }
 
 static void
-handle_remove (GtkWidget * button, gpointer user_data)
+handle_remove (GtkWidget * button, GtkTreeView * tree)
 {
+  GtkListStore * store = GTK_LIST_STORE (gtk_tree_view_get_model (tree));
+  GtkTreeSelection * selection = gtk_tree_view_get_selection (tree);
+
+  GList * paths = gtk_tree_selection_get_selected_rows (selection, NULL);
+
+  /* Convert all paths to iters so we can safely delete multiple paths.  For a
+     GtkListStore, iters persist past model changes. */
+  GList * tree_iters = NULL;
+  GList * iter;
+  for (iter = paths; iter; iter = iter->next) {
+    GtkTreeIter * tree_iter = g_new(GtkTreeIter, 1);
+    if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), tree_iter, (GtkTreePath *)iter->data)) {
+      tree_iters = g_list_prepend (tree_iters, tree_iter);
+    }
+    gtk_tree_path_free (iter->data);
+  }
+  g_list_free (paths);
+
+  /* Now delete each iterator */
+  for (iter = tree_iters; iter; iter = iter->next) {
+    gtk_list_store_remove (store, (GtkTreeIter *)iter->data);
+    g_free (iter->data);
+  }
+  g_list_free (tree_iters);
+}
+
+static void
+handle_edit (GtkCellRendererText * renderer, gchar * path, gchar * new_text,
+             GtkListStore * store)
+{
+  GtkTreeIter iter;
+
+  if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &iter, path)) {
+    gtk_list_store_set (store, &iter, 0, new_text, -1);
+  }
 }
 
 static void
@@ -69,8 +112,12 @@ save_to_settings (GtkWidget * dlg, GObject * store)
   if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
     do {
       GValue value = {0};
+      const gchar * strval;
       gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 0, &value);
-      g_variant_builder_add (&builder, "s", g_value_get_string (&value));
+      strval = g_value_get_string (&value);
+      if (strval != NULL && strval[0] != 0) {
+        g_variant_builder_add (&builder, "s", strval);
+      }
       g_value_unset (&value);
     } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
   }
@@ -109,6 +156,7 @@ datetime_setup_locations_dialog (GtkWindow * parent)
   /* Configure tree */
   GtkCellRenderer * cell = gtk_cell_renderer_text_new ();
   g_object_set (cell, "editable", TRUE, NULL);
+  g_signal_connect (cell, "edited", G_CALLBACK (handle_edit), store);
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1,
                                                _("Location"), cell,
                                                "text", 0, NULL);
@@ -118,8 +166,8 @@ datetime_setup_locations_dialog (GtkWindow * parent)
                                                "text", 1, NULL);
   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)), GTK_SELECTION_MULTIPLE);
 
-  g_signal_connect (WIG ("addButton"), "clicked", G_CALLBACK (handle_add), NULL);
-  g_signal_connect (WIG ("removeButton"), "clicked", G_CALLBACK (handle_remove), NULL);
+  g_signal_connect (WIG ("addButton"), "clicked", G_CALLBACK (handle_add), tree);
+  g_signal_connect (WIG ("removeButton"), "clicked", G_CALLBACK (handle_remove), tree);
 
   fill_from_settings (store, conf);
   g_object_set_data_full (G_OBJECT (dlg), "conf", g_object_ref (conf), g_object_unref);
-- 
cgit v1.2.3


From 07c5056f4604b4294f42492e27ea3fcf85019dc3 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Tue, 22 Feb 2011 13:58:50 -0500
Subject: make remove button insensitive if nothing selected

---
 src/datetime-prefs-locations.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c
index 90b6f97..7df41e7 100644
--- a/src/datetime-prefs-locations.c
+++ b/src/datetime-prefs-locations.c
@@ -130,6 +130,13 @@ save_to_settings (GtkWidget * dlg, GObject * store)
   g_variant_unref (locations);
 }
 
+static void
+selection_changed (GtkTreeSelection * selection, GtkWidget * remove_button)
+{
+  gint count = gtk_tree_selection_count_selected_rows (selection);
+  gtk_widget_set_sensitive (remove_button, count > 0);
+}
+
 GtkWidget *
 datetime_setup_locations_dialog (GtkWindow * parent)
 {
@@ -164,7 +171,11 @@ datetime_setup_locations_dialog (GtkWindow * parent)
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1,
                                                _("Time"), cell,
                                                "text", 1, NULL);
-  gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)), GTK_SELECTION_MULTIPLE);
+
+  GtkTreeSelection * selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+  g_signal_connect (selection, "changed", G_CALLBACK (selection_changed), WIG ("removeButton"));
+  selection_changed (selection, WIG ("removeButton"));
 
   g_signal_connect (WIG ("addButton"), "clicked", G_CALLBACK (handle_add), tree);
   g_signal_connect (WIG ("removeButton"), "clicked", G_CALLBACK (handle_remove), tree);
-- 
cgit v1.2.3


From deafbc1da6b3c29e04455e46414342bcb9841c2a Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Tue, 22 Feb 2011 15:17:48 -0600
Subject: beginnings of completion support

---
 data/datetime-dialog.ui        |  85 ++------------------------
 src/Makefile.am                |   2 +
 src/datetime-prefs-locations.c |  15 +++++
 src/datetime-prefs.c           |  30 +++++++++-
 src/timezone-completion.c      | 131 +++++++++++++++++++++++++++++++++++++++++
 src/timezone-completion.h      |  59 +++++++++++++++++++
 6 files changed, 241 insertions(+), 81 deletions(-)
 create mode 100644 src/timezone-completion.c
 create mode 100644 src/timezone-completion.h

diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui
index b5eba54..26c368b 100644
--- a/data/datetime-dialog.ui
+++ b/data/datetime-dialog.ui
@@ -6,6 +6,8 @@
     False
     Locations
     True
+    300
+    200
     True
     time-admin
     
@@ -169,87 +171,10 @@
                       
                     
                     
-                      
+                      
                         True
-                        False
-                        12
-                        True
-                        
-                          
-                            True
-                            False
-                            6
-                            
-                              
-                                True
-                                False
-                                0
-                                _Region:
-                                True
-                                regionCombo
-                              
-                              
-                                False
-                                True
-                                0
-                              
-                            
-                            
-                              
-                                True
-                                False
-                              
-                              
-                                True
-                                True
-                                1
-                              
-                            
-                          
-                          
-                            True
-                            True
-                            0
-                          
-                        
-                        
-                          
-                            True
-                            False
-                            6
-                            
-                              
-                                True
-                                False
-                                0
-                                Time_zone:
-                                True
-                                timezoneCombo
-                              
-                              
-                                False
-                                True
-                                0
-                              
-                            
-                            
-                              
-                                True
-                                False
-                              
-                              
-                                True
-                                True
-                                1
-                              
-                            
-                          
-                          
-                            False
-                            True
-                            1
-                          
-                        
+                        True
+                        
                       
                       
                         False
diff --git a/src/Makefile.am b/src/Makefile.am
index 4c94f7c..7e8ac4b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,8 @@ indicator_datetime_preferences_SOURCES =\
 	datetime-prefs.c \
 	datetime-prefs-locations.c \
 	datetime-prefs-locations.h \
+	timezone-completion.c \
+	timezone-completion.h \
 	utils.c \
 	utils.h \
 	settings-shared.h
diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c
index 7df41e7..b13d082 100644
--- a/src/datetime-prefs-locations.c
+++ b/src/datetime-prefs-locations.c
@@ -29,6 +29,7 @@ with this program.  If not, see .
 
 #include "datetime-prefs-locations.h"
 #include "settings-shared.h"
+#include "timezone-completion.h"
 
 #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
 
@@ -85,6 +86,16 @@ handle_edit (GtkCellRendererText * renderer, gchar * path, gchar * new_text,
   }
 }
 
+static void
+handle_edit_started (GtkCellRendererText * renderer, GtkCellEditable * editable,
+                     gchar * path, TimezoneCompletion * completion)
+{
+  if (GTK_IS_ENTRY (editable)) {
+    GtkEntry *entry = GTK_ENTRY (editable);
+    gtk_entry_set_completion (entry, GTK_ENTRY_COMPLETION (timezone_completion_new ()));
+  }
+}
+
 static void
 fill_from_settings (GObject * store, GSettings * conf)
 {
@@ -161,8 +172,10 @@ datetime_setup_locations_dialog (GtkWindow * parent)
   GObject * store = gtk_builder_get_object (builder, "locationsStore");
 
   /* Configure tree */
+  TimezoneCompletion * completion = timezone_completion_new ();
   GtkCellRenderer * cell = gtk_cell_renderer_text_new ();
   g_object_set (cell, "editable", TRUE, NULL);
+  g_signal_connect (cell, "editing-started", G_CALLBACK (handle_edit_started), completion);
   g_signal_connect (cell, "edited", G_CALLBACK (handle_edit), store);
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1,
                                                _("Location"), cell,
@@ -181,7 +194,9 @@ datetime_setup_locations_dialog (GtkWindow * parent)
   g_signal_connect (WIG ("removeButton"), "clicked", G_CALLBACK (handle_remove), tree);
 
   fill_from_settings (store, conf);
+
   g_object_set_data_full (G_OBJECT (dlg), "conf", g_object_ref (conf), g_object_unref);
+  g_object_set_data_full (G_OBJECT (dlg), "completion", completion, g_object_unref);
   g_signal_connect (dlg, "destroy", G_CALLBACK (save_to_settings), store);
 
   gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index ee4b26a..dbacee1 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -36,6 +36,7 @@ with this program.  If not, see .
 #include "settings-shared.h"
 #include "utils.h"
 #include "datetime-prefs-locations.h"
+#include "timezone-completion.h"
 #include "cc-timezone-map.h"
 
 #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
@@ -176,8 +177,10 @@ tz_changed (CcTimezoneMap * map, TzLocation * location)
   if (location == NULL)
     return;
 
-  g_dbus_proxy_call (proxy, "SetTimezone", g_variant_new ("(s)", location->zone),
+  gchar * file = g_build_filename ("/usr/share/zoneinfo", location->zone, NULL);
+  g_dbus_proxy_call (proxy, "SetTimezone", g_variant_new ("(s)", file),
                      G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "timezone");
+  g_free (file);
 }
 
 static void
@@ -371,6 +374,25 @@ show_locations (GtkWidget * button, GtkWidget * dlg)
   gtk_widget_show_all (locationsDlg);
 }
 
+static gboolean
+timezone_selected (GtkEntryCompletion * widget, GtkTreeModel * model,
+                   GtkTreeIter * iter, gpointer user_data)
+{
+  GValue value = {0};
+  const gchar * strval;
+
+  gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_ZONE, &value);
+  strval = g_value_get_string (&value);
+
+  if (strval != NULL && strval[0] != 0) {
+    cc_timezone_map_set_timezone (tzmap, strval);
+  }
+
+  g_value_unset (&value);
+
+  return FALSE; // Do normal action too
+}
+
 static GtkWidget *
 create_dialog (void)
 {
@@ -401,6 +423,12 @@ create_dialog (void)
   tzmap = cc_timezone_map_new ();
   gtk_container_add (GTK_CONTAINER (WIG ("mapBox")), GTK_WIDGET (tzmap));
 
+  /* And completion entry */
+  TimezoneCompletion * completion = timezone_completion_new ();
+  gtk_entry_set_completion (GTK_ENTRY (WIG ("timezoneEntry")),
+                            GTK_ENTRY_COMPLETION (completion));
+  g_signal_connect (completion, "match-selected", G_CALLBACK (timezone_selected), NULL);
+
   /* Set up settings bindings */
   g_settings_bind (conf, SETTINGS_SHOW_CLOCK_S, WIG ("showClockCheck"),
                    "active", G_SETTINGS_BIND_DEFAULT);
diff --git a/src/timezone-completion.c b/src/timezone-completion.c
new file mode 100644
index 0000000..d98654a
--- /dev/null
+++ b/src/timezone-completion.c
@@ -0,0 +1,131 @@
+/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Michael Terry 
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, 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, see .
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include 
+#include 
+#include "timezone-completion.h"
+#include "tz.h"
+
+enum {
+  LAST_SIGNAL
+};
+
+/* static guint signals[LAST_SIGNAL] = { }; */
+
+typedef struct _TimezoneCompletionPrivate TimezoneCompletionPrivate;
+struct _TimezoneCompletionPrivate
+{
+  void * placeholder;
+};
+
+#define TIMEZONE_COMPLETION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TIMEZONE_COMPLETION_TYPE, TimezoneCompletionPrivate))
+
+/* Prototypes */
+static void timezone_completion_class_init (TimezoneCompletionClass *klass);
+static void timezone_completion_init       (TimezoneCompletion *self);
+static void timezone_completion_dispose    (GObject *object);
+static void timezone_completion_finalize   (GObject *object);
+
+G_DEFINE_TYPE (TimezoneCompletion, timezone_completion, GTK_TYPE_ENTRY_COMPLETION);
+
+static GtkListStore *
+get_initial_model (void)
+{
+  TzDB * db = tz_load_db ();
+  GPtrArray * locations = tz_get_locations (db);
+
+  GtkListStore * store = gtk_list_store_new (TIMEZONE_COMPLETION_LAST, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+  gint i;
+  for (i = 0; i < locations->len; ++i) {
+    TzLocation * loc = g_ptr_array_index (locations, i);
+    GtkTreeIter iter;
+    gtk_list_store_append (store, &iter);
+
+    /* FIXME: need something better than below for non-English locales */
+    const gchar * last_bit = ((const gchar *)strrchr (loc->zone, '/')) + 1;
+    if (last_bit == NULL)
+      last_bit = loc->zone;
+    gchar * name = g_strdup (last_bit);
+    gchar * underscore;
+    while ((underscore = strchr (name, '_'))) {
+       *underscore = ' ';
+    }
+
+    gtk_list_store_set (store, &iter,
+                        TIMEZONE_COMPLETION_ZONE, loc->zone,
+                        TIMEZONE_COMPLETION_NAME, name,
+                        TIMEZONE_COMPLETION_COUNTRY, loc->country,
+                        -1);
+
+    g_free (name);
+  }
+
+  tz_db_free (db);
+  return store;
+}
+
+static void
+timezone_completion_class_init (TimezoneCompletionClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (TimezoneCompletionPrivate));
+
+  object_class->dispose = timezone_completion_dispose;
+  object_class->finalize = timezone_completion_finalize;
+
+  return;
+}
+
+static void
+timezone_completion_init (TimezoneCompletion *self)
+{
+  GtkListStore * model = get_initial_model ();
+  gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (self), GTK_TREE_MODEL (model));
+  gtk_entry_completion_set_text_column (GTK_ENTRY_COMPLETION (self), TIMEZONE_COMPLETION_NAME);
+  return;
+}
+
+static void
+timezone_completion_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (timezone_completion_parent_class)->dispose (object);
+  return;
+}
+
+static void
+timezone_completion_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (timezone_completion_parent_class)->finalize (object);
+  return;
+}
+
+TimezoneCompletion *
+timezone_completion_new ()
+{
+  TimezoneCompletion * self = g_object_new (TIMEZONE_COMPLETION_TYPE, NULL);
+  return self;
+}
+
diff --git a/src/timezone-completion.h b/src/timezone-completion.h
new file mode 100644
index 0000000..6b3ac2b
--- /dev/null
+++ b/src/timezone-completion.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Michael Terry 
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, 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, see .
+*/
+
+#ifndef __TIMEZONE_COMPLETION_H__
+#define __TIMEZONE_COMPLETION_H__
+
+#include 
+#include 
+#include 
+
+G_BEGIN_DECLS
+
+#define TIMEZONE_COMPLETION_TYPE            (timezone_completion_get_type ())
+#define TIMEZONE_COMPLETION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIMEZONE_COMPLETION_TYPE, TimezoneCompletion))
+#define TIMEZONE_COMPLETION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TIMEZONE_COMPLETION_TYPE, TimezoneCompletionClass))
+#define IS_TIMEZONE_COMPLETION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIMEZONE_COMPLETION_TYPE))
+#define IS_TIMEZONE_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIMEZONE_COMPLETION_TYPE))
+#define TIMEZONE_COMPLETION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TIMEZONE_COMPLETION_TYPE, TimezoneCompletionClass))
+
+typedef struct _TimezoneCompletion      TimezoneCompletion;
+typedef struct _TimezoneCompletionClass TimezoneCompletionClass;
+
+struct _TimezoneCompletionClass {
+  GtkEntryCompletionClass parent_class;
+};
+
+struct _TimezoneCompletion {
+  GtkEntryCompletion parent;
+};
+
+#define TIMEZONE_COMPLETION_ZONE    0
+#define TIMEZONE_COMPLETION_NAME    1
+#define TIMEZONE_COMPLETION_COUNTRY 2
+#define TIMEZONE_COMPLETION_LAST    3
+
+GType timezone_completion_get_type (void);
+TimezoneCompletion * timezone_completion_new ();
+
+G_END_DECLS
+
+#endif /* __TIMEZONE_COMPLETION_H__ */
+
-- 
cgit v1.2.3


From b4a4c9682ca2413175386ad36d06fc4e1032badc Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 13:28:53 -0500
Subject: grab timezone names from geomaps; flesh out support for timezone
 completion in main map and locations dialog; show times in locations dialog

---
 configure.ac                   |   2 +
 data/datetime-dialog.ui        |   2 +
 libmap/Makefile.am             |   1 +
 libmap/Makefile.in             |   1 +
 libmap/README                  |   2 +-
 libmap/cc-timezone-map.c       | 466 ++++++++++++++++++++++++++++++++++++++++-
 libmap/cc-timezone-map.h       |   4 +
 libmap/tz.c                    |  49 +++++
 po/POTFILES.in                 |   2 +
 src/datetime-prefs-locations.c | 147 +++++++++++--
 src/datetime-prefs-locations.h |   3 +-
 src/datetime-prefs.c           |  29 ++-
 src/indicator-datetime.c       | 173 +--------------
 src/settings-shared.h          |  19 ++
 src/timezone-completion.c      | 227 +++++++++++++++++++-
 src/timezone-completion.h      |  12 +-
 src/utils.c                    | 188 +++++++++++++++++
 src/utils.h                    |   3 +
 18 files changed, 1120 insertions(+), 210 deletions(-)

diff --git a/configure.ac b/configure.ac
index bcedddc..08707bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,12 +125,14 @@ AS_IF([test "x$with_gtk" = x3],
 	[PKG_CHECK_MODULES(PREF, gio-2.0 >= $GIO_REQUIRED_VERSION
 	                         gtk+-3.0 >= $GTK3_REQUIRED_VERSION
                                  unique-3.0
+                                 json-glib-1.0
                                  polkit-gtk-1)
 		],
       [test "x$with_gtk" = x2],
 	[PKG_CHECK_MODULES(PREF, gio-2.0 >= $GIO_REQUIRED_VERSION
 	                         gtk+-2.0 >= $GTK_REQUIRED_VERSION
                                  unique-1.0
+                                 json-glib-1.0
                                  polkit-gtk-1)
         ],
     [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui
index 26c368b..8b48702 100644
--- a/data/datetime-dialog.ui
+++ b/data/datetime-dialog.ui
@@ -98,6 +98,8 @@
       
       
       
+      
+      
     
   
   
diff --git a/libmap/Makefile.am b/libmap/Makefile.am
index 0cdeb34..a10b835 100644
--- a/libmap/Makefile.am
+++ b/libmap/Makefile.am
@@ -2,6 +2,7 @@ uidir = $(pkgdatadir)/libmap/ui
 dist_ui_DATA = \
 	data/bg.png \
 	data/cc.png \
+	data/olsen_map.png \
 	data/pin.png \
 	data/timezone_0.png \
 	data/timezone_-10.png \
diff --git a/libmap/Makefile.in b/libmap/Makefile.in
index b4ae6df..dd552a4 100644
--- a/libmap/Makefile.in
+++ b/libmap/Makefile.in
@@ -285,6 +285,7 @@ uidir = $(pkgdatadir)/libmap/ui
 dist_ui_DATA = \
 	data/bg.png \
 	data/cc.png \
+	data/olsen_map.png \
 	data/pin.png \
 	data/timezone_0.png \
 	data/timezone_-10.png \
diff --git a/libmap/README b/libmap/README
index 70d6f6c..c83c6d8 100644
--- a/libmap/README
+++ b/libmap/README
@@ -2,4 +2,4 @@ This static library is a copied version of the code in GNOME 3.0's control cente
 
 Ideally in the future, we can have all three packages using the same code.  But for now, for time reasons (hah), it's just a copy.
 
-To update this copy, put newer versions of the code and data files in place; then fix up any GTK3-isms.
+To update this copy, put newer versions of the code and data files in place; then fix up any GTK3-isms and add cc_timezone_map_set_coords and friends.
diff --git a/libmap/cc-timezone-map.c b/libmap/cc-timezone-map.c
index 960a049..7647925 100644
--- a/libmap/cc-timezone-map.c
+++ b/libmap/cc-timezone-map.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2011 Canonical Ltd.
  *
  * Portions from Ubiquity, Copyright (C) 2009 Canonical Ltd.
  * Written by Evan Dandrea 
@@ -48,10 +49,15 @@ struct _CcTimezoneMapPrivate
 
   GdkPixbuf *background;
   GdkPixbuf *color_map;
+  GdkPixbuf *olsen_map;
 
   guchar *visible_map_pixels;
   gint visible_map_rowstride;
 
+  gint olsen_map_channels;
+  guchar *olsen_map_pixels;
+  gint olsen_map_rowstride;
+
   gdouble selected_offset;
 
   TzDB *tzdb;
@@ -111,6 +117,388 @@ static CcTimezoneMapOffset color_codes[] =
     {-100, 0, 0, 0, 0 }
 };
 
+static const gchar * olsen_map_timezones[] = {
+    "Africa/Abidjan",
+    "Africa/Accra",
+    "Africa/Addis_Ababa",
+    "Africa/Algiers",
+    "Africa/Asmara",
+    "Africa/Bamako",
+    "Africa/Bangui",
+    "Africa/Banjul",
+    "Africa/Bissau",
+    "Africa/Blantyre",
+    "Africa/Brazzaville",
+    "Africa/Bujumbura",
+    "Africa/Cairo",
+    "Africa/Casablanca",
+    "Africa/Conakry",
+    "Africa/Dakar",
+    "Africa/Dar_es_Salaam",
+    "Africa/Djibouti",
+    "Africa/Douala",
+    "Africa/El_Aaiun",
+    "Africa/Freetown",
+    "Africa/Gaborone",
+    "Africa/Harare",
+    "Africa/Johannesburg",
+    "Africa/Kampala",
+    "Africa/Khartoum",
+    "Africa/Kigali",
+    "Africa/Kinshasa",
+    "Africa/Lagos",
+    "Africa/Libreville",
+    "Africa/Lome",
+    "Africa/Luanda",
+    "Africa/Lubumbashi",
+    "Africa/Lusaka",
+    "Africa/Malabo",
+    "Africa/Maputo",
+    "Africa/Maseru",
+    "Africa/Mbabane",
+    "Africa/Mogadishu",
+    "Africa/Monrovia",
+    "Africa/Nairobi",
+    "Africa/Ndjamena",
+    "Africa/Niamey",
+    "Africa/Nouakchott",
+    "Africa/Ouagadougou",
+    "Africa/Porto-Novo",
+    "Africa/Sao_Tome",
+    "Africa/Tripoli",
+    "Africa/Tunis",
+    "Africa/Windhoek",
+    "America/Adak",
+    "America/Anguilla",
+    "America/Antigua",
+    "America/Araguaina",
+    "America/Argentina/Buenos_Aires",
+    "America/Argentina/Catamarca",
+    "America/Argentina/Cordoba",
+    "America/Argentina/Jujuy",
+    "America/Argentina/La_Rioja",
+    "America/Argentina/Mendoza",
+    "America/Argentina/Rio_Gallegos",
+    "America/Argentina/San_Juan",
+    "America/Argentina/San_Luis",
+    "America/Argentina/Tucuman",
+    "America/Argentina/Ushuaia",
+    "America/Aruba",
+    "America/Asuncion",
+    "America/Atikokan",
+    "America/Bahia",
+    "America/Barbados",
+    "America/Belem",
+    "America/Belize",
+    "America/Blanc-Sablon",
+    "America/Boa_Vista",
+    "America/Bogota",
+    "America/Boise",
+    "America/Cambridge_Bay",
+    "America/Campo_Grande",
+    "America/Cancun",
+    "America/Caracas",
+    "America/Cayenne",
+    "America/Cayman",
+    "America/Chicago",
+    "America/Chihuahua",
+    "America/Coral_Harbour",
+    "America/Costa_Rica",
+    "America/Cuiaba",
+    "America/Curacao",
+    "America/Dawson",
+    "America/Dawson_Creek",
+    "America/Denver",
+    "America/Dominica",
+    "America/Edmonton",
+    "America/Eirunepe",
+    "America/El_Salvador",
+    "America/Fortaleza",
+    "America/Glace_Bay",
+    "America/Goose_Bay",
+    "America/Grand_Turk",
+    "America/Grenada",
+    "America/Guadeloupe",
+    "America/Guatemala",
+    "America/Guayaquil",
+    "America/Guyana",
+    "America/Halifax",
+    "America/Havana",
+    "America/Hermosillo",
+    "America/Indiana/Indianapolis",
+    "America/Indiana/Knox",
+    "America/Indiana/Marengo",
+    "America/Indiana/Petersburg",
+    "America/Indiana/Vevay",
+    "America/Indiana/Vincennes",
+    "America/Indiana/Winamac",
+    "America/Inuvik",
+    "America/Iqaluit",
+    "America/Jamaica",
+    "America/Juneau",
+    "America/Kentucky/Louisville",
+    "America/Kentucky/Monticello",
+    "America/La_Paz",
+    "America/Lima",
+    "America/Los_Angeles",
+    "America/Maceio",
+    "America/Managua",
+    "America/Manaus",
+    "America/Marigot",
+    "America/Martinique",
+    "America/Mazatlan",
+    "America/Menominee",
+    "America/Merida",
+    "America/Mexico_City",
+    "America/Miquelon",
+    "America/Moncton",
+    "America/Monterrey",
+    "America/Montevideo",
+    "America/Montreal",
+    "America/Montserrat",
+    "America/Nassau",
+    "America/New_York",
+    "America/Nipigon",
+    "America/Noronha",
+    "America/North_Dakota/Center",
+    "America/North_Dakota/Salem",
+    "America/Panama",
+    "America/Pangnirtung",
+    "America/Paramaribo",
+    "America/Phoenix",
+    "America/Port-au-Prince",
+    "America/Port_of_Spain",
+    "America/Porto_Velho",
+    "America/Puerto_Rico",
+    "America/Rainy_River",
+    "America/Rankin_Inlet",
+    "America/Recife",
+    "America/Regina",
+    "America/Resolute",
+    "America/Rio_Branco",
+    "America/Santarem",
+    "America/Santiago",
+    "America/Santo_Domingo",
+    "America/Sao_Paulo",
+    "America/St_Barthelemy",
+    "America/St_Johns",
+    "America/St_Kitts",
+    "America/St_Lucia",
+    "America/St_Thomas",
+    "America/St_Vincent",
+    "America/Tegucigalpa",
+    "America/Thunder_Bay",
+    "America/Tijuana",
+    "America/Toronto",
+    "America/Tortola",
+    "America/Vancouver",
+    "America/Whitehorse",
+    "America/Winnipeg",
+    "America/Yellowknife",
+    "Ameriica/Swift_Current",
+    "Arctic/Longyearbyen",
+    "Asia/Aden",
+    "Asia/Almaty",
+    "Asia/Amman",
+    "Asia/Anadyr",
+    "Asia/Aqtau",
+    "Asia/Aqtobe",
+    "Asia/Ashgabat",
+    "Asia/Baghdad",
+    "Asia/Bahrain",
+    "Asia/Baku",
+    "Asia/Bangkok",
+    "Asia/Beirut",
+    "Asia/Bishkek",
+    "Asia/Brunei",
+    "Asia/Choibalsan",
+    "Asia/Chongqing",
+    "Asia/Colombo",
+    "Asia/Damascus",
+    "Asia/Dhaka",
+    "Asia/Dili",
+    "Asia/Dubai",
+    "Asia/Dushanbe",
+    "Asia/Gaza",
+    "Asia/Harbin",
+    "Asia/Ho_Chi_Minh",
+    "Asia/Hong_Kong",
+    "Asia/Hovd",
+    "Asia/Irkutsk",
+    "Asia/Jakarta",
+    "Asia/Jayapura",
+    "Asia/Jerusalem",
+    "Asia/Kabul",
+    "Asia/Kamchatka",
+    "Asia/Karachi",
+    "Asia/Kashgar",
+    "Asia/Katmandu",
+    "Asia/Kolkata",
+    "Asia/Krasnoyarsk",
+    "Asia/Kuala_Lumpur",
+    "Asia/Kuching",
+    "Asia/Kuwait",
+    "Asia/Macau",
+    "Asia/Magadan",
+    "Asia/Makassar",
+    "Asia/Manila",
+    "Asia/Muscat",
+    "Asia/Nicosia",
+    "Asia/Novosibirsk",
+    "Asia/Omsk",
+    "Asia/Oral",
+    "Asia/Phnom_Penh",
+    "Asia/Pontianak",
+    "Asia/Pyongyang",
+    "Asia/Qatar",
+    "Asia/Qyzylorda",
+    "Asia/Rangoon",
+    "Asia/Riyadh",
+    "Asia/Sakhalin",
+    "Asia/Samarkand",
+    "Asia/Seoul",
+    "Asia/Shanghai",
+    "Asia/Singapore",
+    "Asia/Taipei",
+    "Asia/Tashkent",
+    "Asia/Tbilisi",
+    "Asia/Tehran",
+    "Asia/Thimphu",
+    "Asia/Tokyo",
+    "Asia/Ulaanbaatar",
+    "Asia/Urumqi",
+    "Asia/Vientiane",
+    "Asia/Vladivostok",
+    "Asia/Yakutsk",
+    "Asia/Yekaterinburg",
+    "Asia/Yerevan",
+    "Atlantic/Azores",
+    "Atlantic/Bermuda",
+    "Atlantic/Canary",
+    "Atlantic/Cape_Verde",
+    "Atlantic/Faroe",
+    "Atlantic/Madeira",
+    "Atlantic/Reykjavik",
+    "Atlantic/South_Georgia",
+    "Atlantic/St_Helena",
+    "Atlantic/Stanley",
+    "Australia/Adelaide",
+    "Australia/Brisbane",
+    "Australia/Broken_Hill",
+    "Australia/Currie",
+    "Australia/Darwin",
+    "Australia/Eucla",
+    "Australia/Hobart",
+    "Australia/Lindeman",
+    "Australia/Lord_Howe",
+    "Australia/Melbourne",
+    "Australia/Perth",
+    "Australia/Sydney",
+    "Europe/Amsterdam",
+    "Europe/Andorra",
+    "Europe/Athens",
+    "Europe/Belgrade",
+    "Europe/Berlin",
+    "Europe/Bratislava",
+    "Europe/Brussels",
+    "Europe/Bucharest",
+    "Europe/Budapest",
+    "Europe/Chisinau",
+    "Europe/Copenhagen",
+    "Europe/Dublin",
+    "Europe/Gibraltar",
+    "Europe/Guernsey",
+    "Europe/Helsinki",
+    "Europe/Isle_of_Man",
+    "Europe/Istanbul",
+    "Europe/Jersey",
+    "Europe/Kaliningrad",
+    "Europe/Kiev",
+    "Europe/Lisbon",
+    "Europe/Ljubljana",
+    "Europe/London",
+    "Europe/Luxembourg",
+    "Europe/Madrid",
+    "Europe/Malta",
+    "Europe/Marienhamn",
+    "Europe/Minsk",
+    "Europe/Monaco",
+    "Europe/Moscow",
+    "Europe/Oslo",
+    "Europe/Paris",
+    "Europe/Podgorica",
+    "Europe/Prague",
+    "Europe/Riga",
+    "Europe/Rome",
+    "Europe/Samara",
+    "Europe/San_Marino",
+    "Europe/Sarajevo",
+    "Europe/Simferopol",
+    "Europe/Skopje",
+    "Europe/Sofia",
+    "Europe/Stockholm",
+    "Europe/Tallinn",
+    "Europe/Tirane",
+    "Europe/Uzhgorod",
+    "Europe/Vaduz",
+    "Europe/Vatican",
+    "Europe/Vienna",
+    "Europe/Vilnius",
+    "Europe/Volgograd",
+    "Europe/Warsaw",
+    "Europe/Zagreb",
+    "Europe/Zaporozhye",
+    "Europe/Zurich",
+    "Indian/Antananarivo",
+    "Indian/Chagos",
+    "Indian/Christmas",
+    "Indian/Cocos",
+    "Indian/Comoro",
+    "Indian/Kerguelen",
+    "Indian/Mahe",
+    "Indian/Maldives",
+    "Indian/Mauritius",
+    "Indian/Mayotte",
+    "Indian/Reunion",
+    "Pacific/Apia",
+    "Pacific/Auckland",
+    "Pacific/Chatham",
+    "Pacific/Easter",
+    "Pacific/Efate",
+    "Pacific/Enderbury",
+    "Pacific/Fakaofo",
+    "Pacific/Fiji",
+    "Pacific/Funafuti",
+    "Pacific/Galapagos",
+    "Pacific/Gambier",
+    "Pacific/Guadalcanal",
+    "Pacific/Guam",
+    "Pacific/Honolulu",
+    "Pacific/Johnston",
+    "Pacific/Kiritimati",
+    "Pacific/Kosrae",
+    "Pacific/Kwajalein",
+    "Pacific/Majuro",
+    "Pacific/Marquesas",
+    "Pacific/Midway",
+    "Pacific/Nauru",
+    "Pacific/Niue",
+    "Pacific/Norfolk",
+    "Pacific/Noumea",
+    "Pacific/Pago_Pago",
+    "Pacific/Palau",
+    "Pacific/Pitcairn",
+    "Pacific/Ponape",
+    "Pacific/Port_Moresby",
+    "Pacific/Rarotonga",
+    "Pacific/Saipan",
+    "Pacific/Tahiti",
+    "Pacific/Tarawa",
+    "Pacific/Tongatapu",
+    "Pacific/Truk",
+    "Pacific/Wake",
+    "Pacific/Wallis"
+};
 
 static void
 cc_timezone_map_get_property (GObject    *object,
@@ -155,6 +543,16 @@ cc_timezone_map_dispose (GObject *object)
       priv->orig_color_map = NULL;
     }
 
+  if (priv->olsen_map)
+    {
+      g_object_unref (priv->olsen_map);
+      priv->olsen_map = NULL;
+
+      priv->olsen_map_channels = 0;
+      priv->olsen_map_pixels = NULL;
+      priv->olsen_map_rowstride = 0;
+    }
+
   if (priv->background)
     {
       g_object_unref (priv->background);
@@ -513,12 +911,10 @@ set_location (CcTimezoneMap *map,
   tz_info_free (info);
 }
 
-static gboolean
-button_press_event (GtkWidget      *widget,
-                    GdkEventButton *event)
+static TzLocation *
+get_loc_for_xy (GtkWidget * widget, gint x, gint y)
 {
   CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv;
-  gint x, y;
   guchar r, g, b, a;
   guchar *pixels;
   gint rowstride;
@@ -529,10 +925,6 @@ button_press_event (GtkWidget      *widget,
   GList *distances = NULL;
   GtkAllocation alloc;
 
-  x = event->x;
-  y = event->y;
-
-
   rowstride = priv->visible_map_rowstride;
   pixels = priv->visible_map_pixels;
 
@@ -578,11 +970,19 @@ button_press_event (GtkWidget      *widget,
     }
   distances = g_list_sort (distances, (GCompareFunc) sort_locations);
 
-
-  set_location (CC_TIMEZONE_MAP (widget), (TzLocation*) distances->data);
+  TzLocation * loc = (TzLocation*) distances->data;
 
   g_list_free (distances);
 
+  return loc;
+}
+
+static gboolean
+button_press_event (GtkWidget      *widget,
+                    GdkEventButton *event)
+{
+  TzLocation * loc = get_loc_for_xy (widget, event->x, event->y);
+  set_location (CC_TIMEZONE_MAP (widget), loc);
   return TRUE;
 }
 
@@ -664,6 +1064,18 @@ cc_timezone_map_init (CcTimezoneMap *self)
       g_clear_error (&err);
     }
 
+  priv->olsen_map = gdk_pixbuf_new_from_file (DATADIR "/olsen_map.png",
+                                              &err);
+  if (!priv->olsen_map)
+    {
+      g_warning ("Could not load olsen map: %s",
+                 (err) ? err->message : "Unknown error");
+      g_clear_error (&err);
+    }
+  priv->olsen_map_channels = gdk_pixbuf_get_n_channels (priv->olsen_map);
+  priv->olsen_map_pixels = gdk_pixbuf_get_pixels (priv->olsen_map);
+  priv->olsen_map_rowstride = gdk_pixbuf_get_rowstride (priv->olsen_map);
+
   priv->tzdb = tz_load_db ();
 
   g_signal_connect (self, "button-press-event", G_CALLBACK (button_press_event),
@@ -704,6 +1116,40 @@ cc_timezone_map_set_timezone (CcTimezoneMap *map,
   gtk_widget_queue_draw (GTK_WIDGET (map));
 }
 
+void
+cc_timezone_map_set_coords (CcTimezoneMap *map, gdouble lon, gdouble lat)
+{
+  const gchar * zone = cc_timezone_map_get_timezone_at_coords (map, lon, lat);
+  cc_timezone_map_set_timezone (map, zone);
+}
+
+const gchar *
+cc_timezone_map_get_timezone_at_coords (CcTimezoneMap *map, gdouble lon, gdouble lat)
+{
+  gint x = (int)(2048.0 / 360.0 * (180.0 + lon));
+  gint y = (int)(1024.0 / 180.0 * (90.0 - lat));
+  gint offset = map->priv->olsen_map_rowstride * y + x * map->priv->olsen_map_channels;
+  guchar color0 = map->priv->olsen_map_pixels[offset];
+  guchar color1 = map->priv->olsen_map_pixels[offset + 1];
+  gint zone = ((color0 & 248) << 1) + ((color1 >>4) & 15);
+
+  const gchar * city = NULL;
+  if (zone < G_N_ELEMENTS(olsen_map_timezones))
+    city = olsen_map_timezones[zone];
+
+  if (city != NULL) {
+    return city;
+  }
+  else {
+    GtkAllocation alloc;
+    gtk_widget_get_allocation (GTK_WIDGET (map), &alloc);
+    x = convert_longtitude_to_x(lon, alloc.width);
+    y = convert_latitude_to_y(lat, alloc.height);
+    TzLocation * loc = get_loc_for_xy(GTK_WIDGET (map), x, y);
+    return loc->zone;
+  }
+}
+
 TzLocation *
 cc_timezone_map_get_location (CcTimezoneMap *map)
 {
diff --git a/libmap/cc-timezone-map.h b/libmap/cc-timezone-map.h
index 3c57b27..8de986d 100644
--- a/libmap/cc-timezone-map.h
+++ b/libmap/cc-timezone-map.h
@@ -72,6 +72,10 @@ CcTimezoneMap *cc_timezone_map_new (void);
 
 void cc_timezone_map_set_timezone (CcTimezoneMap *map,
                                    const gchar   *timezone);
+void cc_timezone_map_set_coords (CcTimezoneMap *map,
+                                 gdouble lon, gdouble lat);
+const gchar * cc_timezone_map_get_timezone_at_coords (CcTimezoneMap *map,
+                                                      gdouble lon, gdouble lat);
 TzLocation * cc_timezone_map_get_location (CcTimezoneMap *map);
 
 G_END_DECLS
diff --git a/libmap/tz.c b/libmap/tz.c
index 3e6c8ae..b77a8ef 100644
--- a/libmap/tz.c
+++ b/libmap/tz.c
@@ -146,6 +146,55 @@ tz_db_free (TzDB *db)
 	g_free (db);
 }
 
+static gint
+sort_locations (TzLocation *a,
+                TzLocation *b)
+{
+  if (a->dist > b->dist)
+    return 1;
+
+  if (a->dist < b->dist)
+    return -1;
+
+  return 0;
+}
+
+static gdouble
+convert_longtitude_to_x (gdouble longitude, gint map_width)
+{
+  const gdouble xdeg_offset = -6;
+  gdouble x;
+
+  x = (map_width * (180.0 + longitude) / 360.0)
+    + (map_width * xdeg_offset / 180.0);
+
+  return x;
+}
+
+static gdouble
+radians (gdouble degrees)
+{
+  return (degrees / 360.0) * G_PI * 2;
+}
+
+static gdouble
+convert_latitude_to_y (gdouble latitude, gdouble map_height)
+{
+  gdouble bottom_lat = -59;
+  gdouble top_lat = 81;
+  gdouble top_per, y, full_range, top_offset, map_range;
+
+  top_per = top_lat / 180.0;
+  y = 1.25 * log (tan (G_PI_4 + 0.4 * radians (latitude)));
+  full_range = 4.6068250867599998;
+  top_offset = full_range * top_per;
+  map_range = fabs (1.25 * log (tan (G_PI_4 + 0.4 * radians (bottom_lat))) - top_offset);
+  y = fabs (y - top_offset);
+  y = y / map_range;
+  y = y * map_height;
+  return y;
+}
+
 GPtrArray *
 tz_get_locations (TzDB *db)
 {
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0fa22d4..84ce021 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,4 +2,6 @@ src/indicator-datetime.c
 src/datetime-service.c
 src/datetime-prefs.c
 src/datetime-prefs-locations.c
+src/utils.c
+src/settings-shared.h
 [type: gettext/glade]data/datetime-dialog.ui
diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c
index b13d082..e29580f 100644
--- a/src/datetime-prefs-locations.c
+++ b/src/datetime-prefs-locations.c
@@ -24,11 +24,13 @@ with this program.  If not, see .
 #include "config.h"
 #endif
 
-#include 
+#include 
+#include 
 #include 
 
 #include "datetime-prefs-locations.h"
 #include "settings-shared.h"
+#include "utils.h"
 #include "timezone-completion.h"
 
 #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
@@ -86,14 +88,105 @@ handle_edit (GtkCellRendererText * renderer, gchar * path, gchar * new_text,
   }
 }
 
+static gboolean
+timezone_selected (GtkEntryCompletion * widget, GtkTreeModel * model,
+                   GtkTreeIter * iter, gpointer user_data)
+{
+  GValue zone_value = {0}, name_value = {0};
+  const gchar * zone, * name;
+
+  gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_ZONE, &zone_value);
+  zone = g_value_get_string (&zone_value);
+
+  gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_NAME, &name_value);
+  name = g_value_get_string (&name_value);
+
+  if (zone == NULL || zone[0] == 0) {
+    GValue lon_value = {0}, lat_value = {0};
+    const gchar * strlon, * strlat;
+    gdouble lon = 0.0, lat = 0.0;
+
+    gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_LONGITUDE, &lon_value);
+    strlon = g_value_get_string (&lon_value);
+    if (strlon != NULL && strlon[0] != 0) {
+      lon = strtod(strlon, NULL);
+    }
+
+    gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_LATITUDE, &lat_value);
+    strlat = g_value_get_string (&lat_value);
+    if (strlat != NULL && strlat[0] != 0) {
+      lat = strtod(strlat, NULL);
+    }
+
+    CcTimezoneMap * tzmap = CC_TIMEZONE_MAP (g_object_get_data (G_OBJECT (widget), "tzmap"));
+    zone = cc_timezone_map_get_timezone_at_coords (tzmap, lon, lat);
+  }
+
+  GtkListStore * store = GTK_LIST_STORE (g_object_get_data (G_OBJECT (widget), "store"));
+  GtkTreeIter * store_iter = (GtkTreeIter *)g_object_get_data (G_OBJECT (widget), "store_iter");
+  if (store != NULL && store_iter != NULL) {
+    gtk_list_store_set (store, store_iter, 0, name, 2, zone, -1);
+  }
+
+  g_value_unset (&name_value);
+  g_value_unset (&zone_value);
+
+  return FALSE; // Do normal action too
+}
+
 static void
 handle_edit_started (GtkCellRendererText * renderer, GtkCellEditable * editable,
                      gchar * path, TimezoneCompletion * completion)
 {
   if (GTK_IS_ENTRY (editable)) {
     GtkEntry *entry = GTK_ENTRY (editable);
-    gtk_entry_set_completion (entry, GTK_ENTRY_COMPLETION (timezone_completion_new ()));
+    gtk_entry_set_completion (entry, GTK_ENTRY_COMPLETION (completion));
+    timezone_completion_watch_entry (completion, entry);
+
+    GtkListStore * store = GTK_LIST_STORE (g_object_get_data (G_OBJECT (completion), "store"));
+    GtkTreeIter * store_iter = g_new(GtkTreeIter, 1);
+    if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), store_iter, path)) {
+      g_object_set_data_full (G_OBJECT (completion), "store_iter", store_iter, g_free);
+    }
+  }
+}
+
+static gboolean
+update_times (GtkListStore * store)
+{
+  /* For each entry, check zone in column 2 and set column 1 to it's time */
+
+  GDateTime * now = g_date_time_new_now_local ();
+
+  GtkTreeIter iter;
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+    do {
+      GValue zone_value = {0};
+      const gchar * strzone;
+
+      gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 2, &zone_value);
+      strzone = g_value_get_string (&zone_value);
+
+      if (strzone != NULL && strzone[0] != 0) {
+        GTimeZone * tz = g_time_zone_new (strzone);
+        GDateTime * now_tz = g_date_time_to_timezone (now, tz);
+        gchar * format = generate_format_string_at_time (now_tz);
+        gchar * time_str = g_date_time_format (now_tz, format);
+
+        gtk_list_store_set (store, &iter, 1, time_str, -1);
+
+        g_free (time_str);
+        g_free (format);
+        g_date_time_unref (now_tz);
+        g_time_zone_unref (tz);
+      }
+
+      g_value_unset (&zone_value);
+    } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
   }
+
+  g_date_time_unref (now);
+  return TRUE;
 }
 
 static void
@@ -106,30 +199,50 @@ fill_from_settings (GObject * store, GSettings * conf)
   gchar ** striter;
   GtkTreeIter iter;
   for (striter = locations; *striter; ++striter) {
+    gchar * zone, * name;
+    split_settings_location (*striter, &zone, &name);
+
     gtk_list_store_append (GTK_LIST_STORE (store), &iter);
-    gtk_list_store_set (GTK_LIST_STORE (store), &iter, 0, *striter, -1);
+    gtk_list_store_set (GTK_LIST_STORE (store), &iter, 0, name, 2, zone, -1);
+
+    g_free (zone);
+    g_free (name);
   }
 
   g_strfreev (locations);
 }
 
 static void
-save_to_settings (GtkWidget * dlg, GObject * store)
+dialog_closed (GtkWidget * dlg, GObject * store)
 {
+  /* Cleanup a tad */
+  guint time_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dlg), "time-id"));
+  g_source_remove (time_id);
+
+  /* Now save to settings */
   GVariantBuilder builder;
   g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
 
   GtkTreeIter iter;
   if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
     do {
-      GValue value = {0};
-      const gchar * strval;
-      gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 0, &value);
-      strval = g_value_get_string (&value);
-      if (strval != NULL && strval[0] != 0) {
-        g_variant_builder_add (&builder, "s", strval);
+      GValue zone_value = {0}, name_value = {0};
+      const gchar * strzone, * strname;
+
+      gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 0, &name_value);
+      gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 2, &zone_value);
+
+      strzone = g_value_get_string (&zone_value);
+      strname = g_value_get_string (&name_value);
+
+      if (strzone != NULL && strzone[0] != 0 && strname != NULL && strname[0] != 0) {
+        gchar * settings_string = g_strdup_printf("%s %s", strzone, strname);
+        g_variant_builder_add (&builder, "s", settings_string);
+        g_free (settings_string);
       }
-      g_value_unset (&value);
+
+      g_value_unset (&zone_value);
+      g_value_unset (&name_value);
     } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
   }
 
@@ -149,7 +262,7 @@ selection_changed (GtkTreeSelection * selection, GtkWidget * remove_button)
 }
 
 GtkWidget *
-datetime_setup_locations_dialog (GtkWindow * parent)
+datetime_setup_locations_dialog (GtkWindow * parent, CcTimezoneMap * map)
 {
   GError * error = NULL;
   GtkBuilder * builder = gtk_builder_new ();
@@ -173,6 +286,10 @@ datetime_setup_locations_dialog (GtkWindow * parent)
 
   /* Configure tree */
   TimezoneCompletion * completion = timezone_completion_new ();
+  g_object_set_data (G_OBJECT (completion), "tzmap", map);
+  g_object_set_data (G_OBJECT (completion), "store", store);
+  g_signal_connect (completion, "match-selected", G_CALLBACK (timezone_selected), NULL);
+
   GtkCellRenderer * cell = gtk_cell_renderer_text_new ();
   g_object_set (cell, "editable", TRUE, NULL);
   g_signal_connect (cell, "editing-started", G_CALLBACK (handle_edit_started), completion);
@@ -195,9 +312,13 @@ datetime_setup_locations_dialog (GtkWindow * parent)
 
   fill_from_settings (store, conf);
 
+  guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_times, store);
+  update_times (GTK_LIST_STORE (store));
+
   g_object_set_data_full (G_OBJECT (dlg), "conf", g_object_ref (conf), g_object_unref);
   g_object_set_data_full (G_OBJECT (dlg), "completion", completion, g_object_unref);
-  g_signal_connect (dlg, "destroy", G_CALLBACK (save_to_settings), store);
+  g_object_set_data (G_OBJECT (dlg), "time-id", GINT_TO_POINTER(time_id));
+  g_signal_connect (dlg, "destroy", G_CALLBACK (dialog_closed), store);
 
   gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
 
diff --git a/src/datetime-prefs-locations.h b/src/datetime-prefs-locations.h
index d5dd534..1760567 100644
--- a/src/datetime-prefs-locations.h
+++ b/src/datetime-prefs-locations.h
@@ -24,10 +24,11 @@ with this program.  If not, see .
 #define __DATETIME_PREFS_LOCATIONS_H__
 
 #include 
+#include "cc-timezone-map.h"
 
 G_BEGIN_DECLS
 
-GtkWidget * datetime_setup_locations_dialog (GtkWindow * parent);
+GtkWidget * datetime_setup_locations_dialog (GtkWindow * parent, CcTimezoneMap * map);
 
 G_END_DECLS
 
diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index dbacee1..622a999 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -25,6 +25,7 @@ with this program.  If not, see .
 #include "config.h"
 #endif
 
+#include 
 #include 
 #include 
 #include 
@@ -104,7 +105,7 @@ add_widget_dependency (GtkWidget * parent, GtkWidget * dependent)
   widget_dependency_cb (parent, NULL, dependent);
 }
 
-static void
+/*static void
 polkit_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent)
 {
   gboolean authorized, sensitive;
@@ -122,7 +123,7 @@ add_polkit_dependency (GtkWidget * parent, GtkWidget * dependent)
   g_signal_connect (parent, "notify::sensitive", G_CALLBACK(polkit_dependency_cb),
                     dependent);
   polkit_dependency_cb (parent, NULL, dependent);
-}
+}*/
 
 static void
 dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command)
@@ -370,7 +371,7 @@ setup_time_spinner (GtkWidget * spinner, GtkWidget * other, gboolean is_time)
 static void
 show_locations (GtkWidget * button, GtkWidget * dlg)
 {
-  GtkWidget * locationsDlg = datetime_setup_locations_dialog (GTK_WINDOW (dlg));
+  GtkWidget * locationsDlg = datetime_setup_locations_dialog (GTK_WINDOW (dlg), tzmap);
   gtk_widget_show_all (locationsDlg);
 }
 
@@ -387,6 +388,25 @@ timezone_selected (GtkEntryCompletion * widget, GtkTreeModel * model,
   if (strval != NULL && strval[0] != 0) {
     cc_timezone_map_set_timezone (tzmap, strval);
   }
+  else {
+    GValue lon_value = {0}, lat_value = {0};
+    const gchar * strlon, * strlat;
+    gdouble lon = 0.0, lat = 0.0;
+
+    gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_LONGITUDE, &lon_value);
+    strlon = g_value_get_string (&lon_value);
+    if (strlon != NULL && strlon[0] != 0) {
+      lon = strtod(strlon, NULL);
+    }
+
+    gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_LATITUDE, &lat_value);
+    strlat = g_value_get_string (&lat_value);
+    if (strlat != NULL && strlat[0] != 0) {
+      lat = strtod(strlat, NULL);
+    }
+
+    cc_timezone_map_set_coords (tzmap, lon, lat);
+  }
 
   g_value_unset (&value);
 
@@ -427,6 +447,7 @@ create_dialog (void)
   TimezoneCompletion * completion = timezone_completion_new ();
   gtk_entry_set_completion (GTK_ENTRY (WIG ("timezoneEntry")),
                             GTK_ENTRY_COMPLETION (completion));
+  timezone_completion_watch_entry (completion, GTK_ENTRY (WIG ("timezoneEntry")));
   g_signal_connect (completion, "match-selected", G_CALLBACK (timezone_selected), NULL);
 
   /* Set up settings bindings */
@@ -464,7 +485,7 @@ create_dialog (void)
   add_widget_dependency (WIG ("showClockCheck"), WIG ("clockOptions"));
   add_widget_dependency (WIG ("showLocationsCheck"), WIG ("locationsButton"));
   add_widget_dependency (WIG ("manualTimeRadio"), WIG ("manualOptions"));
-  add_polkit_dependency (polkit_button, WIG ("timeDateOptions"));
+  //add_polkit_dependency (polkit_button, WIG ("timeDateOptions"));
 
   /* Hacky proxy test for whether evolution-data-server is installed */
   gchar * evo_path = g_find_program_in_path ("evolution");
diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c
index 5e73612..fb421cb 100644
--- a/src/indicator-datetime.c
+++ b/src/indicator-datetime.c
@@ -119,23 +119,6 @@ struct _indicator_item_t {
 #define PROP_SHOW_DATE_S                "show-date"
 #define PROP_CUSTOM_TIME_FORMAT_S       "custom-time-format"
 
-enum {
-	SETTINGS_TIME_LOCALE = 0,
-	SETTINGS_TIME_12_HOUR = 1,
-	SETTINGS_TIME_24_HOUR = 2,
-	SETTINGS_TIME_CUSTOM = 3
-};
-
-/* TRANSLATORS: A format string for the strftime function for
-   a clock showing 12-hour time without seconds. */
-#define DEFAULT_TIME_12_FORMAT   N_("%l:%M %p")
-
-/* TRANSLATORS: A format string for the strftime function for
-   a clock showing 24-hour time without seconds. */
-#define DEFAULT_TIME_24_FORMAT   N_("%H:%M")
-
-#define DEFAULT_TIME_FORMAT      DEFAULT_TIME_12_FORMAT
-
 #define INDICATOR_DATETIME_GET_PRIVATE(o) \
 (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_DATETIME_TYPE, IndicatorDatetimePrivate))
 
@@ -165,7 +148,6 @@ static const gchar * get_accessible_desc  (IndicatorObject * io);
 static GVariant * bind_enum_set           (const GValue * value, const GVariantType * type, gpointer user_data);
 static gboolean bind_enum_get             (GValue * value, GVariant * variant, gpointer user_data);
 static gchar * generate_format_string_now (IndicatorDatetime * self);
-static gchar * generate_format_string_at_time (IndicatorDatetime * self, GDateTime * time);
 static void update_label                  (IndicatorDatetime * io, GDateTime ** datetime);
 static void guess_label_size              (IndicatorDatetime * self);
 static void setup_timer                   (IndicatorDatetime * self, GDateTime * datetime);
@@ -643,7 +625,7 @@ set_label_to_time_in_zone (IndicatorDatetime * self, GtkLabel * label,
 
 	gchar * timestr;
 	if (format == NULL) {
-		gchar * format_for_time = generate_format_string_at_time(self, datetime_now);
+		gchar * format_for_time = generate_format_string_at_time(datetime_now);
 		timestr = g_date_time_format(datetime_now, format_for_time);
 		g_free(format_for_time);
 	}
@@ -987,41 +969,6 @@ style_changed (GtkWidget * widget, GtkStyle * oldstyle, gpointer data)
 	return;
 }
 
-/* Translate msg according to the locale specified by LC_TIME */
-static char *
-T_(const char *msg)
-{
-	/* General strategy here is to make sure LANGUAGE is empty (since that
-	   trumps all LC_* vars) and then to temporarily swap LC_TIME and
-	   LC_MESSAGES.  Then have gettext translate msg.
-
-	   We strdup the strings because the setlocale & *env functions do not
-	   guarantee anything about the storage used for the string, and thus
-	   the string may not be portably safe after multiple calls.
-
-	   Note that while you might think g_dcgettext would do the trick here,
-	   that actually looks in /usr/share/locale/XX/LC_TIME, not the
-	   LC_MESSAGES directory, so we won't find any translation there.
-	*/
-	char *message_locale = g_strdup(setlocale(LC_MESSAGES, NULL));
-	char *time_locale = g_strdup(setlocale(LC_TIME, NULL));
-	char *language = g_strdup(g_getenv("LANGUAGE"));
-	char *rv;
-	g_unsetenv("LANGUAGE");
-	setlocale(LC_MESSAGES, time_locale);
-
-	/* Get the LC_TIME version */
-	rv = _(msg);
-
-	/* Put everything back the way it was */
-	setlocale(LC_MESSAGES, message_locale);
-	g_setenv("LANGUAGE", language, TRUE);
-	g_free(message_locale);
-	g_free(time_locale);
-	g_free(language);
-	return rv;
-}
-
 /* Respond to changes in the screen to update the text gravity */
 static void
 update_text_gravity (GtkWidget *widget, GdkScreen *previous_screen, gpointer data)
@@ -1037,71 +984,6 @@ update_text_gravity (GtkWidget *widget, GdkScreen *previous_screen, gpointer dat
 	pango_context_set_base_gravity(context, PANGO_GRAVITY_AUTO);
 }
 
-/* Tries to figure out what our format string should be.  Lots
-   of translator comments in here. */
-static gchar *
-generate_format_string_full (IndicatorDatetime * self, gboolean show_day, gboolean show_date)
-{
-	gboolean twelvehour = TRUE;
-
-	if (self->priv->time_mode == SETTINGS_TIME_LOCALE) {
-		twelvehour = is_locale_12h();
-	} else if (self->priv->time_mode == SETTINGS_TIME_24_HOUR) {
-		twelvehour = FALSE;
-	}
-
-	const gchar * time_string = NULL;
-	if (twelvehour) {
-		if (self->priv->show_seconds) {
-			/* TRANSLATORS: A format string for the strftime function for
-			   a clock showing 12-hour time with seconds. */
-			time_string = T_("%l:%M:%S %p");
-		} else {
-			time_string = T_(DEFAULT_TIME_12_FORMAT);
-		}
-	} else {
-		if (self->priv->show_seconds) {
-			/* TRANSLATORS: A format string for the strftime function for
-			   a clock showing 24-hour time with seconds. */
-			time_string = T_("%H:%M:%S");
-		} else {
-			time_string = T_(DEFAULT_TIME_24_FORMAT);
-		}
-	}
-	
-	/* Checkpoint, let's not fail */
-	g_return_val_if_fail(time_string != NULL, g_strdup(DEFAULT_TIME_FORMAT));
-
-	/* If there's no date or day let's just leave now and
-	   not worry about the rest of this code */
-	if (!show_date && !show_day) {
-		return g_strdup(time_string);
-	}
-
-	const gchar * date_string = NULL;
-	if (show_date && show_day) {
-		/* TRANSLATORS:  This is a format string passed to strftime to represent
-		   the day of the week, the month and the day of the month. */
-		date_string = T_("%a %b %e");
-	} else if (show_date) {
-		/* TRANSLATORS:  This is a format string passed to strftime to represent
-		   the month and the day of the month. */
-		date_string = T_("%b %e");
-	} else if (show_day) {
-		/* TRANSLATORS:  This is a format string passed to strftime to represent
-		   the day of the week. */
-		date_string = T_("%a");
-	}
-
-	/* Check point, we should have a date string */
-	g_return_val_if_fail(date_string != NULL, g_strdup(time_string));
-
-	/* TRANSLATORS: This is a format string passed to strftime to combine the
-	   date and the time.  The value of "%s, %s" would result in a string like
-	   this in US English 12-hour time: 'Fri Jul 16, 11:50 AM' */
-	return g_strdup_printf(T_("%s, %s"), date_string, time_string);
-}
-
 static gchar *
 generate_format_string_now (IndicatorDatetime * self)
 {
@@ -1109,62 +991,11 @@ generate_format_string_now (IndicatorDatetime * self)
 		return g_strdup(self->priv->custom_string);
 	}
 	else {
-		return generate_format_string_full(self,
-		                                   self->priv->show_day,
+		return generate_format_string_full(self->priv->show_day,
 		                                   self->priv->show_date);
 	}
 }
 
-static gchar *
-generate_format_string_at_time (IndicatorDatetime * self, GDateTime * time)
-{
-	/* This is a bit less free-form than for the main "now" time label. */
-	/* If it is today, just the time should be shown (e.g. “3:55 PM”)
-           If it is a different day this week, the day and time should be shown (e.g. “Wed 3:55 PM”)
-           If it is after this week, the day, date, and time should be shown (e.g. “Wed 21 Apr 3:55 PM”). 
-           In addition, when presenting the times of upcoming events, the time should be followed by the timezone if it is different from the one the computer is currently set to. For example, “Wed 3:55 PM UTC−5”. */
-	gboolean show_day = FALSE;
-	gboolean show_date = FALSE;
-
-	GDateTime * now = g_date_time_new_now_local();
-
-	/* First, are we same day? */
-	gint time_year, time_month, time_day;
-	gint now_year, now_month, now_day;
-	g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
-	g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
-
-	if (time_year != now_year ||
-	    time_month != now_month ||
-	    time_day != now_day) {
-		/* OK, different days so we must at least show the day. */
-		show_day = TRUE;
-
-		/* Is it this week? */
-		/* Here, we define "is this week" as yesterday, today, or the next five days */
-		GDateTime * past = g_date_time_add_days(now, -1);
-		GDateTime * future = g_date_time_add_days(now, 5);
-		GDateTime * past_bound = g_date_time_new_local(g_date_time_get_year(past),
-		                                               g_date_time_get_month(past),
-		                                               g_date_time_get_day_of_month(past),
-		                                               0, 0, 0.0);
-		GDateTime * future_bound = g_date_time_new_local(g_date_time_get_year(future),
-		                                                 g_date_time_get_month(future),
-		                                                 g_date_time_get_day_of_month(future),
-		                                                 23, 59, 59.9);
-		if (g_date_time_compare(time, past_bound) < 0 ||
-		    g_date_time_compare(time, future_bound) > 0) {
-			show_date = TRUE;
-		}
-		g_date_time_unref(past);
-		g_date_time_unref(future);
-		g_date_time_unref(past_bound);
-		g_date_time_unref(future_bound);
-	}
-
-	return generate_format_string_full(self, show_day, show_date);
-}
-
 static void
 timezone_update_labels (indicator_item_t * mi_data)
 {
diff --git a/src/settings-shared.h b/src/settings-shared.h
index 1a66688..d866b81 100644
--- a/src/settings-shared.h
+++ b/src/settings-shared.h
@@ -22,6 +22,8 @@ with this program.  If not, see .
 #ifndef __DATETIME_SETTINGS_SHARED_H__
 #define __DATETIME_SETTINGS_SHARED_H__
 
+#include 
+
 #define SETTINGS_INTERFACE              "com.canonical.indicator.datetime"
 #define SETTINGS_SHOW_CLOCK_S           "show-clock"
 #define SETTINGS_TIME_FORMAT_S          "time-format"
@@ -36,4 +38,21 @@ with this program.  If not, see .
 #define SETTINGS_SHOW_LOCATIONS_S       "show-locations"
 #define SETTINGS_LOCATIONS_S            "locations"
 
+enum {
+	SETTINGS_TIME_LOCALE = 0,
+	SETTINGS_TIME_12_HOUR = 1,
+	SETTINGS_TIME_24_HOUR = 2,
+	SETTINGS_TIME_CUSTOM = 3
+};
+
+/* TRANSLATORS: A format string for the strftime function for
+   a clock showing 12-hour time without seconds. */
+#define DEFAULT_TIME_12_FORMAT   N_("%l:%M %p")
+
+/* TRANSLATORS: A format string for the strftime function for
+   a clock showing 24-hour time without seconds. */
+#define DEFAULT_TIME_24_FORMAT   N_("%H:%M")
+
+#define DEFAULT_TIME_FORMAT      DEFAULT_TIME_12_FORMAT
+
 #endif
diff --git a/src/timezone-completion.c b/src/timezone-completion.c
index d98654a..a1b4d00 100644
--- a/src/timezone-completion.c
+++ b/src/timezone-completion.c
@@ -22,6 +22,7 @@ with this program.  If not, see .
 #include "config.h"
 #endif
 
+#include 
 #include 
 #include 
 #include "timezone-completion.h"
@@ -36,10 +37,17 @@ enum {
 typedef struct _TimezoneCompletionPrivate TimezoneCompletionPrivate;
 struct _TimezoneCompletionPrivate
 {
-  void * placeholder;
+  GtkEntry *     entry;
+  guint          queued_request;
+  guint          changed_id;
+  GCancellable * cancel;
+  gchar *        request_text;
+  GHashTable *   request_table;
 };
 
-#define TIMEZONE_COMPLETION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TIMEZONE_COMPLETION_TYPE, TimezoneCompletionPrivate))
+#define TIMEZONE_COMPLETION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), TIMEZONE_COMPLETION_TYPE, TimezoneCompletionPrivate))
+
+#define GEONAME_URL "http://geoname-lookup.ubuntu.com/?query=%s&release=%s"
 
 /* Prototypes */
 static void timezone_completion_class_init (TimezoneCompletionClass *klass);
@@ -49,13 +57,186 @@ static void timezone_completion_finalize   (GObject *object);
 
 G_DEFINE_TYPE (TimezoneCompletion, timezone_completion, GTK_TYPE_ENTRY_COMPLETION);
 
+static void
+json_parse_ready (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  TimezoneCompletion * completion = TIMEZONE_COMPLETION (user_data);
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE(completion);
+  GError * error = NULL;
+
+  json_parser_load_from_stream_finish (JSON_PARSER (object), res, &error);
+
+  if (priv->cancel && (error == NULL || error->code != G_IO_ERROR_CANCELLED)) {
+    g_cancellable_reset (priv->cancel);
+  }
+
+  if (error != NULL) {
+    g_warning ("Could not parse geoname JSON data: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+g_print("got json\n");
+  GtkListStore * store = GTK_LIST_STORE (gtk_entry_completion_get_model (GTK_ENTRY_COMPLETION (completion)));
+  JsonReader * reader = json_reader_new (json_parser_get_root (JSON_PARSER (object)));
+
+  if (!json_reader_is_array (reader))
+    return;
+
+  gint i, count = json_reader_count_elements (reader);
+  for (i = 0; i < count; ++i) {
+    if (!json_reader_read_element (reader, i))
+      continue;
+
+    if (json_reader_is_object (reader)) {
+      const gchar * name = NULL;
+      const gchar * admin1 = NULL;
+      const gchar * country = NULL;
+      const gchar * longitude = NULL;
+      const gchar * latitude = NULL;
+      if (json_reader_read_member (reader, "name")) {
+        name = json_reader_get_string_value (reader);
+        json_reader_end_member (reader);
+      }
+      if (json_reader_read_member (reader, "admin1")) {
+        admin1 = json_reader_get_string_value (reader);
+        json_reader_end_member (reader);
+      }
+      if (json_reader_read_member (reader, "country")) {
+        country = json_reader_get_string_value (reader);
+        json_reader_end_member (reader);
+      }
+      if (json_reader_read_member (reader, "longitude")) {
+        longitude = json_reader_get_string_value (reader);
+        json_reader_end_member (reader);
+      }
+      if (json_reader_read_member (reader, "latitude")) {
+        latitude = json_reader_get_string_value (reader);
+        json_reader_end_member (reader);
+      }
+
+g_print("adding %s\n", name);
+      GtkTreeIter iter;
+      gtk_list_store_append (store, &iter);
+      gtk_list_store_set (store, &iter,
+                          TIMEZONE_COMPLETION_ZONE, NULL,
+                          TIMEZONE_COMPLETION_NAME, name,
+                          TIMEZONE_COMPLETION_ADMIN1, admin1,
+                          TIMEZONE_COMPLETION_COUNTRY, country,
+                          TIMEZONE_COMPLETION_LONGITUDE, longitude,
+                          TIMEZONE_COMPLETION_LATITUDE, latitude,
+                          -1);
+    }
+
+    json_reader_end_element (reader);
+  }
+
+  g_hash_table_insert (priv->request_table, g_strdup (priv->request_text), NULL);
+}
+
+static void
+geonames_data_ready (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  TimezoneCompletion * completion = TIMEZONE_COMPLETION (user_data);
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (completion);
+  GError * error = NULL;
+  GFileInputStream * stream;
+
+  stream = g_file_read_finish (G_FILE (object), res, &error);
+
+  if (priv->cancel && (error == NULL || error->code != G_IO_ERROR_CANCELLED)) {
+    g_cancellable_reset (priv->cancel);
+  }
+
+  if (error != NULL) {
+    g_warning ("Could not connect to geoname lookup server: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+  JsonParser * parser = json_parser_new ();
+  json_parser_load_from_stream_async (parser, G_INPUT_STREAM (stream), priv->cancel,
+                                      json_parse_ready, user_data);
+}
+
+static gboolean
+request_zones (TimezoneCompletion * completion)
+{
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (completion);
+
+  priv->queued_request = 0;
+
+g_print("requesting json?\n");
+  if (priv->entry == NULL) {
+    return FALSE;
+  }
+
+  const gchar * text = gtk_entry_get_text (priv->entry);
+
+  if (g_hash_table_lookup_extended (priv->request_table, text, NULL, NULL))
+    return FALSE; // already looked this up
+
+  /* Cancel any ongoing request */
+  if (priv->cancel) {
+    g_cancellable_cancel (priv->cancel);
+    g_cancellable_reset (priv->cancel);
+  }
+  g_free (priv->request_text);
+
+  priv->request_text = g_strdup (text);
+
+g_print("requesting json now\n");
+  gchar * escaped = g_uri_escape_string (text, NULL, FALSE);
+  gchar * url = g_strdup_printf (GEONAME_URL, escaped, "11.04");
+
+  GFile * file =  g_file_new_for_uri (url);
+  g_file_read_async (file, G_PRIORITY_DEFAULT, priv->cancel,
+                     geonames_data_ready, completion);
+
+  return FALSE;
+}
+
+static void
+entry_changed (GtkEntry * entry, TimezoneCompletion * completion)
+{
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (completion);
+
+  if (priv->queued_request) {
+    g_source_remove (priv->queued_request);
+  }
+  priv->queued_request = g_timeout_add (300, (GSourceFunc)request_zones, completion);
+}
+
+void
+timezone_completion_watch_entry (TimezoneCompletion * completion, GtkEntry * entry)
+{
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (completion);
+
+  if (priv->entry) {
+    g_source_remove (priv->changed_id);
+    g_object_remove_weak_pointer (G_OBJECT (priv->entry), (gpointer *)&priv->entry);
+  }
+
+  guint id = g_signal_connect (entry, "changed", G_CALLBACK (entry_changed), completion);
+  priv->changed_id = id;
+
+  priv->entry = entry;
+  g_object_add_weak_pointer (G_OBJECT (entry), (gpointer *)&priv->entry);
+}
+
 static GtkListStore *
 get_initial_model (void)
 {
   TzDB * db = tz_load_db ();
   GPtrArray * locations = tz_get_locations (db);
 
-  GtkListStore * store = gtk_list_store_new (TIMEZONE_COMPLETION_LAST, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+  GtkListStore * store = gtk_list_store_new (TIMEZONE_COMPLETION_LAST,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING);
 
   gint i;
   for (i = 0; i < locations->len; ++i) {
@@ -100,23 +281,57 @@ timezone_completion_class_init (TimezoneCompletionClass *klass)
 }
 
 static void
-timezone_completion_init (TimezoneCompletion *self)
+timezone_completion_init (TimezoneCompletion * self)
 {
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (self);
+
   GtkListStore * model = get_initial_model ();
   gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (self), GTK_TREE_MODEL (model));
   gtk_entry_completion_set_text_column (GTK_ENTRY_COMPLETION (self), TIMEZONE_COMPLETION_NAME);
+
+  priv->cancel = g_cancellable_new ();
+
+  priv->request_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
   return;
 }
 
 static void
-timezone_completion_dispose (GObject *object)
+timezone_completion_dispose (GObject * object)
 {
   G_OBJECT_CLASS (timezone_completion_parent_class)->dispose (object);
+
+  TimezoneCompletion * completion = TIMEZONE_COMPLETION (object);
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (completion);
+
+  if (priv->changed_id) {
+    g_source_remove (priv->changed_id);
+    priv->changed_id = 0;
+  }
+
+  if (priv->entry != NULL) {
+    g_object_remove_weak_pointer (G_OBJECT (priv->entry), (gpointer *)&priv->entry);
+  }
+
+  if (priv->queued_request) {
+    g_source_remove (priv->queued_request);
+    priv->queued_request = 0;
+  }
+
+  if (priv->cancel != NULL) {
+    g_cancellable_cancel (priv->cancel);
+    g_object_unref (priv->cancel);
+    priv->cancel = NULL;
+  }
+
+  g_free (priv->request_text);
+  g_hash_table_destroy (priv->request_table);
+
   return;
 }
 
 static void
-timezone_completion_finalize (GObject *object)
+timezone_completion_finalize (GObject * object)
 {
   G_OBJECT_CLASS (timezone_completion_parent_class)->finalize (object);
   return;
diff --git a/src/timezone-completion.h b/src/timezone-completion.h
index 6b3ac2b..fdfb234 100644
--- a/src/timezone-completion.h
+++ b/src/timezone-completion.h
@@ -45,13 +45,17 @@ struct _TimezoneCompletion {
   GtkEntryCompletion parent;
 };
 
-#define TIMEZONE_COMPLETION_ZONE    0
-#define TIMEZONE_COMPLETION_NAME    1
-#define TIMEZONE_COMPLETION_COUNTRY 2
-#define TIMEZONE_COMPLETION_LAST    3
+#define TIMEZONE_COMPLETION_ZONE      0
+#define TIMEZONE_COMPLETION_NAME      1
+#define TIMEZONE_COMPLETION_ADMIN1    2
+#define TIMEZONE_COMPLETION_COUNTRY   3
+#define TIMEZONE_COMPLETION_LONGITUDE 4
+#define TIMEZONE_COMPLETION_LATITUDE  5
+#define TIMEZONE_COMPLETION_LAST      6
 
 GType timezone_completion_get_type (void);
 TimezoneCompletion * timezone_completion_new ();
+void timezone_completion_watch_entry (TimezoneCompletion * completion, GtkEntry * entry);
 
 G_END_DECLS
 
diff --git a/src/utils.c b/src/utils.c
index 69143b9..f73ed14 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -20,10 +20,17 @@ You should have received a copy of the GNU General Public License along
 with this program.  If not, see .
 */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include 
+#include 
 #include 
 #include 
 #include 
 #include "utils.h"
+#include "settings-shared.h"
 
 /* Check the system locale setting to see if the format is 24-hour
    time or 12-hour time */
@@ -43,3 +50,184 @@ is_locale_12h (void)
 	return TRUE;
 }
 
+void
+split_settings_location (const gchar * location, gchar ** zone, gchar ** name)
+{
+  gchar * location_dup = g_strdup (location);
+  gchar * first = strchr (location_dup, ' ');
+
+  if (first) {
+    first[0] = 0;
+  }
+
+  if (zone) {
+    *zone = location_dup;
+  }
+
+  if (name) {
+    gchar * after = first ? g_strstrip (first + 1) : NULL;
+    if (after == NULL || after[0] == 0) {
+      /* Make up name from zone */
+      gchar * slash = strrchr (location_dup, '/');
+      after = slash ? slash + 1 : location_dup;
+    }
+
+    *name = g_strdup (after);
+  }
+}
+
+/* Translate msg according to the locale specified by LC_TIME */
+static char *
+T_(const char *msg)
+{
+	/* General strategy here is to make sure LANGUAGE is empty (since that
+	   trumps all LC_* vars) and then to temporarily swap LC_TIME and
+	   LC_MESSAGES.  Then have gettext translate msg.
+
+	   We strdup the strings because the setlocale & *env functions do not
+	   guarantee anything about the storage used for the string, and thus
+	   the string may not be portably safe after multiple calls.
+
+	   Note that while you might think g_dcgettext would do the trick here,
+	   that actually looks in /usr/share/locale/XX/LC_TIME, not the
+	   LC_MESSAGES directory, so we won't find any translation there.
+	*/
+	char *message_locale = g_strdup(setlocale(LC_MESSAGES, NULL));
+	char *time_locale = g_strdup(setlocale(LC_TIME, NULL));
+	char *language = g_strdup(g_getenv("LANGUAGE"));
+	char *rv;
+	g_unsetenv("LANGUAGE");
+	setlocale(LC_MESSAGES, time_locale);
+
+	/* Get the LC_TIME version */
+	rv = _(msg);
+
+	/* Put everything back the way it was */
+	setlocale(LC_MESSAGES, message_locale);
+	g_setenv("LANGUAGE", language, TRUE);
+	g_free(message_locale);
+	g_free(time_locale);
+	g_free(language);
+	return rv;
+}
+
+/* Tries to figure out what our format string should be.  Lots
+   of translator comments in here. */
+gchar *
+generate_format_string_full (gboolean show_day, gboolean show_date)
+{
+	gboolean twelvehour = TRUE;
+
+	GSettings * settings = g_settings_new (SETTINGS_INTERFACE);
+	gint time_mode = g_settings_get_enum (settings, SETTINGS_TIME_FORMAT_S);
+	gboolean show_seconds = g_settings_get_boolean (settings, SETTINGS_SHOW_SECONDS_S);
+	g_object_unref (settings);
+
+	if (time_mode == SETTINGS_TIME_LOCALE) {
+		twelvehour = is_locale_12h();
+	} else if (time_mode == SETTINGS_TIME_24_HOUR) {
+		twelvehour = FALSE;
+	}
+
+	const gchar * time_string = NULL;
+	if (twelvehour) {
+		if (show_seconds) {
+			/* TRANSLATORS: A format string for the strftime function for
+			   a clock showing 12-hour time with seconds. */
+			time_string = T_("%l:%M:%S %p");
+		} else {
+			time_string = T_(DEFAULT_TIME_12_FORMAT);
+		}
+	} else {
+		if (show_seconds) {
+			/* TRANSLATORS: A format string for the strftime function for
+			   a clock showing 24-hour time with seconds. */
+			time_string = T_("%H:%M:%S");
+		} else {
+			time_string = T_(DEFAULT_TIME_24_FORMAT);
+		}
+	}
+	
+	/* Checkpoint, let's not fail */
+	g_return_val_if_fail(time_string != NULL, g_strdup(DEFAULT_TIME_FORMAT));
+
+	/* If there's no date or day let's just leave now and
+	   not worry about the rest of this code */
+	if (!show_date && !show_day) {
+		return g_strdup(time_string);
+	}
+
+	const gchar * date_string = NULL;
+	if (show_date && show_day) {
+		/* TRANSLATORS:  This is a format string passed to strftime to represent
+		   the day of the week, the month and the day of the month. */
+		date_string = T_("%a %b %e");
+	} else if (show_date) {
+		/* TRANSLATORS:  This is a format string passed to strftime to represent
+		   the month and the day of the month. */
+		date_string = T_("%b %e");
+	} else if (show_day) {
+		/* TRANSLATORS:  This is a format string passed to strftime to represent
+		   the day of the week. */
+		date_string = T_("%a");
+	}
+
+	/* Check point, we should have a date string */
+	g_return_val_if_fail(date_string != NULL, g_strdup(time_string));
+
+	/* TRANSLATORS: This is a format string passed to strftime to combine the
+	   date and the time.  The value of "%s, %s" would result in a string like
+	   this in US English 12-hour time: 'Fri Jul 16, 11:50 AM' */
+	return g_strdup_printf(T_("%s, %s"), date_string, time_string);
+}
+
+gchar *
+generate_format_string_at_time (GDateTime * time)
+{
+	/* This is a bit less free-form than for the main "now" time label. */
+	/* If it is today, just the time should be shown (e.g. “3:55 PM”)
+           If it is a different day this week, the day and time should be shown (e.g. “Wed 3:55 PM”)
+           If it is after this week, the day, date, and time should be shown (e.g. “Wed 21 Apr 3:55 PM”). 
+           In addition, when presenting the times of upcoming events, the time should be followed by the timezone if it is different from the one the computer is currently set to. For example, “Wed 3:55 PM UTC−5”. */
+	gboolean show_day = FALSE;
+	gboolean show_date = FALSE;
+
+	GDateTime * now = g_date_time_new_now_local();
+
+	/* First, are we same day? */
+	gint time_year, time_month, time_day;
+	gint now_year, now_month, now_day;
+	g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
+	g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
+
+	if (time_year != now_year ||
+	    time_month != now_month ||
+	    time_day != now_day) {
+		/* OK, different days so we must at least show the day. */
+		show_day = TRUE;
+
+		/* Is it this week? */
+		/* Here, we define "is this week" as yesterday, today, or the next five days */
+		GDateTime * past = g_date_time_add_days(now, -1);
+		GDateTime * future = g_date_time_add_days(now, 5);
+		GDateTime * past_bound = g_date_time_new_local(g_date_time_get_year(past),
+		                                               g_date_time_get_month(past),
+		                                               g_date_time_get_day_of_month(past),
+		                                               0, 0, 0.0);
+		GDateTime * future_bound = g_date_time_new_local(g_date_time_get_year(future),
+		                                                 g_date_time_get_month(future),
+		                                                 g_date_time_get_day_of_month(future),
+		                                                 23, 59, 59.9);
+		if (g_date_time_compare(time, past_bound) < 0 ||
+		    g_date_time_compare(time, future_bound) > 0) {
+			show_date = TRUE;
+		}
+		g_date_time_unref(past);
+		g_date_time_unref(future);
+		g_date_time_unref(past_bound);
+		g_date_time_unref(future_bound);
+	}
+
+	return generate_format_string_full(show_day, show_date);
+}
+
diff --git a/src/utils.h b/src/utils.h
index f6305c8..5f7842c 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -28,6 +28,9 @@ with this program.  If not, see .
 G_BEGIN_DECLS
 
 gboolean is_locale_12h (void);
+void split_settings_location (const gchar * location, gchar ** zone, gchar ** name);
+gchar * generate_format_string_full (gboolean show_day, gboolean show_date);
+gchar * generate_format_string_at_time (GDateTime * time);
 
 G_END_DECLS
 
-- 
cgit v1.2.3


From b3a34d487c8c3724752b522fd352c96ba0bcf1a4 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 14:07:19 -0500
Subject: add week-start controls and settings

---
 data/com.canonical.indicator.datetime.gschema.xml | 12 +++++
 data/datetime-dialog.ui                           |  5 ++-
 src/datetime-prefs.c                              | 53 +++++++++++++++++++++--
 src/settings-shared.h                             |  2 +-
 src/utils.c                                       | 11 +++++
 src/utils.h                                       |  1 +
 6 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/data/com.canonical.indicator.datetime.gschema.xml b/data/com.canonical.indicator.datetime.gschema.xml
index b33f34e..5361896 100644
--- a/data/com.canonical.indicator.datetime.gschema.xml
+++ b/data/com.canonical.indicator.datetime.gschema.xml
@@ -5,6 +5,11 @@
 		
 		
 	
+	
+		
+		
+		
+	
 	
 		
 			true
@@ -78,6 +83,13 @@
 			  Shows the week numbers in the monthly calendar in indicator-datetime's menu.
 			
 		
+		
+			'locale-default'
+			When the week starts
+			
+			  Controls whether weeks in the calendar are shown to start on Sunday or Monday.
+			
+		
 		
 			true
 			Show events in the indicator
diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui
index 8b48702..c2a39b9 100644
--- a/data/datetime-dialog.ui
+++ b/data/datetime-dialog.ui
@@ -578,6 +578,7 @@
                                   
                                     True
                                     False
+                                    6
                                     
                                       
                                         Include week num_bers
@@ -597,8 +598,8 @@
                                     
                                     
                                       
+                                        True
                                         False
-                                        True
                                         0
                                         Week begins on:
                                       
@@ -610,8 +611,8 @@
                                     
                                     
                                       
+                                        True
                                         False
-                                        True
                                         True
                                         
                                           
diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index 622a999..44b9b24 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -29,7 +29,7 @@ with this program.  If not, see .
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -85,6 +85,45 @@ bind_hours_get (GValue * value, GVariant * variant, gpointer user_data)
   return TRUE;
 }
 
+/* Turns the boolean property into a string gsettings */
+static GVariant *
+bind_week_start_set (const GValue * value, const GVariantType * type, gpointer user_data)
+{
+  const gchar * output = NULL;
+  gboolean is_sunday_button = (gboolean)GPOINTER_TO_INT(user_data);
+
+  if (g_value_get_boolean(value)) {
+    /* Only do anything if we're setting active = true */
+    output = is_sunday_button ? "sunday" : "monday";
+  } else {
+    return NULL;
+  }
+
+  return g_variant_new_string (output);
+}
+
+/* Turns a string gsettings into a boolean property */
+static gboolean
+bind_week_start_get (GValue * value, GVariant * variant, gpointer user_data)
+{
+  const gchar * str = g_variant_get_string(variant, NULL);
+  gboolean output = FALSE;
+  gboolean is_sunday_button = (gboolean)GPOINTER_TO_INT(user_data);
+
+  if (g_strcmp0(str, "locale-default") == 0) {
+    output = (is_sunday_button == is_locale_week_start_sunday ());
+  } else if (g_strcmp0(str, "sunday") == 0) {
+    output = is_sunday_button;
+  } else if (g_strcmp0(str, "monday") == 0) {
+    output = !is_sunday_button;
+  } else {
+    return FALSE;
+  }
+
+  g_value_set_boolean (value, output);
+  return TRUE;
+}
+
 static void
 widget_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent)
 {
@@ -473,8 +512,16 @@ create_dialog (void)
                    "active", G_SETTINGS_BIND_DEFAULT);
   g_settings_bind (conf, SETTINGS_SHOW_WEEK_NUMBERS_S, WIG ("includeWeekNumbersCheck"),
                    "active", G_SETTINGS_BIND_DEFAULT);
-  /*g_settings_bind_(conf, SETTINGS_WEEK_BEGINS_SUNDAY_S, WIG ("startOnSundayRadio"),
-                   "active", G_SETTINGS_BIND_DEFAULT);*/
+  g_settings_bind_with_mapping (conf, SETTINGS_WEEK_START_S,
+                                WIG ("startOnSundayRadio"), "active",
+                                G_SETTINGS_BIND_DEFAULT,
+                                bind_week_start_get, bind_week_start_set,
+                                GINT_TO_POINTER(TRUE), NULL);
+  g_settings_bind_with_mapping (conf, SETTINGS_WEEK_START_S,
+                                WIG ("startOnMondayRadio"), "active",
+                                G_SETTINGS_BIND_DEFAULT,
+                                bind_week_start_get, bind_week_start_set,
+                                GINT_TO_POINTER(FALSE), NULL);
   g_settings_bind (conf, SETTINGS_SHOW_EVENTS_S, WIG ("showEventsCheck"),
                    "active", G_SETTINGS_BIND_DEFAULT);
   g_settings_bind (conf, SETTINGS_SHOW_LOCATIONS_S, WIG ("showLocationsCheck"),
diff --git a/src/settings-shared.h b/src/settings-shared.h
index d866b81..b8e1789 100644
--- a/src/settings-shared.h
+++ b/src/settings-shared.h
@@ -33,7 +33,7 @@ with this program.  If not, see .
 #define SETTINGS_CUSTOM_TIME_FORMAT_S   "custom-time-format"
 #define SETTINGS_SHOW_CALENDAR_S        "show-calendar"
 #define SETTINGS_SHOW_WEEK_NUMBERS_S    "show-week-numbers"
-#define SETTINGS_WEEK_BEGINS_SUNDAY_S   "week-begins-sunday"
+#define SETTINGS_WEEK_START_S           "week-start"
 #define SETTINGS_SHOW_EVENTS_S          "show-events"
 #define SETTINGS_SHOW_LOCATIONS_S       "show-locations"
 #define SETTINGS_LOCATIONS_S            "locations"
diff --git a/src/utils.c b/src/utils.c
index f73ed14..89c499b 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -50,6 +50,17 @@ is_locale_12h (void)
 	return TRUE;
 }
 
+/* Check the system locale setting to see if the week starts on Sunday or Monday */
+gboolean
+is_locale_week_start_sunday (void)
+{
+	const char * week_1stday = nl_langinfo (_NL_TIME_WEEK_1STDAY);
+
+  /* This appears to be a special value that libc uses for Sunday, it's not
+     really a string */
+  return (GPOINTER_TO_INT (week_1stday) == 19971130);
+}
+
 void
 split_settings_location (const gchar * location, gchar ** zone, gchar ** name)
 {
diff --git a/src/utils.h b/src/utils.h
index 5f7842c..3dc8df1 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -28,6 +28,7 @@ with this program.  If not, see .
 G_BEGIN_DECLS
 
 gboolean is_locale_12h (void);
+gboolean is_locale_week_start_sunday (void);
 void split_settings_location (const gchar * location, gchar ** zone, gchar ** name);
 gchar * generate_format_string_full (gboolean show_day, gboolean show_date);
 gchar * generate_format_string_at_time (GDateTime * time);
-- 
cgit v1.2.3


From 415577b327454a934d48ad06c86c2aaa75cc0adf Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 14:08:28 -0500
Subject: whoops, uncomment polkit bits

---
 src/datetime-prefs.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index 44b9b24..20f9829 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -144,7 +144,7 @@ add_widget_dependency (GtkWidget * parent, GtkWidget * dependent)
   widget_dependency_cb (parent, NULL, dependent);
 }
 
-/*static void
+static void
 polkit_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent)
 {
   gboolean authorized, sensitive;
@@ -162,7 +162,7 @@ add_polkit_dependency (GtkWidget * parent, GtkWidget * dependent)
   g_signal_connect (parent, "notify::sensitive", G_CALLBACK(polkit_dependency_cb),
                     dependent);
   polkit_dependency_cb (parent, NULL, dependent);
-}*/
+}
 
 static void
 dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command)
@@ -532,7 +532,7 @@ create_dialog (void)
   add_widget_dependency (WIG ("showClockCheck"), WIG ("clockOptions"));
   add_widget_dependency (WIG ("showLocationsCheck"), WIG ("locationsButton"));
   add_widget_dependency (WIG ("manualTimeRadio"), WIG ("manualOptions"));
-  //add_polkit_dependency (polkit_button, WIG ("timeDateOptions"));
+  add_polkit_dependency (polkit_button, WIG ("timeDateOptions"));
 
   /* Hacky proxy test for whether evolution-data-server is installed */
   gchar * evo_path = g_find_program_in_path ("evolution");
-- 
cgit v1.2.3


From cf3ae1adfd378d4bfb3a9cf02609ba45d9f764a8 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 14:42:24 -0500
Subject: hook show-locations up

---
 src/datetime-service.c | 33 ++++++++++++++++++++++-----------
 src/settings-shared.h  |  2 --
 2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/src/datetime-service.c b/src/datetime-service.c
index 1f3eac6..45efbf6 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -114,6 +114,8 @@ check_timezone_sync (void) {
 		g_debug("Timezones are different");
 	}
 
+	gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
+
 	if (geo_location != NULL && current_location != NULL) {
 		g_debug("Got timezone %s", current_timezone);
 		g_debug("Got timezone %s", geo_timezone);
@@ -144,7 +146,7 @@ check_timezone_sync (void) {
 				// TODO work out the current location name in a nice way
 				dbusmenu_menuitem_property_set (current_location, TIMEZONE_MENUITEM_PROP_ZONE, label);
 				// TODO work out the current time at that location 
-				dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+				dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 				dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
 			} else {
 				g_debug("Label for current location is null, this shouldn't happen");
@@ -153,20 +155,20 @@ check_timezone_sync (void) {
 				// TODO work out the geo location name in a nice way
 				dbusmenu_menuitem_property_set (geo_location, TIMEZONE_MENUITEM_PROP_ZONE, geo_timezone);
 				// TODO work out the current time at that location 
-				dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+				dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 			}
 		} else {
 			// TODO work out the geo location name in a nice way
 			dbusmenu_menuitem_property_set (geo_location, TIMEZONE_MENUITEM_PROP_ZONE, geo_timezone);
 			// TODO work out the current time at that location 
-			dbusmenu_menuitem_property_set_bool(geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+			dbusmenu_menuitem_property_set_bool(geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 			
 			// TODO work out the current location name in a nice way
 			dbusmenu_menuitem_property_set (current_location, TIMEZONE_MENUITEM_PROP_ZONE, current_timezone);
 			// TODO work out the current time at that location 
 			dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
-			dbusmenu_menuitem_property_set_bool(current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-			dbusmenu_menuitem_property_set_bool(locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+			dbusmenu_menuitem_property_set_bool(current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
+			dbusmenu_menuitem_property_set_bool(locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 		}
 	}
 	g_debug("Finished checking timezone sync");
@@ -368,10 +370,8 @@ update_timezone_menu_items(gpointer user_data) {
 	
 	/* Remove all of the previous locations */
 	if (dconflocations != NULL) {
-		g_debug("Freeing old locations");
 		while (dconflocations != NULL) {
 			DbusmenuMenuitem * litem =  DBUSMENU_MENUITEM(dconflocations->data);
-			g_debug("Freeing old location: %p", litem);
 			// Remove all the existing menu items which are in dconflocations.
 			dconflocations = g_list_remove(dconflocations, litem);
 			dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem));
@@ -379,11 +379,13 @@ update_timezone_menu_items(gpointer user_data) {
 		}
 	}
 	
+	gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
+
 	// TODO: Remove items from the dconflocations at the end of the iteration
 	// Make sure if there are multiple locations, our current location is shown
 	if (len > 0) {
-		dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-		dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+		dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
+		dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 		dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
 	} else {
 		g_debug("No locations configured (Empty List)");
@@ -401,7 +403,7 @@ update_timezone_menu_items(gpointer user_data) {
 			dbusmenu_menuitem_property_set		(item, TIMEZONE_MENUITEM_PROP_ZONE, locations[i]);
 			dbusmenu_menuitem_property_set_bool (item, TIMEZONE_MENUITEM_PROP_RADIO, FALSE);
 			dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
-			dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+			dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 			dbusmenu_menuitem_child_add_position (root, item, offset++);
 			g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
 			dconflocations = g_list_append(dconflocations, item);
@@ -727,6 +729,13 @@ check_for_timeadmin (gpointer user_data)
 	return FALSE;
 }
 
+static void
+show_locations_changed (void)
+{
+	/* Re-calculate */
+	check_timezone_sync();
+}
+
 /* Does the work to build the default menu, really calls out
    to other functions but this is the core to clean up the
    main function. */
@@ -757,7 +766,7 @@ build_menus (DbusmenuMenuitem * root)
 	
 	locations_separator = dbusmenu_menuitem_new();
 	dbusmenu_menuitem_property_set(locations_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-	dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+	dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
 	dbusmenu_menuitem_child_append(root, locations_separator);
 
 	geo_location = dbusmenu_menuitem_new();
@@ -778,6 +787,8 @@ build_menus (DbusmenuMenuitem * root)
 	
 	check_timezone_sync();
 	
+	g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
+
 	DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
 	dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
 	dbusmenu_menuitem_child_append(root, separator);
diff --git a/src/settings-shared.h b/src/settings-shared.h
index b8e1789..a4fac24 100644
--- a/src/settings-shared.h
+++ b/src/settings-shared.h
@@ -22,8 +22,6 @@ with this program.  If not, see .
 #ifndef __DATETIME_SETTINGS_SHARED_H__
 #define __DATETIME_SETTINGS_SHARED_H__
 
-#include 
-
 #define SETTINGS_INTERFACE              "com.canonical.indicator.datetime"
 #define SETTINGS_SHOW_CLOCK_S           "show-clock"
 #define SETTINGS_TIME_FORMAT_S          "time-format"
-- 
cgit v1.2.3


From 3488f85406e03ebdbecfcc25f520689f300f8f9a Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 14:47:10 -0500
Subject: make map larger

---
 data/datetime-dialog.ui | 1 +
 1 file changed, 1 insertion(+)

diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui
index c2a39b9..b8d0777 100644
--- a/data/datetime-dialog.ui
+++ b/data/datetime-dialog.ui
@@ -158,6 +158,7 @@
                     6
                     
                       
+                        300
                         True
                         False
                         0
-- 
cgit v1.2.3


From 02a56bbe87dba95388735c9961345b5166940b1c Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 15:13:42 -0500
Subject: disable clicking on locations; use pretty zone names in indicator

---
 src/Makefile.am          |  2 ++
 src/datetime-service.c   | 64 ++++++++++++++----------------------------------
 src/dbus-shared.h        |  3 ++-
 src/indicator-datetime.c | 10 +++++---
 src/utils.c              | 13 +++++++---
 5 files changed, 37 insertions(+), 55 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 7e8ac4b..6d388c7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,8 @@ indicator_datetime_service_SOURCES = \
 	calendar-menu-item.c \
 	calendar-menu-item.h \
 	datetime-service.c \
+	utils.c \
+	utils.h \
 	dbus-shared.h \
 	settings-shared.h
 indicator_datetime_service_CFLAGS = \
diff --git a/src/datetime-service.c b/src/datetime-service.c
index 45efbf6..ab609c4 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -53,6 +53,7 @@ with this program.  If not, see .
 #include "datetime-interface.h"
 #include "dbus-shared.h"
 #include "settings-shared.h"
+#include "utils.h"
 
 
 static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data);
@@ -90,6 +91,16 @@ static GeoclueAddress * geo_address = NULL;
 static gchar 			* current_timezone = NULL;
 static gchar 			* geo_timezone = NULL;
 
+static void
+set_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
+{
+	gchar * zone, * name;
+	split_settings_location (location, &zone, &name);
+
+	dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_NAME, name);
+	dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, zone);
+}
+
 /* Check to see if our timezones are the same */
 static void
 check_timezone_sync (void) {
@@ -144,7 +155,7 @@ check_timezone_sync (void) {
 			
 			if (label != NULL) {
 				// TODO work out the current location name in a nice way
-				dbusmenu_menuitem_property_set (current_location, TIMEZONE_MENUITEM_PROP_ZONE, label);
+				set_timezone_label (current_location, label);
 				// TODO work out the current time at that location 
 				dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 				dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
@@ -153,18 +164,18 @@ check_timezone_sync (void) {
 			}
 			if (geo_timezone != NULL) {	
 				// TODO work out the geo location name in a nice way
-				dbusmenu_menuitem_property_set (geo_location, TIMEZONE_MENUITEM_PROP_ZONE, geo_timezone);
+				set_timezone_label (geo_location, geo_timezone);
 				// TODO work out the current time at that location 
 				dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 			}
 		} else {
 			// TODO work out the geo location name in a nice way
-			dbusmenu_menuitem_property_set (geo_location, TIMEZONE_MENUITEM_PROP_ZONE, geo_timezone);
+			set_timezone_label (geo_location, geo_timezone);
 			// TODO work out the current time at that location 
 			dbusmenu_menuitem_property_set_bool(geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 			
 			// TODO work out the current location name in a nice way
-			dbusmenu_menuitem_property_set (current_location, TIMEZONE_MENUITEM_PROP_ZONE, current_timezone);
+			set_timezone_label (current_location, current_timezone);
 			// TODO work out the current time at that location 
 			dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
 			dbusmenu_menuitem_property_set_bool(current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
@@ -211,42 +222,6 @@ update_current_timezone (void) {
 	return;
 }
 
-/* See how our timezone setting went */
-static void
-quick_set_tz_cb (OobsObject * obj, OobsResult result, gpointer user_data)
-{
-	if (result == OOBS_RESULT_OK) {
-		g_debug("Timezone set");
-	} else {
-		g_warning("Unable to quick set timezone");
-	}
-	return;
-}
-
-/* Set the timezone to the Geoclue discovered one */
-static void
-quick_set_tz (DbusmenuMenuitem * menuitem, guint timestamp, gpointer user_data)
-{
-	const gchar * tz = dbusmenu_menuitem_property_get(menuitem, TIMEZONE_MENUITEM_PROP_ZONE);
-
-	g_debug("Quick setting timezone to: %s", tz);
-
-	g_return_if_fail(tz != NULL);
-
-	if (g_strcmp0(tz, current_timezone) == 0)
-		return;
-
-	OobsObject * obj = oobs_time_config_get();
-	g_return_if_fail(obj != NULL);
-
-	OobsTimeConfig * timeconfig = OOBS_TIME_CONFIG(obj);
-	oobs_time_config_set_timezone(timeconfig, tz);
-
-	oobs_object_commit_async(obj, quick_set_tz_cb, NULL);
-
-	return;
-}
-
 /* Updates the label in the date menuitem */
 static gboolean
 update_datetime (gpointer user_data)
@@ -400,12 +375,11 @@ update_timezone_menu_items(gpointer user_data) {
 			g_debug("Adding timezone in update_timezones %s", locations[i]);
 			item = dbusmenu_menuitem_new();
 			dbusmenu_menuitem_property_set      (item, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
-			dbusmenu_menuitem_property_set		(item, TIMEZONE_MENUITEM_PROP_ZONE, locations[i]);
+			set_timezone_label (item, locations[i]);
 			dbusmenu_menuitem_property_set_bool (item, TIMEZONE_MENUITEM_PROP_RADIO, FALSE);
 			dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
 			dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
 			dbusmenu_menuitem_child_add_position (root, item, offset++);
-			g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
 			dconflocations = g_list_append(dconflocations, item);
 		}
 	}
@@ -771,18 +745,16 @@ build_menus (DbusmenuMenuitem * root)
 
 	geo_location = dbusmenu_menuitem_new();
 	dbusmenu_menuitem_property_set      (geo_location, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
-	dbusmenu_menuitem_property_set		(geo_location, TIMEZONE_MENUITEM_PROP_ZONE, "");
+	set_timezone_label (geo_location, "");
 	dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
 	dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-	g_signal_connect(G_OBJECT(geo_location), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
 	dbusmenu_menuitem_child_append(root, geo_location);
 
 	current_location = dbusmenu_menuitem_new();
 	dbusmenu_menuitem_property_set      (current_location, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
-	dbusmenu_menuitem_property_set		(current_location, TIMEZONE_MENUITEM_PROP_ZONE, "");
+	set_timezone_label (current_location, "");
 	dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
 	dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-	g_signal_connect(G_OBJECT(current_location), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
 	dbusmenu_menuitem_child_append(root, current_location);
 	
 	check_timezone_sync();
diff --git a/src/dbus-shared.h b/src/dbus-shared.h
index bad8354..f0f05a9 100644
--- a/src/dbus-shared.h
+++ b/src/dbus-shared.h
@@ -35,5 +35,6 @@ with this program.  If not, see .
 #define APPOINTMENT_MENUITEM_PROP_RIGHT    "appointment-time"
 
 #define TIMEZONE_MENUITEM_TYPE             "timezone-item"	
-#define TIMEZONE_MENUITEM_PROP_ZONE        "timezone-zone"
+#define TIMEZONE_MENUITEM_PROP_ZONE        "timezone-zone"	
+#define TIMEZONE_MENUITEM_PROP_NAME        "timezone-name"
 #define TIMEZONE_MENUITEM_PROP_RADIO       "timezone-radio"
diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c
index fb421cb..33f78c4 100644
--- a/src/indicator-datetime.c
+++ b/src/indicator-datetime.c
@@ -999,13 +999,13 @@ generate_format_string_now (IndicatorDatetime * self)
 static void
 timezone_update_labels (indicator_item_t * mi_data)
 {
-	const gchar * zone_name = dbusmenu_menuitem_property_get(mi_data->mi, TIMEZONE_MENUITEM_PROP_ZONE);
+	const gchar * zone = dbusmenu_menuitem_property_get(mi_data->mi, TIMEZONE_MENUITEM_PROP_ZONE);
+	const gchar * name = dbusmenu_menuitem_property_get(mi_data->mi, TIMEZONE_MENUITEM_PROP_NAME);
 
-	/* TODO: Make zone name a little more user friendly */
-	gtk_label_set_text(GTK_LABEL(mi_data->label), zone_name);
+	gtk_label_set_text(GTK_LABEL(mi_data->label), name);
 
 	/* Show current time in that zone on the right */
-	GTimeZone * tz = g_time_zone_new(zone_name);
+	GTimeZone * tz = g_time_zone_new(zone);
 	set_label_to_time_in_zone(mi_data->self, GTK_LABEL(mi_data->right), tz, NULL, NULL);
 	g_time_zone_unref(tz);
 }
@@ -1051,6 +1051,8 @@ indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant *value,
 		}
 	} else if (!g_strcmp0(prop, TIMEZONE_MENUITEM_PROP_ZONE)) {
 		timezone_update_labels(mi_data);
+	} else if (!g_strcmp0(prop, TIMEZONE_MENUITEM_PROP_NAME)) {
+		timezone_update_labels(mi_data);
 	} else if (!g_strcmp0(prop, TIMEZONE_MENUITEM_PROP_RADIO)) {
 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi_data->gmi), g_variant_get_boolean(value));
 	} else {
diff --git a/src/utils.c b/src/utils.c
index 89c499b..20ae958 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -79,11 +79,16 @@ split_settings_location (const gchar * location, gchar ** zone, gchar ** name)
     gchar * after = first ? g_strstrip (first + 1) : NULL;
     if (after == NULL || after[0] == 0) {
       /* Make up name from zone */
-      gchar * slash = strrchr (location_dup, '/');
-      after = slash ? slash + 1 : location_dup;
+      gchar * chr = strrchr (location_dup, '/');
+      after = g_strdup (chr ? chr + 1 : location_dup);
+      while ((chr = strchr (after, '_')) != NULL) { /* and turn underscores to spaces */
+        *chr = ' ';
+      }
+      *name = after;
+    }
+    else {
+      *name = g_strdup (after);
     }
-
-    *name = g_strdup (after);
   }
 }
 
-- 
cgit v1.2.3


From 66f988fe7a494e1aa12c161e415660fba247aaf4 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 15:30:30 -0500
Subject: some cleanup; when map changes, update entry too

---
 src/datetime-prefs.c      | 26 ++++++++++++++++++++------
 src/indicator-datetime.c  |  4 ++--
 src/timezone-completion.c |  4 ----
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index 20f9829..3f5e5e6 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -43,7 +43,8 @@ with this program.  If not, see .
 #define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
 
 GDBusProxy * proxy = NULL;
-GtkWidget * autoRadio = NULL;
+GtkWidget * auto_radio = NULL;
+GtkWidget * tz_entry = NULL;
 CcTimezoneMap * tzmap = NULL;
 
 /* Turns the boolean property into a string gsettings */
@@ -203,14 +204,23 @@ ntp_query_answered (GObject *object, GAsyncResult *res, gpointer user_data)
   gboolean can_use_ntp, is_using_ntp;
   g_variant_get (answers, "(bb)", &can_use_ntp, &is_using_ntp);
 
-  gtk_widget_set_sensitive (GTK_WIDGET (autoRadio), can_use_ntp);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (autoRadio), is_using_ntp);
+  gtk_widget_set_sensitive (GTK_WIDGET (auto_radio), can_use_ntp);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_radio), is_using_ntp);
 
-  g_signal_connect (autoRadio, "notify::active", G_CALLBACK (toggle_ntp), NULL);
+  g_signal_connect (auto_radio, "notify::active", G_CALLBACK (toggle_ntp), NULL);
 
   g_variant_unref (answers);
 }
 
+static void
+sync_entry (const gchar * location)
+{
+  gchar * name;
+  split_settings_location (location, NULL, &name);
+  gtk_entry_set_text (GTK_ENTRY (tz_entry), name);
+  g_free (name);
+}
+
 static void
 tz_changed (CcTimezoneMap * map, TzLocation * location)
 {
@@ -221,6 +231,8 @@ tz_changed (CcTimezoneMap * map, TzLocation * location)
   g_dbus_proxy_call (proxy, "SetTimezone", g_variant_new ("(s)", file),
                      G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "timezone");
   g_free (file);
+
+  sync_entry (location->zone);
 }
 
 static void
@@ -240,6 +252,7 @@ tz_query_answered (GObject *object, GAsyncResult *res, gpointer user_data)
 
   cc_timezone_map_set_timezone (tzmap, timezone);
 
+  sync_entry (timezone);
   g_signal_connect (tzmap, "location-changed", G_CALLBACK (tz_changed), NULL);
 
   g_variant_unref (answers);
@@ -259,7 +272,7 @@ void proxy_ready (GObject *object, GAsyncResult *res, gpointer user_data)
 
   /* And now, do initial proxy configuration */
   g_dbus_proxy_call (proxy, "GetUsingNtp", NULL, G_DBUS_CALL_FLAGS_NONE, -1,
-                     NULL, ntp_query_answered, autoRadio);
+                     NULL, ntp_query_answered, auto_radio);
   g_dbus_proxy_call (proxy, "GetTimezone", NULL, G_DBUS_CALL_FLAGS_NONE, -1,
                      NULL, tz_query_answered, NULL);
 }
@@ -543,7 +556,8 @@ create_dialog (void)
   setup_time_spinner (WIG ("dateSpinner"), WIG ("timeSpinner"), FALSE);
 
   GtkWidget * dlg = WIG ("timeDateDialog");
-  autoRadio = WIG ("automaticTimeRadio");
+  auto_radio = WIG ("automaticTimeRadio");
+  tz_entry = WIG ("timezoneEntry");
 
   g_signal_connect (WIG ("locationsButton"), "clicked", G_CALLBACK (show_locations), dlg);
 
diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c
index 33f78c4..2e336c7 100644
--- a/src/indicator-datetime.c
+++ b/src/indicator-datetime.c
@@ -1176,7 +1176,7 @@ timezone_toggled_cb (GtkCheckMenuItem *checkmenuitem, DbusmenuMenuitem * dbusite
 }
 
 static void
-timezone_destroyed_cb (DbusmenuMenuitem * dbusitem, indicator_item_t * mi_data)
+timezone_destroyed_cb (indicator_item_t * mi_data, DbusmenuMenuitem * dbusitem)
 {
 	IndicatorDatetimePrivate *priv = INDICATOR_DATETIME_GET_PRIVATE(mi_data->self);
 	priv->timezone_items = g_list_remove(priv->timezone_items, mi_data);
@@ -1241,7 +1241,7 @@ new_timezone_item(DbusmenuMenuitem * newitem,
 
 	g_signal_connect(G_OBJECT(mi_data->gmi), "toggled", G_CALLBACK(timezone_toggled_cb), newitem);
 	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(indicator_prop_change_cb), mi_data);
-	g_signal_connect(G_OBJECT(newitem), "destroyed", G_CALLBACK(timezone_destroyed_cb), mi_data);
+	g_object_weak_ref(G_OBJECT(newitem), (GWeakNotify)timezone_destroyed_cb, mi_data);
 
 	return TRUE;
 }
diff --git a/src/timezone-completion.c b/src/timezone-completion.c
index a1b4d00..840b3e4 100644
--- a/src/timezone-completion.c
+++ b/src/timezone-completion.c
@@ -76,7 +76,6 @@ json_parse_ready (GObject *object, GAsyncResult *res, gpointer user_data)
     return;
   }
 
-g_print("got json\n");
   GtkListStore * store = GTK_LIST_STORE (gtk_entry_completion_get_model (GTK_ENTRY_COMPLETION (completion)));
   JsonReader * reader = json_reader_new (json_parser_get_root (JSON_PARSER (object)));
 
@@ -115,7 +114,6 @@ g_print("got json\n");
         json_reader_end_member (reader);
       }
 
-g_print("adding %s\n", name);
       GtkTreeIter iter;
       gtk_list_store_append (store, &iter);
       gtk_list_store_set (store, &iter,
@@ -166,7 +164,6 @@ request_zones (TimezoneCompletion * completion)
 
   priv->queued_request = 0;
 
-g_print("requesting json?\n");
   if (priv->entry == NULL) {
     return FALSE;
   }
@@ -185,7 +182,6 @@ g_print("requesting json?\n");
 
   priv->request_text = g_strdup (text);
 
-g_print("requesting json now\n");
   gchar * escaped = g_uri_escape_string (text, NULL, FALSE);
   gchar * url = g_strdup_printf (GEONAME_URL, escaped, "11.04");
 
-- 
cgit v1.2.3


From d38ff688556788a5d6c8e3f033b460c8ac849039 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 14:46:46 -0600
Subject: skip duplicate completions

---
 src/timezone-completion.c | 55 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 10 deletions(-)

diff --git a/src/timezone-completion.c b/src/timezone-completion.c
index 840b3e4..7f5ad68 100644
--- a/src/timezone-completion.c
+++ b/src/timezone-completion.c
@@ -114,16 +114,51 @@ json_parse_ready (GObject *object, GAsyncResult *res, gpointer user_data)
         json_reader_end_member (reader);
       }
 
+      /* See if we have this in our store already */
       GtkTreeIter iter;
-      gtk_list_store_append (store, &iter);
-      gtk_list_store_set (store, &iter,
-                          TIMEZONE_COMPLETION_ZONE, NULL,
-                          TIMEZONE_COMPLETION_NAME, name,
-                          TIMEZONE_COMPLETION_ADMIN1, admin1,
-                          TIMEZONE_COMPLETION_COUNTRY, country,
-                          TIMEZONE_COMPLETION_LONGITUDE, longitude,
-                          TIMEZONE_COMPLETION_LATITUDE, latitude,
-                          -1);
+      gboolean skip = FALSE;
+      if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+        do {
+          GValue value = {0};
+
+          gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, TIMEZONE_COMPLETION_NAME, &value);
+          if (g_strcmp0 (g_value_get_string (&value), name) != 0) {
+            g_value_unset (&value);
+            continue;
+          }
+          g_value_unset (&value);
+
+          gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, TIMEZONE_COMPLETION_ADMIN1, &value);
+          if (g_strcmp0 (g_value_get_string (&value), admin1) != 0) {
+            g_value_unset (&value);
+            continue;
+          }
+          g_value_unset (&value);
+
+          gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, TIMEZONE_COMPLETION_COUNTRY, &value);
+          if (g_strcmp0 (g_value_get_string (&value), country) != 0) {
+            g_value_unset (&value);
+            continue;
+          }
+          g_value_unset (&value);
+
+          /* Must be the same, skip this one */
+          skip = TRUE;
+          break;
+        } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
+      }
+
+      if (!skip) {
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter,
+                            TIMEZONE_COMPLETION_ZONE, NULL,
+                            TIMEZONE_COMPLETION_NAME, name,
+                            TIMEZONE_COMPLETION_ADMIN1, admin1,
+                            TIMEZONE_COMPLETION_COUNTRY, country,
+                            TIMEZONE_COMPLETION_LONGITUDE, longitude,
+                            TIMEZONE_COMPLETION_LATITUDE, latitude,
+                            -1);
+      }
     }
 
     json_reader_end_element (reader);
@@ -183,7 +218,7 @@ request_zones (TimezoneCompletion * completion)
   priv->request_text = g_strdup (text);
 
   gchar * escaped = g_uri_escape_string (text, NULL, FALSE);
-  gchar * url = g_strdup_printf (GEONAME_URL, escaped, "11.04");
+  gchar * url = g_strdup_printf (GEONAME_URL, escaped, "11.04"); // FIXME: don't hardcode
 
   GFile * file =  g_file_new_for_uri (url);
   g_file_read_async (file, G_PRIORITY_DEFAULT, priv->cancel,
-- 
cgit v1.2.3


From e2fa62d9ad271f26f2a8e4d9297190e0250bb967 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 15:13:11 -0600
Subject: show admin1 and country in completion dropdown

---
 src/timezone-completion.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/timezone-completion.c b/src/timezone-completion.c
index 7f5ad68..ab7ae5e 100644
--- a/src/timezone-completion.c
+++ b/src/timezone-completion.c
@@ -298,6 +298,35 @@ get_initial_model (void)
   return store;
 }
 
+static void
+data_func (GtkCellLayout *cell_layout, GtkCellRenderer *cell,
+           GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
+{
+  GValue name_val = {0}, admin1_val = {0}, country_val = {0};
+  const gchar * name, * admin1, * country;
+
+  gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, TIMEZONE_COMPLETION_NAME, &name_val);
+  gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, TIMEZONE_COMPLETION_ADMIN1, &admin1_val);
+  gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, TIMEZONE_COMPLETION_COUNTRY, &country_val);
+
+  name = g_value_get_string (&name_val);
+  admin1 = g_value_get_string (&admin1_val);
+  country = g_value_get_string (&country_val);
+
+  gchar * user_name;
+  if (admin1 == NULL || admin1[0] == 0) {
+    user_name = g_strdup_printf ("%s (%s)", name, country);
+  } else {
+    user_name = g_strdup_printf ("%s (%s, %s)", name, admin1, country);
+  }
+
+  g_object_set (G_OBJECT (cell), "markup", user_name, NULL);
+
+  g_value_unset (&name_val);
+  g_value_unset (&admin1_val);
+  g_value_unset (&country_val);
+}
+
 static void
 timezone_completion_class_init (TimezoneCompletionClass *klass)
 {
@@ -318,12 +347,16 @@ timezone_completion_init (TimezoneCompletion * self)
 
   GtkListStore * model = get_initial_model ();
   gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (self), GTK_TREE_MODEL (model));
-  gtk_entry_completion_set_text_column (GTK_ENTRY_COMPLETION (self), TIMEZONE_COMPLETION_NAME);
+  g_object_set (G_OBJECT (self), "text-column", TIMEZONE_COMPLETION_NAME, NULL);
 
   priv->cancel = g_cancellable_new ();
 
   priv->request_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
+  GtkCellRenderer * cell = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, TRUE);
+  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (self), cell, data_func, NULL, NULL);
+
   return;
 }
 
-- 
cgit v1.2.3


From ad847471eee3e68c27505af6a35245f9e3f7f532 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 15:26:49 -0600
Subject: add geonames watermark

---
 libmap/README            |  2 +-
 libmap/cc-timezone-map.c | 30 ++++++++++++++++++++++++++++++
 libmap/cc-timezone-map.h |  2 ++
 src/datetime-prefs.c     |  2 ++
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/libmap/README b/libmap/README
index c83c6d8..6766b42 100644
--- a/libmap/README
+++ b/libmap/README
@@ -2,4 +2,4 @@ This static library is a copied version of the code in GNOME 3.0's control cente
 
 Ideally in the future, we can have all three packages using the same code.  But for now, for time reasons (hah), it's just a copy.
 
-To update this copy, put newer versions of the code and data files in place; then fix up any GTK3-isms and add cc_timezone_map_set_coords and friends.
+To update this copy, put newer versions of the code and data files in place; then fix up any GTK3-isms and add cc_timezone_map_set_coords and friends.  And the watermark.
diff --git a/libmap/cc-timezone-map.c b/libmap/cc-timezone-map.c
index 7647925..5ece1c2 100644
--- a/libmap/cc-timezone-map.c
+++ b/libmap/cc-timezone-map.c
@@ -60,6 +60,8 @@ struct _CcTimezoneMapPrivate
 
   gdouble selected_offset;
 
+  gchar *watermark;
+
   TzDB *tzdb;
   TzLocation *location;
   GHashTable *alias_db;
@@ -574,6 +576,12 @@ cc_timezone_map_dispose (GObject *object)
       priv->alias_db = NULL;
     }
 
+  if (priv->watermark)
+    {
+      g_free (priv->watermark);
+      priv->watermark = NULL;
+    }
+
   G_OBJECT_CLASS (cc_timezone_map_parent_class)->dispose (object);
 }
 
@@ -822,6 +830,18 @@ cc_timezone_map_draw (GtkWidget *widget,
       g_object_unref (pin);
     }
 
+  if (priv->watermark) {
+    cairo_text_extents_t extent;
+    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_font_size(cr, 12.0);
+    cairo_set_source_rgba(cr, 1, 1, 1, 0.5);
+    cairo_text_extents(cr, priv->watermark, &extent);
+    cairo_move_to(cr, alloc.width - extent.x_advance + extent.x_bearing - 5,
+                      alloc.height - extent.height - extent.y_bearing - 5);
+    cairo_show_text(cr, priv->watermark);
+    cairo_stroke(cr);
+  }
+
   return TRUE;
 }
 
@@ -1150,6 +1170,16 @@ cc_timezone_map_get_timezone_at_coords (CcTimezoneMap *map, gdouble lon, gdouble
   }
 }
 
+void
+cc_timezone_map_set_watermark (CcTimezoneMap *map, const gchar * watermark)
+{
+  if (map->priv->watermark)
+    g_free (map->priv->watermark);
+
+  map->priv->watermark = g_strdup (watermark);
+  gtk_widget_queue_draw (GTK_WIDGET (map));
+}
+
 TzLocation *
 cc_timezone_map_get_location (CcTimezoneMap *map)
 {
diff --git a/libmap/cc-timezone-map.h b/libmap/cc-timezone-map.h
index 8de986d..ace1107 100644
--- a/libmap/cc-timezone-map.h
+++ b/libmap/cc-timezone-map.h
@@ -70,6 +70,8 @@ GType cc_timezone_map_get_type (void) G_GNUC_CONST;
 
 CcTimezoneMap *cc_timezone_map_new (void);
 
+void cc_timezone_map_set_watermark (CcTimezoneMap * map,
+                                    const gchar * watermark);
 void cc_timezone_map_set_timezone (CcTimezoneMap *map,
                                    const gchar   *timezone);
 void cc_timezone_map_set_coords (CcTimezoneMap *map,
diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index 3f5e5e6..fbadd27 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -494,6 +494,8 @@ create_dialog (void)
   /* Add map */
   tzmap = cc_timezone_map_new ();
   gtk_container_add (GTK_CONTAINER (WIG ("mapBox")), GTK_WIDGET (tzmap));
+  /* Fufill the CC by Attribution license requirements for the Geonames lookup */
+  cc_timezone_map_set_watermark (tzmap, "Geonames.org");
 
   /* And completion entry */
   TimezoneCompletion * completion = timezone_completion_new ();
-- 
cgit v1.2.3


From 7ef186559335f0f82cf2985ada9151f2232d2c90 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Wed, 23 Feb 2011 15:31:18 -0600
Subject: don't have the map draw a highlight if no zone selected

---
 libmap/cc-timezone-map.c | 48 +++++++++++++++++++++++-------------------------
 1 file changed, 23 insertions(+), 25 deletions(-)

diff --git a/libmap/cc-timezone-map.c b/libmap/cc-timezone-map.c
index 5ece1c2..ec12c84 100644
--- a/libmap/cc-timezone-map.c
+++ b/libmap/cc-timezone-map.c
@@ -774,6 +774,23 @@ cc_timezone_map_draw (GtkWidget *widget,
   gdk_cairo_set_source_pixbuf (cr, priv->background, 0, 0);
   cairo_paint (cr);
 
+  /* paint watermark */
+  if (priv->watermark) {
+    cairo_text_extents_t extent;
+    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_font_size(cr, 12.0);
+    cairo_set_source_rgba(cr, 1, 1, 1, 0.5);
+    cairo_text_extents(cr, priv->watermark, &extent);
+    cairo_move_to(cr, alloc.width - extent.x_advance + extent.x_bearing - 5,
+                      alloc.height - extent.height - extent.y_bearing - 5);
+    cairo_show_text(cr, priv->watermark);
+    cairo_stroke(cr);
+  }
+
+  if (!priv->location) {
+    return TRUE;
+  }
+
   /* paint hilight */
   file = g_strdup_printf (DATADIR "/timezone_%s.png",
                           g_ascii_formatd (buf, sizeof (buf),
@@ -810,38 +827,19 @@ cc_timezone_map_draw (GtkWidget *widget,
       g_clear_error (&err);
     }
 
-  if (priv->location)
-    {
-      pointx = convert_longtitude_to_x (priv->location->longitude, alloc.width);
-      pointy = convert_latitude_to_y (priv->location->latitude, alloc.height);
-
-      if (pointy > alloc.height)
-        pointy = alloc.height;
+  pointx = convert_longtitude_to_x (priv->location->longitude, alloc.width);
+  pointy = convert_latitude_to_y (priv->location->latitude, alloc.height);
 
-      if (pin)
-        {
-          gdk_cairo_set_source_pixbuf (cr, pin, pointx - 8, pointy - 14);
-          cairo_paint (cr);
-        }
-    }
+  if (pointy > alloc.height)
+    pointy = alloc.height;
 
   if (pin)
     {
+      gdk_cairo_set_source_pixbuf (cr, pin, pointx - 8, pointy - 14);
+      cairo_paint (cr);
       g_object_unref (pin);
     }
 
-  if (priv->watermark) {
-    cairo_text_extents_t extent;
-    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-    cairo_set_font_size(cr, 12.0);
-    cairo_set_source_rgba(cr, 1, 1, 1, 0.5);
-    cairo_text_extents(cr, priv->watermark, &extent);
-    cairo_move_to(cr, alloc.width - extent.x_advance + extent.x_bearing - 5,
-                      alloc.height - extent.height - extent.y_bearing - 5);
-    cairo_show_text(cr, priv->watermark);
-    cairo_stroke(cr);
-  }
-
   return TRUE;
 }
 
-- 
cgit v1.2.3


From e1ed5129d99c0b7d6f8829a146173b940ce8890d Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Thu, 24 Feb 2011 10:31:33 -0500
Subject: have location column expand

---
 src/datetime-prefs-locations.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c
index e29580f..ce3acaa 100644
--- a/src/datetime-prefs-locations.c
+++ b/src/datetime-prefs-locations.c
@@ -297,6 +297,9 @@ datetime_setup_locations_dialog (GtkWindow * parent, CcTimezoneMap * map)
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1,
                                                _("Location"), cell,
                                                "text", 0, NULL);
+  GtkTreeViewColumn * loc_col = gtk_tree_view_get_column (GTK_TREE_VIEW (tree), 0);
+  gtk_tree_view_column_set_expand (loc_col, TRUE);
+
   cell = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1,
                                                _("Time"), cell,
-- 
cgit v1.2.3


From 671bcdaf530e6723c2208bb98ae9cae1b1dc23c8 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Thu, 24 Feb 2011 11:01:03 -0500
Subject: don't update locations dialog's times when editing

---
 src/datetime-prefs-locations.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c
index ce3acaa..0c9a93c 100644
--- a/src/datetime-prefs-locations.c
+++ b/src/datetime-prefs-locations.c
@@ -152,9 +152,17 @@ handle_edit_started (GtkCellRendererText * renderer, GtkCellEditable * editable,
 }
 
 static gboolean
-update_times (GtkListStore * store)
+update_times (TimezoneCompletion * completion)
 {
   /* For each entry, check zone in column 2 and set column 1 to it's time */
+  GtkListStore * store = GTK_LIST_STORE (g_object_get_data (G_OBJECT (completion), "store"));
+  GObject * cell = G_OBJECT (g_object_get_data (G_OBJECT (completion), "name-cell"));
+
+  gboolean editing;
+  g_object_get (cell, "editing", &editing, NULL);
+  if (editing) { /* No updates while editing, it cancels the edit */
+    return TRUE;
+  }
 
   GDateTime * now = g_date_time_new_now_local ();
 
@@ -299,6 +307,7 @@ datetime_setup_locations_dialog (GtkWindow * parent, CcTimezoneMap * map)
                                                "text", 0, NULL);
   GtkTreeViewColumn * loc_col = gtk_tree_view_get_column (GTK_TREE_VIEW (tree), 0);
   gtk_tree_view_column_set_expand (loc_col, TRUE);
+  g_object_set_data (G_OBJECT (completion), "name-cell", cell);
 
   cell = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1,
@@ -315,8 +324,8 @@ datetime_setup_locations_dialog (GtkWindow * parent, CcTimezoneMap * map)
 
   fill_from_settings (store, conf);
 
-  guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_times, store);
-  update_times (GTK_LIST_STORE (store));
+  guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_times, completion);
+  update_times (completion);
 
   g_object_set_data_full (G_OBJECT (dlg), "conf", g_object_ref (conf), g_object_unref);
   g_object_set_data_full (G_OBJECT (dlg), "completion", completion, g_object_unref);
-- 
cgit v1.2.3


From ef1648eeba51b9c2e29a3890a6057b569c67b543 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Thu, 24 Feb 2011 11:41:37 -0500
Subject: make sure user always sees new model from geonames when we get it

---
 src/timezone-completion.c | 122 ++++++++++++++++++++++++++--------------------
 1 file changed, 68 insertions(+), 54 deletions(-)

diff --git a/src/timezone-completion.c b/src/timezone-completion.c
index ab7ae5e..f570c33 100644
--- a/src/timezone-completion.c
+++ b/src/timezone-completion.c
@@ -37,6 +37,7 @@ enum {
 typedef struct _TimezoneCompletionPrivate TimezoneCompletionPrivate;
 struct _TimezoneCompletionPrivate
 {
+  GtkTreeModel * initial_model;
   GtkEntry *     entry;
   guint          queued_request;
   guint          changed_id;
@@ -57,6 +58,16 @@ static void timezone_completion_finalize   (GObject *object);
 
 G_DEFINE_TYPE (TimezoneCompletion, timezone_completion, GTK_TYPE_ENTRY_COMPLETION);
 
+static void
+save_and_use_model (TimezoneCompletion * completion, GtkTreeModel * model)
+{
+  TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE(completion);
+
+  g_hash_table_insert (priv->request_table, g_strdup (priv->request_text), g_object_ref (model));
+  gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (completion), model);
+  gtk_entry_completion_complete (GTK_ENTRY_COMPLETION (completion));
+}
+
 static void
 json_parse_ready (GObject *object, GAsyncResult *res, gpointer user_data)
 {
@@ -73,10 +84,18 @@ json_parse_ready (GObject *object, GAsyncResult *res, gpointer user_data)
   if (error != NULL) {
     g_warning ("Could not parse geoname JSON data: %s", error->message);
     g_error_free (error);
+    save_and_use_model (completion, priv->initial_model);
     return;
   }
 
-  GtkListStore * store = GTK_LIST_STORE (gtk_entry_completion_get_model (GTK_ENTRY_COMPLETION (completion)));
+  GtkListStore * store = gtk_list_store_new (TIMEZONE_COMPLETION_LAST,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING);
+
   JsonReader * reader = json_reader_new (json_parser_get_root (JSON_PARSER (object)));
 
   if (!json_reader_is_array (reader))
@@ -114,57 +133,23 @@ json_parse_ready (GObject *object, GAsyncResult *res, gpointer user_data)
         json_reader_end_member (reader);
       }
 
-      /* See if we have this in our store already */
       GtkTreeIter iter;
-      gboolean skip = FALSE;
-      if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
-        do {
-          GValue value = {0};
-
-          gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, TIMEZONE_COMPLETION_NAME, &value);
-          if (g_strcmp0 (g_value_get_string (&value), name) != 0) {
-            g_value_unset (&value);
-            continue;
-          }
-          g_value_unset (&value);
-
-          gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, TIMEZONE_COMPLETION_ADMIN1, &value);
-          if (g_strcmp0 (g_value_get_string (&value), admin1) != 0) {
-            g_value_unset (&value);
-            continue;
-          }
-          g_value_unset (&value);
-
-          gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, TIMEZONE_COMPLETION_COUNTRY, &value);
-          if (g_strcmp0 (g_value_get_string (&value), country) != 0) {
-            g_value_unset (&value);
-            continue;
-          }
-          g_value_unset (&value);
-
-          /* Must be the same, skip this one */
-          skip = TRUE;
-          break;
-        } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
-      }
-
-      if (!skip) {
-        gtk_list_store_append (store, &iter);
-        gtk_list_store_set (store, &iter,
-                            TIMEZONE_COMPLETION_ZONE, NULL,
-                            TIMEZONE_COMPLETION_NAME, name,
-                            TIMEZONE_COMPLETION_ADMIN1, admin1,
-                            TIMEZONE_COMPLETION_COUNTRY, country,
-                            TIMEZONE_COMPLETION_LONGITUDE, longitude,
-                            TIMEZONE_COMPLETION_LATITUDE, latitude,
-                            -1);
-      }
+      gtk_list_store_append (store, &iter);
+      gtk_list_store_set (store, &iter,
+                          TIMEZONE_COMPLETION_ZONE, NULL,
+                          TIMEZONE_COMPLETION_NAME, name,
+                          TIMEZONE_COMPLETION_ADMIN1, admin1,
+                          TIMEZONE_COMPLETION_COUNTRY, country,
+                          TIMEZONE_COMPLETION_LONGITUDE, longitude,
+                          TIMEZONE_COMPLETION_LATITUDE, latitude,
+                          -1);
     }
 
     json_reader_end_element (reader);
   }
 
-  g_hash_table_insert (priv->request_table, g_strdup (priv->request_text), NULL);
+  save_and_use_model (completion, GTK_TREE_MODEL (store));
+  g_object_unref (G_OBJECT (store));
 }
 
 static void
@@ -184,6 +169,7 @@ geonames_data_ready (GObject *object, GAsyncResult *res, gpointer user_data)
   if (error != NULL) {
     g_warning ("Could not connect to geoname lookup server: %s", error->message);
     g_error_free (error);
+    save_and_use_model (completion, priv->initial_model);
     return;
   }
 
@@ -205,8 +191,12 @@ request_zones (TimezoneCompletion * completion)
 
   const gchar * text = gtk_entry_get_text (priv->entry);
 
-  if (g_hash_table_lookup_extended (priv->request_table, text, NULL, NULL))
-    return FALSE; // already looked this up
+  gpointer data;
+  if (g_hash_table_lookup_extended (priv->request_table, text, NULL, &data)) {
+    gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (completion), GTK_TREE_MODEL (data));
+    gtk_entry_completion_complete (GTK_ENTRY_COMPLETION (completion));
+    return FALSE;
+  }
 
   /* Cancel any ongoing request */
   if (priv->cancel) {
@@ -327,6 +317,14 @@ data_func (GtkCellLayout *cell_layout, GtkCellRenderer *cell,
   g_value_unset (&country_val);
 }
 
+static gboolean
+match_func (GtkEntryCompletion *completion, const gchar *key,
+            GtkTreeIter *iter, gpointer user_data)
+{
+  // geonames does the work for us
+  return TRUE;
+}
+
 static void
 timezone_completion_class_init (TimezoneCompletionClass *klass)
 {
@@ -345,13 +343,17 @@ timezone_completion_init (TimezoneCompletion * self)
 {
   TimezoneCompletionPrivate * priv = TIMEZONE_COMPLETION_GET_PRIVATE (self);
 
-  GtkListStore * model = get_initial_model ();
-  gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (self), GTK_TREE_MODEL (model));
-  g_object_set (G_OBJECT (self), "text-column", TIMEZONE_COMPLETION_NAME, NULL);
+  priv->initial_model = GTK_TREE_MODEL (get_initial_model ());
+
+  gtk_entry_completion_set_match_func (GTK_ENTRY_COMPLETION (self), match_func, NULL, NULL);
+  g_object_set (G_OBJECT (self),
+                "text-column", TIMEZONE_COMPLETION_NAME,
+                "popup-set-width", FALSE,
+                NULL);
 
   priv->cancel = g_cancellable_new ();
 
-  priv->request_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  priv->request_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 
   GtkCellRenderer * cell = gtk_cell_renderer_text_new ();
   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, TRUE);
@@ -377,6 +379,11 @@ timezone_completion_dispose (GObject * object)
     g_object_remove_weak_pointer (G_OBJECT (priv->entry), (gpointer *)&priv->entry);
   }
 
+  if (priv->initial_model != NULL) {
+    g_object_unref (G_OBJECT (priv->initial_model));
+    priv->initial_model = NULL;
+  }
+
   if (priv->queued_request) {
     g_source_remove (priv->queued_request);
     priv->queued_request = 0;
@@ -388,8 +395,15 @@ timezone_completion_dispose (GObject * object)
     priv->cancel = NULL;
   }
 
-  g_free (priv->request_text);
-  g_hash_table_destroy (priv->request_table);
+  if (priv->request_text != NULL) {
+    g_free (priv->request_text);
+    priv->request_text = NULL;
+  }
+
+  if (priv->request_table != NULL) {
+    g_hash_table_destroy (priv->request_table);
+    priv->request_table = NULL;
+  }
 
   return;
 }
-- 
cgit v1.2.3


From 350271ee98b2ae288f9f1dde5eaea635e9dff3b7 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Fri, 25 Feb 2011 08:18:15 -0500
Subject: add missing olsen_map.png

---
 libmap/data/olsen_map.png | Bin 0 -> 54969 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 libmap/data/olsen_map.png

diff --git a/libmap/data/olsen_map.png b/libmap/data/olsen_map.png
new file mode 100644
index 0000000..f9bb75c
Binary files /dev/null and b/libmap/data/olsen_map.png differ
-- 
cgit v1.2.3


From 2a6b56d0f00d2e23ca48687fe1c81d4e88be3b28 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Fri, 25 Feb 2011 09:18:57 -0500
Subject: remove week-start preference

---
 data/com.canonical.indicator.datetime.gschema.xml | 12 -----
 data/datetime-dialog.ui                           | 61 -----------------------
 src/datetime-prefs.c                              | 49 ------------------
 src/settings-shared.h                             |  1 -
 src/utils.c                                       | 11 ----
 src/utils.h                                       |  1 -
 6 files changed, 135 deletions(-)

diff --git a/data/com.canonical.indicator.datetime.gschema.xml b/data/com.canonical.indicator.datetime.gschema.xml
index 5361896..b33f34e 100644
--- a/data/com.canonical.indicator.datetime.gschema.xml
+++ b/data/com.canonical.indicator.datetime.gschema.xml
@@ -5,11 +5,6 @@
 		
 		
 	
-	
-		
-		
-		
-	
 	
 		
 			true
@@ -83,13 +78,6 @@
 			  Shows the week numbers in the monthly calendar in indicator-datetime's menu.
 			
 		
-		
-			'locale-default'
-			When the week starts
-			
-			  Controls whether weeks in the calendar are shown to start on Sunday or Monday.
-			
-		
 		
 			true
 			Show events in the indicator
diff --git a/data/datetime-dialog.ui b/data/datetime-dialog.ui
index b8d0777..35cb172 100644
--- a/data/datetime-dialog.ui
+++ b/data/datetime-dialog.ui
@@ -597,67 +597,6 @@
                                         0
                                       
                                     
-                                    
-                                      
-                                        True
-                                        False
-                                        0
-                                        Week begins on:
-                                      
-                                      
-                                        True
-                                        True
-                                        1
-                                      
-                                    
-                                    
-                                      
-                                        True
-                                        False
-                                        True
-                                        
-                                          
-                                            S_unday
-                                            True
-                                            True
-                                            False
-                                            False
-                                            True
-                                            0
-                                            True
-                                            True
-                                          
-                                          
-                                            True
-                                            True
-                                            0
-                                          
-                                        
-                                        
-                                          
-                                            Monda_y
-                                            True
-                                            True
-                                            False
-                                            False
-                                            True
-                                            0
-                                            True
-                                            startOnSundayRadio
-                                          
-                                          
-                                            True
-                                            True
-                                            1
-                                          
-                                        
-                                      
-                                      
-                                        True
-                                        True
-                                        2
-                                      
-                                    
                                   
                                 
                               
diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c
index fbadd27..e69d58b 100644
--- a/src/datetime-prefs.c
+++ b/src/datetime-prefs.c
@@ -86,45 +86,6 @@ bind_hours_get (GValue * value, GVariant * variant, gpointer user_data)
   return TRUE;
 }
 
-/* Turns the boolean property into a string gsettings */
-static GVariant *
-bind_week_start_set (const GValue * value, const GVariantType * type, gpointer user_data)
-{
-  const gchar * output = NULL;
-  gboolean is_sunday_button = (gboolean)GPOINTER_TO_INT(user_data);
-
-  if (g_value_get_boolean(value)) {
-    /* Only do anything if we're setting active = true */
-    output = is_sunday_button ? "sunday" : "monday";
-  } else {
-    return NULL;
-  }
-
-  return g_variant_new_string (output);
-}
-
-/* Turns a string gsettings into a boolean property */
-static gboolean
-bind_week_start_get (GValue * value, GVariant * variant, gpointer user_data)
-{
-  const gchar * str = g_variant_get_string(variant, NULL);
-  gboolean output = FALSE;
-  gboolean is_sunday_button = (gboolean)GPOINTER_TO_INT(user_data);
-
-  if (g_strcmp0(str, "locale-default") == 0) {
-    output = (is_sunday_button == is_locale_week_start_sunday ());
-  } else if (g_strcmp0(str, "sunday") == 0) {
-    output = is_sunday_button;
-  } else if (g_strcmp0(str, "monday") == 0) {
-    output = !is_sunday_button;
-  } else {
-    return FALSE;
-  }
-
-  g_value_set_boolean (value, output);
-  return TRUE;
-}
-
 static void
 widget_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent)
 {
@@ -527,16 +488,6 @@ create_dialog (void)
                    "active", G_SETTINGS_BIND_DEFAULT);
   g_settings_bind (conf, SETTINGS_SHOW_WEEK_NUMBERS_S, WIG ("includeWeekNumbersCheck"),
                    "active", G_SETTINGS_BIND_DEFAULT);
-  g_settings_bind_with_mapping (conf, SETTINGS_WEEK_START_S,
-                                WIG ("startOnSundayRadio"), "active",
-                                G_SETTINGS_BIND_DEFAULT,
-                                bind_week_start_get, bind_week_start_set,
-                                GINT_TO_POINTER(TRUE), NULL);
-  g_settings_bind_with_mapping (conf, SETTINGS_WEEK_START_S,
-                                WIG ("startOnMondayRadio"), "active",
-                                G_SETTINGS_BIND_DEFAULT,
-                                bind_week_start_get, bind_week_start_set,
-                                GINT_TO_POINTER(FALSE), NULL);
   g_settings_bind (conf, SETTINGS_SHOW_EVENTS_S, WIG ("showEventsCheck"),
                    "active", G_SETTINGS_BIND_DEFAULT);
   g_settings_bind (conf, SETTINGS_SHOW_LOCATIONS_S, WIG ("showLocationsCheck"),
diff --git a/src/settings-shared.h b/src/settings-shared.h
index a4fac24..df2260e 100644
--- a/src/settings-shared.h
+++ b/src/settings-shared.h
@@ -31,7 +31,6 @@ with this program.  If not, see .
 #define SETTINGS_CUSTOM_TIME_FORMAT_S   "custom-time-format"
 #define SETTINGS_SHOW_CALENDAR_S        "show-calendar"
 #define SETTINGS_SHOW_WEEK_NUMBERS_S    "show-week-numbers"
-#define SETTINGS_WEEK_START_S           "week-start"
 #define SETTINGS_SHOW_EVENTS_S          "show-events"
 #define SETTINGS_SHOW_LOCATIONS_S       "show-locations"
 #define SETTINGS_LOCATIONS_S            "locations"
diff --git a/src/utils.c b/src/utils.c
index 20ae958..7471926 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -50,17 +50,6 @@ is_locale_12h (void)
 	return TRUE;
 }
 
-/* Check the system locale setting to see if the week starts on Sunday or Monday */
-gboolean
-is_locale_week_start_sunday (void)
-{
-	const char * week_1stday = nl_langinfo (_NL_TIME_WEEK_1STDAY);
-
-  /* This appears to be a special value that libc uses for Sunday, it's not
-     really a string */
-  return (GPOINTER_TO_INT (week_1stday) == 19971130);
-}
-
 void
 split_settings_location (const gchar * location, gchar ** zone, gchar ** name)
 {
diff --git a/src/utils.h b/src/utils.h
index 3dc8df1..5f7842c 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -28,7 +28,6 @@ with this program.  If not, see .
 G_BEGIN_DECLS
 
 gboolean is_locale_12h (void);
-gboolean is_locale_week_start_sunday (void);
 void split_settings_location (const gchar * location, gchar ** zone, gchar ** name);
 gchar * generate_format_string_full (gboolean show_day, gboolean show_date);
 gchar * generate_format_string_at_time (GDateTime * time);
-- 
cgit v1.2.3


From 42125be0102026e6ecae842413261a8b05a25e96 Mon Sep 17 00:00:00 2001
From: Michael Terry 
Date: Fri, 25 Feb 2011 11:41:56 -0500
Subject: fix a couple memory leaks noted by MacSlow

---
 libmap/test-timezone.c | 1 +
 src/datetime-service.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/libmap/test-timezone.c b/libmap/test-timezone.c
index d667c42..c1935fd 100644
--- a/libmap/test-timezone.c
+++ b/libmap/test-timezone.c
@@ -47,6 +47,7 @@ int main (int argc, char **argv)
 
 		g_free (filename);
 		g_free (path);
+		tz_info_free (info);
 	}
 	tz_db_free (db);
 	g_free (pixmap_dir);
diff --git a/src/datetime-service.c b/src/datetime-service.c
index ab609c4..af63a2a 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -99,6 +99,9 @@ set_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
 
 	dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_NAME, name);
 	dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, zone);
+
+	g_free (zone);
+	g_free (name);
 }
 
 /* Check to see if our timezones are the same */
-- 
cgit v1.2.3