aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac6
-rw-r--r--src/datetime-service.c58
-rw-r--r--src/dbus-shared.h9
-rw-r--r--src/indicator-datetime.c147
4 files changed, 217 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 9118db8..cc96999 100644
--- a/configure.ac
+++ b/configure.ac
@@ -59,6 +59,8 @@ GIO_REQUIRED_VERSION=2.25.11
INDICATOR_DISPLAY_OBJECTS=0.1.10
GEOCLUE_REQUIRED_VERSION=0.12.0
OOBS_REQUIRED_VERSION=2.31.0
+ECAL_REQUIRED_VERSION=2.30
+ICAL_REQUIRED_VERSION=0.44
AS_IF([test "x$with_gtk" = x3],
[PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION
@@ -80,7 +82,9 @@ PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION
libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS
gio-2.0 >= $GIO_REQUIRED_VERSION
geoclue >= $GEOCLUE_REQUIRED_VERSION
- liboobs-1 >= $OOBS_REQUIRED_VERSION)
+ liboobs-1 >= $OOBS_REQUIRED_VERSION
+ libecal-1.2 >= $ECAL_REQUIRED_VERSION
+ libical >= $ICAL_REQUIRED_VERSION)
AC_SUBST(INDICATOR_CFLAGS)
AC_SUBST(INDICATOR_LIBS)
diff --git a/src/datetime-service.c b/src/datetime-service.c
index 8a31940..3fe6ebb 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -23,6 +23,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libindicator/indicator-service.h>
#include <locale.h>
+#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
@@ -33,6 +34,15 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <geoclue/geoclue-master.h>
#include <geoclue/geoclue-master-client.h>
+#include <time.h>
+#include <libecal/e-cal.h>
+#include <libical/ical.h>
+#include <libecal/e-cal-time-util.h>
+#include <libedataserver/e-source.h>
+// Other users of ecal seem to also include these, not sure why they should be included by the above
+#include <libical/icaltime.h>
+
+
#include <oobs/oobs-timeconfig.h>
#include "datetime-interface.h"
@@ -225,6 +235,32 @@ check_for_calendar (gpointer user_data)
return FALSE;
}
+static gboolean
+update_timezone_menu_items(gpointer user_data) {
+ // Get the location preferences and the current location, highlight the current location somehow
+ return FALSE;
+}
+
+/* Populate the menu with todays, next 5 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 gboolean
+update_appointment_menu_items (gpointer user_data) {
+ DbusmenuMenuitem * item = NULL;
+
+ gint i;
+ for (i = 0; i < 5; i++) {
+ item = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, APPOINTMENT_MENUITEM_TYPE);
+ dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_LABEL, "fake summary");
+ dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, "9:00pm");
+ dbusmenu_menuitem_child_append (root, item);
+ }
+ return TRUE;
+}
+
/* Looks for the time and date admin application and enables the
item we have one */
static gboolean
@@ -272,8 +308,28 @@ build_menus (DbusmenuMenuitem * root)
g_idle_add(check_for_calendar, NULL);
}
+ DbusmenuMenuitem * separator;
+
+ separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator);
- DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
+ // This just populates the items on startup later we want to be able to update the appointments before
+ // presenting the menu.
+ update_appointment_menu_items(NULL);
+ if (calendar != NULL) {
+ // TODO Create "Add appointment" menu item
+ }
+ // TODO Create FFR? "Add timer" menu item
+
+ separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator);
+
+ update_timezone_menu_items(NULL);
+ // TODO Create "Add location" menu item
+
+ separator = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
dbusmenu_menuitem_child_append(root, separator);
diff --git a/src/dbus-shared.h b/src/dbus-shared.h
index e6dc241..d13cb32 100644
--- a/src/dbus-shared.h
+++ b/src/dbus-shared.h
@@ -29,3 +29,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define DBUSMENU_CALENDAR_MENUITEM_TYPE "x-canonical-calendar-item"
+#define APPOINTMENT_MENUITEM_TYPE "appointment-item"
+#define APPOINTMENT_MENUITEM_PROP_LABEL "appointment-label"
+#define APPOINTMENT_MENUITEM_PROP_ICON "appointment-icon"
+#define APPOINTMENT_MENUITEM_PROP_RIGHT "appointment-time"
+
+#define TIMEZONE_MENUITEM_TYPE "timezone-item"
+#define TIMEZONE_MENUITEM_PROP_LABEL "timezone-label"
+#define TIMEZONE_MENUITEM_PROP_RADIO "timezone-radio"
+#define TIMEZONE_MENUITEM_PROP_RIGHT "timezone-time"
diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c
index c386300..e7a448e 100644
--- a/src/indicator-datetime.c
+++ b/src/indicator-datetime.c
@@ -41,6 +41,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
/* DBusMenu */
#include <libdbusmenu-gtk/menu.h>
#include <libido/idocalendarmenuitem.h>
+#include <libdbusmenu-gtk/menuitem.h>
#include "dbus-shared.h"
@@ -102,6 +103,13 @@ enum {
PROP_CUSTOM_TIME_FORMAT
};
+typedef struct _indicator_item_t indicator_item_t;
+struct _indicator_item_t {
+ GtkWidget * icon;
+ GtkWidget * label;
+ GtkWidget * right;
+};
+
#define PROP_TIME_FORMAT_S "time-format"
#define PROP_SHOW_SECONDS_S "show-seconds"
#define PROP_SHOW_DAY_S "show-day"
@@ -174,6 +182,8 @@ INDICATOR_SET_TYPE(INDICATOR_DATETIME_TYPE)
G_DEFINE_TYPE (IndicatorDatetime, indicator_datetime, INDICATOR_OBJECT_TYPE);
+static GtkSizeGroup * indicator_right_group = NULL;
+
static void
indicator_datetime_class_init (IndicatorDatetimeClass *klass)
{
@@ -330,7 +340,7 @@ service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
}
if (error != NULL) {
- g_error("Could not grab DBus proxy for %s: %s", SERVICE_NAME, error->message);
+ g_warning("Could not grab DBus proxy for %s: %s", SERVICE_NAME, error->message);
g_error_free(error);
return;
}
@@ -1055,6 +1065,128 @@ generate_format_string (IndicatorDatetime * self)
return g_strdup_printf(T_("%s, %s"), date_string, time_string);
}
+/* 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, gchar * 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), value);
+ } else if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_RIGHT)) {
+ /* Set the right label */
+ gtk_label_set_text(GTK_LABEL(mi_data->right), value);
+ } 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 {
+ g_warning("Indicator Item property '%s' unknown", prop);
+ }
+ 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);
+ /* Note: not checking parent, it's reasonable for it to be NULL */
+
+ indicator_item_t * mi_data = g_new0(indicator_item_t, 1);
+
+ GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
+
+ GtkWidget * hbox = gtk_hbox_new(FALSE, 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);
+ 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(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(gmi), hbox);
+ gtk_widget_show(hbox);
+
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+
+ g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(indicator_prop_change_cb), mi_data);
+ g_signal_connect_swapped(G_OBJECT(newitem), "destroyed", G_CALLBACK(g_free), mi_data);
+
+ return TRUE;
+}
+
static gboolean
new_calendar_item (DbusmenuMenuitem * newitem,
DbusmenuMenuitem * parent,
@@ -1082,6 +1214,17 @@ new_calendar_item (DbusmenuMenuitem * newitem,
return TRUE;
}
+static gboolean
+new_timezone_item(DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data)
+{
+ // Menu item with a radio button and a right aligned time
+
+ return TRUE;
+}
+
/* Grabs the label. Creates it if it doesn't
exist already */
static GtkLabel *
@@ -1121,6 +1264,8 @@ get_menu (IndicatorObject * io)
g_object_set_data (G_OBJECT (client), "indicator", io);
dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_CALENDAR_MENUITEM_TYPE, new_calendar_item);
+ dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), APPOINTMENT_MENUITEM_TYPE, new_appointment_item);
+ dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), TIMEZONE_MENUITEM_TYPE, new_timezone_item);
return GTK_MENU(self->priv->menu);
}