diff options
author | Charles Kerr <charles.kerr@canonical.com> | 2013-06-14 16:01:43 -0500 |
---|---|---|
committer | Charles Kerr <charles.kerr@canonical.com> | 2013-06-14 16:01:43 -0500 |
commit | e392dd10a5dde1a0333fdeb963ecb1efecc8b19a (patch) | |
tree | a289289da305cf050d861418e32d1be16371b366 | |
parent | 8002a463e5fcd9d0b65ca2a445addf37cb117e32 (diff) | |
download | ayatana-indicator-datetime-e392dd10a5dde1a0333fdeb963ecb1efecc8b19a.tar.gz ayatana-indicator-datetime-e392dd10a5dde1a0333fdeb963ecb1efecc8b19a.tar.bz2 ayatana-indicator-datetime-e392dd10a5dde1a0333fdeb963ecb1efecc8b19a.zip |
remove the old indicator & service code
-rw-r--r-- | src/datetime-interface.c | 200 | ||||
-rw-r--r-- | src/datetime-interface.h | 57 | ||||
-rw-r--r-- | src/datetime-service.c | 1138 | ||||
-rw-r--r-- | src/datetime-service.xml | 11 | ||||
-rw-r--r-- | src/indicator-datetime.c | 1535 |
5 files changed, 0 insertions, 2941 deletions
diff --git a/src/datetime-interface.c b/src/datetime-interface.c deleted file mode 100644 index 72c7437..0000000 --- a/src/datetime-interface.c +++ /dev/null @@ -1,200 +0,0 @@ -/* -An indicator to time and date related information in the menubar. - -Copyright 2010 Canonical Ltd. - -Authors: - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gio/gio.h> - -#include "datetime-interface.h" -#include "gen-datetime-service.xml.h" -#include "dbus-shared.h" - -/** - DatetimeInterfacePrivate: - @dbus_registration: The handle for this object being registered - on dbus. - - Structure to define the memory for the private area - of the datetime interface instance. -*/ -struct _DatetimeInterfacePrivate { - GDBusConnection * bus; - GCancellable * bus_cancel; - guint dbus_registration; -}; - -#define DATETIME_INTERFACE_GET_PRIVATE(o) (DATETIME_INTERFACE(o)->priv) - -/* GDBus Stuff */ -static GDBusNodeInfo * node_info = NULL; -static GDBusInterfaceInfo * interface_info = NULL; - -static void datetime_interface_class_init (DatetimeInterfaceClass *klass); -static void datetime_interface_init (DatetimeInterface *self); -static void datetime_interface_dispose (GObject *object); -static void datetime_interface_finalize (GObject *object); -static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data); - -G_DEFINE_TYPE (DatetimeInterface, datetime_interface, G_TYPE_OBJECT); - -static void -datetime_interface_class_init (DatetimeInterfaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (DatetimeInterfacePrivate)); - - object_class->dispose = datetime_interface_dispose; - object_class->finalize = datetime_interface_finalize; - - /* Setting up the DBus interfaces */ - if (node_info == NULL) { - GError * error = NULL; - - node_info = g_dbus_node_info_new_for_xml(_datetime_service, &error); - if (error != NULL) { - g_error("Unable to parse Datetime Service Interface description: %s", error->message); - g_error_free(error); - } - } - - if (interface_info == NULL) { - interface_info = g_dbus_node_info_lookup_interface(node_info, SERVICE_IFACE); - - if (interface_info == NULL) { - g_error("Unable to find interface '" SERVICE_IFACE "'"); - } - } - - return; -} - -static void -datetime_interface_init (DatetimeInterface *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, DATETIME_INTERFACE_TYPE, DatetimeInterfacePrivate); - - self->priv->bus = NULL; - self->priv->bus_cancel = NULL; - self->priv->dbus_registration = 0; - - self->priv->bus_cancel = g_cancellable_new(); - g_bus_get(G_BUS_TYPE_SESSION, - self->priv->bus_cancel, - bus_get_cb, - self); - - return; -} - -static void -bus_get_cb (GObject * object G_GNUC_UNUSED, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - GDBusConnection * connection = g_bus_get_finish(res, &error); - - if (error != NULL) { - g_error("OMG! Unable to get a connection to DBus: %s", error->message); - g_error_free(error); - return; - } - - DatetimeInterfacePrivate * priv = DATETIME_INTERFACE_GET_PRIVATE(user_data); - - g_warn_if_fail(priv->bus == NULL); - priv->bus = connection; - - g_clear_object (&priv->bus_cancel); - - /* Now register our object on our new connection */ - priv->dbus_registration = g_dbus_connection_register_object(priv->bus, - SERVICE_OBJ, - interface_info, - NULL, - user_data, - NULL, - &error); - - if (error != NULL) { - g_error("Unable to register the object to DBus: %s", error->message); - g_error_free(error); - return; - } - - return; -} - -static void -datetime_interface_dispose (GObject *object) -{ - DatetimeInterfacePrivate * priv = DATETIME_INTERFACE_GET_PRIVATE(object); - - if (priv->dbus_registration != 0) { - g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration); - /* Don't care if it fails, there's nothing we can do */ - priv->dbus_registration = 0; - } - - g_clear_object (&priv->bus); - - if (priv->bus_cancel != NULL) { - g_cancellable_cancel(priv->bus_cancel); - g_clear_object (&priv->bus_cancel); - } - - G_OBJECT_CLASS (datetime_interface_parent_class)->dispose (object); - return; -} - -static void -datetime_interface_finalize (GObject *object) -{ - - G_OBJECT_CLASS (datetime_interface_parent_class)->finalize (object); - return; -} - -void -datetime_interface_update (DatetimeInterface *self) -{ - g_return_if_fail(IS_DATETIME_INTERFACE(self)); - - DatetimeInterfacePrivate * priv = DATETIME_INTERFACE_GET_PRIVATE(self); - GError * error = NULL; - - g_dbus_connection_emit_signal (priv->bus, - NULL, - SERVICE_OBJ, - SERVICE_IFACE, - "UpdateTime", - NULL, - &error); - - if (error != NULL) { - g_error("Unable to send UpdateTime signal: %s", error->message); - g_error_free(error); - return; - } - - return; -} diff --git a/src/datetime-interface.h b/src/datetime-interface.h deleted file mode 100644 index ae85605..0000000 --- a/src/datetime-interface.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -An indicator to time and date related information in the menubar. - -Copyright 2010 Canonical Ltd. - -Authors: - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef __DATETIME_INTERFACE_H__ -#define __DATETIME_INTERFACE_H__ - -#include <glib.h> -#include <glib-object.h> - -G_BEGIN_DECLS - -#define DATETIME_INTERFACE_TYPE (datetime_interface_get_type ()) -#define DATETIME_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DATETIME_INTERFACE_TYPE, DatetimeInterface)) -#define DATETIME_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DATETIME_INTERFACE_TYPE, DatetimeInterfaceClass)) -#define IS_DATETIME_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DATETIME_INTERFACE_TYPE)) -#define IS_DATETIME_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DATETIME_INTERFACE_TYPE)) -#define DATETIME_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DATETIME_INTERFACE_TYPE, DatetimeInterfaceClass)) - -typedef struct _DatetimeInterface DatetimeInterface; -typedef struct _DatetimeInterfacePrivate DatetimeInterfacePrivate; -typedef struct _DatetimeInterfaceClass DatetimeInterfaceClass; - -struct _DatetimeInterfaceClass { - GObjectClass parent_class; - - void (*update_time) (void); -}; - -struct _DatetimeInterface { - GObject parent; - DatetimeInterfacePrivate * priv; -}; - -GType datetime_interface_get_type (void); -void datetime_interface_update (DatetimeInterface *self); - -G_END_DECLS - -#endif diff --git a/src/datetime-service.c b/src/datetime-service.c deleted file mode 100644 index 1a29949..0000000 --- a/src/datetime-service.c +++ /dev/null @@ -1,1138 +0,0 @@ -/*-*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* -An indicator to time and date related information in the menubar. - -Copyright 2010 Canonical Ltd. - -Authors: - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#include <config.h> -#include <libindicator/indicator-service.h> -#include <locale.h> - -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <glib/gi18n.h> -#include <math.h> /* fabs() */ - -#include <libdbusmenu-gtk/menuitem.h> -#include <libdbusmenu-glib/server.h> -#include <libdbusmenu-glib/client.h> -#include <libdbusmenu-glib/menuitem.h> - -#include <cairo/cairo.h> - -#include "datetime-interface.h" -#include "dbus-shared.h" -#include "settings-shared.h" -#include "planner-eds.h" -#include "timezone-file.h" -#include "timezone-geoclue.h" -#include "utils.h" - -/* how often to check for clock skew */ -#define SKEW_CHECK_INTERVAL_SEC 10 - -#define MAX_APPOINTMENT_MENUITEMS 5 - -#define SKEW_DIFF_THRESHOLD_SEC (SKEW_CHECK_INTERVAL_SEC + 5) - -#ifdef HAVE_CCPANEL - #define SETTINGS_APP_INVOCATION "gnome-control-center indicator-datetime" -#else - #define SETTINGS_APP_INVOCATION "gnome-control-center datetime" -#endif - -static gboolean get_greeter_mode (void); - -static void quick_set_tz (DbusmenuMenuitem * menuitem, guint timestamp, gpointer user_data); - -static DbusmenuMenuitem * root = NULL; -static DatetimeInterface * dbus = NULL; - -typedef struct IndicatorDatetimeService -{ - DbusmenuMenuitem * date; - DbusmenuMenuitem * calendar; - DbusmenuMenuitem * settings; - DbusmenuMenuitem * events_separator; - DbusmenuMenuitem * locations_separator; - DbusmenuMenuitem * add_appointment; - DbusmenuMenuitem * appointment_menuitems[MAX_APPOINTMENT_MENUITEMS]; - - GSList * location_menu_items; - gboolean updating_appointments; - time_t start_time_appointments; - GSettings * conf; - - IndicatorDatetimeTimezone * geo_location; - IndicatorDatetimeTimezone * tz_file; - IndicatorDatetimePlanner * planner; - - guint ecaltimer; - guint day_timer; -} -IndicatorDatetimeService; - -static void update_location_menu_items (IndicatorDatetimeService * self); -static void update_appointment_menu_items (IndicatorDatetimeService * self); -static void day_timer_reset (IndicatorDatetimeService * self); - -/** - * A temp struct used by update_location_menu_items() for pruning duplicates and sorting. - */ -struct TimeLocation -{ - gint32 offset; - gchar * zone; - gchar * name; - gboolean visible; -}; - -static void -time_location_free (struct TimeLocation * loc) -{ - g_free (loc->name); - g_free (loc->zone); - g_free (loc); -} - -static struct TimeLocation* -time_location_new (const char * zone, const char * name, gboolean visible, time_t now) -{ - struct TimeLocation * loc = g_new (struct TimeLocation, 1); - GTimeZone * tz = g_time_zone_new (zone); - gint interval = g_time_zone_find_interval (tz, G_TIME_TYPE_UNIVERSAL, now); - loc->offset = g_time_zone_get_offset (tz, interval); - loc->zone = g_strdup (zone); - loc->name = g_strdup (name); - loc->visible = visible; - g_time_zone_unref (tz); - g_debug ("%s zone '%s' name '%s' offset is %d", G_STRLOC, zone, name, (int)loc->offset); - return loc; -} - -static int -time_location_compare (const struct TimeLocation * a, const struct TimeLocation * b) -{ - int ret = a->offset - b->offset; /* primary key */ - if (!ret) - ret = g_strcmp0 (a->name, b->name); /* secondary key */ - if (!ret) - ret = a->visible - b->visible; /* tertiary key */ - g_debug ("%s comparing '%s' (%d) to '%s' (%d), returning %d", G_STRLOC, a->name, (int)a->offset, b->name, (int)b->offset, ret); - return ret; -} - -static GSList* -locations_add (GSList * locations, const char * zone, const char * name, gboolean visible, time_t now) -{ - struct TimeLocation * loc = time_location_new (zone, name, visible, now); - - if (g_slist_find_custom (locations, loc, (GCompareFunc)time_location_compare) == NULL) - { - g_debug ("%s Adding zone '%s', name '%s'", G_STRLOC, zone, name); - locations = g_slist_append (locations, loc); - } - else - { - g_debug("%s Skipping duplicate zone '%s' name '%s'", G_STRLOC, zone, name); - time_location_free (loc); - } - - return locations; -} - -/* Update the timezone entries */ -static void -update_location_menu_items (IndicatorDatetimeService * self) -{ - /* if we're in greeter mode, don't bother */ - if (self->locations_separator == NULL) - return; - - /* remove the previous locations */ - while (self->location_menu_items != NULL) { - DbusmenuMenuitem * item = DBUSMENU_MENUITEM(self->location_menu_items->data); - self->location_menu_items = g_slist_remove (self->location_menu_items, item); - dbusmenu_menuitem_child_delete (root, DBUSMENU_MENUITEM(item)); - g_object_unref (item); - } - - /*** - **** Build a list of locations to add: use geo_timezone, - **** current_timezone, and SETTINGS_LOCATIONS_S, but omit duplicates. - ***/ - - GSList * locations = NULL; - const time_t now = time(NULL); /* FIXME: unmockable */ - - /* maybe add geo_timezone */ - if (self->geo_location != NULL) { - const char * geo_timezone = indicator_datetime_timezone_get_timezone (self->geo_location); - if (geo_timezone && *geo_timezone) { - const gboolean visible = g_settings_get_boolean (self->conf, SETTINGS_SHOW_DETECTED_S); - gchar * name = get_current_zone_name (geo_timezone); - locations = locations_add (locations, geo_timezone, name, visible, now); - g_free (name); - } - } - - /* maybe add current_timezone */ - if (self->tz_file != NULL) { - const char * tz = indicator_datetime_timezone_get_timezone (self->tz_file); - if (tz && *tz) { - const gboolean visible = g_settings_get_boolean (self->conf, SETTINGS_SHOW_DETECTED_S); - gchar * name = get_current_zone_name (tz); - locations = locations_add (locations, tz, name, visible, now); - g_free (name); - } - } - - /* maybe add the user-specified custom locations */ - gchar ** user_locations = g_settings_get_strv (self->conf, SETTINGS_LOCATIONS_S); - if (user_locations != NULL) { - guint i; - const guint location_count = g_strv_length (user_locations); - const gboolean visible = g_settings_get_boolean (self->conf, SETTINGS_SHOW_LOCATIONS_S); - g_debug ("%s Found %u user-specified locations", G_STRLOC, location_count); - for (i=0; i<location_count; i++) { - gchar * zone; - gchar * name; - split_settings_location (user_locations[i], &zone, &name); - locations = locations_add (locations, zone, name, visible, now); - g_free (name); - g_free (zone); - } - g_strfreev (user_locations); - user_locations = NULL; - } - - /* finally create menuitems for each location */ - gint offset = dbusmenu_menuitem_get_position (self->locations_separator, root)+1; - GSList * l; - gboolean have_visible_location = FALSE; - for (l=locations; l!=NULL; l=l->next) { - struct TimeLocation * loc = l->data; - g_debug("%s Adding location: zone '%s', name '%s'", G_STRLOC, loc->zone, loc->name); - DbusmenuMenuitem * item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE); - dbusmenu_menuitem_property_set (item, TIMEZONE_MENUITEM_PROP_NAME, loc->name); - dbusmenu_menuitem_property_set (item, TIMEZONE_MENUITEM_PROP_ZONE, loc->zone); - 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, loc->visible); - 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); - self->location_menu_items = g_slist_append (self->location_menu_items, item); - if (loc->visible) - have_visible_location = TRUE; - time_location_free (loc); - } - g_slist_free (locations); - locations = NULL; - - /* if there's at least one item being shown, show the separator too */ - dbusmenu_menuitem_property_set_bool (self->locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, have_visible_location); -} - -static void -quick_set_tz_cb (GObject *object, GAsyncResult *res, gpointer data G_GNUC_UNUSED) -{ - GError * error = NULL; - GVariant * answers = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); - - if (error != NULL) { - g_warning("Could not set timezone using timedated: %s", error->message); - g_clear_error (&error); - return; - } - - g_variant_unref (answers); -} - -static void -quick_set_tz_proxy_cb (GObject *object G_GNUC_UNUSED, GAsyncResult *res, gpointer zone) -{ - GError * error = NULL; - - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (error != NULL) { - g_warning("Could not grab DBus proxy for timedated: %s", error->message); - g_clear_error (&error); - g_free (zone); - return; - } - - g_dbus_proxy_call (proxy, "SetTimezone", g_variant_new ("(sb)", zone, TRUE), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, quick_set_tz_cb, NULL); - g_free (zone); - g_object_unref (proxy); -} - -static void -quick_set_tz (DbusmenuMenuitem * menuitem, guint timestamp G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) -{ - 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); - - const gchar * name = dbusmenu_menuitem_property_get(menuitem, TIMEZONE_MENUITEM_PROP_NAME); - - /* Set it in gsettings so we don't lose user's preferred name */ - GSettings * conf = g_settings_new (SETTINGS_INTERFACE); - gchar * tz_full = g_strdup_printf ("%s %s", tz, name); - g_settings_set_string (conf, SETTINGS_TIMEZONE_NAME_S, tz_full); - g_free (tz_full); - g_object_unref (conf); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, - "org.freedesktop.timedate1", - "/org/freedesktop/timedate1", - "org.freedesktop.timedate1", - NULL, quick_set_tz_proxy_cb, g_strdup (tz)); - - return; -} - -/* Updates the label in the date menuitem */ -static gboolean -update_datetime (gpointer gself) -{ - GDateTime *datetime; - gchar * utf8; - IndicatorDatetimeService * self = gself; - - g_debug("Updating Date/Time"); - - datetime = g_date_time_new_now_local (); /* FIXME: unmockable */ - if (datetime == NULL) { - g_warning("Error getting local time"); - dbusmenu_menuitem_property_set(self->date, DBUSMENU_MENUITEM_PROP_LABEL, _("Error getting time")); - return FALSE; - } - - /* eranslators: strftime(3) style date format on top of the menu when you click on the clock */ - utf8 = g_date_time_format (datetime, _("%A, %e %B %Y")); - dbusmenu_menuitem_property_set (self->date, DBUSMENU_MENUITEM_PROP_LABEL, utf8); - g_free(utf8); - - g_date_time_unref (datetime); - return G_SOURCE_REMOVE; -} - -/* Run a particular program based on an activation */ -static void -execute_command (const gchar * command) -{ - GError * error = NULL; - - g_debug("Issuing command '%s'", command); - if (!g_spawn_command_line_async(command, &error)) { - g_warning("Unable to start %s: %s", (char *)command, error->message); - g_clear_error (&error); - } -} - -/* Run a particular program based on an activation */ -static void -activate_cb (DbusmenuMenuitem * menuitem G_GNUC_UNUSED, - guint timestamp G_GNUC_UNUSED, - const gchar * command) -{ - execute_command (command); -} - -static gboolean -update_appointment_menu_items_idle (gpointer gself) -{ - update_appointment_menu_items (gself); - - return G_SOURCE_REMOVE; -} - -static void -update_appointment_menu_items_soon (IndicatorDatetimeService * self) -{ - g_idle_add (update_appointment_menu_items_idle, self); -} - -static void -hide_all_appointments (IndicatorDatetimeService * self) -{ - int i; - - for (i=0; i<MAX_APPOINTMENT_MENUITEMS; i++) - { - if (self->appointment_menuitems[i]) - { - dbusmenu_menuitem_property_set_bool (self->appointment_menuitems[i], DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - dbusmenu_menuitem_property_set_bool (self->appointment_menuitems[i], DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } - } -} - -static gboolean -month_changed_cb (DbusmenuMenuitem * menuitem, - gchar * name G_GNUC_UNUSED, - GVariant * variant, - guint timestamp G_GNUC_UNUSED, - gpointer gself) -{ - IndicatorDatetimeService * self = gself; - - self->start_time_appointments = (time_t)g_variant_get_uint32(variant); - - g_debug("Received month changed with timestamp: %d -> %s",(int)self->start_time_appointments, ctime(&self->start_time_appointments)); - - /* By default, one of the first things we do is - clear the marks as we don't know the correct - ones yet and we don't want to confuse the user. */ - - dbusmenu_menuitem_property_remove(menuitem, CALENDAR_MENUITEM_PROP_MARKS); - - update_appointment_menu_items_soon (self); - return TRUE; -} - -static gboolean -day_selected_cb (DbusmenuMenuitem * menuitem, - gchar * name G_GNUC_UNUSED, - GVariant * variant, - guint timestamp G_GNUC_UNUSED, - gpointer gself) -{ - time_t new_time; - IndicatorDatetimeService * self = gself; - - new_time = (time_t)g_variant_get_uint32(variant); - - if (self->start_time_appointments == 0 || new_time == 0) - { - /* If we've got nothing, assume everyhting is going to - get repopulated, let's start with a clean slate */ - dbusmenu_menuitem_property_remove (menuitem, CALENDAR_MENUITEM_PROP_MARKS); - } - else - { - /* No check to see if we changed months. If we did we'll - want to clear the marks. Otherwise we're cool keeping - them around. */ - struct tm start_tm; - struct tm new_tm; - - localtime_r (&self->start_time_appointments, &start_tm); - localtime_r (&new_time, &new_tm); - - if (start_tm.tm_mon != new_tm.tm_mon) - dbusmenu_menuitem_property_remove(menuitem, CALENDAR_MENUITEM_PROP_MARKS); - } - - self->start_time_appointments = new_time; - - g_debug ("Received day-selected with timestamp: %d -> %s",(int)self->start_time_appointments, ctime(&self->start_time_appointments)); - update_appointment_menu_items_soon (self); - - return TRUE; -} - -static gboolean -day_selected_double_click_cb (DbusmenuMenuitem * menuitem G_GNUC_UNUSED, - gchar * name G_GNUC_UNUSED, - GVariant * variant, - guint timestamp G_GNUC_UNUSED, - gpointer gself) -{ - time_t evotime; - GDateTime * dt; - IndicatorDatetimeService * self = gself; - - evotime = (time_t) g_variant_get_uint32 (variant); - dt = g_date_time_new_from_unix_utc (evotime); - indicator_datetime_planner_activate_time (self->planner, dt); - g_date_time_unref (dt); - - return TRUE; -} - - -static gboolean -update_appointment_menu_items_timerfunc (gpointer self) -{ - update_appointment_menu_items (self); - return G_SOURCE_CONTINUE; -} - -static void -start_ecal_timer (IndicatorDatetimeService * self) -{ - if (self->ecaltimer != 0) - self->ecaltimer = g_timeout_add_seconds (60*5, update_appointment_menu_items_timerfunc, self); -} - -static void -stop_ecal_timer (IndicatorDatetimeService * self) -{ - if (self->ecaltimer != 0) - { - g_source_remove (self->ecaltimer); - self->ecaltimer = 0; - } -} - -static gboolean -idle_start_ecal_timer (gpointer gself) -{ - start_ecal_timer (gself); - - return G_SOURCE_REMOVE; -} - -static void -show_events_changed (IndicatorDatetimeService * self) -{ - const gboolean b = g_settings_get_boolean (self->conf, SETTINGS_SHOW_EVENTS_S); - - dbusmenu_menuitem_property_set_bool (self->add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, b); - dbusmenu_menuitem_property_set_bool (self->events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, b); - - if (b) - { - start_ecal_timer (self); - } - else - { - hide_all_appointments (self); - stop_ecal_timer (self); - } -} - - -/* Looks for the calendar application and enables the item if - we have one, starts ecal timer if events are turned on */ -static gboolean -check_for_calendar (gpointer gself) -{ - gboolean b; - IndicatorDatetimeService * self = gself; - - g_return_val_if_fail (self->calendar != NULL, FALSE); - - dbusmenu_menuitem_property_set_bool(self->date, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - - if (!get_greeter_mode () && indicator_datetime_planner_is_configured(self->planner)) { - - int i; - int pos = 2; - - g_signal_connect (G_OBJECT(self->date), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_cb), "evolution -c calendar"); - - self->events_separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(self->events_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_add_position(root, self->events_separator, pos++); - - for (i=0; i<MAX_APPOINTMENT_MENUITEMS; i++) - { - DbusmenuMenuitem * 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); - dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - self->appointment_menuitems[i] = item; - dbusmenu_menuitem_child_add_position(root, item, pos++); - } - - self->add_appointment = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (self->add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Event…")); - dbusmenu_menuitem_property_set_bool(self->add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - g_signal_connect(G_OBJECT(self->add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar"); - dbusmenu_menuitem_child_add_position (root, self->add_appointment, pos++); - - if (g_settings_get_boolean(self->conf, SETTINGS_SHOW_EVENTS_S)) { - dbusmenu_menuitem_property_set_bool(self->add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - dbusmenu_menuitem_property_set_bool(self->events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - g_idle_add((GSourceFunc)idle_start_ecal_timer, self); - } else { - dbusmenu_menuitem_property_set_bool(self->add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_property_set_bool(self->events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - stop_ecal_timer (self); - } - - // Connect to calendar events - g_signal_connect(self->calendar, "event::month-changed", G_CALLBACK(month_changed_cb), self); - g_signal_connect(self->calendar, "event::day-selected", G_CALLBACK(day_selected_cb), self); - g_signal_connect(self->calendar, "event::day-selected-double-click", G_CALLBACK(day_selected_double_click_cb), self); - } else { - g_debug("Unable to find calendar app."); - if (self->add_appointment != NULL) - dbusmenu_menuitem_property_set_bool(self->add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - if (self->events_separator != NULL) - dbusmenu_menuitem_property_set_bool(self->events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } - - b = g_settings_get_boolean (self->conf, SETTINGS_SHOW_CALENDAR_S); - dbusmenu_menuitem_property_set_bool(self->calendar, DBUSMENU_MENUITEM_PROP_ENABLED, b); - dbusmenu_menuitem_property_set_bool(self->calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, b); - - return FALSE; -} - -static GdkPixbuf * -create_color_icon_pixbuf (const char * color_spec) -{ - static int width = -1; - static int height = -1; - GdkPixbuf * pixbuf = NULL; - - if (width == -1) - { - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height); - width = CLAMP (width, 10, 30); - height = CLAMP (height, 10, 30); - } - - if (color_spec && *color_spec) - { - cairo_surface_t * surface; - cairo_t * cr; - GdkRGBA rgba; - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cr = cairo_create (surface); - - if (gdk_rgba_parse (&rgba, color_spec)) - gdk_cairo_set_source_rgba (cr, &rgba); - - 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); - - pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height); - - cairo_destroy (cr); - cairo_surface_destroy (surface); - } - - return pixbuf; -} - - -/** - * Populate the menu with todays, next MAX_APPOINTMENT_MENUITEMS appointments. - * we should hook into the ABOUT TO SHOW signal and use that to update the appointments. - * Experience has shown that caldav's and webcals can be slow to load from eds - * this is a problem mainly on the EDS side of things, not ours. - */ -static void -update_appointment_menu_items (IndicatorDatetimeService * self) -{ - char * str; - GSList * l; - GSList * appointments; - gint i; - GDateTime * begin; - GDateTime * end; - GdkPixbuf * pixbuf; - gint apt_output; - GVariantBuilder markeddays; - GVariant * marks; - - // 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. - - g_debug ("Update appointments called"); - - if (self->calendar == NULL) - return; - if (!g_settings_get_boolean (self->conf, SETTINGS_SHOW_EVENTS_S)) - return; - if (self->updating_appointments) - return; - - self->updating_appointments = TRUE; - - g_variant_builder_init (&markeddays, G_VARIANT_TYPE ("ai")); - - if (self->start_time_appointments != 0) - begin = g_date_time_new_from_unix_local (self->start_time_appointments); - else - begin = g_date_time_new_now_local (); /* FIXME: unmockable */ - end = g_date_time_add_months (begin, 1); - indicator_datetime_planner_set_timezone (self->planner, indicator_datetime_timezone_get_timezone (self->tz_file)); - appointments = indicator_datetime_planner_get_appointments (self->planner, begin, end); - - hide_all_appointments (self); - - /* decide whether to use 12hr or 24hr format */ - str = g_settings_get_string (self->conf, SETTINGS_TIME_FORMAT_S); - if (g_strcmp0 (str, "12-hour") == 0) - apt_output = SETTINGS_TIME_12_HOUR; - else if (g_strcmp0 (str, "24-hour") == 0) - apt_output = SETTINGS_TIME_24_HOUR; - else if (is_locale_12h()) - apt_output = SETTINGS_TIME_12_HOUR; - else - apt_output = SETTINGS_TIME_24_HOUR; - g_free (str); - - i = 0; - for (l=appointments; l!=NULL; l=l->next) - { - GDateTime * due; - DbusmenuMenuitem * item; - const struct IndicatorDatetimeAppt * appt = l->data; - char * right = NULL; - - due = appt->is_event ? appt->begin : appt->end; - - /* mark day if our query hasn't hit the next month. */ - if (g_date_time_get_month (begin) == g_date_time_get_month (due)) - g_variant_builder_add (&markeddays, "i", g_date_time_get_day_of_month (due)); - - if (i >= MAX_APPOINTMENT_MENUITEMS) - continue; - - item = self->appointment_menuitems[i]; - i++; - - /* remove the icon as we might not replace it on error */ - dbusmenu_menuitem_property_remove(item, APPOINTMENT_MENUITEM_PROP_ICON); - - /* remove the activate handler */ - g_signal_handlers_disconnect_matched(G_OBJECT(item), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(activate_cb), NULL); - - 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 (item, APPOINTMENT_MENUITEM_PROP_LABEL, appt->summary); - - gboolean full_day = FALSE; - if (appt->is_event) - full_day = g_date_time_difference (appt->end, appt->begin) == G_TIME_SPAN_DAY; - - if (full_day) - { - /* TRANSLATORS: This is a strftime string for the day for full day events - in the menu. It should most likely be either '%A' for a full text day - (Wednesday) or '%a' for a shortened one (Wed). You should only need to - change for '%a' in the case of languages with very long day names. */ - right = g_date_time_format (due, _("%A")); - } - else - { - int ay, am, ad; - int by, bm, bd; - gboolean same_day; - gboolean hr12; - const char * fmt; - - g_date_time_get_ymd (due, &ay, &am, &ad); - g_date_time_get_ymd (begin, &by, &bm, &bd); - same_day = (ay==by) && (am==bm) && (ad==bd); - hr12 = apt_output == SETTINGS_TIME_12_HOUR; - - if (same_day && hr12) - fmt = _(DEFAULT_TIME_12_FORMAT); - else if (same_day) - fmt = _(DEFAULT_TIME_24_FORMAT); - else if (hr12) - fmt = _(DEFAULT_TIME_12_FORMAT_WITH_DAY); - else - fmt = _(DEFAULT_TIME_24_FORMAT_WITH_DAY); - - right = g_date_time_format (due, fmt); - } - - dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); - g_free (right); - - // 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); -/* FIXME: appointment menuitems aren't clickable */ -#if 0 - gchar * ad = isodate_from_time_t(mktime(due)); - gchar * cmd = g_strconcat("evolution calendar:///?startdate=", ad, NULL); - g_debug("Command to Execute: %s", cmd); - g_signal_connect_data (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(activate_cb), cmd, (GClosureNotify)g_free, 0); - g_free (ad); -#endif - - if ((pixbuf = create_color_icon_pixbuf (appt->color))) - { - dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); - g_clear_object (&pixbuf); - } - } - - - marks = g_variant_builder_end (&markeddays); - dbusmenu_menuitem_property_set_variant (self->calendar, CALENDAR_MENUITEM_PROP_MARKS, marks); - - g_slist_free_full (appointments, (GDestroyNotify)indicator_datetime_appt_free); - - self->updating_appointments = FALSE; - g_date_time_unref (end); - g_date_time_unref (begin); -} - -/* Looks for the time and date admin application and enables the - item we have one */ -static gboolean -check_for_timeadmin (gpointer gself) -{ - gchar * timeadmin; - IndicatorDatetimeService * self = gself; - - g_return_val_if_fail (self->settings != NULL, FALSE); - - timeadmin = g_find_program_in_path ("gnome-control-center"); - if (timeadmin != NULL) - { - g_debug ("Found the gnome-control-center application: %s", timeadmin); - dbusmenu_menuitem_property_set_bool (self->settings, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - g_free(timeadmin); - } - else - { - g_debug ("Unable to find gnome-control-center app."); - dbusmenu_menuitem_property_set_bool (self->settings, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - } - - return G_SOURCE_REMOVE; -} - -/* 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. */ -static void -build_menus (IndicatorDatetimeService * self, DbusmenuMenuitem * root) -{ - g_debug("Building Menus."); - if (self->date == NULL) { - self->date = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (self->date, DBUSMENU_MENUITEM_PROP_LABEL, _("No date yet…")); - dbusmenu_menuitem_property_set_bool(self->date, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - dbusmenu_menuitem_child_append(root, self->date); - - g_idle_add(update_datetime, self); - } - - if (self->calendar == NULL) { - self->calendar = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (self->calendar, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CALENDAR_MENUITEM_TYPE); - /* insensitive until we check for available apps */ - dbusmenu_menuitem_property_set_bool(self->calendar, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - g_signal_connect (G_OBJECT(self->calendar), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_cb), "evolution -c calendar"); - dbusmenu_menuitem_child_append(root, self->calendar); - - g_idle_add(check_for_calendar, self); - } - - if (!get_greeter_mode ()) { - self->locations_separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(self->locations_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_property_set_bool (self->locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_append(root, self->locations_separator); - - update_location_menu_items (self); - - g_signal_connect (self->conf, "changed::" SETTINGS_SHOW_EVENTS_S, G_CALLBACK (show_events_changed), self); - g_signal_connect_swapped (self->conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (update_location_menu_items), self); - g_signal_connect_swapped (self->conf, "changed::" SETTINGS_SHOW_DETECTED_S, G_CALLBACK (update_location_menu_items), self); - g_signal_connect_swapped (self->conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (update_location_menu_items), self); - g_signal_connect_swapped (self->conf, "changed::" SETTINGS_TIME_FORMAT_S, G_CALLBACK (update_appointment_menu_items), self); - - DbusmenuMenuitem * separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append(root, separator); - - self->settings = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (self->settings, DBUSMENU_MENUITEM_PROP_LABEL, _("Time & Date Settings…")); - /* insensitive until we check for available apps */ - dbusmenu_menuitem_property_set_bool(self->settings, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - g_signal_connect(G_OBJECT(self->settings), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), SETTINGS_APP_INVOCATION); - dbusmenu_menuitem_child_append(root, self->settings); - g_idle_add(check_for_timeadmin, self); - update_appointment_menu_items_soon (self); - } - - return; -} - -static void -on_clock_skew (gpointer self) -{ - /* tell the indicators to refresh */ - if (IS_DATETIME_INTERFACE (dbus)) - datetime_interface_update (DATETIME_INTERFACE(dbus)); - - /* update our day label */ - update_datetime (self); - day_timer_reset (self); -} - -static void -on_timezone_changed (gpointer self) -{ - update_location_menu_items (self); - - on_clock_skew (self); -} - -/* Execute at a given time, update and setup a new - timer to go again. */ -static gboolean -day_timer_func (gpointer self) -{ - day_timer_reset (self); - update_datetime (self); - - return G_SOURCE_REMOVE; -} - -/* Sets up the time to launch the timer to update the - date in the datetime entry */ -static void -day_timer_reset (IndicatorDatetimeService * self) -{ - GDateTime * now; - GDateTime * tomorrow; - GDateTime * new_day; - guint seconds_until_tomorrow; - - if (self->day_timer != 0) - { - g_source_remove (self->day_timer); - self->day_timer = 0; - } - - now = g_date_time_new_now_local (); - tomorrow = g_date_time_add_days (now, 1); - new_day = g_date_time_new_local (g_date_time_get_year (tomorrow), - g_date_time_get_month (tomorrow), - g_date_time_get_day_of_month (tomorrow), - 0, 0, 0); - seconds_until_tomorrow = (guint)(g_date_time_difference (new_day, now) / G_TIME_SPAN_SECOND); -g_message ("seconds until tomorrow is %u", seconds_until_tomorrow); - - self->day_timer = g_timeout_add_seconds (seconds_until_tomorrow + 15, - day_timer_func, - self); - - g_date_time_unref (new_day); - g_date_time_unref (tomorrow); - g_date_time_unref (now); -} - -static gboolean -skew_check_timer_func (gpointer self) -{ - static time_t prev_time = 0; - const time_t cur_time = time (NULL); /* FIXME: unmockable */ - const double diff_sec = fabs (difftime (cur_time, prev_time)); - - if (prev_time && (diff_sec > SKEW_DIFF_THRESHOLD_SEC)) - { - g_debug (G_STRLOC" clock skew detected (%.0f seconds)", diff_sec); - on_clock_skew (self); - } - - prev_time = cur_time; - return G_SOURCE_CONTINUE; -} - -static void -session_active_change_cb (GDBusProxy * proxy G_GNUC_UNUSED, - gchar * sender_name G_GNUC_UNUSED, - gchar * signal_name, - GVariant * parameters, - gpointer gself) -{ - IndicatorDatetimeService * self = gself; - - /* suspending / returning from suspend (true / false) */ - if (g_strcmp0(signal_name, "PrepareForSleep") == 0) - { - gboolean sleeping = FALSE; - g_variant_get (parameters, "(b)", &sleeping); - if (!sleeping) - { - g_debug ("System has been resumed; adjusting clock"); - on_clock_skew (self); - } - } -} - -/* for hooking into console kit signal on wake from suspend */ -static void -system_proxy_cb (GObject * object G_GNUC_UNUSED, - GAsyncResult * res, - gpointer gself) -{ - GError * error = NULL; - - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - - if (error != NULL) { - g_warning("Could not grab DBus proxy for logind: %s", error->message); - g_clear_error (&error); - return; - } - - g_signal_connect(proxy, "g-signal", G_CALLBACK(session_active_change_cb), gself); -} - -/**** -***** -****/ - -static gboolean -get_greeter_mode (void) -{ - const gchar *var; - var = g_getenv("INDICATOR_GREETER_MODE"); - return (g_strcmp0(var, "1") == 0); -} - -/* Repsonds to the service object saying it's time to shutdown. - It stops the mainloop. */ -static void -service_shutdown (IndicatorService * service G_GNUC_UNUSED, - gpointer gmainloop) -{ - g_warning ("Shutting down service!"); - g_main_loop_quit (gmainloop); -} - -static void -on_use_geoclue_changed_cb (GSettings * settings, - gchar * key G_GNUC_UNUSED, - gpointer gself) -{ - IndicatorDatetimeService * self = gself; - const gboolean use_geoclue = g_settings_get_boolean (settings, "show-auto-detected-location"); - - if (self->geo_location && !use_geoclue) - { - g_signal_handlers_disconnect_by_func (self->geo_location, update_location_menu_items, self); - g_clear_object (&self->geo_location); - update_location_menu_items (self); - } - else if (use_geoclue && !self->geo_location) - { - self->geo_location = indicator_datetime_timezone_geoclue_new (); - g_signal_connect_swapped (self->geo_location, "notify::timezone", - G_CALLBACK(update_location_menu_items), self); - } -} - -/* Function to build everything up. Entry point from asm. */ -int -main (int argc, char ** argv) -{ - GMainLoop * mainloop; - IndicatorService * service; - DbusmenuServer * server; - struct IndicatorDatetimeService self; - - memset (&self, 0, sizeof(struct IndicatorDatetimeService)); - - gtk_init (&argc, &argv); - mainloop = g_main_loop_new (NULL, FALSE); - - /* acknowledging the service init and setting up the interface */ - service = indicator_service_new_version(SERVICE_NAME, SERVICE_VERSION); - g_signal_connect (service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, - G_CALLBACK(service_shutdown), mainloop); - - /* setting up i18n and gettext. apparently we need all of these. */ - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain (GETTEXT_PACKAGE); - - /* set up GSettings */ - self.conf = g_settings_new (SETTINGS_INTERFACE); - g_signal_connect (self.conf, "changed::show-auto-detected-location", - G_CALLBACK(on_use_geoclue_changed_cb), &self); - - /* setup geoclue */ - on_use_geoclue_changed_cb (self.conf, NULL, &self); - - /* setup timezone watch */ - self.tz_file = indicator_datetime_timezone_file_new (TIMEZONE_FILE); - g_signal_connect_swapped (self.tz_file, "notify::timezone", - G_CALLBACK(on_timezone_changed), &self); - - /* build our list of appointment calendar sources. - When a source changes, update our menu items. - When sources are added or removed, update our list and menu items. */ - self.planner = indicator_datetime_planner_eds_new (); - g_signal_connect_swapped (self.planner, "appointments-changed", - G_CALLBACK(update_appointment_menu_items_soon), &self); - - /* building the base menu */ - server = dbusmenu_server_new (MENU_OBJ); - root = dbusmenu_menuitem_new (); - dbusmenu_server_set_root (server, root); - - build_menus (&self, root); - - /* cache the timezone */ - update_location_menu_items (&self); - - /* setup dbus interface */ - dbus = g_object_new (DATETIME_INTERFACE_TYPE, NULL); - - /* set up the day timer */ - day_timer_reset (&self); - - /* set up the skew-check timer */ - g_timeout_add_seconds (SKEW_CHECK_INTERVAL_SEC, - skew_check_timer_func, - &self); - - /* and watch for system resumes */ - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - NULL, /* FIXME: cancellable */ - system_proxy_cb, - &self); - - g_main_loop_run (mainloop); - g_main_loop_unref (mainloop); - - g_object_unref (self.conf); - g_object_unref (dbus); - g_object_unref (service); - g_object_unref (server); - g_object_unref (root); - g_object_unref (self.planner); - g_object_unref (self.geo_location); - g_object_unref (self.tz_file); - - return 0; -} diff --git a/src/datetime-service.xml b/src/datetime-service.xml deleted file mode 100644 index eda064f..0000000 --- a/src/datetime-service.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<node name="/"> - <interface name="com.canonical.indicator.datetime.service"> - -<!-- Methods --> - -<!-- Signals --> - <signal name="UpdateTime" /> - - </interface> -</node> diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c deleted file mode 100644 index f7d1a78..0000000 --- a/src/indicator-datetime.c +++ /dev/null @@ -1,1535 +0,0 @@ -/* -An indicator to time and date related information in the menubar. - -Copyright 2010 Canonical Ltd. - -Authors: - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <locale.h> -#include <langinfo.h> -#include <string.h> -#include <time.h> - -/* GStuff */ -#include <glib.h> -#include <glib/gprintf.h> -#include <glib-object.h> -#include <glib/gi18n-lib.h> -#include <gio/gio.h> - -/* Indicator Stuff */ -#include <libindicator/indicator.h> -#include <libindicator/indicator-object.h> -#include <libindicator/indicator-service-manager.h> - -/* DBusMenu */ -#include <libdbusmenu-gtk/menu.h> -#include <libido/libido.h> -#include <libdbusmenu-gtk/menuitem.h> - -#include "utils.h" -#include "dbus-shared.h" -#include "settings-shared.h" - - -#define INDICATOR_DATETIME_TYPE (indicator_datetime_get_type ()) -#define INDICATOR_DATETIME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_DATETIME_TYPE, IndicatorDatetime)) -#define INDICATOR_DATETIME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_DATETIME_TYPE, IndicatorDatetimeClass)) -#define IS_INDICATOR_DATETIME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_DATETIME_TYPE)) -#define IS_INDICATOR_DATETIME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_DATETIME_TYPE)) -#define INDICATOR_DATETIME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_DATETIME_TYPE, IndicatorDatetimeClass)) - -typedef struct _IndicatorDatetime IndicatorDatetime; -typedef struct _IndicatorDatetimeClass IndicatorDatetimeClass; -typedef struct _IndicatorDatetimePrivate IndicatorDatetimePrivate; - -struct _IndicatorDatetimeClass { - IndicatorObjectClass parent_class; -}; - -struct _IndicatorDatetime { - IndicatorObject parent; - IndicatorDatetimePrivate * priv; -}; - -struct _IndicatorDatetimePrivate { - GtkLabel * label; - guint timer; - - gchar * time_string; - - gboolean show_clock; - gint time_mode; - gboolean show_seconds; - gboolean show_date; - gboolean show_day; - gchar * custom_string; - gboolean custom_show_seconds; - - gboolean show_week_numbers; - gboolean show_calendar; - gint week_start; - - guint idle_measure; - gint max_width; - - IndicatorServiceManager * sm; - DbusmenuGtkMenu * menu; - - GCancellable * service_proxy_cancel; - GDBusProxy * service_proxy; - IdoCalendarMenuItem *ido_calendar; - - GList * timezone_items; - - GSettings * settings; - - GtkSizeGroup * indicator_right_group; -}; - -/* Enum for the properties so that they can be quickly - found and looked up. */ -enum { - PROP_0, - PROP_SHOW_CLOCK, - PROP_TIME_FORMAT, - PROP_SHOW_SECONDS, - PROP_SHOW_DAY, - PROP_SHOW_DATE, - PROP_CUSTOM_TIME_FORMAT, - PROP_SHOW_WEEK_NUMBERS, - PROP_SHOW_CALENDAR -}; - -typedef struct _indicator_item_t indicator_item_t; -struct _indicator_item_t { - IndicatorDatetime * self; - DbusmenuMenuitem * mi; - GtkWidget * gmi; - GtkWidget * icon; - GtkWidget * label; - GtkWidget * right; -}; - -#define PROP_SHOW_CLOCK_S "show-clock" -#define PROP_TIME_FORMAT_S "time-format" -#define PROP_SHOW_SECONDS_S "show-seconds" -#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 PROP_SHOW_CALENDAR_S "show-calendar" - -enum { - STRFTIME_MASK_NONE = 0, /* Hours or minutes as we always test those */ - STRFTIME_MASK_SECONDS = 1 << 0, /* Seconds count */ - STRFTIME_MASK_AMPM = 1 << 1, /* AM/PM counts */ - STRFTIME_MASK_WEEK = 1 << 2, /* Day of the week maters (Sat, Sun, etc.) */ - STRFTIME_MASK_DAY = 1 << 3, /* Day of the month counts (Feb 1st) */ - STRFTIME_MASK_MONTH = 1 << 4, /* Which month matters */ - STRFTIME_MASK_YEAR = 1 << 5, /* Which year matters */ - /* Last entry, combines all previous */ - STRFTIME_MASK_ALL = (STRFTIME_MASK_SECONDS | STRFTIME_MASK_AMPM | STRFTIME_MASK_WEEK | STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH | STRFTIME_MASK_YEAR) -}; - -GType indicator_datetime_get_type (void) G_GNUC_CONST; - -static void indicator_datetime_class_init (IndicatorDatetimeClass *klass); -static void indicator_datetime_init (IndicatorDatetime *self); -static void timezone_update_all_labels (IndicatorDatetime *self); -static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void indicator_datetime_dispose (GObject *object); -static void indicator_datetime_finalize (GObject *object); -static GtkLabel * get_label (IndicatorObject * io); -static GtkMenu * get_menu (IndicatorObject * io); -static const gchar * get_accessible_desc (IndicatorObject * io); -static const gchar * get_name_hint (IndicatorObject * io); -static gboolean bind_enum_get (GValue * value, GVariant * variant, gpointer user_data); -static gchar * generate_format_string_now (IndicatorDatetime * self); -static void update_label (IndicatorDatetime * io, GDateTime ** datetime); -static void guess_label_size (IndicatorDatetime * self); -static void setup_timer (IndicatorDatetime * self, GDateTime * datetime); -static void update_time (IndicatorDatetime * self); -static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data); -static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); -static gint generate_strftime_bitmask (const char *time_str); -static void timezone_update_labels (indicator_item_t * mi_data); -static gboolean new_calendar_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data); -static gboolean new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data); -static gboolean new_timezone_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data); - -/* Indicator Module Config */ -INDICATOR_SET_VERSION -INDICATOR_SET_TYPE(INDICATOR_DATETIME_TYPE) - -G_DEFINE_TYPE (IndicatorDatetime, indicator_datetime, INDICATOR_OBJECT_TYPE); - -static void -indicator_datetime_class_init (IndicatorDatetimeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (IndicatorDatetimePrivate)); - - object_class->dispose = indicator_datetime_dispose; - object_class->finalize = indicator_datetime_finalize; - - object_class->set_property = set_property; - object_class->get_property = get_property; - - IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); - - io_class->get_label = get_label; - io_class->get_menu = get_menu; - io_class->get_accessible_desc = get_accessible_desc; - io_class->get_name_hint = get_name_hint; - - g_object_class_install_property (object_class, - PROP_SHOW_CLOCK, - g_param_spec_boolean(PROP_SHOW_CLOCK_S, - "Whether to show the clock in the menu bar.", - "Shows indicator-datetime in the shell's menu bar.", - TRUE, /* default */ - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_TIME_FORMAT, - g_param_spec_int(PROP_TIME_FORMAT_S, - "A choice of which format should be used on the panel", - "Chooses between letting the locale choose the time, 12-hour time, 24-time or using the custom string passed to g_date_time_format().", - SETTINGS_TIME_LOCALE, /* min */ - SETTINGS_TIME_CUSTOM, /* max */ - SETTINGS_TIME_LOCALE, /* default */ - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_SHOW_SECONDS, - g_param_spec_boolean(PROP_SHOW_SECONDS_S, - "Whether to show seconds in the indicator.", - "Shows seconds along with the time in the indicator. Also effects refresh interval.", - FALSE, /* default */ - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_SHOW_DAY, - g_param_spec_boolean(PROP_SHOW_DAY_S, - "Whether to show the day of the week in the indicator.", - "Shows the day of the week along with the time in the indicator.", - FALSE, /* default */ - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_SHOW_DATE, - g_param_spec_boolean(PROP_SHOW_DATE_S, - "Whether to show the day and month in the indicator.", - "Shows the day and month along with the time in the indicator.", - FALSE, /* default */ - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_CUSTOM_TIME_FORMAT, - g_param_spec_string(PROP_CUSTOM_TIME_FORMAT_S, - "The format that is used to show the time on the panel.", - "A format string in the form used to pass to g_date_time_format() to make a string for displaying on the panel.", - 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)); - g_object_class_install_property (object_class, - PROP_SHOW_CALENDAR, - g_param_spec_boolean(PROP_SHOW_CALENDAR_S, - "Whether to show the calendar.", - "Shows the monthly calendar in indicator-datetime's menu.", - TRUE, /* default */ - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - return; -} - -static void -menu_visible_notify_cb(GtkWidget * menu, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data) -{ - IndicatorDatetime * self; - g_debug ("notify visible signal received"); - - self = INDICATOR_DATETIME (user_data); - g_assert (self != NULL); - - /* if the calendar widget's been created, set it to today's datë */ - if (self->priv->ido_calendar != NULL) { - GtkWidget * w; - GtkCalendar * calendar; - gint cur_y, cur_m, cur_d; - guint cal_y, cal_m, cal_d; - GDateTime * datetime = g_date_time_new_now_local (); - - g_date_time_get_ymd (datetime, &cur_y, &cur_m, &cur_d); - w = ido_calendar_menu_item_get_calendar (self->priv->ido_calendar); - calendar = GTK_CALENDAR(w); - g_return_if_fail (calendar != NULL); - - gtk_calendar_get_date (calendar, &cal_y, &cal_m, &cal_d); - if ((cur_y != cal_y) || (cur_m-1 != cal_m)) - gtk_calendar_select_month (calendar, cur_m-1, cur_y); /* (cur_m is 1-based) */ - if (cur_d != cal_d) - gtk_calendar_select_day (calendar, cur_d); - - g_date_time_unref (datetime); - } - - /* Update in case date was changed outside of indicator-datetime */ - update_label(self, NULL); - timezone_update_all_labels(self); - - // Make sure the day-selected signal is sent so the menu updates - may duplicate - /*GVariant *variant = g_variant_new_uint32((guint)curtime); - guint timestamp = (guint)time(NULL); - dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(self->priv->ido_calendar), "day-selected", variant, timestamp);*/ -} - -static void -indicator_datetime_init (IndicatorDatetime *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - INDICATOR_DATETIME_TYPE, - IndicatorDatetimePrivate); - - self->priv->label = NULL; - self->priv->timer = 0; - - self->priv->idle_measure = 0; - self->priv->max_width = 0; - - self->priv->show_clock = TRUE; - self->priv->time_mode = SETTINGS_TIME_LOCALE; - self->priv->show_seconds = FALSE; - self->priv->show_date = FALSE; - self->priv->show_day = FALSE; - self->priv->custom_string = g_strdup(DEFAULT_TIME_FORMAT); - self->priv->custom_show_seconds = FALSE; - - self->priv->time_string = generate_format_string_now(self); - - self->priv->service_proxy = NULL; - - self->priv->sm = NULL; - self->priv->menu = NULL; - - self->priv->settings = g_settings_new(SETTINGS_INTERFACE); - if (self->priv->settings != NULL) { - g_settings_bind(self->priv->settings, - SETTINGS_SHOW_CLOCK_S, - self, - PROP_SHOW_CLOCK_S, - G_SETTINGS_BIND_GET); - g_settings_bind_with_mapping(self->priv->settings, - SETTINGS_TIME_FORMAT_S, - self, - PROP_TIME_FORMAT_S, - G_SETTINGS_BIND_GET, - bind_enum_get, - NULL, NULL, NULL); /* set mapping, userdata and destroy func */ - g_settings_bind(self->priv->settings, - SETTINGS_SHOW_SECONDS_S, - self, - PROP_SHOW_SECONDS_S, - G_SETTINGS_BIND_GET); - g_settings_bind(self->priv->settings, - SETTINGS_SHOW_DAY_S, - self, - PROP_SHOW_DAY_S, - G_SETTINGS_BIND_GET); - g_settings_bind(self->priv->settings, - SETTINGS_SHOW_DATE_S, - self, - PROP_SHOW_DATE_S, - G_SETTINGS_BIND_GET); - g_settings_bind(self->priv->settings, - SETTINGS_CUSTOM_TIME_FORMAT_S, - self, - PROP_CUSTOM_TIME_FORMAT_S, - G_SETTINGS_BIND_GET); - g_settings_bind(self->priv->settings, - SETTINGS_SHOW_WEEK_NUMBERS_S, - self, - PROP_SHOW_WEEK_NUMBERS_S, - G_SETTINGS_BIND_GET); - g_settings_bind(self->priv->settings, - SETTINGS_SHOW_CALENDAR_S, - self, - PROP_SHOW_CALENDAR_S, - G_SETTINGS_BIND_GET); - } else { - g_warning("Unable to get settings for '" SETTINGS_INTERFACE "'"); - } - - self->priv->sm = indicator_service_manager_new_version(SERVICE_NAME, SERVICE_VERSION); - self->priv->indicator_right_group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); - - self->priv->menu = dbusmenu_gtkmenu_new(SERVICE_NAME, MENU_OBJ); - - g_signal_connect(self->priv->menu, "notify::visible", G_CALLBACK(menu_visible_notify_cb), self); - - DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(self->priv->menu); - dbusmenu_client_add_type_handler_full(DBUSMENU_CLIENT(client), DBUSMENU_CALENDAR_MENUITEM_TYPE, new_calendar_item, self, NULL); - dbusmenu_client_add_type_handler_full(DBUSMENU_CLIENT(client), APPOINTMENT_MENUITEM_TYPE, new_appointment_item, self, NULL); - dbusmenu_client_add_type_handler_full(DBUSMENU_CLIENT(client), TIMEZONE_MENUITEM_TYPE, new_timezone_item, self, NULL); - - self->priv->service_proxy_cancel = g_cancellable_new(); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - SERVICE_NAME, - SERVICE_OBJ, - SERVICE_IFACE, - self->priv->service_proxy_cancel, - service_proxy_cb, - self); - - return; -} - -/* Callback from trying to create the proxy for the serivce, this - could include starting the service. Sometime it'll fail and - we'll try to start that dang service again! */ -static void -service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - - IndicatorDatetime * self = INDICATOR_DATETIME(user_data); - g_return_if_fail(self != NULL); - IndicatorDatetimePrivate * priv = self->priv; - - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - - g_clear_object (&priv->service_proxy_cancel); - - if (error != NULL) { - g_warning("Could not grab DBus proxy for %s: %s", SERVICE_NAME, error->message); - g_error_free(error); - return; - } - - /* Okay, we're good to grab the proxy at this point, we're - sure that it's ours. */ - priv->service_proxy = proxy; - - g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self); - - return; -} - -static void -indicator_datetime_dispose (GObject *object) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(object); - IndicatorDatetimePrivate * priv = self->priv; - - if (priv->timer != 0) { - g_source_remove(priv->timer); - priv->timer = 0; - } - - if (priv->idle_measure != 0) { - g_source_remove(priv->idle_measure); - priv->idle_measure = 0; - } - - g_clear_object (&priv->label); - g_clear_object (&priv->menu); - g_clear_object (&priv->sm); - g_clear_object (&priv->settings); - g_clear_object (&priv->service_proxy); - g_clear_object (&priv->indicator_right_group); - g_clear_object (&priv->ido_calendar); - g_clear_object (&priv->service_proxy_cancel); - - G_OBJECT_CLASS (indicator_datetime_parent_class)->dispose (object); - return; -} - -static void -indicator_datetime_finalize (GObject *object) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(object); - - if (self->priv->time_string != NULL) { - g_free(self->priv->time_string); - self->priv->time_string = NULL; - } - - if (self->priv->custom_string != NULL) { - g_free(self->priv->custom_string); - self->priv->custom_string = NULL; - } - - G_OBJECT_CLASS (indicator_datetime_parent_class)->finalize (object); - return; -} - -/* Turns a string GVariant into an int value */ -static gboolean -bind_enum_get (GValue * value, GVariant * variant, gpointer user_data) -{ - const gchar * str = g_variant_get_string(variant, NULL); - gint output = 0; - - if (g_strcmp0(str, "locale-default") == 0) { - output = SETTINGS_TIME_LOCALE; - } else if (g_strcmp0(str, "12-hour") == 0) { - output = SETTINGS_TIME_12_HOUR; - } else if (g_strcmp0(str, "24-hour") == 0) { - output = SETTINGS_TIME_24_HOUR; - } else if (g_strcmp0(str, "custom") == 0) { - output = SETTINGS_TIME_CUSTOM; - } else { - return FALSE; - } - - g_value_set_int(value, output); - return TRUE; -} - -static void -timezone_update_all_labels (IndicatorDatetime * self) -{ - IndicatorDatetimePrivate *priv = self->priv; - - g_list_foreach(priv->timezone_items, (GFunc)timezone_update_labels, NULL); -} - -/* Sets a property on the object */ -static void -set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(object); - gboolean update = FALSE; - - switch(prop_id) { - case PROP_SHOW_CLOCK: { - if (g_value_get_boolean(value) != self->priv->show_clock) { - self->priv->show_clock = g_value_get_boolean(value); - if (self->priv->label != NULL) { - gtk_widget_set_visible (GTK_WIDGET (self->priv->label), self->priv->show_clock); - } - } - break; - } - case PROP_TIME_FORMAT: { - gint newval = g_value_get_int(value); - if (newval != self->priv->time_mode) { - update = TRUE; - self->priv->time_mode = newval; - setup_timer(self, NULL); - } - break; - } - case PROP_SHOW_SECONDS: { - if (g_value_get_boolean(value) != self->priv->show_seconds) { - self->priv->show_seconds = !self->priv->show_seconds; - if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { - update = TRUE; - setup_timer(self, NULL); - } - } - break; - } - case PROP_SHOW_DAY: { - if (g_value_get_boolean(value) != self->priv->show_day) { - self->priv->show_day = !self->priv->show_day; - if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { - update = TRUE; - } - } - break; - } - case PROP_SHOW_DATE: { - if (g_value_get_boolean(value) != self->priv->show_date) { - self->priv->show_date = !self->priv->show_date; - if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { - update = TRUE; - } - } - break; - } - case PROP_CUSTOM_TIME_FORMAT: { - const gchar * newstr = g_value_get_string(value); - if (g_strcmp0(newstr, self->priv->custom_string) != 0) { - if (self->priv->custom_string != NULL) { - g_free(self->priv->custom_string); - self->priv->custom_string = NULL; - } - self->priv->custom_string = g_strdup(newstr); - gint time_mask = generate_strftime_bitmask(newstr); - self->priv->custom_show_seconds = (time_mask & STRFTIME_MASK_SECONDS); - if (self->priv->time_mode == SETTINGS_TIME_CUSTOM) { - update = TRUE; - setup_timer(self, NULL); - } - } - 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; - } - case PROP_SHOW_CALENDAR: { - if (g_value_get_boolean(value) != self->priv->show_calendar) { - self->priv->show_calendar = g_value_get_boolean(value); - if (self->priv->ido_calendar != NULL) { - gtk_widget_set_visible (GTK_WIDGET (self->priv->ido_calendar), self->priv->show_calendar); - } - } - break; - } - default: { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - return; - } - } - - if (!update) { - return; - } - - /* Get the new format string */ - gchar * newformat = generate_format_string_now(self); - - /* check to ensure the format really changed */ - if (g_strcmp0(self->priv->time_string, newformat) == 0) { - g_free(newformat); - return; - } - - /* Okay now process the change */ - if (self->priv->time_string != NULL) { - g_free(self->priv->time_string); - self->priv->time_string = NULL; - } - self->priv->time_string = newformat; - - /* And update everything */ - update_label(self, NULL); - timezone_update_all_labels(self); - guess_label_size(self); - - return; -} - -/* Gets a property from the object */ -static void -get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(object); - - switch(prop_id) { - case PROP_SHOW_CLOCK: - g_value_set_boolean(value, self->priv->show_clock); - break; - case PROP_TIME_FORMAT: - g_value_set_int(value, self->priv->time_mode); - break; - case PROP_SHOW_SECONDS: - g_value_set_boolean(value, self->priv->show_seconds); - break; - case PROP_SHOW_DAY: - g_value_set_boolean(value, self->priv->show_day); - break; - case PROP_SHOW_DATE: - g_value_set_boolean(value, self->priv->show_date); - break; - 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; - case PROP_SHOW_CALENDAR: - g_value_set_boolean(value, self->priv->show_calendar); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - return; - } - - return; -} - -/* Looks at the size of the label, if it grew beyond what we - thought was the max, make sure it doesn't shrink again. */ -static gboolean -idle_measure (gpointer data) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(data); - self->priv->idle_measure = 0; - - GtkAllocation allocation; - gtk_widget_get_allocation(GTK_WIDGET(self->priv->label), &allocation); - - if (allocation.width > self->priv->max_width) { - if (self->priv->max_width != 0) { - g_warning("Guessed wrong. We thought the max would be %d but we're now at %d", self->priv->max_width, allocation.width); - } - self->priv->max_width = allocation.width; - gtk_widget_set_size_request(GTK_WIDGET(self->priv->label), self->priv->max_width, -1); - } - - return FALSE; -} - -/* Updates the accessible description */ -static void -update_accessible_description (IndicatorDatetime * io) -{ - GList * entries = indicator_object_get_entries(INDICATOR_OBJECT(io)); - IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data; - - entry->accessible_desc = get_accessible_desc(INDICATOR_OBJECT(io)); - - g_signal_emit(G_OBJECT(io), - INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID, - 0, - entry, - TRUE); - - g_list_free(entries); - - return; -} - -/* Updates the label to be the current time. */ -static void -set_label_to_time_in_zone (IndicatorDatetime * self, GtkLabel * label, - GTimeZone * tz, const gchar * format, - GDateTime ** datetime) -{ - gboolean unref_tz = FALSE; - if (tz == NULL) { - gchar * zone = read_timezone (); - if (zone == NULL) - return; - tz = g_time_zone_new(zone); - unref_tz = TRUE; - g_free (zone); - } - - GDateTime * datetime_now; - datetime_now = g_date_time_new_now(tz); - - gchar * timestr; - if (format == NULL) { - 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); - } - else { - timestr = g_date_time_format(datetime_now, format); - if (timestr == NULL) { - g_warning ("The custom date format is not valid, check the\n" - "g_date_time_format() documentation for the supported\n" - "format specifiers "); - timestr = g_strdup ("Date format not supported"); - } - } - - gboolean use_markup = FALSE; - if (pango_parse_markup(timestr, -1, 0, NULL, NULL, NULL, NULL)) - use_markup = TRUE; - - if (use_markup) - gtk_label_set_markup(label, timestr); - else - gtk_label_set_text(label, timestr); - - g_free(timestr); - - if (datetime) - *datetime = datetime_now; - else - g_date_time_unref(datetime_now); - - if (unref_tz) - g_time_zone_unref(tz); - - return; -} - -/* Updates the label to be the current time. */ -static void -update_label (IndicatorDatetime * io, GDateTime ** datetime) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(io); - - if (self->priv->label == NULL) return; - - set_label_to_time_in_zone(self, self->priv->label, NULL, self->priv->time_string, datetime); - - if (self->priv->idle_measure == 0) { - self->priv->idle_measure = g_idle_add(idle_measure, io); - } - - update_accessible_description(io); - - return; -} - -/* Update the time right now. Usually the result of a timezone switch. */ -static void -update_time (IndicatorDatetime * self) -{ - GDateTime * dt = NULL; - update_label(self, &dt); - timezone_update_all_labels(self); - if (dt != NULL) { - setup_timer(self, dt); - g_date_time_unref(dt); - } - return; -} - -/* Receives all signals from the service, routed to the appropriate functions */ -static void -receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, - GVariant * parameters, gpointer user_data) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(user_data); - - if (g_strcmp0(signal_name, "UpdateTime") == 0) { - update_time(self); - } - - return; -} - -/* Runs every minute and updates the time */ -gboolean -timer_func (gpointer user_data) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(user_data); - self->priv->timer = 0; - GDateTime * dt = NULL; - update_label(self, &dt); - timezone_update_all_labels(self); - if (dt != NULL) { - setup_timer(self, dt); - g_date_time_unref(dt); - } - return FALSE; -} - -/* Configure the timer to run the next time through */ -static void -setup_timer (IndicatorDatetime * self, GDateTime * datetime) -{ - gboolean unref = FALSE; - - if (self->priv->timer != 0) { - g_source_remove(self->priv->timer); - self->priv->timer = 0; - } - - if (self->priv->show_seconds || - (self->priv->time_mode == SETTINGS_TIME_CUSTOM && self->priv->custom_show_seconds)) { - self->priv->timer = g_timeout_add_full(G_PRIORITY_HIGH, 999, timer_func, self, NULL); - } else { - if (datetime == NULL) { - datetime = g_date_time_new_now_local(); - unref = TRUE; - } - - /* Plus 2 so we're just after the minute, don't want to be early. */ - gint seconds = (gint)g_date_time_get_seconds(datetime); - self->priv->timer = g_timeout_add_seconds(60 - seconds + 2, timer_func, self); - - if (unref) { - g_date_time_unref(datetime); - } - } - - return; -} - -/* Does a quick meausre of how big the string is in - pixels with a Pango layout */ -static gint -measure_string (GtkStyle * style, PangoContext * context, const gchar * string) -{ - PangoLayout * layout = pango_layout_new(context); - - if (pango_parse_markup(string, -1, 0, NULL, NULL, NULL, NULL)) - pango_layout_set_markup(layout, string, -1); - else - pango_layout_set_text(layout, string, -1); - - pango_layout_set_font_description(layout, style->font_desc); - - gint width; - pango_layout_get_pixel_size(layout, &width, NULL); - g_object_unref(layout); - return width; -} - -/* Format for the table of strftime() modifiers to what - we need to check when determining the length */ -typedef struct _strftime_type_t strftime_type_t; -struct _strftime_type_t { - char character; - gint mask; -}; - -/* A table taken from the man page of strftime to what the different - characters can effect. These are worst case in that we need to - test the length based on all these things to ensure that we have - a reasonable string lenght measurement. */ -const static strftime_type_t strftime_type[] = { - {'a', STRFTIME_MASK_WEEK}, - {'A', STRFTIME_MASK_WEEK}, - {'b', STRFTIME_MASK_MONTH}, - {'B', STRFTIME_MASK_MONTH}, - {'c', STRFTIME_MASK_ALL}, /* We don't know, so we have to assume all */ - {'C', STRFTIME_MASK_YEAR}, - {'d', STRFTIME_MASK_MONTH}, - {'D', STRFTIME_MASK_MONTH | STRFTIME_MASK_YEAR | STRFTIME_MASK_DAY}, - {'e', STRFTIME_MASK_DAY}, - {'F', STRFTIME_MASK_MONTH | STRFTIME_MASK_YEAR | STRFTIME_MASK_DAY}, - {'G', STRFTIME_MASK_YEAR}, - {'g', STRFTIME_MASK_YEAR}, - {'h', STRFTIME_MASK_MONTH}, - {'j', STRFTIME_MASK_DAY}, - {'m', STRFTIME_MASK_MONTH}, - {'p', STRFTIME_MASK_AMPM}, - {'P', STRFTIME_MASK_AMPM}, - {'r', STRFTIME_MASK_AMPM}, - {'s', STRFTIME_MASK_SECONDS}, - {'S', STRFTIME_MASK_SECONDS}, - {'T', STRFTIME_MASK_SECONDS}, - {'u', STRFTIME_MASK_WEEK}, - {'U', STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH}, - {'V', STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH}, - {'w', STRFTIME_MASK_DAY}, - {'W', STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH}, - {'x', STRFTIME_MASK_YEAR | STRFTIME_MASK_MONTH | STRFTIME_MASK_DAY | STRFTIME_MASK_WEEK}, - {'X', STRFTIME_MASK_SECONDS}, - {'y', STRFTIME_MASK_YEAR}, - {'Y', STRFTIME_MASK_YEAR}, - /* Last one */ - {0, 0} -}; - -#define FAT_NUMBER 8 - -/* Looks through the characters in the format string to - ensure that we can figure out which of the things we - need to check in determining the length. */ -static gint -generate_strftime_bitmask (const char *time_str) -{ - gint retval = 0; - glong strlength = g_utf8_strlen(time_str, -1); - gint i; - g_debug("Evaluating bitmask for '%s'", time_str); - - for (i = 0; i < strlength; i++) { - if (time_str[i] == '%' && i + 1 < strlength) { - gchar evalchar = time_str[i + 1]; - - /* If we're using alternate formats we need to skip those characters */ - if (evalchar == 'E' || evalchar == 'O') { - if (i + 2 < strlength) { - evalchar = time_str[i + 2]; - } else { - continue; - } - } - - /* Let's look at that character in the table */ - int j; - for (j = 0; strftime_type[j].character != 0; j++) { - if (strftime_type[j].character == evalchar) { - retval |= strftime_type[j].mask; - break; - } - } - } - } - - return retval; -} - -/* Build an array up of all the time values that we want to check - for length to ensure we're in a good place */ -static void -build_timeval_array (GArray * timevals, gint mask) -{ - struct tm mytm = {0}; - - /* Sun 12/28/8888 00:00 */ - mytm.tm_hour = 0; - mytm.tm_mday = 28; - mytm.tm_mon = 11; - mytm.tm_year = 8888 - 1900; - mytm.tm_wday = 0; - mytm.tm_yday = 363; - g_array_append_val(timevals, mytm); - - if (mask & STRFTIME_MASK_AMPM) { - /* Sun 12/28/8888 12:00 */ - mytm.tm_hour = 12; - g_array_append_val(timevals, mytm); - } - - /* NOTE: Ignoring year 8888 should handle it */ - - if (mask & STRFTIME_MASK_MONTH) { - gint oldlen = timevals->len; - gint i, j; - for (i = 0; i < oldlen; i++) { - for (j = 0; j < 11; j++) { - struct tm localval = g_array_index(timevals, struct tm, i); - localval.tm_mon = j; - /* Not sure if I need to adjust yday & wday, hope not */ - g_array_append_val(timevals, localval); - } - } - } - - /* Doing these together as it seems like just slightly more - coverage on the numerical days, but worth it. */ - if (mask & (STRFTIME_MASK_WEEK | STRFTIME_MASK_DAY)) { - gint oldlen = timevals->len; - gint i, j; - for (i = 0; i < oldlen; i++) { - for (j = 22; j < 28; j++) { - struct tm localval = g_array_index(timevals, struct tm, i); - - gint diff = 28 - j; - - localval.tm_mday = j; - localval.tm_wday = localval.tm_wday - diff; - if (localval.tm_wday < 0) { - localval.tm_wday += 7; - } - localval.tm_yday = localval.tm_yday - diff; - - g_array_append_val(timevals, localval); - } - } - } - - return; -} - -/* Try to get a good guess at what a maximum width of the entire - string would be. */ -static void -guess_label_size (IndicatorDatetime * self) -{ - /* This is during startup. */ - if (self->priv->label == NULL) return; - - GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(self->priv->label)); - PangoContext * context = gtk_widget_get_pango_context(GTK_WIDGET(self->priv->label)); - gint * max_width = &(self->priv->max_width); - gint posibilitymask = generate_strftime_bitmask(self->priv->time_string); - - /* Reset max width */ - *max_width = 0; - - /* Build the array of possibilities that we want to test */ - GArray * timevals = g_array_new(FALSE, TRUE, sizeof(struct tm)); - build_timeval_array(timevals, posibilitymask); - - g_debug("Checking against %d possible times", timevals->len); - gint check_time; - for (check_time = 0; check_time < timevals->len; check_time++) { - struct tm * timeval = &g_array_index(timevals, struct tm, check_time); - GDateTime * dt = g_date_time_new_local(timeval->tm_year, timeval->tm_mon, timeval->tm_mday, timeval->tm_hour, timeval->tm_min, timeval->tm_sec); - gchar * timestr = g_date_time_format(dt, self->priv->time_string); - - gint length = measure_string(style, context, timestr); - - g_free(timestr); - g_date_time_unref(dt); - - if (length > *max_width) { - *max_width = length; - } - } - - g_array_free(timevals, TRUE); - - gtk_widget_set_size_request(GTK_WIDGET(self->priv->label), self->priv->max_width, -1); - g_debug("Guessing max time width: %d", self->priv->max_width); - - return; -} - -/* React to the style changing, which could mean an font - update. */ -static void -style_changed (GtkWidget * widget, GtkStyle * oldstyle, gpointer data) -{ - g_debug("New style for time label"); - IndicatorDatetime * self = INDICATOR_DATETIME(data); - guess_label_size(self); - update_label(self, NULL); - timezone_update_all_labels(self); - return; -} - -/* Respond to changes in the screen to update the text gravity */ -static void -update_text_gravity (GtkWidget *widget, GdkScreen *previous_screen, gpointer data) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(data); - if (self->priv->label == NULL) return; - - PangoLayout *layout; - PangoContext *context; - - layout = gtk_label_get_layout (GTK_LABEL(self->priv->label)); - context = pango_layout_get_context(layout); - pango_context_set_base_gravity(context, PANGO_GRAVITY_AUTO); -} - -static gchar * -generate_format_string_now (IndicatorDatetime * self) -{ - if (self->priv->time_mode == SETTINGS_TIME_CUSTOM) { - return g_strdup(self->priv->custom_string); - } - else { - return generate_format_string_full(self->priv->show_day, - self->priv->show_date); - } -} - -static void -timezone_update_labels (indicator_item_t * mi_data) -{ - 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); - - 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); - set_label_to_time_in_zone(mi_data->self, GTK_LABEL(mi_data->right), tz, NULL, NULL); - g_time_zone_unref(tz); -} - -/* Whenever we have a property change on a DbusmenuMenuitem - we need to be responsive to that. */ -static void -indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant *value, indicator_item_t * mi_data) -{ - if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_LABEL)) { - /* Set the main label */ - gtk_label_set_text(GTK_LABEL(mi_data->label), g_variant_get_string(value, NULL)); - } else if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_RIGHT)) { - /* Set the right label */ - gtk_label_set_text(GTK_LABEL(mi_data->right), g_variant_get_string(value, NULL)); - } else if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_ICON)) { - /* We don't use the value here, which is probably less efficient, - but it's easier to use the easy function. And since th value - is already cached, shouldn't be a big deal really. */ - GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(mi, APPOINTMENT_MENUITEM_PROP_ICON); - if (pixbuf != NULL) { - /* If we've got a pixbuf we need to make sure it's of a reasonable - size to fit in the menu. If not, rescale it. */ - GdkPixbuf * resized_pixbuf; - gint width, height; - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - if (gdk_pixbuf_get_width(pixbuf) > width || - gdk_pixbuf_get_height(pixbuf) > height) { - g_debug("Resizing icon from %dx%d to %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), width, height); - resized_pixbuf = gdk_pixbuf_scale_simple(pixbuf, - width, - height, - GDK_INTERP_BILINEAR); - } else { - g_debug("Happy with icon sized %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); - resized_pixbuf = pixbuf; - } - gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), resized_pixbuf); - /* The other pixbuf should be free'd by the dbusmenu. */ - if (resized_pixbuf != pixbuf) { - g_object_unref(resized_pixbuf); - } - } - } 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)); - } - return; -} -// Properties for marking and unmarking the calendar -static void -calendar_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant *value, IdoCalendarMenuItem * mi_data) -{ - g_debug("Changing calendar property: %s", prop); - if (!g_strcmp0(prop, CALENDAR_MENUITEM_PROP_MARKS)) { - ido_calendar_menu_item_clear_marks (IDO_CALENDAR_MENU_ITEM (mi_data)); - - if (value != NULL) { - GVariantIter *iter; - gint day; - - g_debug("\tMarks: %s", g_variant_print(value, FALSE)); - - g_variant_get (value, "ai", &iter); - while (g_variant_iter_loop (iter, "i", &day)) { - ido_calendar_menu_item_mark_day (IDO_CALENDAR_MENU_ITEM (mi_data), day); - } - g_variant_iter_free (iter); - } else { - g_debug("\tMarks: <cleared>"); - } - } - return; -} - -/* We have a small little menuitem type that handles all - of the fun stuff for indicators. Mostly this is the - shifting over and putting the icon in with some right - side text that'll be determined by the service. - Copied verbatim from an old revision (including comments) of indicator-messages -*/ -static gboolean -new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data) -{ - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); - g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - g_return_val_if_fail(IS_INDICATOR_DATETIME(user_data), FALSE); - /* Note: not checking parent, it's reasonable for it to be NULL */ - IndicatorDatetime * self = INDICATOR_DATETIME(user_data); - - indicator_item_t * mi_data = g_new0(indicator_item_t, 1); - - mi_data->gmi = gtk_menu_item_new(); - - GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - - /* Icon, probably someone's face or avatar on an IM */ - mi_data->icon = gtk_image_new(); - GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(newitem, APPOINTMENT_MENUITEM_PROP_ICON); - - if (pixbuf != NULL) { - /* If we've got a pixbuf we need to make sure it's of a reasonable - size to fit in the menu. If not, rescale it. */ - GdkPixbuf * resized_pixbuf; - gint width, height; - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - if (gdk_pixbuf_get_width(pixbuf) > width || - gdk_pixbuf_get_height(pixbuf) > height) { - g_debug("Resizing icon from %dx%d to %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), width, height); - resized_pixbuf = gdk_pixbuf_scale_simple(pixbuf, - width, - height, - GDK_INTERP_BILINEAR); - } else { - g_debug("Happy with icon sized %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); - resized_pixbuf = pixbuf; - } - - gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), resized_pixbuf); - - /* The other pixbuf should be free'd by the dbusmenu. */ - if (resized_pixbuf != pixbuf) { - g_object_unref(resized_pixbuf); - } - } - gtk_misc_set_alignment(GTK_MISC(mi_data->icon), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->icon, FALSE, FALSE, 0); - gtk_widget_show(mi_data->icon); - - /* Label, probably a username, chat room or mailbox name */ - mi_data->label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, APPOINTMENT_MENUITEM_PROP_LABEL)); - gtk_misc_set_alignment(GTK_MISC(mi_data->label), 0.0, 0.5); - - GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(mi_data->label)); - PangoContext * context = gtk_widget_get_pango_context(GTK_WIDGET(mi_data->label)); - gint length = measure_string(style, context, "MMMMMMMMMMMMMMM"); // 15 char wide string max - gtk_widget_set_size_request(GTK_WIDGET(mi_data->label), length, -1); // Set the min size in pixels - - gtk_label_set_ellipsize(GTK_LABEL(mi_data->label), PANGO_ELLIPSIZE_END); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, 0); - gtk_widget_show(mi_data->label); - - /* Usually either the time or the count on the individual - item. */ - mi_data->right = gtk_label_new(dbusmenu_menuitem_property_get(newitem, APPOINTMENT_MENUITEM_PROP_RIGHT)); - gtk_size_group_add_widget(self->priv->indicator_right_group, mi_data->right); - gtk_misc_set_alignment(GTK_MISC(mi_data->right), 1.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->right, FALSE, FALSE, 0); - gtk_widget_show(mi_data->right); - - gtk_container_add(GTK_CONTAINER(mi_data->gmi), hbox); - gtk_widget_show(hbox); - - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(mi_data->gmi), parent); - - g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(indicator_prop_change_cb), mi_data); - return TRUE; -} - -static void -month_changed_cb (IdoCalendarMenuItem *ido, - gpointer user_data) -{ - guint d,m,y; - DbusmenuMenuitem * item = DBUSMENU_MENUITEM (user_data); - ido_calendar_menu_item_get_date(ido, &y, &m, &d); - struct tm date = {0}; - date.tm_mday = d; - date.tm_mon = m; - date.tm_year = y - 1900; - guint selecteddate = (guint)mktime(&date); - g_debug("Got month changed signal: %s", asctime(&date)); - GVariant *variant = g_variant_new_uint32(selecteddate); - guint timestamp = (guint)time(NULL); - dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(item), "month-changed", variant, timestamp); -} - -static void -day_selected_cb (IdoCalendarMenuItem *ido, - gpointer user_data) -{ - guint d,m,y; - DbusmenuMenuitem * item = DBUSMENU_MENUITEM (user_data); - ido_calendar_menu_item_get_date(ido, &y, &m, &d); - struct tm date = {0}; - date.tm_mday = d; - date.tm_mon = m; - date.tm_year = y - 1900; - guint selecteddate = (guint)mktime(&date); - g_debug("Got day selected signal: %s", asctime(&date)); - GVariant *variant = g_variant_new_uint32(selecteddate); - guint timestamp = (guint)time(NULL); - dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(item), "day-selected", variant, timestamp); -} - -static void -day_selected_double_click_cb (IdoCalendarMenuItem *ido, - gpointer user_data) -{ - guint d,m,y; - DbusmenuMenuitem * item = DBUSMENU_MENUITEM (user_data); - ido_calendar_menu_item_get_date(ido, &y, &m, &d); - struct tm date = {0}; - date.tm_mday = d; - date.tm_mon = m; - date.tm_year = y - 1900; - guint selecteddate = (guint)mktime(&date); - g_debug("Got day selected double click signal: %s", asctime(&date)); - GVariant *variant = g_variant_new_uint32(selecteddate); - guint timestamp = (guint)time(NULL); - dbusmenu_menuitem_handle_event(DBUSMENU_MENUITEM(item), "day-selected-double-click", variant, timestamp); -} - -static gboolean -new_calendar_item (DbusmenuMenuitem * newitem, - DbusmenuMenuitem * parent, - DbusmenuClient * client, - gpointer user_data) -{ - g_debug("New calendar item"); - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); - g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - g_return_val_if_fail(IS_INDICATOR_DATETIME(user_data), FALSE); - /* Note: not checking parent, it's reasonable for it to be NULL */ - - IndicatorDatetime *self = INDICATOR_DATETIME(user_data); - - IdoCalendarMenuItem *ido = IDO_CALENDAR_MENU_ITEM (ido_calendar_menu_item_new ()); - self->priv->ido_calendar = ido; - - GtkCalendarDisplayOptions flags = ido_calendar_menu_item_get_display_options (self->priv->ido_calendar); - if (self->priv->show_week_numbers == 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); - - gtk_widget_set_visible (GTK_WIDGET (self->priv->ido_calendar), self->priv->show_calendar); - - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(ido), parent); - - g_signal_connect_after(ido, "month-changed", G_CALLBACK(month_changed_cb), (gpointer)newitem); - g_signal_connect_after(ido, "day-selected", G_CALLBACK(day_selected_cb), (gpointer)newitem); - g_signal_connect_after(ido, "day-selected-double-click", G_CALLBACK(day_selected_double_click_cb), (gpointer)newitem); - - g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(calendar_prop_change_cb), ido); - - /* Run the current values through prop changed */ - GVariant * propval = NULL; - - propval = dbusmenu_menuitem_property_get_variant(newitem, CALENDAR_MENUITEM_PROP_MARKS); - if (propval != NULL) { - calendar_prop_change_cb(newitem, CALENDAR_MENUITEM_PROP_MARKS, propval, ido); - } - - return TRUE; -} - -static void -timezone_toggled_cb (GtkCheckMenuItem *checkmenuitem, DbusmenuMenuitem * dbusitem) -{ - /* Make sure that the displayed radio-active setting is always - consistent with the dbus menuitem */ - gtk_check_menu_item_set_active(checkmenuitem, - dbusmenu_menuitem_property_get_bool(dbusitem, TIMEZONE_MENUITEM_PROP_RADIO)); -} - -static void -timezone_destroyed_cb (indicator_item_t * mi_data, DbusmenuMenuitem * dbusitem) -{ - IndicatorDatetime *self = INDICATOR_DATETIME (mi_data->self); - IndicatorDatetimePrivate *priv = self->priv; - - priv->timezone_items = g_list_remove(priv->timezone_items, mi_data); - g_signal_handlers_disconnect_by_func(G_OBJECT(mi_data->gmi), G_CALLBACK(timezone_toggled_cb), dbusitem); - g_free(mi_data); -} - -static gboolean -new_timezone_item(DbusmenuMenuitem * newitem, - DbusmenuMenuitem * parent, - DbusmenuClient * client, - gpointer user_data) -{ - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); - g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - g_return_val_if_fail(IS_INDICATOR_DATETIME(user_data), FALSE); - /* Note: not checking parent, it's reasonable for it to be NULL */ - - IndicatorDatetime * self = INDICATOR_DATETIME(user_data); - IndicatorDatetimePrivate *priv = self->priv; - - // Menu item with a radio button and a right aligned time - indicator_item_t * mi_data = g_new0(indicator_item_t, 1); - - priv->timezone_items = g_list_prepend(priv->timezone_items, mi_data); - - mi_data->self = self; - mi_data->mi = newitem; - mi_data->gmi = gtk_check_menu_item_new(); - - gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(mi_data->gmi), TRUE); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi_data->gmi), - dbusmenu_menuitem_property_get_bool(newitem, TIMEZONE_MENUITEM_PROP_RADIO)); - - GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - - /* Label, probably a username, chat room or mailbox name */ - mi_data->label = gtk_label_new(""); - gtk_misc_set_alignment(GTK_MISC(mi_data->label), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, 0); - gtk_widget_show(mi_data->label); - - /* Usually either the time or the count on the individual - item. */ - mi_data->right = gtk_label_new(""); - gtk_size_group_add_widget(self->priv->indicator_right_group, mi_data->right); - gtk_misc_set_alignment(GTK_MISC(mi_data->right), 1.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->right, FALSE, FALSE, 0); - gtk_widget_show(mi_data->right); - - timezone_update_labels(mi_data); - - gtk_container_add(GTK_CONTAINER(mi_data->gmi), hbox); - gtk_widget_show(hbox); - - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(mi_data->gmi), parent); - - 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_object_weak_ref(G_OBJECT(newitem), (GWeakNotify)timezone_destroyed_cb, mi_data); - - return TRUE; -} - -/* Grabs the label. Creates it if it doesn't - exist already */ -static GtkLabel * -get_label (IndicatorObject * io) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(io); - - /* If there's not a label, we'll build ourselves one */ - if (self->priv->label == NULL) { - self->priv->label = GTK_LABEL(gtk_label_new("Time")); - gtk_label_set_justify (GTK_LABEL(self->priv->label), GTK_JUSTIFY_CENTER); - g_object_ref(G_OBJECT(self->priv->label)); - g_signal_connect(G_OBJECT(self->priv->label), "style-set", G_CALLBACK(style_changed), self); - g_signal_connect(G_OBJECT(self->priv->label), "screen-changed", G_CALLBACK(update_text_gravity), self); - guess_label_size(self); - update_label(self, NULL); - gtk_widget_set_visible(GTK_WIDGET (self->priv->label), self->priv->show_clock); - } - - if (self->priv->timer == 0) { - setup_timer(self, NULL); - } - - return self->priv->label; -} - -static GtkMenu * -get_menu (IndicatorObject * io) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(io); - - return GTK_MENU(self->priv->menu); -} - -static const gchar * -get_accessible_desc (IndicatorObject * io) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(io); - const gchar * name; - - if (self->priv->label != NULL) { - name = gtk_label_get_text(self->priv->label); - return name; - } - return NULL; -} - -static const gchar * -get_name_hint (IndicatorObject * io) -{ - return PACKAGE_NAME; -} |