diff --git a/src/gcal-event-widget.c b/src/gcal-event-widget.c index dff9b9f1..147aadc0 100644 --- a/src/gcal-event-widget.c +++ b/src/gcal-event-widget.c @@ -43,6 +43,14 @@ enum PROP_DTSTART }; +enum +{ + ACTIVATED, + NUM_SIGNALS +}; + +static guint signals[NUM_SIGNALS] = { 0, }; + static void gcal_event_widget_constructed (GObject *object); static void gcal_event_widget_set_property (GObject *object, @@ -77,6 +85,9 @@ static void gcal_event_widget_size_allocate (GtkWidget *widget, static gboolean gcal_event_widget_draw (GtkWidget *widget, cairo_t *cr); +static gboolean gcal_event_widget_button_press_event (GtkWidget *widget, + GdkEventButton *event); + G_DEFINE_TYPE(GcalEventWidget, gcal_event_widget, GTK_TYPE_WIDGET) static void @@ -99,6 +110,7 @@ gcal_event_widget_class_init(GcalEventWidgetClass *klass) widget_class->unmap = gcal_event_widget_unmap; widget_class->size_allocate = gcal_event_widget_size_allocate; widget_class->draw = gcal_event_widget_draw; + widget_class->button_press_event = gcal_event_widget_button_press_event; g_object_class_install_property (object_class, PROP_UUID, @@ -136,6 +148,16 @@ gcal_event_widget_class_init(GcalEventWidgetClass *klass) G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + signals[ACTIVATED] = g_signal_new ("activated", + GCAL_TYPE_EVENT_WIDGET, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GcalEventWidgetClass, + activated), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + g_type_class_add_private((gpointer)klass, sizeof(GcalEventWidgetPrivate)); } @@ -343,10 +365,10 @@ gcal_event_widget_map (GtkWidget *widget) GcalEventWidgetPrivate *priv; priv = GCAL_EVENT_WIDGET (widget)->priv; - GTK_WIDGET_CLASS (gcal_event_widget_parent_class)->map (widget); - - if (priv->event_window) + if (priv->event_window != NULL) gdk_window_show (priv->event_window); + + GTK_WIDGET_CLASS (gcal_event_widget_parent_class)->map (widget); } static void @@ -355,7 +377,7 @@ gcal_event_widget_unmap (GtkWidget *widget) GcalEventWidgetPrivate *priv; priv = GCAL_EVENT_WIDGET (widget)->priv; - if (priv->event_window) + if (priv->event_window != NULL) gdk_window_hide (priv->event_window); GTK_WIDGET_CLASS (gcal_event_widget_parent_class)->unmap (widget); @@ -461,6 +483,19 @@ gcal_event_widget_draw (GtkWidget *widget, return FALSE; } +static gboolean +gcal_event_widget_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + g_debug ("button pressed over event: %s", + GCAL_EVENT_WIDGET (widget)->priv->uuid); + + if (event->type == GDK_2BUTTON_PRESS) + g_signal_emit (widget, signals[ACTIVATED], 0); + + return TRUE; +} + GtkWidget* gcal_event_widget_new (gchar *uuid) { diff --git a/src/gcal-event-widget.h b/src/gcal-event-widget.h index 88aed66a..4e3f1bcf 100644 --- a/src/gcal-event-widget.h +++ b/src/gcal-event-widget.h @@ -38,6 +38,14 @@ typedef struct _GcalEventWidget GcalEventWidget; typedef struct _GcalEventWidgetClass GcalEventWidgetClass; typedef struct _GcalEventWidgetPrivate GcalEventWidgetPrivate; +struct _GcalEventWidgetClass +{ + GtkWidgetClass parent_class; + + /* signals */ + void (*activated) (GcalEventWidget *event_widget); +}; + struct _GcalEventWidget { GtkWidget parent; @@ -45,12 +53,6 @@ struct _GcalEventWidget GcalEventWidgetPrivate *priv; }; -struct _GcalEventWidgetClass -{ - GtkWidgetClass parent_class; -}; - - GType gcal_event_widget_get_type (void); GtkWidget* gcal_event_widget_new (gchar *uuid); diff --git a/src/gcal-month-view.c b/src/gcal-month-view.c index fd09c8d6..104fe6f7 100644 --- a/src/gcal-month-view.c +++ b/src/gcal-month-view.c @@ -327,10 +327,10 @@ gcal_month_view_map (GtkWidget *widget) GcalMonthViewPrivate *priv; priv = GCAL_MONTH_VIEW (widget)->priv; - GTK_WIDGET_CLASS (gcal_month_view_parent_class)->map (widget); - if (priv->event_window) gdk_window_show (priv->event_window); + + GTK_WIDGET_CLASS (gcal_month_view_parent_class)->map (widget); } static void diff --git a/src/gcal-utils.c b/src/gcal-utils.c index 93485f34..17391cd1 100644 --- a/src/gcal-utils.c +++ b/src/gcal-utils.c @@ -22,6 +22,7 @@ #include +#include #include G_DEFINE_BOXED_TYPE (icaltimetype, icaltime, gcal_dup_icaltime, g_free) @@ -105,3 +106,181 @@ gcal_dup_icaltime (icaltimetype *date) return new_date; } + +/* + * gcal_get_source_name: + * + * This method assume it receive only the model inside GcalManager + * */ +gchar* +gcal_get_source_name (GtkTreeModel *model, + const gchar *uid) +{ + GtkTreeIter iter; + gboolean valid; + gchar *name; + + name = NULL; + valid = gtk_tree_model_get_iter_first (model, &iter); + while (valid) + { + gchar *name_data; + gchar *uid_data; + + gtk_tree_model_get (model, &iter, + 0, &uid_data, + 1, &name_data, + -1); + + if (g_strcmp0 (uid_data, uid) == 0) + { + name = g_strdup (name_data); + + g_free (name_data); + g_free (uid_data); + break; + } + + g_free (name_data); + g_free (uid_data); + + valid = gtk_tree_model_iter_next (model, &iter); + } + return name; +} + +gchar* +gcal_get_source_uid (GtkTreeModel *model, + const gchar *name) +{ + GtkTreeIter iter; + gboolean valid; + gchar *uid; + + uid = NULL; + valid = gtk_tree_model_get_iter_first (model, &iter); + while (valid) + { + gchar *name_data; + gchar *uid_data; + + gtk_tree_model_get (model, &iter, + 0, &uid_data, + 1, &name_data, + -1); + + if (g_strcmp0 (name_data, name) == 0) + { + uid = g_strdup (uid_data); + + g_free (name_data); + g_free (uid_data); + break; + } + + g_free (name_data); + g_free (uid_data); + + valid = gtk_tree_model_iter_next (model, &iter); + } + return uid; +} + +/* Function to do a last minute fixup of the AM/PM stuff if the locale + * and gettext haven't done it right. Most English speaking countries + * except the USA use the 24 hour clock (UK, Australia etc). However + * since they are English nobody bothers to write a language + * translation (gettext) file. So the locale turns off the AM/PM, but + * gettext does not turn on the 24 hour clock. Leaving a mess. + * + * This routine checks if AM/PM are defined in the locale, if not it + * forces the use of the 24 hour clock. + * + * The function itself is a front end on strftime and takes exactly + * the same arguments. + * + * TODO: Actually remove the '%p' from the fixed up string so that + * there isn't a stray space. + */ + +gsize +e_strftime_fix_am_pm (gchar *str, + gsize max, + const gchar *fmt, + const struct tm *tm) +{ + gchar buf[10]; + gchar *sp; + gchar *ffmt; + gsize ret; + + if (strstr(fmt, "%p")==NULL && strstr(fmt, "%P")==NULL) { + /* No AM/PM involved - can use the fmt string directly */ + ret = e_strftime (str, max, fmt, tm); + } else { + /* Get the AM/PM symbol from the locale */ + e_strftime (buf, 10, "%p", tm); + + if (buf[0]) { + /* AM/PM have been defined in the locale + * so we can use the fmt string directly. */ + ret = e_strftime (str, max, fmt, tm); + } else { + /* No AM/PM defined by locale + * must change to 24 hour clock. */ + ffmt = g_strdup (fmt); + for (sp=ffmt; (sp=strstr(sp, "%l")); sp++) { + /* Maybe this should be 'k', but I have never + * seen a 24 clock actually use that format. */ + sp[1]='H'; + } + for (sp=ffmt; (sp=strstr(sp, "%I")); sp++) { + sp[1]='H'; + } + ret = e_strftime (str, max, ffmt, tm); + g_free (ffmt); + } + } + + return (ret); +} + +gsize +e_utf8_strftime_fix_am_pm (gchar *str, + gsize max, + const gchar *fmt, + const struct tm *tm) +{ + gsize sz, ret; + gchar *locale_fmt, *buf; + + locale_fmt = g_locale_from_utf8 (fmt, -1, NULL, &sz, NULL); + if (!locale_fmt) + return 0; + + ret = e_strftime_fix_am_pm (str, max, locale_fmt, tm); + if (!ret) { + g_free (locale_fmt); + return 0; + } + + buf = g_locale_to_utf8 (str, ret, NULL, &sz, NULL); + if (!buf) { + g_free (locale_fmt); + return 0; + } + + if (sz >= max) { + gchar *tmp = buf + max - 1; + tmp = g_utf8_find_prev_char (buf, tmp); + if (tmp) + sz = tmp - buf; + else + sz = 0; + } + memcpy (str, buf, sz); + str[sz] = '\0'; + g_free (locale_fmt); + g_free (buf); + return sz; +} diff --git a/src/gcal-utils.h b/src/gcal-utils.h index b49b8fc0..877a49c4 100644 --- a/src/gcal-utils.h +++ b/src/gcal-utils.h @@ -47,16 +47,33 @@ typedef enum } GcalEditableMode; typedef -const gchar* (*GcalTranslateFunc) (GtkWidget *source_widget); +const gchar* (*GcalTranslateFunc) (GtkWidget *source_widget); -GType icaltime_get_type (void) G_GNUC_CONST; +GType icaltime_get_type (void) G_GNUC_CONST; -void gcal_gtk_tree_view_set_activate_on_single_click (GtkTreeView *tree_view, - gboolean should_activate); +void gcal_gtk_tree_view_set_activate_on_single_click (GtkTreeView *tree_view, + gboolean should_activate); -const gchar* gcal_get_group_name (const gchar *base_uri); +const gchar* gcal_get_group_name (const gchar *base_uri); -icaltimetype* gcal_dup_icaltime (icaltimetype *date); +icaltimetype* gcal_dup_icaltime (icaltimetype *date); + +gchar* gcal_get_source_name (GtkTreeModel *model, + const gchar *uid); + +gchar* gcal_get_source_uid (GtkTreeModel *model, + const gchar *name); + +/* code brought from evolution */ +gsize e_strftime_fix_am_pm (gchar *str, + gsize max, + const gchar *fmt, + const struct tm *tm); +gsize e_utf8_strftime_fix_am_pm (gchar *str, + + gsize max, + const gchar *fmt, + const struct tm *tm); #endif // __GCAL_UTILS_H__ diff --git a/src/gcal-window.c b/src/gcal-window.c index c1723bc6..76e67164 100644 --- a/src/gcal-window.c +++ b/src/gcal-window.c @@ -55,6 +55,8 @@ GcalManager* gcal_window_get_manager (GcalWindow *window) static void gcal_window_set_sources_view (GcalWindow *window); +static void gcal_window_init_event_view (GcalWindow *window); + static void gcal_window_view_changed (GcalToolbar *main_toolbar, GcalViewTypeEnum view_type, gpointer user_data); @@ -75,6 +77,9 @@ static void gcal_window_events_added (GcalManager *manager gpointer events_list, gpointer user_data); +static void gcal_window_event_activated (GcalEventWidget *event_widget, + gpointer user_data); + G_DEFINE_TYPE(GcalWindow, gcal_window, GTK_TYPE_APPLICATION_WINDOW) static void @@ -306,6 +311,28 @@ gcal_window_set_sources_view (GcalWindow *window) window); } +static void +gcal_window_init_event_view (GcalWindow *window) +{ + GcalWindowPrivate *priv; + + g_return_if_fail (GCAL_IS_WINDOW (window)); + priv = window->priv; + + priv->add_view = gcal_event_view_new_with_manager ( + gcal_window_get_manager (window)); + gtk_widget_set_hexpand (priv->add_view, TRUE); + gtk_widget_set_vexpand (priv->add_view, TRUE); + gtk_widget_set_margin_top (priv->add_view, 10); + gtk_widget_set_margin_left (priv->add_view, 20); + gtk_widget_set_margin_right (priv->add_view, 20); + + gtk_widget_show (priv->add_view); + gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), + priv->add_view, + NULL); +} + static void gcal_window_view_changed (GcalToolbar *main_toolbar, GcalViewTypeEnum view_type, @@ -365,28 +392,12 @@ gcal_window_add_event (GcalToolbar *main_toolbar, priv = GCAL_WINDOW (user_data)->priv; if (priv->add_view == NULL) - { - priv->add_view = gcal_event_view_new_with_manager ( - gcal_window_get_manager (GCAL_WINDOW (user_data))); - gtk_widget_set_hexpand (priv->add_view, TRUE); - gtk_widget_set_vexpand (priv->add_view, TRUE); - gtk_widget_set_margin_top (priv->add_view, 10); - gtk_widget_set_margin_left (priv->add_view, 20); - gtk_widget_set_margin_right (priv->add_view, 20); + gcal_window_init_event_view (GCAL_WINDOW (user_data)); - gtk_widget_show (priv->add_view); - gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), - priv->add_view, - NULL); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), -1); - } - else - { - //TODO: Reload/clean/reinitialize status - gtk_notebook_set_current_page ( - GTK_NOTEBOOK (priv->notebook), - gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), priv->add_view)); - } + //TODO: Reload/clean/reinitialize status + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (priv->notebook), + gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), priv->add_view)); } static void @@ -471,6 +482,12 @@ gcal_window_events_added (GcalManager *manager, event); gtk_style_context_add_class (gtk_widget_get_style_context (event), "event"); + + g_signal_connect (event, + "activated", + G_CALLBACK (gcal_window_event_activated), + user_data); + g_free (summary); gdk_rgba_free (color); } @@ -484,6 +501,29 @@ gcal_window_events_added (GcalManager *manager, } } +static void +gcal_window_event_activated (GcalEventWidget *event_widget, + gpointer user_data) +{ + GcalWindowPrivate *priv; + + g_return_if_fail (GCAL_IS_WINDOW (user_data)); + priv = GCAL_WINDOW (user_data)->priv; + + g_debug ("event_activated: %s", gcal_event_widget_peek_uuid (event_widget)); + if (priv->add_view == NULL) + gcal_window_init_event_view (GCAL_WINDOW (user_data)); + + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (priv->notebook), + gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), priv->add_view)); + + gcal_event_view_load_event (GCAL_EVENT_VIEW (priv->add_view), + gcal_event_widget_peek_uuid (event_widget)); +} + +/* Public API */ + GtkWidget* gcal_window_new (GcalApplication *app) {