aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac42
-rw-r--r--src/datetime-service.c166
-rw-r--r--src/indicator-datetime.c45
3 files changed, 167 insertions, 86 deletions
diff --git a/configure.ac b/configure.ac
index cc96999..4f35d38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,7 +60,10 @@ INDICATOR_DISPLAY_OBJECTS=0.1.10
GEOCLUE_REQUIRED_VERSION=0.12.0
OOBS_REQUIRED_VERSION=2.31.0
ECAL_REQUIRED_VERSION=2.30
+EDS_REQUIRED_VERSION=2.30
ICAL_REQUIRED_VERSION=0.44
+CAIRO_REQUIRED_VERSION=1.10
+GDK_REQUIRED_VERSION=2.22
AS_IF([test "x$with_gtk" = x3],
[PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION
@@ -77,15 +80,36 @@ AS_IF([test "x$with_gtk" = x3],
[AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
)
-PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION
- dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION
- libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS
- gio-2.0 >= $GIO_REQUIRED_VERSION
- geoclue >= $GEOCLUE_REQUIRED_VERSION
- liboobs-1 >= $OOBS_REQUIRED_VERSION
- libecal-1.2 >= $ECAL_REQUIRED_VERSION
- libical >= $ICAL_REQUIRED_VERSION)
-
+AS_IF([test "x$with_gtk" = x3],
+ [PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION
+ dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION
+ dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION
+ libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS
+ gio-2.0 >= $GIO_REQUIRED_VERSION
+ geoclue >= $GEOCLUE_REQUIRED_VERSION
+ liboobs-1 >= $OOBS_REQUIRED_VERSION
+ libecal-1.2 >= $ECAL_REQUIRED_VERSION
+ libical >= $ICAL_REQUIRED_VERSION
+ libedataserver-1.2 >= EDS_REQUIRED_VERSION
+ cairo >= CAIRO_REQUIRED_VERSION
+ gdk-2.0 >= GDK_REQUIRED_VERSION)
+ ],
+ [test "x$with_gtk" = x2],
+ [PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION
+ dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION
+ dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION
+ libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS
+ gio-2.0 >= $GIO_REQUIRED_VERSION
+ geoclue >= $GEOCLUE_REQUIRED_VERSION
+ liboobs-1 >= $OOBS_REQUIRED_VERSION
+ libecal-1.2 >= $ECAL_REQUIRED_VERSION
+ libical >= $ICAL_REQUIRED_VERSION
+ libedataserver-1.2 >= EDS_REQUIRED_VERSION
+ cairo >= CAIRO_REQUIRED_VERSION
+ gdk-2.0 >= GDK_REQUIRED_VERSION)
+ ],
+ [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
+)
AC_SUBST(INDICATOR_CFLAGS)
AC_SUBST(INDICATOR_LIBS)
diff --git a/src/datetime-service.c b/src/datetime-service.c
index c8194a4..3aa6acf 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -24,9 +24,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <locale.h>
#include <gtk/gtk.h>
+#include <gdk/gdk.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
+#include <math.h>
+#include <libdbusmenu-gtk/menuitem.h>
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/client.h>
#include <libdbusmenu-glib/menuitem.h>
@@ -41,6 +44,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#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 <cairo/cairo.h>
#include <oobs/oobs-timeconfig.h>
@@ -49,6 +53,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dbus-shared.h"
static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data);
+static gboolean update_appointment_menu_items (gpointer user_data);
static void setup_timer (void);
static IndicatorService * service = NULL;
@@ -63,6 +68,8 @@ static DbusmenuMenuitem * date = NULL;
static DbusmenuMenuitem * calendar = NULL;
static DbusmenuMenuitem * settings = NULL;
static DbusmenuMenuitem * tzchange = NULL;
+static DbusmenuMenuitem * add_appointment = NULL;
+static DbusmenuMenuitem * add_location = NULL;
static GList * appointments = NULL;
static ECal * ecal = NULL;
static const gchar * ecal_timezone = NULL;
@@ -230,10 +237,47 @@ check_for_calendar (gpointer user_data)
g_debug("Found the calendar application: %s", evo);
dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+
+ GError *gerror = NULL;
+ // TODO: In reality we should iterate sources of calendar, but getting the local one doens't lag for > a minute
+ g_debug("Setting up ecal.");
+ if (!ecal)
+ ecal = e_cal_new_system_calendar();
+
+ if (!ecal) {
+ g_debug("e_cal_new_system_calendar failed");
+ ecal = NULL;
+ }
+ g_debug("Open calendar.");
+ if (!e_cal_open(ecal, FALSE, &gerror) ) {
+ g_debug("e_cal_open: %s\n", gerror->message);
+ g_free(ecal);
+ ecal = NULL;
+ }
+ g_debug("Get calendar timezone.");
+ if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror)) {
+ g_debug("failed to get time zone\n");
+ g_free(ecal);
+ ecal = NULL;
+ }
+
+ /* This timezone represents the timezone of the calendar, this might be different to the current UTC offset.
+ * this means we'll have some geoclue interaction going on, and possibly the user will be involved in setting
+ * their location manually, case in point: trains have satellite links which often geoclue to sweden,
+ * this shouldn't automatically set the location and mess up all the appointments for the user.
+ */
+ if (ecal) ecal_timezone = icaltimezone_get_tzid(tzone);
+
+ update_appointment_menu_items(NULL);
+ g_signal_connect(root, DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(update_appointment_menu_items), NULL);
+
g_free(evo);
} else {
g_debug("Unable to find calendar app.");
dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
}
return FALSE;
@@ -241,7 +285,12 @@ check_for_calendar (gpointer user_data)
static gboolean
update_timezone_menu_items(gpointer user_data) {
- // Get the location preferences and the current location, highlight the current location somehow
+ // Get the current location as specified by the user as a place name and time and add it,
+ // Get the location from geoclue as a place and time and add it,
+ // Get the evolution calendar timezone as a place and time and add it,
+ // Get the current timezone that the clock uses and select that
+ // Iterate over configured places and add any which aren't already listed
+ // Hook up each of these to setting the time/current timezone
return FALSE;
}
@@ -293,6 +342,7 @@ update_appointment_menu_items (gpointer user_data) {
time_t t1, t2;
gchar *query, *is, *ie, *ad;
GList *objects = NULL, *l;
+ DbusmenuMenuitem * item = NULL;
GError *gerror = NULL;
gint i;
gint width, height;
@@ -315,18 +365,18 @@ update_appointment_menu_items (gpointer user_data) {
}
g_debug("Number of objects returned: %d", g_list_length(objects));
gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-
- /* Remove all of the previous appointments */
if (appointments != NULL) {
g_debug("Freeing old appointments");
- while (appointments != NULL) {
- DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointments->data);
- g_debug("Freeing old appointment: %p", litem);
+ for (l = appointments; l; l = l->next) {
+ g_debug("Freeing old appointment");
+ item = l->data;
// Remove all the existing menu items which are in appointments.
- appointments = g_list_remove(appointments, litem);
- dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem));
- g_object_unref(G_OBJECT(litem));
+ appointments = g_list_remove(appointments, item);
+ dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item));
+ //g_free(item); freeing makes it crash :/ is that a double free from child delete?
+ item = NULL;
}
+ appointments = NULL;
}
// Sort the list see above FIXME regarding queries
@@ -342,7 +392,6 @@ update_appointment_menu_items (gpointer user_data) {
char right[20];
//const gchar *uri;
struct tm tmp_tm;
- DbusmenuMenuitem * item;
ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp);
@@ -417,31 +466,31 @@ update_appointment_menu_items (gpointer user_data) {
g_debug("Command to Execute: %s", cmd);
- // Get the colour E_CAL_COMPONENT_FIELD_COLOR
- // Get the icon, either EVENT or MEMO or TODO?
- // needs EDS, ecal component colours are broken...
- //gdouble red, blue, green;
- //ECalSource *source = e_cal_get_source (ecalcomp->client);
- //if (!ecalcomp->color && e_source_get_color (source, &source_color)) {
- //g_free (comp_data->color);
- //ecalcomp->color = g_strdup_printf ("#%06x", source_color & 0xffffff);
- //}
- //g_debug("Colour to use: %s", ecalcomp->color);
-
- //cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
- //cairo_t *cr = cairo_create(cs);
-
- // TODO: Draw the correct icon for the appointment type and then tint it using mask fill.
+ ESource *source = e_cal_get_source (ecal);
+ //e_source_get_color (source, &source_color); api has been changed
+ const gchar *color_spec = e_source_peek_color_spec(source);
+ GdkColor color;
+ g_debug("Colour to use: %s", color_spec);
+
+ // Draw the correct icon for the appointment type and then tint it using mask fill.
// For now we'll create a circle
+ if (color_spec != NULL) {
+ gdk_color_parse (color_spec, &color);
+
+ cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ cairo_t *cr = cairo_create(cs);
+ cairo_arc (cr, width/2, height/2, width/2, 0, 2 * M_PI);
+ gdk_cairo_set_source_color(cr, &color);
+ cairo_fill(cr);
-
- //GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs, 0,0,0,0, width, height);
-
- //dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf);
-
+ GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs,
+ gdk_colormap_new(gdk_drawable_get_visual((GdkDrawable*)cs), TRUE), 0,0,0,0, width, height);
+ cairo_destroy(cr);
+
+ dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf);
+ }
dbusmenu_menuitem_child_add_position (root, item, 4+i);
appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove
- g_debug("Adding appointment: %p", item);
if (i == 4) break; // See above FIXME regarding query result limit
i++;
@@ -504,51 +553,12 @@ build_menus (DbusmenuMenuitem * root)
dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
dbusmenu_menuitem_child_append(root, separator);
- // This just populates the items on startup later we want to be able to update the appointments before
- // presenting the menu.
- if (calendar != NULL) {
- GError *gerror = NULL;
- // TODO: In reality we should iterate sources of calendar, but getting the local one doens't lag for > a minute
- g_debug("Setting up ecal.");
- if (!ecal)
- ecal = e_cal_new_system_calendar();
-
- if (!ecal) {
- g_debug("e_cal_new_system_calendar failed");
- ecal = NULL;
- }
- g_debug("Open calendar.");
- if (!e_cal_open(ecal, FALSE, &gerror) ) {
- g_debug("e_cal_open: %s\n", gerror->message);
- g_free(ecal);
- ecal = NULL;
- }
- g_debug("Get calendar timezone.");
- if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror)) {
- g_debug("failed to get time zone\n");
- g_free(ecal);
- ecal = NULL;
- }
-
- /* This timezone represents the timezone of the calendar, this might be different to the current UTC offset.
- * this means we'll have some geoclue interaction going on, and possibly the user will be involved in setting
- * their location manually, case in point: trains have satellite links which often geoclue to sweden,
- * this shouldn't automatically set the location and mess up all the appointments for the user.
- */
- if (ecal) ecal_timezone = icaltimezone_get_tzid(tzone);
-
- g_signal_connect(root, DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(update_appointment_menu_items), NULL);
- update_appointment_menu_items(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
+ add_appointment = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment"));
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ g_signal_connect(G_OBJECT(add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar");
+ dbusmenu_menuitem_child_add_position (root, add_appointment, 4);
separator = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
@@ -561,6 +571,10 @@ build_menus (DbusmenuMenuitem * root)
dbusmenu_menuitem_child_append(root, tzchange);
check_timezone_sync();
+ separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator);
+
settings = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set (settings, DBUSMENU_MENUITEM_PROP_LABEL, _("Time & Date Settings..."));
/* insensitive until we check for available apps */
diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c
index 7748a8c..1f61864 100644
--- a/src/indicator-datetime.c
+++ b/src/indicator-datetime.c
@@ -105,6 +105,7 @@ enum {
typedef struct _indicator_item_t indicator_item_t;
struct _indicator_item_t {
+ GtkWidget * radio;
GtkWidget * icon;
GtkWidget * label;
GtkWidget * right;
@@ -175,6 +176,7 @@ 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 GSList *location_group = NULL;
/* Indicator Module Config */
INDICATOR_SET_VERSION
@@ -1221,9 +1223,50 @@ new_timezone_item(DbusmenuMenuitem * newitem,
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 */
+
// Menu item with a radio button and a right aligned time
+ 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);
+
+ mi_data->radio = gtk_radio_button_new(location_group);
+ if (location_group == NULL)
+ location_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(mi_data->radio));
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mi_data->radio),
+ dbusmenu_menuitem_property_get_bool(newitem, TIMEZONE_MENUITEM_PROP_RADIO));
- return TRUE;
+ gtk_box_pack_start(GTK_BOX(hbox), mi_data->radio, FALSE, FALSE, 0);
+ gtk_widget_show(mi_data->radio);
+
+ /* 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;
}
/* Grabs the label. Creates it if it doesn't