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 --- 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 ++++++++ 7 files changed, 356 insertions(+), 38 deletions(-) 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 (limited to 'src') 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 --- src/datetime-prefs.c | 223 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 197 insertions(+), 26 deletions(-) (limited to 'src') 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 --- src/datetime-prefs.c | 158 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 41 deletions(-) (limited to 'src') 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 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 --- src/Makefile.am | 2 + src/datetime-prefs-locations.c | 137 +++++++++++++++++++++++++++++++++++++++++ src/datetime-prefs-locations.h | 34 ++++++++++ src/datetime-prefs.c | 11 +++- 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/datetime-prefs-locations.c create mode 100644 src/datetime-prefs-locations.h (limited to 'src') 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 --- src/Makefile.am | 2 ++ src/datetime-prefs.c | 58 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 7 deletions(-) (limited to 'src') 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 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(-) (limited to 'src') 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(-) (limited to 'src') 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 --- 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 +++++++++++++++++++ 5 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 src/timezone-completion.c create mode 100644 src/timezone-completion.h (limited to 'src') 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 --- 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 + 9 files changed, 602 insertions(+), 199 deletions(-) (limited to 'src') 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 --- src/datetime-prefs.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/settings-shared.h | 2 +- src/utils.c | 11 +++++++++++ src/utils.h | 1 + 4 files changed, 63 insertions(+), 4 deletions(-) (limited to 'src') 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(-) (limited to 'src') 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(-) (limited to 'src') 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 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(-) (limited to 'src') 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(-) (limited to 'src') 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(-) (limited to 'src') 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(-) (limited to 'src') 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 --- src/datetime-prefs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') 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 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(+) (limited to 'src') 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(-) (limited to 'src') 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(-) (limited to 'src') 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 486ad3625ca52b318f5514f782b90f1eda0b87e7 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Thu, 24 Feb 2011 15:02:00 -0500 Subject: have spinners work in unison -- only save when neither is focused --- src/datetime-prefs.c | 124 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index fbadd27..d053c7e 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -46,6 +46,11 @@ GDBusProxy * proxy = NULL; GtkWidget * auto_radio = NULL; GtkWidget * tz_entry = NULL; CcTimezoneMap * tzmap = NULL; +GtkWidget * time_spin = NULL; +GtkWidget * date_spin = NULL; +GDateTime * manual_time = NULL; +guint save_time_id = 0; +gboolean user_edited_time = FALSE; /* Turns the boolean property into a string gsettings */ static GVariant * @@ -277,13 +282,56 @@ void proxy_ready (GObject *object, GAsyncResult *res, gpointer user_data) NULL, tz_query_answered, NULL); } +static gboolean +are_spinners_focused (void) +{ + // save_time_id means that we were in focus and haven't finished our save + // yet, so act like we are still focused. + return save_time_id || gtk_widget_has_focus (time_spin) || gtk_widget_has_focus (date_spin); +} + +static gboolean +save_time (gpointer user_data) +{ + if (user_edited_time) { + g_dbus_proxy_call (proxy, "SetTime", g_variant_new ("(x)", g_date_time_to_unix (manual_time)), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "time"); + } + user_edited_time = FALSE; + save_time_id = 0; + return FALSE; +} + +static gboolean +spin_focus_in (void) +{ + if (save_time_id > 0) { + g_source_remove (save_time_id); + save_time_id = 0; + } + return FALSE; +} + +static gboolean +spin_focus_out (void) +{ + /* We want to only save when both spinners are unfocused. But it's difficult + to tell who is about to get focus during a focus-out. So we set an idle + callback to save the time if we don't focus in to another spinner by that + time. */ + if (save_time_id == 0) { + save_time_id = g_idle_add ((GSourceFunc)save_time, NULL); + } + return FALSE; +} + static int input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) { 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 (); + GDateTime * now = manual_time; gint year, month, day, hour, minute, second; year = g_date_time_get_year (now); month = g_date_time_get_month (now); @@ -291,7 +339,6 @@ input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) 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; @@ -354,10 +401,9 @@ input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) return TRUE; } - 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"); + g_date_time_unref (manual_time); + manual_time = g_date_time_new_local (year, month, day, hour, minute, second); + user_edited_time = TRUE; return TRUE; } @@ -365,12 +411,6 @@ input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) 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; @@ -385,39 +425,60 @@ format_time_text (GtkWidget * spinner, gpointer user_data) format = "%Y-%m-%d"; } - gchar * formatted = g_date_time_format (datetime, format); + gchar * formatted = g_date_time_format (manual_time, format); gtk_entry_set_text (GTK_ENTRY (spinner), formatted); return TRUE; } static gboolean -update_spinner (GtkWidget * spinner) +update_spinners (void) { /* 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); - + then using the value of the spinner itself. And don't update while user is + editing. */ + if (!are_spinners_focused ()) { + if (manual_time != NULL) { + g_date_time_unref (manual_time); + } + manual_time = g_date_time_new_now_local (); + format_time_text (time_spin, NULL); + format_time_text (date_spin, NULL); + } return TRUE; } static void -setup_time_spinner (GtkWidget * spinner, GtkWidget * other, gboolean is_time) +setup_time_spinners (GtkWidget * time, GtkWidget * date) { - /* 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), 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)); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (time), FALSE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (date), FALSE); - /* 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)); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (time), TRUE); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (date), TRUE); + + g_signal_connect (time, "input", G_CALLBACK (input_time_text), date); + g_signal_connect (date, "input", G_CALLBACK (input_time_text), time); + + g_signal_connect (time, "output", G_CALLBACK (format_time_text), date); + g_signal_connect (date, "output", G_CALLBACK (format_time_text), time); + + g_signal_connect (time, "focus-in-event", G_CALLBACK (spin_focus_in), date); + g_signal_connect (date, "focus-in-event", G_CALLBACK (spin_focus_in), time); - update_spinner (spinner); + g_signal_connect (time, "focus-out-event", G_CALLBACK (spin_focus_out), date); + g_signal_connect (date, "focus-out-event", G_CALLBACK (spin_focus_out), time); + + g_object_set_data (G_OBJECT (time), "is-time", GINT_TO_POINTER (TRUE)); + g_object_set_data (G_OBJECT (date), "is-time", GINT_TO_POINTER (FALSE)); + + time_spin = time; + date_spin = date; + + /* 2 seconds is what the indicator itself uses */ + guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_spinners, NULL); + g_signal_connect_swapped (time_spin, "destroy", G_CALLBACK (g_source_remove), GINT_TO_POINTER (time_id)); + update_spinners (); } static void @@ -554,8 +615,7 @@ create_dialog (void) gtk_widget_set_sensitive (WIG ("showEventsCheck"), (evo_path != NULL)); g_free (evo_path); - setup_time_spinner (WIG ("timeSpinner"), WIG ("dateSpinner"), TRUE); - setup_time_spinner (WIG ("dateSpinner"), WIG ("timeSpinner"), FALSE); + setup_time_spinners (WIG ("timeSpinner"), WIG ("dateSpinner")); GtkWidget * dlg = WIG ("timeDateDialog"); auto_radio = WIG ("automaticTimeRadio"); -- cgit v1.2.3 From 398154d354d19a85f629a6d7131b1a7bd6b7b869 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Fri, 25 Feb 2011 14:04:46 +0000 Subject: Fixing up indicator-datetime * Config options * Calendar update signals from calendar widget - should update appointments/marks not working at present --- src/datetime-service.c | 87 ++++++++++++++++++++++++++---------------------- src/dbus-shared.h | 9 ++++- src/indicator-datetime.c | 61 +++++++++++++++++++++++++++++++-- 3 files changed, 114 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 347fecb..6a9575e 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -54,8 +54,11 @@ with this program. If not, see . #include "dbus-shared.h" -#define SETTINGS_INTERFACE "com.canonical.indicator.datetime" -#define SETTINGS_LOCATIONS "locations" +#define SETTINGS_INTERFACE "com.canonical.indicator.datetime" +#define SETTINGS_LOCATIONS "locations" +#define SETTINGS_SHOW_CALENDAR "show-calendar" +#define SETTINGS_SHOW_EVENTS "show-events" +#define SETTINGS_SHOW_LOCATIONS "show-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); @@ -115,6 +118,13 @@ check_timezone_sync (void) { } else { g_debug("Timezones are different"); } + + if (!g_settings_get_boolean(conf, SETTINGS_SHOW_LOCATIONS)) { + dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + return; + } if (geo_location != NULL && current_location != NULL) { g_debug("Got timezone %s", current_timezone); @@ -288,52 +298,35 @@ activate_cb (DbusmenuMenuitem * menuitem, guint timestamp, const gchar *command) } } +static gboolean +month_changed_cb (DbusmenuMenuitem * menuitem, GVariant *variant, guint timestamp) +{ + // TODO: * Decode the month/year from the string we received + // * Check what our current month/year are + // * Set some globals so when we-re-run update appointment menu items it gets the right start date + // * update appointment menu items + g_debug("Received month changed : %s", g_variant_get_string(variant, NULL)); + return TRUE; +} + /* Looks for the calendar application and enables the item if we have one */ static gboolean check_for_calendar (gpointer user_data) { g_return_val_if_fail (calendar != NULL, FALSE); + + if (!g_settings_get_boolean(conf, SETTINGS_SHOW_CALENDAR)) return FALSE; gchar *evo = g_find_program_in_path("evolution"); if (evo != NULL) { g_debug("Found the calendar application: %s", evo); dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); -/* - GError *gerror = NULL; - // TODO: In reality we should iterate sources of calendar, but getting the local one doens't lag for > a minute - g_debug("Setting up ecal."); - if (!ecal) - ecal = e_cal_new_system_calendar(); - - if (!ecal) { - g_debug("e_cal_new_system_calendar failed"); - ecal = NULL; - } - g_debug("Open calendar."); - if (!e_cal_open(ecal, FALSE, &gerror) ) { - g_debug("e_cal_open: %s\n", gerror->message); - g_free(ecal); - ecal = NULL; - } - g_debug("Get calendar timezone."); - if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror)) { - g_debug("failed to get time zone\n"); - g_free(ecal); - ecal = NULL; - } - - This timezone represents the timezone of the calendar, this might be different to the current UTC offset. - * this means we'll have some geoclue interaction going on, and possibly the user will be involved in setting - * their location manually, case in point: trains have satellite links which often geoclue to sweden, - * this shouldn't automatically set the location and mess up all the appointments for the user. - - if (ecal) ecal_timezone = icaltimezone_get_tzid(tzone); - */ + DbusmenuMenuitem * separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_add_position(root, separator, 3); + dbusmenu_menuitem_child_add_position(root, separator, 2); add_appointment = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment")); @@ -342,9 +335,12 @@ check_for_calendar (gpointer user_data) g_signal_connect(G_OBJECT(add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar"); dbusmenu_menuitem_child_add_position (root, add_appointment, 3); - update_appointment_menu_items(NULL); - g_signal_connect(root, DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(update_appointment_menu_items), NULL); - + // Update the calendar items every 30 minutes if it updates the first time + if (update_appointment_menu_items(NULL)) + g_timeout_add_seconds(60*30, update_appointment_menu_items, NULL); + + // Connect to event::month-changed + g_signal_connect(calendar, "event::month-changed", G_CALLBACK(month_changed_cb), NULL); g_free(evo); } else { g_debug("Unable to find calendar app."); @@ -358,7 +354,14 @@ check_for_calendar (gpointer user_data) static gboolean update_timezone_menu_items(gpointer user_data) { + if (!g_settings_get_boolean(conf, SETTINGS_SHOW_LOCATIONS)) { + dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + return FALSE; + } g_debug("Updating timezone menu items"); + gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS); if (locations == NULL) { g_debug("No locations configured (NULL)"); @@ -425,7 +428,8 @@ auth_func (ECal *ecal, const gchar *prompt, const gchar *key, gpointer user_data else component_name = "Calendar"; gchar *password = e_passwords_get_password (component_name, key); - + gboolean remember; + if (password == NULL) { password = e_passwords_ask_password ( _("Enter password"), @@ -493,6 +497,9 @@ static gboolean update_appointment_menu_items (gpointer user_data) { // FFR: we should take into account short term timers, for instance // tea timers, pomodoro timers etc... that people may add, this is hinted to in the spec. + if (calendar == NULL) return FALSE; + if (!g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS)) return FALSE; + time_t t1, t2; gchar *query, *is, *ie, *ad; GList *objects = NULL, *l; @@ -545,7 +552,6 @@ update_appointment_menu_items (gpointer user_data) { g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL); ECal *ecal = e_cal_new(source, E_CAL_SOURCE_TYPE_EVENT); e_cal_set_auth_func (ecal, (ECalAuthFunc) auth_func, NULL); - //icaltimezone * tzone; if (!e_cal_open(ecal, FALSE, &gerror)) { g_debug("Failed to get ecal sources %s", gerror->message); @@ -558,7 +564,8 @@ update_appointment_menu_items (gpointer user_data) { if (!e_cal_get_object_list_as_comp(ecal, query, &objects, &gerror)) { g_debug("Failed to get objects\n"); g_free(ecal); - return FALSE; + gerror = NULL; + continue; } g_debug("Number of objects returned: %d", g_list_length(objects)); diff --git a/src/dbus-shared.h b/src/dbus-shared.h index bad8354..93ea5a1 100644 --- a/src/dbus-shared.h +++ b/src/dbus-shared.h @@ -27,7 +27,14 @@ with this program. If not, see . #define MENU_OBJ "/com/canonical/indicator/datetime/menu" -#define DBUSMENU_CALENDAR_MENUITEM_TYPE "x-canonical-calendar-item" +#define DBUSMENU_CALENDAR_MENUITEM_TYPE "x-canonical-calendar-item" + +// The following properties are not *really* properties, but are just +// a way of accessing the calendar from the service +#define CALENDAR_MENUITEM_PROP_MARK "calendar-mark" +#define CALENDAR_MENUITEM_PROP_UNMARK "calendar-unmark" +#define CALENDAR_MENUITEM_PROP_CLEAR_MARKS "calendar-clear-marks" + #define APPOINTMENT_MENUITEM_TYPE "appointment-item" #define APPOINTMENT_MENUITEM_PROP_LABEL "appointment-label" diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 54b4507..e793d71 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -26,9 +26,11 @@ with this program. If not, see . #include #include #include +#include /* GStuff */ #include +#include #include #include #include @@ -79,6 +81,9 @@ struct _IndicatorDatetimePrivate { gchar * custom_string; gboolean custom_show_seconds; + gboolean show_week_numbers; + gint week_start; + guint idle_measure; gint max_width; @@ -102,7 +107,8 @@ enum { PROP_SHOW_SECONDS, PROP_SHOW_DAY, PROP_SHOW_DATE, - PROP_CUSTOM_TIME_FORMAT + PROP_CUSTOM_TIME_FORMAT, + PROP_SHOW_WEEK_NUMBERS }; typedef struct _indicator_item_t indicator_item_t; @@ -120,6 +126,7 @@ struct _indicator_item_t { #define PROP_SHOW_DAY_S "show-day" #define PROP_SHOW_DATE_S "show-date" #define PROP_CUSTOM_TIME_FORMAT_S "custom-time-format" +#define PROP_SHOW_WEEK_NUMBERS_S "show-week-numbers" #define SETTINGS_INTERFACE "com.canonical.indicator.datetime" #define SETTINGS_TIME_FORMAT_S "time-format" @@ -127,6 +134,7 @@ struct _indicator_item_t { #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_WEEK_NUMBERS_S "show-week-numbers" enum { SETTINGS_TIME_LOCALE = 0, @@ -247,6 +255,13 @@ indicator_datetime_class_init (IndicatorDatetimeClass *klass) DEFAULT_TIME_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_SHOW_WEEK_NUMBERS, + g_param_spec_boolean(PROP_SHOW_WEEK_NUMBERS_S, + "Whether to show the week numbers in the calendar.", + "Shows the week numbers in the monthly calendar in indicator-datetime's menu.", + FALSE, /* default */ + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); return; } @@ -305,6 +320,11 @@ indicator_datetime_init (IndicatorDatetime *self) self, PROP_CUSTOM_TIME_FORMAT_S, G_SETTINGS_BIND_DEFAULT); + g_settings_bind(self->priv->settings, + SETTINGS_SHOW_WEEK_NUMBERS_S, + self, + PROP_SHOW_WEEK_NUMBERS_S, + G_SETTINGS_BIND_DEFAULT); } else { g_warning("Unable to get settings for '" SETTINGS_INTERFACE "'"); } @@ -531,6 +551,18 @@ set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec } break; } + case PROP_SHOW_WEEK_NUMBERS: { + if (g_value_get_boolean(value) != self->priv->show_week_numbers) { + GtkCalendarDisplayOptions flags = ido_calendar_menu_item_get_display_options (self->priv->ido_calendar); + if (g_value_get_boolean(value) == TRUE) + flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS; + else + flags &= ~GTK_CALENDAR_SHOW_WEEK_NUMBERS; + ido_calendar_menu_item_set_display_options (self->priv->ido_calendar, flags); + self->priv->show_week_numbers = g_value_get_boolean(value); + } + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); return; @@ -586,6 +618,9 @@ get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspe case PROP_CUSTOM_TIME_FORMAT: g_value_set_string(value, self->priv->custom_string); break; + case PROP_SHOW_WEEK_NUMBERS: + g_value_set_boolean(value, self->priv->show_week_numbers); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); return; @@ -1224,6 +1259,15 @@ indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant *value, 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)); + + // Properties for marking and unmarking the calendar + + } else if (!g_strcmp0(prop, CALENDAR_MENUITEM_PROP_MARK)) { + ido_calendar_menu_item_mark_day (IDO_CALENDAR_MENU_ITEM (mi_data), g_variant_get_int16(value)); + } else if (!g_strcmp0(prop, CALENDAR_MENUITEM_PROP_UNMARK)) { + ido_calendar_menu_item_unmark_day (IDO_CALENDAR_MENU_ITEM (mi_data), g_variant_get_int16(value)); + } else if (!g_strcmp0(prop, CALENDAR_MENUITEM_PROP_CLEAR_MARKS)) { + ido_calendar_menu_item_clear_marks (IDO_CALENDAR_MENU_ITEM (mi_data)); } else { g_warning("Indicator Item property '%s' unknown", prop); } @@ -1307,6 +1351,19 @@ new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbu return TRUE; } +static void +month_changed_cb (IdoCalendarMenuItem *ido, + gpointer user_data) +{ + gchar datestring[20]; + guint d,m,y; + ido_calendar_menu_item_get_date(ido, &y, &m, &d); + g_sprintf(datestring, "%d-%d-%d", y, m, d); + GVariant *variant = g_variant_new_string(datestring); + guint timestamp = (guint)time(NULL); + dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(ido), "event::month-changed", variant, timestamp); + g_debug("Got month changed signal: %s", datestring); +} static gboolean new_calendar_item (DbusmenuMenuitem * newitem, @@ -1331,7 +1388,7 @@ new_calendar_item (DbusmenuMenuitem * newitem, self->priv->ido_calendar = ido; dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(ido), parent); - + g_signal_connect(ido, "month-changed", G_CALLBACK(month_changed_cb), NULL); return TRUE; } -- 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 --- src/datetime-prefs.c | 49 ------------------------------------------------- src/settings-shared.h | 1 - src/utils.c | 11 ----------- src/utils.h | 1 - 4 files changed, 62 deletions(-) (limited to 'src') 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 03eafa311a71cacae4ecca3f198ea7131f33dbb7 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Fri, 25 Feb 2011 15:09:27 +0000 Subject: Get ido calendar and dbusmenu the right way around --- src/indicator-datetime.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index e793d71..ac8db54 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -1357,11 +1357,12 @@ month_changed_cb (IdoCalendarMenuItem *ido, { gchar datestring[20]; guint d,m,y; + DbusmenuMenuitem * item = DBUSMENU_MENUITEM (user_data); ido_calendar_menu_item_get_date(ido, &y, &m, &d); g_sprintf(datestring, "%d-%d-%d", y, m, d); GVariant *variant = g_variant_new_string(datestring); guint timestamp = (guint)time(NULL); - dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(ido), "event::month-changed", variant, timestamp); + dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(item), "event::month-changed", variant, timestamp); g_debug("Got month changed signal: %s", datestring); } @@ -1388,7 +1389,7 @@ new_calendar_item (DbusmenuMenuitem * newitem, self->priv->ido_calendar = ido; dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(ido), parent); - g_signal_connect(ido, "month-changed", G_CALLBACK(month_changed_cb), NULL); + g_signal_connect_after(ido, "month-changed", G_CALLBACK(month_changed_cb), (gpointer)newitem); return TRUE; } -- cgit v1.2.3 From d0e5a69a026bc879759cde57f8ba324c67b6b37a Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Fri, 25 Feb 2011 15:43:41 +0000 Subject: Updated to free errors just in case(tm) at dbarths request shortened the update time to 5 minutes for calendars --- src/datetime-service.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 6a9575e..a3e45bf 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -218,6 +218,7 @@ update_current_timezone (void) { check_timezone_sync(); + if (error != NULL) g_error_free(error); return; } @@ -335,9 +336,9 @@ check_for_calendar (gpointer user_data) g_signal_connect(G_OBJECT(add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar"); dbusmenu_menuitem_child_add_position (root, add_appointment, 3); - // Update the calendar items every 30 minutes if it updates the first time + // Update the calendar items every 5 minutes if it updates the first time if (update_appointment_menu_items(NULL)) - g_timeout_add_seconds(60*30, update_appointment_menu_items, NULL); + g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL); // Connect to event::month-changed g_signal_connect(calendar, "event::month-changed", G_CALLBACK(month_changed_cb), NULL); @@ -710,6 +711,8 @@ update_appointment_menu_items (gpointer user_data) { if (i == 4) break; // See above FIXME regarding query result limit i++; } + + if (gerror != NULL) g_error_free(gerror); g_object_unref(allobjects); g_debug("End of objects"); return TRUE; -- 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 --- src/datetime-service.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') 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 From bbd56b119d18a83600c1be706078d3e0d759583d Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Mon, 28 Feb 2011 16:45:59 +0000 Subject: Minor change for kenvandine to test sorting --- src/datetime-service.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 6303a98..a6e756e 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -422,8 +422,10 @@ compare_appointment_items (ECalComponent *a, ECalComponentVType vtype = e_cal_component_get_vtype (a); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return -1; - + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { + g_debug("E-Cal Component is neither an event or a todo"); + return -1; + } if (vtype == E_CAL_COMPONENT_EVENT) e_cal_component_get_dtstart (a, &datetime_a); else @@ -432,8 +434,11 @@ compare_appointment_items (ECalComponent *a, t_a = mktime(&tm_a); vtype = e_cal_component_get_vtype (b); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return 1; - + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { + e_cal_component_free_datetime (&datetime_a); + g_debug("E-Cal Component is neither an event or a todo"); + return -1; + } if (vtype == E_CAL_COMPONENT_EVENT) e_cal_component_get_dtstart (b, &datetime_b); else -- cgit v1.2.3 From 2de6f443b603965a7fc786df9ef58fcc63841daf Mon Sep 17 00:00:00 2001 From: Ken VanDine Date: Mon, 28 Feb 2011 23:05:10 -0500 Subject: Simplify calendar query, we don't need to compute times for the range. The query system has a built in way to specify a relative range. --- src/datetime-service.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 6303a98..078ede0 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -462,8 +462,7 @@ update_appointment_menu_items (gpointer user_data) { if (calendar == NULL) return FALSE; if (!g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) return FALSE; - time_t t1, t2; - gchar *query, *is, *ie, *ad; + gchar *query, *ad; GList *objects = NULL, *l; GList *allobjects = NULL; GSList *g; @@ -472,13 +471,6 @@ update_appointment_menu_items (gpointer user_data) { gint width, height; ESourceList * sources = NULL; - time(&t1); - time(&t2); - t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now */ - - is = isodate_from_time_t(t1); - ie = isodate_from_time_t(t2); - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); /* Remove all of the previous appointments */ @@ -497,7 +489,7 @@ update_appointment_menu_items (gpointer user_data) { // TODO Remove all highlights from the calendar widget // FIXME can we put a limit on the number of results? Or if not complete, or is event/todo? Or sort it by date? - query = g_strdup_printf("(occur-in-time-range? (make-time\"%s\") (make-time\"%s\"))", is, ie); + query = g_strdup_printf("(occur-in-time-range? (time-now) (time-add-day (time-now) 7))"); if (!e_cal_get_sources(&sources, E_CAL_SOURCE_TYPE_EVENT, &gerror)) { g_debug("Failed to get ecal sources\n"); -- cgit v1.2.3 From cf5abb9ac1ec68e2e1acd8d252611d40ff244a2b Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Tue, 1 Mar 2011 17:05:51 +0000 Subject: These changes should fix the problems with the recurring appointments and dconf changes for show/hide events --- src/datetime-service.c | 129 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index a6e756e..fd73024 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -73,6 +73,7 @@ static DatetimeInterface * dbus = NULL; static DbusmenuMenuitem * date = NULL; static DbusmenuMenuitem * calendar = NULL; static DbusmenuMenuitem * settings = NULL; +static DbusmenuMenuitem * events_separator = NULL; static DbusmenuMenuitem * locations_separator = NULL; static DbusmenuMenuitem * geo_location = NULL; static DbusmenuMenuitem * current_location = NULL; @@ -278,8 +279,38 @@ month_changed_cb (DbusmenuMenuitem * menuitem, GVariant *variant, guint timestam return TRUE; } +static guint ecaltimer = 0; + +static void +start_ecal_timer(void) +{ + if (ecaltimer != 0) g_source_remove(ecaltimer); + if (update_appointment_menu_items(NULL)) + ecaltimer = g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL); +} + +static void +stop_ecal_timer(void) +{ + if (ecaltimer != 0) g_source_remove(ecaltimer); +} + +static void +show_events_changed (void) +{ + if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) { + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + start_ecal_timer(); + } else { + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + stop_ecal_timer(); + } +} + /* Looks for the calendar application and enables the item if - we have one */ + we have one, starts ecal timer if events are turned on */ static gboolean check_for_calendar (gpointer user_data) { @@ -293,21 +324,26 @@ check_for_calendar (gpointer user_data) dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - DbusmenuMenuitem * separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_add_position(root, separator, 2); - + events_separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(events_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + dbusmenu_menuitem_child_add_position(root, events_separator, 2); add_appointment = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment")); + dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment")); dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); g_signal_connect(G_OBJECT(add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar"); dbusmenu_menuitem_child_add_position (root, add_appointment, 3); - // Update the calendar items every 5 minutes if it updates the first time - if (update_appointment_menu_items(NULL)) - g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL); - + + if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) { + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + start_ecal_timer(); + } else { + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + stop_ecal_timer(); + } + // Connect to event::month-changed g_signal_connect(calendar, "event::month-changed", G_CALLBACK(month_changed_cb), NULL); g_free(evo); @@ -381,7 +417,11 @@ update_timezone_menu_items(gpointer user_data) { // Authentication function static gchar * -auth_func (ECal *ecal, const gchar *prompt, const gchar *key, gpointer user_data) { +auth_func (ECal *ecal, + const gchar *prompt, + const gchar *key, + gpointer user_data) +{ gboolean remember; // TODO: Is this useful? Should we be storing it somewhere? ESource *source = e_cal_get_source (ecal); gchar *auth_domain = e_source_get_duped_property (source, "auth-domain"); @@ -411,8 +451,8 @@ auth_func (ECal *ecal, const gchar *prompt, const gchar *key, gpointer user_data // Compare function for g_list_sort of ECalComponent objects static gint compare_appointment_items (ECalComponent *a, - ECalComponent *b) { - + ECalComponent *b) +{ ECalComponentDateTime datetime_a, datetime_b; struct tm tm_a, tm_b; time_t t_a, t_b; @@ -422,10 +462,8 @@ compare_appointment_items (ECalComponent *a, ECalComponentVType vtype = e_cal_component_get_vtype (a); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { - g_debug("E-Cal Component is neither an event or a todo"); - return -1; - } + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return -1; + if (vtype == E_CAL_COMPONENT_EVENT) e_cal_component_get_dtstart (a, &datetime_a); else @@ -434,11 +472,8 @@ compare_appointment_items (ECalComponent *a, t_a = mktime(&tm_a); vtype = e_cal_component_get_vtype (b); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { - e_cal_component_free_datetime (&datetime_a); - g_debug("E-Cal Component is neither an event or a todo"); - return -1; - } + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return 1; + if (vtype == E_CAL_COMPONENT_EVENT) e_cal_component_get_dtstart (b, &datetime_b); else @@ -447,12 +482,29 @@ compare_appointment_items (ECalComponent *a, t_b = mktime(&tm_b); // Compare datetime_a and datetime_b, newest first in this sort. - if (t_a > t_b) retval = 1; - else if (t_a < t_b) retval = -1; - - e_cal_component_free_datetime (&datetime_a); - e_cal_component_free_datetime (&datetime_b); - return retval; + if (t_a > t_b) return = 1; + else if (t_a < t_b) return = -1; +} + +static gboolean +populate_appointment_instances (ECalComponent *comp, + time_t instance_start, + time_t instance_end, + gpointer data) +{ + // DEBUG what is the address of "objects" from data + + // The aim here is to receive a usable pointer to the objects list + // append to it, and change the list that data points at. + // this is a crafty hack so we're able to sort the items afterwards + GList *objects = (GList *)data; + data = (GList *)g_list_append(objects, comp); + + // DEBUG objects should have changed in the resultant location too + + // TODO We also may as well use this opportunity to "mark days" in the calendar + // as we're iterating everything of interest here anyway. + return TRUE; } /* Populate the menu with todays, next 5 appointments. @@ -461,7 +513,8 @@ compare_appointment_items (ECalComponent *a, * this is a problem mainly on the EDS side of things, not ours. */ static gboolean -update_appointment_menu_items (gpointer user_data) { +update_appointment_menu_items (gpointer user_data) +{ // FFR: we should take into account short term timers, for instance // tea timers, pomodoro timers etc... that people may add, this is hinted to in the spec. if (calendar == NULL) return FALSE; @@ -481,8 +534,6 @@ update_appointment_menu_items (gpointer user_data) { time(&t2); t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now */ - is = isodate_from_time_t(t1); - ie = isodate_from_time_t(t2); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); @@ -502,7 +553,7 @@ update_appointment_menu_items (gpointer user_data) { // TODO Remove all highlights from the calendar widget // FIXME can we put a limit on the number of results? Or if not complete, or is event/todo? Or sort it by date? - query = g_strdup_printf("(occur-in-time-range? (make-time\"%s\") (make-time\"%s\"))", is, ie); + //query = g_strdup_printf("(occur-in-time-range? (make-time\"%s\") (make-time\"%s\"))", is, ie); if (!e_cal_get_sources(&sources, E_CAL_SOURCE_TYPE_EVENT, &gerror)) { g_debug("Failed to get ecal sources\n"); @@ -527,15 +578,10 @@ update_appointment_menu_items (gpointer user_data) { continue; } - g_debug("Getting objects with query: %s", query); - if (!e_cal_get_object_list_as_comp(ecal, query, &objects, &gerror)) { - g_debug("Failed to get objects\n"); - g_free(ecal); - gerror = NULL; - continue; - } + g_debug("Generating instances"); + e_cal_generate_instances (client, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) &objects); g_debug("Number of objects returned: %d", g_list_length(objects)); - + if (allobjects == NULL) { allobjects = objects; } else if (objects != NULL) { @@ -761,6 +807,7 @@ build_menus (DbusmenuMenuitem * root) check_timezone_sync(); g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL); + g_signal_connect (conf, "changed::" SETTINGS_SHOW_EVENTS_S, G_CALLBACK (show_events_changed), NULL); DbusmenuMenuitem * separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); -- cgit v1.2.3 From 4ebd048f21f54e01029d50d7d9fe0e9899bc25c2 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Tue, 1 Mar 2011 17:22:44 +0000 Subject: Fixes for the recurring tasks and events settings change, the pointers are currently a bit chewed up as I try to figure out the right way round to get this. --- src/datetime-service.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index fd73024..33b9720 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -456,9 +456,8 @@ compare_appointment_items (ECalComponent *a, ECalComponentDateTime datetime_a, datetime_b; struct tm tm_a, tm_b; time_t t_a, t_b; - gint retval = 0; - if (a == NULL || b == NULL) return retval; + if (a == NULL || b == NULL) return 0; ECalComponentVType vtype = e_cal_component_get_vtype (a); @@ -482,8 +481,9 @@ compare_appointment_items (ECalComponent *a, t_b = mktime(&tm_b); // Compare datetime_a and datetime_b, newest first in this sort. - if (t_a > t_b) return = 1; - else if (t_a < t_b) return = -1; + if (t_a > t_b) return 1; + else if (t_a < t_b) return -1; + return 0; } static gboolean @@ -521,7 +521,7 @@ update_appointment_menu_items (gpointer user_data) if (!g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) return FALSE; time_t t1, t2; - gchar *query, *is, *ie, *ad; + gchar *ad; GList *objects = NULL, *l; GList *allobjects = NULL; GSList *g; @@ -579,7 +579,7 @@ update_appointment_menu_items (gpointer user_data) } g_debug("Generating instances"); - e_cal_generate_instances (client, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) &objects); + e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) objects); g_debug("Number of objects returned: %d", g_list_length(objects)); if (allobjects == NULL) { -- cgit v1.2.3 From 6ee562ac5028df8f28e3559656117d7093b0f73c Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 1 Mar 2011 16:31:28 -0500 Subject: let date spin buttons work --- src/datetime-prefs.c | 57 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index c71217a..b6fd1c9 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -48,9 +48,9 @@ GtkWidget * tz_entry = NULL; CcTimezoneMap * tzmap = NULL; GtkWidget * time_spin = NULL; GtkWidget * date_spin = NULL; -GDateTime * manual_time = NULL; guint save_time_id = 0; gboolean user_edited_time = FALSE; +gboolean changing_time = FALSE; /* Turns the boolean property into a string gsettings */ static GVariant * @@ -255,7 +255,8 @@ static gboolean save_time (gpointer user_data) { if (user_edited_time) { - g_dbus_proxy_call (proxy, "SetTime", g_variant_new ("(x)", g_date_time_to_unix (manual_time)), + gdouble current_value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (date_spin)); + g_dbus_proxy_call (proxy, "SetTime", g_variant_new ("(x)", (guint64)current_value), G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "time"); } user_edited_time = FALSE; @@ -287,12 +288,15 @@ spin_focus_out (void) } static int -input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) +input_time_text (GtkWidget * spinner, gdouble * value, gpointer user_data) { 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 = manual_time; + gdouble current_value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinner)); + *value = current_value; + + GDateTime * now = g_date_time_new_from_unix_utc (current_value); gint year, month, day, hour, minute, second; year = g_date_time_get_year (now); month = g_date_time_get_month (now); @@ -362,9 +366,13 @@ input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data) return TRUE; } - g_date_time_unref (manual_time); - manual_time = g_date_time_new_local (year, month, day, hour, minute, second); + gboolean prev_changing = changing_time; + changing_time = TRUE; + GDateTime * new_time = g_date_time_new_local (year, month, day, hour, minute, second); + *value = g_date_time_to_unix (new_time); user_edited_time = TRUE; + g_date_time_unref (new_time); + changing_time = prev_changing; return TRUE; } @@ -386,12 +394,25 @@ format_time_text (GtkWidget * spinner, gpointer user_data) format = "%Y-%m-%d"; } - gchar * formatted = g_date_time_format (manual_time, format); + GDateTime * datetime = g_date_time_new_from_unix_utc (gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinner))); + gchar * formatted = g_date_time_format (datetime, format); gtk_entry_set_text (GTK_ENTRY (spinner), formatted); + g_date_time_unref (datetime); return TRUE; } +static void +spin_copy_value (GtkSpinButton * spinner, GtkSpinButton * other) +{ + if (gtk_spin_button_get_value (spinner) != gtk_spin_button_get_value (other)) { + gtk_spin_button_set_value (other, gtk_spin_button_get_value (spinner)); + } + if (!changing_time) { /* Means user pressed spin buttons */ + user_edited_time = TRUE; + } +} + static gboolean update_spinners (void) { @@ -399,12 +420,13 @@ update_spinners (void) then using the value of the spinner itself. And don't update while user is editing. */ if (!are_spinners_focused ()) { - if (manual_time != NULL) { - g_date_time_unref (manual_time); - } - manual_time = g_date_time_new_now_local (); - format_time_text (time_spin, NULL); - format_time_text (date_spin, NULL); + gboolean prev_changing = changing_time; + changing_time = TRUE; + GDateTime * now = g_date_time_new_now_local (); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (time_spin), (gdouble)g_date_time_to_unix (now)); + /* will be copied to other spin button */ + g_date_time_unref (now); + changing_time = prev_changing; } return TRUE; } @@ -412,12 +434,6 @@ update_spinners (void) static void setup_time_spinners (GtkWidget * time, GtkWidget * date) { - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (time), FALSE); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (date), FALSE); - - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (time), TRUE); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (date), TRUE); - g_signal_connect (time, "input", G_CALLBACK (input_time_text), date); g_signal_connect (date, "input", G_CALLBACK (input_time_text), time); @@ -430,6 +446,9 @@ setup_time_spinners (GtkWidget * time, GtkWidget * date) g_signal_connect (time, "focus-out-event", G_CALLBACK (spin_focus_out), date); g_signal_connect (date, "focus-out-event", G_CALLBACK (spin_focus_out), time); + g_signal_connect (time, "value-changed", G_CALLBACK (spin_copy_value), date); + g_signal_connect (date, "value-changed", G_CALLBACK (spin_copy_value), time); + g_object_set_data (G_OBJECT (time), "is-time", GINT_TO_POINTER (TRUE)); g_object_set_data (G_OBJECT (date), "is-time", GINT_TO_POINTER (FALSE)); -- cgit v1.2.3 From 3abcff1218b921f7ab88ebf73c392a9c998a5df2 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 2 Mar 2011 12:16:05 +0000 Subject: Better handling of recurring items get_dtstart returns the same date for all items unfortunately --- src/datetime-service.c | 71 ++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 33b9720..d553240 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -81,6 +81,7 @@ static DbusmenuMenuitem * current_location = NULL; static DbusmenuMenuitem * add_appointment = NULL; static GList * appointments = NULL; static GList * dconflocations = NULL; +static GList * tmpobjects = NULL; GSettings *conf; @@ -449,19 +450,25 @@ auth_func (ECal *ecal, // Compare function for g_list_sort of ECalComponent objects -static gint +// Generate instances sorts them by time anyway +/*static gint compare_appointment_items (ECalComponent *a, ECalComponent *b) { + g_debug("Comparing two items from list %d %d", (int)a, (int)b); ECalComponentDateTime datetime_a, datetime_b; struct tm tm_a, tm_b; time_t t_a, t_b; + gint retval = 0; if (a == NULL || b == NULL) return 0; ECalComponentVType vtype = e_cal_component_get_vtype (a); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return -1; + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { + g_debug("A is Not a todo or event"); + return 1; + } if (vtype == E_CAL_COMPONENT_EVENT) e_cal_component_get_dtstart (a, &datetime_a); @@ -471,7 +478,10 @@ compare_appointment_items (ECalComponent *a, t_a = mktime(&tm_a); vtype = e_cal_component_get_vtype (b); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return 1; + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { + g_debug("B is Not a todo or event"); + return -1; + } if (vtype == E_CAL_COMPONENT_EVENT) e_cal_component_get_dtstart (b, &datetime_b); @@ -481,10 +491,16 @@ compare_appointment_items (ECalComponent *a, t_b = mktime(&tm_b); // Compare datetime_a and datetime_b, newest first in this sort. - if (t_a > t_b) return 1; - else if (t_a < t_b) return -1; + if (t_a > t_b) { + g_debug("A > B: %d > %d", (int)t_a, (int)t_b); + retval = 1; + } else if (t_a < t_b) { + g_debug("B > A: %d > %d", (int)t_b, (int)t_a); + retval = -1; + } + g_debug("A == B: %d == %d", (int)t_a, (int)t_b); return 0; -} +}*/ static gboolean populate_appointment_instances (ECalComponent *comp, @@ -492,15 +508,11 @@ populate_appointment_instances (ECalComponent *comp, time_t instance_end, gpointer data) { - // DEBUG what is the address of "objects" from data - - // The aim here is to receive a usable pointer to the objects list - // append to it, and change the list that data points at. - // this is a crafty hack so we're able to sort the items afterwards - GList *objects = (GList *)data; - data = (GList *)g_list_append(objects, comp); - - // DEBUG objects should have changed in the resultant location too + g_debug("Appending item %d", (int)comp); + ECalComponentVType vtype = e_cal_component_get_vtype (comp); + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return FALSE; + g_object_ref(comp); + tmpobjects = g_list_append(tmpobjects, comp); // TODO We also may as well use this opportunity to "mark days" in the calendar // as we're iterating everything of interest here anyway. @@ -522,17 +534,18 @@ update_appointment_menu_items (gpointer user_data) time_t t1, t2; gchar *ad; - GList *objects = NULL, *l; + GList *l; GList *allobjects = NULL; GSList *g; GError *gerror = NULL; + tmpobjects = NULL; gint i; gint width, height; ESourceList * sources = NULL; time(&t1); time(&t2); - t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now */ + t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now, we actually need number_of_days_in_this_month */ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); @@ -551,9 +564,6 @@ update_appointment_menu_items (gpointer user_data) } // TODO Remove all highlights from the calendar widget - - // FIXME can we put a limit on the number of results? Or if not complete, or is event/todo? Or sort it by date? - //query = g_strdup_printf("(occur-in-time-range? (make-time\"%s\") (make-time\"%s\"))", is, ie); if (!e_cal_get_sources(&sources, E_CAL_SOURCE_TYPE_EVENT, &gerror)) { g_debug("Failed to get ecal sources\n"); @@ -579,21 +589,13 @@ update_appointment_menu_items (gpointer user_data) } g_debug("Generating instances"); - e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) objects); - g_debug("Number of objects returned: %d", g_list_length(objects)); - - if (allobjects == NULL) { - allobjects = objects; - } else if (objects != NULL) { - allobjects = g_list_concat(allobjects, objects); - g_object_unref(objects); - } + e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, NULL); + g_debug("Number of objects returned: %d", g_list_length(tmpobjects)); } } + allobjects = tmpobjects; + tmpobjects = NULL; - // Sort the list see above FIXME regarding queries - g_debug("Sorting objects list"); - allobjects = g_list_sort(allobjects, (GCompareFunc) compare_appointment_items); i = 0; for (l = allobjects; l; l = l->next) { ECalComponent *ecalcomp = l->data; @@ -719,12 +721,13 @@ update_appointment_menu_items (gpointer user_data) dbusmenu_menuitem_child_add_position (root, item, 3+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove g_debug("Adding appointment: %p", item); - - if (i == 4) break; // See above FIXME regarding query result limit + + if (i == 4) break; i++; } if (gerror != NULL) g_error_free(gerror); + for (l = allobjects; l; l = l->next) g_object_unref(l->data); g_object_unref(allobjects); g_debug("End of objects"); return TRUE; -- cgit v1.2.3 From 7b2980b759af73f4ae6ac76409d10d908762d24f Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 2 Mar 2011 13:31:45 +0000 Subject: * Fixed adding/removing locations not triggering update * Improved update appointment menu items code * Improved populate_appointment_instances * Opened up objects generation to include marking days --- src/datetime-service.c | 114 +++++++++++-------------------------------------- 1 file changed, 24 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index d553240..b748841 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -448,60 +448,6 @@ auth_func (ECal *ecal, return password; } - -// Compare function for g_list_sort of ECalComponent objects -// Generate instances sorts them by time anyway -/*static gint -compare_appointment_items (ECalComponent *a, - ECalComponent *b) -{ - g_debug("Comparing two items from list %d %d", (int)a, (int)b); - ECalComponentDateTime datetime_a, datetime_b; - struct tm tm_a, tm_b; - time_t t_a, t_b; - gint retval = 0; - - if (a == NULL || b == NULL) return 0; - - ECalComponentVType vtype = e_cal_component_get_vtype (a); - - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { - g_debug("A is Not a todo or event"); - return 1; - } - - if (vtype == E_CAL_COMPONENT_EVENT) - e_cal_component_get_dtstart (a, &datetime_a); - else - e_cal_component_get_due (a, &datetime_a); - tm_a = icaltimetype_to_tm(datetime_a.value); - t_a = mktime(&tm_a); - - vtype = e_cal_component_get_vtype (b); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) { - g_debug("B is Not a todo or event"); - return -1; - } - - if (vtype == E_CAL_COMPONENT_EVENT) - e_cal_component_get_dtstart (b, &datetime_b); - else - e_cal_component_get_due (b, &datetime_b); - tm_b = icaltimetype_to_tm(datetime_b.value); - t_b = mktime(&tm_b); - - // Compare datetime_a and datetime_b, newest first in this sort. - if (t_a > t_b) { - g_debug("A > B: %d > %d", (int)t_a, (int)t_b); - retval = 1; - } else if (t_a < t_b) { - g_debug("B > A: %d > %d", (int)t_b, (int)t_a); - retval = -1; - } - g_debug("A == B: %d == %d", (int)t_a, (int)t_b); - return 0; -}*/ - static gboolean populate_appointment_instances (ECalComponent *comp, time_t instance_start, @@ -511,11 +457,13 @@ populate_appointment_instances (ECalComponent *comp, g_debug("Appending item %d", (int)comp); ECalComponentVType vtype = e_cal_component_get_vtype (comp); if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return FALSE; + + icalproperty_status status; + e_cal_component_get_status (comp, &status); + if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) return FALSE; + g_object_ref(comp); tmpobjects = g_list_append(tmpobjects, comp); - - // TODO We also may as well use this opportunity to "mark days" in the calendar - // as we're iterating everything of interest here anyway. return TRUE; } @@ -577,7 +525,7 @@ update_appointment_menu_items (gpointer user_data) for (s = e_source_group_peek_sources (group); s; s = s->next) { ESource *source = E_SOURCE (s->data); - g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL); + //g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL); ECal *ecal = e_cal_new(source, E_CAL_SOURCE_TYPE_EVENT); e_cal_set_auth_func (ecal, (ECalAuthFunc) auth_func, NULL); @@ -603,27 +551,27 @@ update_appointment_menu_items (gpointer user_data) ECalComponentDateTime datetime; icaltimezone *appointment_zone = NULL; icaltimezone *current_zone = NULL; - icalproperty_status status; gchar *summary, *cmd; char right[20]; //const gchar *uri; struct tm tmp_tm; DbusmenuMenuitem * item; - g_debug("Start Object"); + g_debug("Start Object %p", ecalcomp); ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); - // See above FIXME regarding query result - // If it's not an event or todo, continue no-increment - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) - continue; - - // See above FIXME regarding query result - // if the status is completed, continue no-increment - e_cal_component_get_status (ecalcomp, &status); - if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) - continue; - + if (vtype == E_CAL_COMPONENT_EVENT) + e_cal_component_get_dtstart (ecalcomp, &datetime); + else + e_cal_component_get_due (ecalcomp, &datetime); + + if (!datetime.value) continue; + + // TODO Mark days with appointments in the current month + + if (i >= 5) continue; + i++; + item = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, APPOINTMENT_MENUITEM_TYPE); dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); @@ -638,23 +586,13 @@ update_appointment_menu_items (gpointer user_data) g_free (summary); // Due text - if (vtype == E_CAL_COMPONENT_EVENT) - e_cal_component_get_dtstart (ecalcomp, &datetime); - else - e_cal_component_get_due (ecalcomp, &datetime); - - // FIXME need to get the timezone of the above datetime, - // and get the icaltimezone of the geoclue timezone/selected timezone (whichever is preferred) - if (!datetime.value) { - g_free(item); - continue; - } - appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid); current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone); if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone? appointment_zone = current_zone; } + // FIXME need to get the timezone of the above datetime, + // and get the icaltimezone of the geoclue timezone/selected timezone (whichever is preferred) // TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone // TODO: Add the appointment timezone to the list if it's not already there. @@ -680,12 +618,11 @@ update_appointment_menu_items (gpointer user_data) e_cal_component_free_datetime (&datetime); - ad = isodate_from_time_t(mktime(&tmp_tm)); // Now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution // FIXME Because the URI stuff is really broken, we're going to open the calendar at todays date instead - //e_cal_component_get_uid(ecalcomp, &uri); + ad = isodate_from_time_t(mktime(&tmp_tm)); cmd = g_strconcat("evolution calendar:///?startdate=", ad, NULL); g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_cb), cmd); @@ -718,17 +655,13 @@ update_appointment_menu_items (gpointer user_data) dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); } - dbusmenu_menuitem_child_add_position (root, item, 3+i); + dbusmenu_menuitem_child_add_position (root, item, 2+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove g_debug("Adding appointment: %p", item); - - if (i == 4) break; - i++; } if (gerror != NULL) g_error_free(gerror); for (l = allobjects; l; l = l->next) g_object_unref(l->data); - g_object_unref(allobjects); g_debug("End of objects"); return TRUE; } @@ -810,6 +743,7 @@ build_menus (DbusmenuMenuitem * root) check_timezone_sync(); g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL); + g_signal_connect (conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL); g_signal_connect (conf, "changed::" SETTINGS_SHOW_EVENTS_S, G_CALLBACK (show_events_changed), NULL); DbusmenuMenuitem * separator = dbusmenu_menuitem_new(); -- cgit v1.2.3 From 44bd4d29adb79c74ffbedc551a5a2414d652e7b1 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 2 Mar 2011 14:00:41 +0000 Subject: Remove items from menu when the show events key changes --- src/datetime-service.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index b748841..1983275 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -306,6 +306,18 @@ show_events_changed (void) } else { dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + /* Remove all of the previous appointments */ + if (appointments != NULL) { + g_debug("Freeing old appointments"); + while (appointments != NULL) { + DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointments->data); + g_debug("Freeing old appointment: %p", litem); + // Remove all the existing menu items which are in appointments. + appointments = g_list_remove(appointments, litem); + dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem)); + g_object_unref(G_OBJECT(litem)); + } + } stop_ecal_timer(); } } -- cgit v1.2.3 From 64fe32bfc19ffbfcf83e9d047cd0ebc1b881a785 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Thu, 3 Mar 2011 12:45:11 +0000 Subject: This actually gets the current recurrance times etc... properly - we're close to getting colours too ;) --- src/datetime-service.c | 228 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 162 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 1983275..2250c59 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -81,7 +81,7 @@ static DbusmenuMenuitem * current_location = NULL; static DbusmenuMenuitem * add_appointment = NULL; static GList * appointments = NULL; static GList * dconflocations = NULL; -static GList * tmpobjects = NULL; +static GList * comp_instances = NULL; GSettings *conf; @@ -93,6 +93,13 @@ static GeoclueAddress * geo_address = NULL; static gchar * current_timezone = NULL; static gchar * geo_timezone = NULL; +struct comp_instance { + ECalComponent *comp; + time_t start; + time_t end; + ESource *source; +}; + static void set_timezone_label (DbusmenuMenuitem * mi, const gchar * location) { @@ -460,13 +467,26 @@ auth_func (ECal *ecal, return password; } +static gint +compare_comp_instances (gconstpointer a, + gconstpointer b) +{ + const struct comp_instance *ci_a = a; + const struct comp_instance *ci_b = b; + time_t d = ci_a->start - ci_b->start; + if (d < 0) return -1; + else if (d > 0) return 1; + return 0; +} + static gboolean populate_appointment_instances (ECalComponent *comp, time_t instance_start, time_t instance_end, gpointer data) { - g_debug("Appending item %d", (int)comp); + g_debug("Appending item %p", comp); + ECalComponentVType vtype = e_cal_component_get_vtype (comp); if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return FALSE; @@ -475,7 +495,63 @@ populate_appointment_instances (ECalComponent *comp, if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) return FALSE; g_object_ref(comp); - tmpobjects = g_list_append(tmpobjects, comp); + + ECalComponentDateTime datetime; + icaltimezone *appointment_zone = NULL; + icaltimezone *current_zone = NULL; + + if (vtype == E_CAL_COMPONENT_EVENT) + e_cal_component_get_dtstart (comp, &datetime); + else + e_cal_component_get_due (comp, &datetime); + + appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid); + current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone); + if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone? + appointment_zone = current_zone; + } + + // TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone + // TODO: Add the appointment timezone to the list if it's not already there. + + GSList *period_list = NULL, *l; + if (e_cal_component_has_recurrences (comp)) { + e_cal_component_get_rdate_list (comp, &period_list); + g_debug("ECalComponent has recurrences"); + } else { + g_debug("ECalComponent doesn't have recurrences"); + } + + struct comp_instance *ci; + ci = g_new (struct comp_instance, 1); + + // Do we get rdate_list? + if (period_list != NULL) { + g_debug("Got recurring periods"); + for (l = period_list; l; l = l->next) { + ECalComponentPeriod *period = l->data; + struct tm tmp_tm = icaltimetype_to_tm_with_zone (&period->start, appointment_zone, current_zone); + time_t start = mktime(&tmp_tm); + g_debug("period time: %d", (int)start); + + tmp_tm = icaltimetype_to_tm_with_zone (&period->u.end, appointment_zone, current_zone); + time_t end = mktime(&tmp_tm); + + if (start >= instance_start && end < instance_end) { + ci->start = start; + ci->end = end; + } + } + } else { + ci->start = instance_start; + ci->end = instance_end; + g_debug("Got no recurring periods set time to start %s, end %s", ctime(&instance_start), ctime(&instance_end)); + } + + ci->comp = comp; + ci->source = E_SOURCE(data); + + comp_instances = g_list_append(comp_instances, ci); return TRUE; } @@ -495,10 +571,9 @@ update_appointment_menu_items (gpointer user_data) time_t t1, t2; gchar *ad; GList *l; - GList *allobjects = NULL; + //GList *allobjects = NULL; GSList *g; GError *gerror = NULL; - tmpobjects = NULL; gint i; gint width, height; ESourceList * sources = NULL; @@ -507,9 +582,6 @@ update_appointment_menu_items (gpointer user_data) time(&t2); t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now, we actually need number_of_days_in_this_month */ - - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - /* Remove all of the previous appointments */ if (appointments != NULL) { g_debug("Freeing old appointments"); @@ -529,7 +601,18 @@ update_appointment_menu_items (gpointer user_data) g_debug("Failed to get ecal sources\n"); return FALSE; } - + + // Free comp_instances if not NULL + if (comp_instances != NULL) { + g_debug("Freeing comp_instances: may be an overlap\n"); + for (l = comp_instances; l; l = l->next) { + const struct comp_instance *ci = l->data; + g_object_unref(ci->comp); + g_list_free(comp_instances); + comp_instances = NULL; + } + } + // iterate the query for all sources for (g = e_source_list_peek_groups (sources); g; g = g->next) { ESourceGroup *group = E_SOURCE_GROUP (g->data); @@ -549,37 +632,31 @@ update_appointment_menu_items (gpointer user_data) } g_debug("Generating instances"); - e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, NULL); - g_debug("Number of objects returned: %d", g_list_length(tmpobjects)); + e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) source); + g_debug("Number of objects returned: %d", g_list_length(comp_instances)); } } - allobjects = tmpobjects; - tmpobjects = NULL; - + GList *sorted_comp_instances = g_list_sort(comp_instances, compare_comp_instances); + comp_instances = NULL; i = 0; - for (l = allobjects; l; l = l->next) { - ECalComponent *ecalcomp = l->data; + + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + if (width == 0) width = 16; + if (height == 0) height = 16; + + for (l = sorted_comp_instances; l; l = l->next) { + struct comp_instance *ci = l->data; + ECalComponent *ecalcomp = ci->comp; ECalComponentText valuetext; - ECalComponentDateTime datetime; - icaltimezone *appointment_zone = NULL; - icaltimezone *current_zone = NULL; + //ECalComponentDateTime datetime; gchar *summary, *cmd; char right[20]; //const gchar *uri; - struct tm tmp_tm; DbusmenuMenuitem * item; g_debug("Start Object %p", ecalcomp); - ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); - - if (vtype == E_CAL_COMPONENT_EVENT) - e_cal_component_get_dtstart (ecalcomp, &datetime); - else - e_cal_component_get_due (ecalcomp, &datetime); - - if (!datetime.value) continue; - // TODO Mark days with appointments in the current month + // TODO Mark days if (i >= 5) continue; i++; @@ -597,75 +674,89 @@ update_appointment_menu_items (gpointer user_data) g_debug("Summary: %s", summary); g_free (summary); - // Due text - appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid); - current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone); - if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone? - appointment_zone = current_zone; - } + //appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid); + //current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone); + //if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone? + // appointment_zone = current_zone; + //} // FIXME need to get the timezone of the above datetime, // and get the icaltimezone of the geoclue timezone/selected timezone (whichever is preferred) // TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone // TODO: Add the appointment timezone to the list if it's not already there. - tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, current_zone); + //tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, current_zone); + + // Due text + ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); - g_debug("Generate time string"); // Get today time_t curtime = time(NULL); - struct tm* today = localtime(&curtime); - if (today->tm_mday == tmp_tm.tm_mday && - today->tm_mon == tmp_tm.tm_mon && - today->tm_year == tmp_tm.tm_year) - strftime(right, 20, "%l:%M %P", &tmp_tm); + struct tm *today = localtime(&curtime); + + int mday = today->tm_mday; + int mon = today->tm_mon; + int year = today->tm_year; + + struct tm *due; + g_debug("Start time %s", ctime(&ci->start)); + if (vtype == E_CAL_COMPONENT_EVENT) due = localtime(&ci->start); + else if (vtype == E_CAL_COMPONENT_TODO) due = localtime(&ci->end); + else continue; + + strftime(right, 20, "%a %l:%M %p", due); + g_debug("Start time %s -> %s", asctime(due), right); + + int dmday = due->tm_mday; + int dmon = due->tm_mon; + int dyear = due->tm_year; + + if ((mday == dmday) && (mon == dmon) && (year == dyear)) + strftime(right, 20, "%l:%M %p", due); else - strftime(right, 20, "%a %l:%M %P", &tmp_tm); + strftime(right, 20, "%a %l:%M %p", due); g_debug("Appointment time: %s", right); - g_debug("Appointment timezone: %s", datetime.tzid); - g_debug("Appointment timezone: %s", icaltimezone_get_tzid(appointment_zone)); // These two should be the same + //g_debug("Appointment timezone: %s", datetime.tzid); + //g_debug("Appointment timezone: %s", icaltimezone_get_tzid(appointment_zone)); // These two should be the same //g_debug("Calendar timezone: %s", ecal_timezone); dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); - e_cal_component_free_datetime (&datetime); + //e_cal_component_free_datetime (&datetime); // Now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution // FIXME Because the URI stuff is really broken, we're going to open the calendar at todays date instead //e_cal_component_get_uid(ecalcomp, &uri); - ad = isodate_from_time_t(mktime(&tmp_tm)); + ad = isodate_from_time_t(mktime(due)); cmd = g_strconcat("evolution calendar:///?startdate=", ad, NULL); g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_cb), cmd); g_debug("Command to Execute: %s", cmd); - - // FIXME This is now more difficult to get right with more sources, as we need to keep track - // of which ecal or source goes with each ECalComponent :/ - - //ESource *source = e_cal_get_source (ecal); - //e_source_get_color (source, &source_color); api has been changed - const gchar *color_spec = NULL; //e_source_peek_color_spec(source); + + const gchar *color_spec = e_source_peek_color_spec(ci->source); g_debug("Colour to use: %s", color_spec); // Draw the correct icon for the appointment type and then tint it using mask fill. // For now we'll create a circle if (color_spec != NULL) { - GdkColor color; + // Fixme causes segfault, but we have colours now yay! + /*GdkColor color; gdk_color_parse (color_spec, &color); - - cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cairo_t *cr = cairo_create(cs); - cairo_arc (cr, width/2, height/2, width/2, 0, 2 * M_PI); - gdk_cairo_set_source_color(cr, &color); - cairo_fill(cr); + GdkPixmap *pixmap = gdk_pixmap_new(NULL, width, height, 32); + if (pixmap != NULL) { + cairo_t *cr = gdk_cairo_create(pixmap); + cairo_arc (cr, width/2, height/2, width/2, 0, 2 * M_PI); + gdk_cairo_set_source_color(cr, &color); + cairo_fill(cr); - GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs, - gdk_colormap_new(gdk_drawable_get_visual((GdkDrawable*)cs), TRUE), 0,0,0,0, width, height); - cairo_destroy(cr); + GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)pixmap, + gdk_colormap_new(gdk_drawable_get_visual((GdkDrawable*)pixmap), TRUE), 0,0,0,0, width, height); + cairo_destroy(cr); - dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + }*/ } dbusmenu_menuitem_child_add_position (root, item, 2+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove @@ -673,7 +764,12 @@ update_appointment_menu_items (gpointer user_data) } if (gerror != NULL) g_error_free(gerror); - for (l = allobjects; l; l = l->next) g_object_unref(l->data); + for (l = sorted_comp_instances; l; l = l->next) { + const struct comp_instance *ci = l->data; + g_object_unref(ci->comp); + g_list_free(sorted_comp_instances); + } + g_debug("End of objects"); return TRUE; } -- cgit v1.2.3 From 8dbd819cd5143cb6016b775d0e229819cf324604 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Thu, 3 Mar 2011 09:34:57 -0500 Subject: fix some visual issues mpt found; drop libmap/Makefile.in from bzr --- src/datetime-prefs.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index e69d58b..2435eff 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -30,6 +30,7 @@ with this program. If not, see . #include #include #include +#include #include #include #include @@ -426,6 +427,32 @@ timezone_selected (GtkEntryCompletion * widget, GtkTreeModel * model, return FALSE; // Do normal action too } +static gboolean +key_pressed (GtkWidget * widget, GdkEventKey * event, gpointer user_data) +{ + switch (event->keyval) { + case GDK_KEY_Escape: + gtk_widget_destroy (widget); + return TRUE; + } + return FALSE; +} + +static GtkWidget * +get_child_of_type (GtkContainer * parent, GType type) +{ + GList * children, * iter; + + children = gtk_container_get_children (parent); + for (iter = children; iter; iter = iter->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (iter->data, type)) { + return GTK_WIDGET (iter->data); + } + } + + return NULL; +} + static GtkWidget * create_dialog (void) { @@ -451,6 +478,11 @@ create_dialog (void) 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); + /* Make sure border around button is visible */ + GtkWidget * polkit_button_button = get_child_of_type (GTK_CONTAINER (polkit_button), GTK_TYPE_BUTTON); + if (polkit_button_button != NULL) { + gtk_button_set_relief (GTK_BUTTON (polkit_button_button), GTK_RELIEF_NORMAL); + } /* Add map */ tzmap = cc_timezone_map_new (); @@ -513,6 +545,7 @@ create_dialog (void) tz_entry = WIG ("timezoneEntry"); g_signal_connect (WIG ("locationsButton"), "clicked", G_CALLBACK (show_locations), dlg); + g_signal_connect (dlg, "key-press-event", G_CALLBACK (key_pressed), NULL); /* Grab proxy for settings daemon */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, @@ -565,7 +598,7 @@ main (int argc, char ** argv) unique_app_watch_window (app, GTK_WINDOW (dlg)); gtk_widget_show_all (dlg); - g_signal_connect (dlg, "response", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect (dlg, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_main (); } -- cgit v1.2.3 From 55736aa91ce77af6127ec115860cb2379158d48b Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Thu, 3 Mar 2011 09:44:42 -0500 Subject: add back missing unref --- src/datetime-prefs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index b6fd1c9..901c290 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -304,6 +304,7 @@ input_time_text (GtkWidget * spinner, gdouble * value, gpointer user_data) 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; -- cgit v1.2.3 From 27e4da12f64cf3fbb3ae581a70503865c64e76b2 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Thu, 3 Mar 2011 13:46:29 +0000 Subject: Added decent conversion from cairo context to pixbuf and updated the colour code so it works. Currently we show a rectangle, but we could equally use a mask. --- src/datetime-service.c | 66 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 2250c59..45546a0 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -641,8 +641,8 @@ update_appointment_menu_items (gpointer user_data) i = 0; gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - if (width == 0) width = 16; - if (height == 0) height = 16; + if (width == 0) width = 12; + if (height == 0) height = 12; for (l = sorted_comp_instances; l; l = l->next) { struct comp_instance *ci = l->data; @@ -742,21 +742,55 @@ update_appointment_menu_items (gpointer user_data) // For now we'll create a circle if (color_spec != NULL) { // Fixme causes segfault, but we have colours now yay! - /*GdkColor color; - gdk_color_parse (color_spec, &color); - GdkPixmap *pixmap = gdk_pixmap_new(NULL, width, height, 32); - if (pixmap != NULL) { - cairo_t *cr = gdk_cairo_create(pixmap); - cairo_arc (cr, width/2, height/2, width/2, 0, 2 * M_PI); - gdk_cairo_set_source_color(cr, &color); - cairo_fill(cr); - - GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)pixmap, - gdk_colormap_new(gdk_drawable_get_visual((GdkDrawable*)pixmap), TRUE), 0,0,0,0, width, height); - cairo_destroy(cr); + GdkColor color; + gdk_color_parse (color_spec, &color); + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height ); + + cairo_t *cr = cairo_create(surface); + gdk_cairo_set_source_color(cr, &color); + cairo_paint(cr); + cairo_set_source_rgba(cr, 0,0,0,0.5); + cairo_set_line_width(cr, 1); + cairo_rectangle (cr, 0.5, 0.5, width-1, height-1); + cairo_stroke(cr); + // Convert to pixbuf, in gtk3 this is done with gdk_pixbuf_get_from_surface + cairo_content_t content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR; + GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + !!(content & CAIRO_CONTENT_ALPHA), + 8, width, height); + + gint sstride = cairo_image_surface_get_stride( surface ); + gint dstride = gdk_pixbuf_get_rowstride (pixbuf); + guchar *spixels = cairo_image_surface_get_data( surface ); + guchar *dpixels = gdk_pixbuf_get_pixels (pixbuf); + + + int x, y; + for (y = 0; y < height; y++) { + guint32 *src = (guint32 *) spixels; + + for (x = 0; x < width; x++) { + guint alpha = src[x] >> 24; + + if (alpha == 0) { + dpixels[x * 4 + 0] = 0; + dpixels[x * 4 + 1] = 0; + dpixels[x * 4 + 2] = 0; + } else { + dpixels[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; + dpixels[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; + dpixels[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + } + dpixels[x * 4 + 3] = alpha; + } + spixels += sstride; + dpixels += dstride; + } + + cairo_surface_destroy (surface); + cairo_destroy(cr); - dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); - }*/ + dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); } dbusmenu_menuitem_child_add_position (root, item, 2+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove -- cgit v1.2.3 From 76825a8ee0227c18fd02a30ab74ecc5a95382b6d Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Thu, 3 Mar 2011 14:45:37 +0000 Subject: Added some small fixes to make sure the pixbuf redraws everytime. There may be some memory leaks corrupting data somewhere. --- src/datetime-service.c | 77 +++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index 45546a0..fd14af9 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -82,6 +82,7 @@ static DbusmenuMenuitem * add_appointment = NULL; static GList * appointments = NULL; static GList * dconflocations = NULL; static GList * comp_instances = NULL; +static gboolean updating_appointments = FALSE; GSettings *conf; @@ -567,6 +568,8 @@ update_appointment_menu_items (gpointer user_data) // tea timers, pomodoro timers etc... that people may add, this is hinted to in the spec. if (calendar == NULL) return FALSE; if (!g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) return FALSE; + if (updating_appointments) return TRUE; + updating_appointments = TRUE; time_t t1, t2; gchar *ad; @@ -640,10 +643,6 @@ update_appointment_menu_items (gpointer user_data) comp_instances = NULL; i = 0; - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - if (width == 0) width = 12; - if (height == 0) height = 12; - for (l = sorted_comp_instances; l; l = l->next) { struct comp_instance *ci = l->data; ECalComponent *ecalcomp = ci->comp; @@ -743,7 +742,12 @@ update_appointment_menu_items (gpointer user_data) if (color_spec != NULL) { // Fixme causes segfault, but we have colours now yay! GdkColor color; - gdk_color_parse (color_spec, &color); + gdk_color_parse (color_spec, &color); + + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + if (width == 0) width = 12; + if (height == 0) height = 12; + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height ); cairo_t *cr = cairo_create(surface); @@ -758,39 +762,39 @@ update_appointment_menu_items (gpointer user_data) GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!(content & CAIRO_CONTENT_ALPHA), 8, width, height); - - gint sstride = cairo_image_surface_get_stride( surface ); - gint dstride = gdk_pixbuf_get_rowstride (pixbuf); - guchar *spixels = cairo_image_surface_get_data( surface ); - guchar *dpixels = gdk_pixbuf_get_pixels (pixbuf); - - - int x, y; - for (y = 0; y < height; y++) { - guint32 *src = (guint32 *) spixels; - - for (x = 0; x < width; x++) { - guint alpha = src[x] >> 24; - - if (alpha == 0) { - dpixels[x * 4 + 0] = 0; - dpixels[x * 4 + 1] = 0; - dpixels[x * 4 + 2] = 0; - } else { - dpixels[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; - dpixels[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; - dpixels[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + if (pixbuf != NULL) { + gint sstride = cairo_image_surface_get_stride( surface ); + gint dstride = gdk_pixbuf_get_rowstride (pixbuf); + guchar *spixels = cairo_image_surface_get_data( surface ); + guchar *dpixels = gdk_pixbuf_get_pixels (pixbuf); + + int x, y; + for (y = 0; y < height; y++) { + guint32 *src = (guint32 *) spixels; + + for (x = 0; x < width; x++) { + guint alpha = src[x] >> 24; + + if (alpha == 0) { + dpixels[x * 4 + 0] = 0; + dpixels[x * 4 + 1] = 0; + dpixels[x * 4 + 2] = 0; + } else { + dpixels[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; + dpixels[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; + dpixels[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + } + dpixels[x * 4 + 3] = alpha; } - dpixels[x * 4 + 3] = alpha; - } - spixels += sstride; - dpixels += dstride; - } - - cairo_surface_destroy (surface); - cairo_destroy(cr); + spixels += sstride; + dpixels += dstride; + } + + cairo_surface_destroy (surface); + cairo_destroy(cr); - dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + } } dbusmenu_menuitem_child_add_position (root, item, 2+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove @@ -804,6 +808,7 @@ update_appointment_menu_items (gpointer user_data) g_list_free(sorted_comp_instances); } + updating_appointments = FALSE; g_debug("End of objects"); return TRUE; } -- cgit v1.2.3 From 3aa4316f935bead55058441956d8b80e01146199 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Thu, 3 Mar 2011 14:59:17 +0000 Subject: Width appears to be repeatedly overwritten with zero --- src/datetime-service.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/datetime-service.c b/src/datetime-service.c index fd14af9..7b135a8 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -643,6 +643,9 @@ update_appointment_menu_items (gpointer user_data) comp_instances = NULL; i = 0; + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + if (width == 0) width = 12; + if (height == 0) height = 12; for (l = sorted_comp_instances; l; l = l->next) { struct comp_instance *ci = l->data; ECalComponent *ecalcomp = ci->comp; @@ -743,13 +746,11 @@ update_appointment_menu_items (gpointer user_data) // Fixme causes segfault, but we have colours now yay! GdkColor color; gdk_color_parse (color_spec, &color); - - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - if (width == 0) width = 12; - if (height == 0) height = 12; cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height ); - + // Width keeps becoming zero!! + if (width == 0) width = 12; + if (height == 0) height = 12; cairo_t *cr = cairo_create(surface); gdk_cairo_set_source_color(cr, &color); cairo_paint(cr); @@ -759,6 +760,9 @@ update_appointment_menu_items (gpointer user_data) cairo_stroke(cr); // Convert to pixbuf, in gtk3 this is done with gdk_pixbuf_get_from_surface cairo_content_t content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR; + // Width keeps becoming zero!! + if (width == 0) width = 12; + if (height == 0) height = 12; GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!(content & CAIRO_CONTENT_ALPHA), 8, width, height); -- cgit v1.2.3 From cd4699a975d0c019d0143d26cfaa0758af1e655f Mon Sep 17 00:00:00 2001 From: Ken VanDine Date: Thu, 3 Mar 2011 13:14:14 -0500 Subject: quit when the close putton is clicked --- src/datetime-prefs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index cb38c24..5248911 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -678,6 +678,7 @@ main (int argc, char ** argv) unique_app_watch_window (app, GTK_WINDOW (dlg)); gtk_widget_show_all (dlg); + g_signal_connect (dlg, "response", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect (dlg, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_main (); } -- cgit v1.2.3