r1346 - in trunk/src/target/OM-2007/applications/openmoko-today: . src tests
dodji at sita.openmoko.org
dodji at sita.openmoko.org
Tue Mar 13 17:52:05 CET 2007
Author: dodji
Date: 2007-03-13 17:52:01 +0100 (Tue, 13 Mar 2007)
New Revision: 1346
Added:
trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.c
trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.h
trunk/src/target/OM-2007/applications/openmoko-today/tests/events-area-test.c
Modified:
trunk/src/target/OM-2007/applications/openmoko-today/ChangeLog
trunk/src/target/OM-2007/applications/openmoko-today/src/Makefile.am
trunk/src/target/OM-2007/applications/openmoko-today/src/today-main.c
trunk/src/target/OM-2007/applications/openmoko-today/tests/Makefile.am
Log:
Initial commit of the TodayEventsArea widget
* src/today-events-area.c,h: initial attempt at coding an
EventArea widget that takes a list of ECalComponent representing
a list of event and showing these events "page by page".
You can select events, and cycle through the event pages.
* src/today-main.c: use the new EventArea widget for testing
For now,the code loads all the events from the calendar, not only
those of today. This is just to test the paging code.
* tests/events-area-test.c: a small test program for the widget
Modified: trunk/src/target/OM-2007/applications/openmoko-today/ChangeLog
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/ChangeLog 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/ChangeLog 2007-03-13 16:52:01 UTC (rev 1346)
@@ -1 +1,10 @@
+Tue, 13 Mar 2007 17:31:00 +0100 Dodji Seketeli <dodji at o-hand.com>
+ * src/today-events-area.c,h: initial attempt at coding an
+ EventArea widget that takes a list of ECalComponent representing
+ a list of event and showing these events "page by page".
+ You can select events, and cycle through the event pages.
+ * src/today-main.c: use the new EventArea widget for testing
+ For now,the code loads all the events from the calendar, not only
+ those of today. This is just to test the paging code.
+ * tests/events-area-test.c: a small test program for the widget
Modified: trunk/src/target/OM-2007/applications/openmoko-today/src/Makefile.am
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/src/Makefile.am 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/src/Makefile.am 2007-03-13 16:52:01 UTC (rev 1346)
@@ -8,7 +8,7 @@
bin_PROGRAMS = today
-today_SOURCES = today-main.c
+today_SOURCES = today-main.c today-events-area.h today-events-area.c
today_LDADD = @TODAY_LIBS@
Added: trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.c
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.c 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.c 2007-03-13 16:52:01 UTC (rev 1346)
@@ -0,0 +1,719 @@
+/*
+ * Today - At a glance view of date, time, calender events, todo items and
+ * other images.
+ *
+ * Copyright (C) 2007 by OpenMoko, Inc.
+ * Written by OpenedHand Ltd <info at openedhand.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <string.h>
+#include <libecal/e-cal-time-util.h>
+#include <libecal/e-cal-component.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtkeventbox.h>
+#include <gtk/gtklabel.h>
+#include "today-events-area.h"
+
+struct _TodayEventsAreaPrivate {
+ GList *events ;
+ GtkWidget *left ;
+ GtkWidget *left_event_box ;
+ GtkWidget *paging_info ;
+ GtkWidget *right ;
+
+ GList *cur_event ;
+ GList *page_start ;
+ int page_start_index ;
+ int cur_event_index ;
+ int max_visible_events ;
+ int nb_events ;
+};
+
+static void today_events_area_finalize (GObject *a_obj);
+static void today_events_area_init (TodayEventsArea *a_this);
+static void clear_right_hand_side (TodayEventsArea *a_this);
+static void init_right_hand_side (TodayEventsArea *a_this);
+static void clear_left_hand_side (TodayEventsArea *a_this);
+static void init_left_hand_side (TodayEventsArea *a_this);
+static void reinit_area (TodayEventsArea *a_this) ;
+static int get_nb_events_real (TodayEventsArea *a_this) ;
+static gboolean update_paging_info (TodayEventsArea *a_this) ;
+static GList* select_event (TodayEventsArea *a_this,
+ GList *a_event) ;
+static void render_event (TodayEventsArea *a_this,
+ GList *a_event) ;
+static void render_events_page (TodayEventsArea *a_this,
+ GList *a_from) ;
+static void render_events_page_auto (TodayEventsArea *a_this) ;
+static void e_cal_component_list_free (GList * list) ;
+static gchar* icaltime_to_pretty_string (const icaltimetype *timetype) ;
+static int get_list_elem_index (GList *a_elem) ;
+
+G_DEFINE_TYPE (TodayEventsArea, today_events_area, GTK_TYPE_TABLE)
+
+static void
+today_events_area_class_init (TodayEventsAreaClass *a_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (a_class);
+ object_class->finalize = today_events_area_finalize;
+ g_type_class_add_private (object_class, sizeof (TodayEventsAreaPrivate));
+}
+
+static void
+today_events_area_init (TodayEventsArea *a_this)
+{
+ g_return_if_fail (GTK_IS_TABLE (a_this)) ;
+
+ a_this->priv = G_TYPE_INSTANCE_GET_PRIVATE (a_this,
+ TODAY_TYPE_EVENTS_AREA,
+ TodayEventsAreaPrivate);
+
+ gtk_table_resize (GTK_TABLE (a_this), 1, 2) ;
+ reinit_area (a_this) ;
+}
+
+static void
+today_events_area_finalize (GObject *a_obj)
+{
+ TodayEventsArea *self = TODAY_EVENTS_AREA (a_obj) ;
+ g_return_if_fail (self && self->priv) ;
+
+ if (self->priv->events)
+ {
+ e_cal_component_list_free (self->priv->events) ;
+ self->priv->events = NULL ;
+ }
+ self->priv->cur_event = NULL ;
+ self->priv->cur_event_index = 0 ;
+ self->priv->page_start = NULL ;
+ self->priv->max_visible_events = 0 ;
+
+ self->priv = NULL ;
+
+ /*chain up*/
+ (*G_OBJECT_CLASS (today_events_area_parent_class)->finalize) (a_obj);
+}
+/********************
+ * <signal callbacks>
+ ********************/
+gboolean
+on_button_pressed_in_left_cb (GtkWidget *a_event_box,
+ GdkEventButton *a_button,
+ TodayEventsArea *a_area)
+{
+ g_return_val_if_fail (a_area && TODAY_IS_EVENTS_AREA (a_area), FALSE) ;
+ if (a_event_box) {/*keep compiler happy*/}
+
+ if (a_button->type == GDK_BUTTON_PRESS)
+ today_events_area_select_next_event (a_area) ;
+
+ return FALSE ;
+}
+
+gboolean
+on_button_pressed_in_infoline_cb (GtkWidget *a_event_box,
+ GdkEventButton *a_button,
+ TodayEventsArea *a_area)
+{
+ int event_index = 0 ;
+ GList *event_elem = NULL ;
+
+ g_return_val_if_fail (a_area && TODAY_IS_EVENTS_AREA (a_area), FALSE) ;
+
+ if (a_button->type != GDK_BUTTON_PRESS)
+ return FALSE ;
+
+ event_index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a_event_box),
+ "event-index")) ;
+ event_elem = g_list_nth (a_area->priv->events, event_index) ;
+ select_event (a_area, event_elem) ;
+
+ return FALSE;
+}
+
+/********************
+ * </signal callbacks>
+ ********************/
+
+/**********************
+ * <private api>
+ **********************/
+
+/**
+ * e_cal_component_list_free:
+ * @list: the list ECalComooment to free
+ *
+ * Free a list of ECalComponent
+ */
+static void
+e_cal_component_list_free (GList * a_list)
+{
+ GList *cur = NULL;
+
+ for (cur = a_list; cur; cur = cur->next)
+ {
+ /*if an element of the list is not of type ECalComponent, leak it */
+ if (cur->data && E_IS_CAL_COMPONENT (cur->data))
+ {
+ g_object_unref (G_OBJECT (cur->data));
+ cur->data = NULL;
+ }
+ else
+ {
+ g_warning ("cur->data is not of type ECalComponent !");
+ }
+ }
+ g_list_free (a_list);
+}
+
+static void
+clear_right_hand_side (TodayEventsArea *a_this)
+{
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv) ;
+
+ if (a_this->priv->right)
+ {
+ gtk_widget_destroy (a_this->priv->right) ;
+ a_this->priv->right = NULL ;
+ }
+}
+
+static void
+init_right_hand_side (TodayEventsArea *a_this)
+{
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv) ;
+
+ if (a_this->priv->right)
+ clear_right_hand_side (a_this) ;
+
+ a_this->priv->right = gtk_vbox_new (TRUE, 0) ;
+ gtk_widget_show (a_this->priv->right) ;
+ gtk_table_attach_defaults (GTK_TABLE (a_this),
+ a_this->priv->right,
+ 1, 2, 0, 1) ;
+}
+
+static void
+clear_left_hand_side (TodayEventsArea *a_this)
+{
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv) ;
+
+ if (a_this->priv->left)
+ {
+ gtk_widget_destroy (a_this->priv->left) ;
+ a_this->priv->left = NULL ;
+ a_this->priv->left_event_box = NULL ;
+ a_this->priv->paging_info = NULL ;
+ }
+}
+
+static void
+init_left_hand_side (TodayEventsArea *a_this)
+{
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv) ;
+
+ if (a_this->priv->left)
+ clear_left_hand_side (a_this) ;
+
+ a_this->priv->left_event_box = gtk_event_box_new ();
+ gtk_widget_add_events (a_this->priv->left_event_box,
+ GDK_BUTTON_PRESS_MASK) ;
+ g_signal_connect (G_OBJECT (a_this->priv->left_event_box),
+ "button-press-event",
+ G_CALLBACK (on_button_pressed_in_left_cb),
+ a_this) ;
+ a_this->priv->paging_info = gtk_label_new ("0/0") ;
+ gtk_container_add (GTK_CONTAINER (a_this->priv->left_event_box),
+ a_this->priv->paging_info) ;
+
+ a_this->priv->left = gtk_vbox_new (TRUE, 0) ;
+ gtk_box_pack_start (GTK_BOX (a_this->priv->left),
+ a_this->priv->left_event_box,
+ FALSE, FALSE, 0) ;
+
+ gtk_table_attach_defaults (GTK_TABLE (a_this),
+ a_this->priv->left,
+ 0, 1, 0, 1) ;
+ gtk_widget_show_all (a_this->priv->left) ;
+}
+
+static void
+reinit_area (TodayEventsArea *a_this)
+{
+ g_return_if_fail (a_this && TODAY_IS_EVENTS_AREA (a_this)) ;
+
+ init_left_hand_side (a_this) ;
+ init_right_hand_side (a_this) ;
+}
+
+static int
+get_nb_events_real (TodayEventsArea *a_this)
+{
+ GList *cur = NULL ;
+ int result = 0 ;
+
+ g_return_val_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv,
+ -1) ;
+
+ for (cur = a_this->priv->events ; cur ; cur = cur->next)
+ ++result ;
+ return result ;
+}
+
+static gboolean
+update_paging_info (TodayEventsArea *a_this)
+{
+ gchar *str ;
+
+ g_return_val_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv,
+ FALSE) ;
+
+ g_return_val_if_fail (a_this->priv->paging_info, FALSE) ;
+ g_return_val_if_fail (a_this->priv->cur_event, FALSE) ;
+ g_return_val_if_fail (a_this->priv->events, FALSE) ;
+
+ str = g_strdup_printf ("%d/%d",
+ a_this->priv->cur_event_index + 1,
+ a_this->priv->nb_events) ;
+
+ gtk_label_set_text (GTK_LABEL (a_this->priv->paging_info), str) ;
+ g_free (str) ;
+
+ return TRUE ;
+}
+
+static GList*
+select_event (TodayEventsArea *a_this,
+ GList *a_event)
+{
+ int event_index = 0 ;
+
+ g_return_val_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv,
+ FALSE) ;
+
+ if (!a_this->priv->events || !a_event)
+ {
+ return NULL ;
+ }
+ event_index = get_list_elem_index (a_event) ;
+ g_return_val_if_fail (event_index >= 0, NULL) ;
+
+ a_this->priv->cur_event = a_event ;
+ a_this->priv->cur_event_index = event_index ;
+
+ if ((a_this->priv->page_start_index + a_this->priv->max_visible_events
+ <= a_this->priv->cur_event_index)
+ ||
+ (a_this->priv->cur_event_index < a_this->priv->page_start_index))
+ {
+ render_events_page_auto (a_this) ;
+ }
+
+ update_paging_info (a_this) ;
+
+ return a_event;
+
+}
+
+/*
+ * if the timetype is today, then only display it's hour part,
+ * without the seconds
+ * If it's not today, then only display it's date part, without the year
+ */
+static gchar*
+icaltime_to_pretty_string (const icaltimetype *timetype)
+{
+#define TMP_STR_LEN 10
+ icaltimetype today ;
+ gboolean hour_only = FALSE ;
+ gboolean date_only = FALSE ;
+ gchar *result = NULL ;
+ gchar tmp_str[TMP_STR_LEN+1] ;
+ struct tm native_tm ;
+
+ g_return_val_if_fail (timetype, NULL) ;
+
+ today = icaltime_today () ;
+ if (!icaltime_compare_date_only (*timetype, today))
+ {
+ hour_only = TRUE ;
+ }
+ else
+ {
+ date_only = TRUE ;
+ }
+ if (hour_only)
+ {
+ result = g_strdup_printf ("%d:%d", timetype->hour, timetype->minute) ;
+ }
+ else if (date_only)
+ {
+ native_tm = icaltimetype_to_tm ((icaltimetype*)timetype) ;
+ memset (tmp_str, 0, TMP_STR_LEN+1) ;
+ strftime (tmp_str, TMP_STR_LEN, "%d/%b", &native_tm) ;
+ result = g_strdup (tmp_str) ;
+ }
+ return result ;
+}
+
+static int
+get_list_elem_index (GList *a_elem)
+{
+ int nb = -1 ;
+ GList *cur = NULL ;
+
+ for (cur = a_elem ; cur ; cur = cur->prev)
+ ++nb ;
+
+ return nb ;
+}
+
+static void
+render_event (TodayEventsArea *a_this,
+ GList *a_event)
+{
+ GtkWidget *infoline ;
+ GtkWidget *label ;
+ GtkWidget *event_box ;
+ ECalComponentText text ;
+ ECalComponentDateTime start_date ;
+ ECalComponent *event ;
+ int event_index ;
+ gchar *tmp_str, *tmp_str2 ;
+
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv
+ && a_this->priv->right
+ && GTK_IS_BOX (a_this->priv->right)) ;
+
+ g_return_if_fail (a_event && a_event->data) ;
+
+ event = a_event->data ;
+ g_return_if_fail (E_IS_CAL_COMPONENT (event)) ;
+ event_index = get_list_elem_index (a_event) ;
+ g_return_if_fail (event_index >= 0) ;
+
+ /*get the event summary*/
+ e_cal_component_get_summary (event, &text) ;
+
+ /*get the event starting date*/
+ e_cal_component_get_dtstart (event, &start_date) ;
+ tmp_str = icaltime_to_pretty_string (start_date.value) ;
+ e_cal_component_free_datetime (&start_date) ;
+
+ /*build event infoline*/
+ tmp_str2 = g_strdup_printf ("%s %s", text.value, tmp_str) ;
+ g_free (tmp_str) ;
+ label = gtk_label_new (tmp_str2) ;
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0) ;
+ gtk_widget_show (label) ;
+ g_free (tmp_str2) ;
+ infoline = gtk_hbox_new (TRUE, 0) ;
+ gtk_widget_show (infoline) ;
+ gtk_box_pack_start_defaults (GTK_BOX (infoline), label) ;
+ event_box = gtk_event_box_new () ;
+ gtk_widget_show (event_box) ;
+ g_object_set_data (G_OBJECT (event_box),
+ "event-index",
+ GINT_TO_POINTER (event_index)) ;
+ g_signal_connect (G_OBJECT (event_box), "button-press-event",
+ G_CALLBACK (on_button_pressed_in_infoline_cb),
+ a_this) ;
+ gtk_container_add (GTK_CONTAINER (event_box), infoline) ;
+ gtk_box_pack_start_defaults (GTK_BOX (a_this->priv->right), event_box) ;
+}
+
+static void
+render_events_page (TodayEventsArea *a_this, GList *a_from)
+{
+ GList *cur = NULL ;
+ int nb_rendered = 0 ;
+
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv
+ && a_this->priv->right
+ && GTK_IS_BOX (a_this->priv->right)) ;
+
+ if (!a_this->priv->events)
+ return ;
+
+ if (a_from)
+ {
+ a_this->priv->page_start = a_from ;
+ }
+ else
+ {
+ a_this->priv->page_start = a_this->priv->events ;
+ }
+ g_return_if_fail (a_this->priv->page_start) ;
+
+ a_this->priv->page_start_index =
+ get_list_elem_index (a_this->priv->page_start) ;
+
+ init_right_hand_side (a_this) ;
+ for (cur = a_this->priv->page_start ;
+ cur && (nb_rendered < a_this->priv->max_visible_events);
+ cur = cur->next, ++nb_rendered)
+ {
+ render_event (a_this, cur) ;
+ }
+}
+
+static void
+render_events_page_auto (TodayEventsArea *a_this)
+{
+ int page_end=0 ;
+ int page_start=0 ;
+ GList *from = NULL ;
+ g_return_if_fail (a_this
+ && TODAY_IS_EVENTS_AREA (a_this)
+ && a_this->priv) ;
+
+ /*
+ * compute a page start index so that the current event index
+ * is inside [page_start page_end],
+ * with page_end - page_start == max_visible_events
+ */
+ if (a_this->priv->cur_event_index > a_this->priv->page_start_index)
+ {
+ for (page_end = a_this->priv->max_visible_events ;
+ page_end <= a_this->priv->cur_event_index;
+ page_end += a_this->priv->max_visible_events)
+ {
+ }
+ page_start = page_end - a_this->priv->max_visible_events ;
+ }
+ else
+ {
+ for (page_start = 0 ;
+ page_start + a_this->priv->max_visible_events <=
+ a_this->priv->cur_event_index;
+ page_start += a_this->priv->max_visible_events)
+ {
+ }
+ }
+
+ from = g_list_nth (a_this->priv->events, page_start) ;
+ g_return_if_fail (from) ;
+ render_events_page (a_this, from) ;
+}
+
+
+/**********************
+ * </private api>
+ **********************/
+
+/**********************
+ * <public api>
+ **********************/
+
+GtkWidget*
+today_events_area_new ()
+{
+ GObject *result;
+ result = g_object_new (TODAY_TYPE_EVENTS_AREA, NULL) ;
+ /*provide gobject param getter/setter for this*/
+ today_events_area_set_max_visible_events (TODAY_EVENTS_AREA (result), 4) ;
+ return GTK_WIDGET (result);
+}
+
+/**
+ *today_events_area_set_events:
+ *@a_this: current instance of TodayEventsArea
+ *@a_events: the events to set. Once set, the events belong to
+ *the current instance of EventsArea and will be freed by it
+ */
+void
+today_events_area_set_events (TodayEventsArea *a_this,
+ GList *a_events)
+{
+ g_return_if_fail (a_this && TODAY_IS_EVENTS_AREA (a_this)) ;
+ g_return_if_fail (a_this->priv) ;
+
+ if (a_this->priv->events)
+ e_cal_component_list_free (a_this->priv->events) ;
+
+ a_this->priv->events = a_events ;
+ a_this->priv->nb_events = get_nb_events_real (a_this) ;
+ a_this->priv->cur_event = NULL ;
+ a_this->priv->page_start = NULL ;
+ a_this->priv->cur_event_index = 0 ;
+
+ reinit_area (a_this) ;
+
+ if (!a_this->priv->events)
+ return ;
+
+ today_events_area_select_next_event (a_this) ;
+
+ /*
+ * walk the events and render them
+ * on the right hand side
+ * of the event area
+ */
+ render_events_page (a_this, a_events) ;
+ update_paging_info (a_this) ;
+}
+
+GList*
+today_events_area_get_events (TodayEventsArea *a_this)
+{
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ NULL);
+ return a_this->priv->events ;
+}
+
+int
+today_events_area_get_nb_events (TodayEventsArea *a_this)
+{
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ -1);
+ return a_this->priv->nb_events ;
+}
+
+ECalComponent*
+today_events_area_get_cur_event (TodayEventsArea *a_this)
+{
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ NULL);
+
+ return a_this->priv->cur_event->data ;
+}
+
+int
+today_events_area_get_cur_event_index (TodayEventsArea *a_this)
+{
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ -1);
+ return a_this->priv->cur_event_index ;
+}
+
+ECalComponent*
+today_events_area_select_next_event (TodayEventsArea *a_this)
+{
+ GList *result = NULL ;
+
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ NULL);
+
+ if (!a_this->priv->events)
+ {
+ a_this->priv->cur_event = NULL ;
+ a_this->priv->cur_event_index = -1 ;
+ goto out ;
+ }
+
+ if (!a_this->priv->cur_event)
+ {
+ result = select_event (a_this, a_this->priv->events) ;
+ goto out ;
+ }
+
+ if (a_this->priv->cur_event->next)
+ {
+ result = select_event (a_this, a_this->priv->cur_event->next) ;
+ }
+ else
+ {
+ /*reached end of events, cycle to the first event in list*/
+ result = select_event (a_this, a_this->priv->events) ;
+ }
+
+out:
+ if (!result)
+ return NULL ;
+ return result->data ;
+}
+
+ECalComponent*
+today_events_area_goto_next_page (TodayEventsArea *a_this)
+{
+ int start_index = 0 ;
+ GList *page_start = NULL, *event = NULL;
+
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ NULL);
+
+ start_index = get_list_elem_index (a_this->priv->page_start) ;
+ start_index += a_this->priv->max_visible_events ;
+ page_start = g_list_nth (a_this->priv->events, start_index) ;
+ if (!page_start)
+ page_start = a_this->priv->events ;
+ event = select_event (a_this, page_start) ;
+ if (!event)
+ return NULL ;
+ return event->data ;
+}
+
+void
+today_events_area_set_max_visible_events (TodayEventsArea *a_this,
+ int a_max)
+{
+ g_return_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv);
+
+ a_this->priv->max_visible_events = a_max ;
+}
+
+int
+today_events_area_get_max_visible_events (TodayEventsArea *a_this)
+{
+ g_return_val_if_fail (a_this &&
+ TODAY_IS_EVENTS_AREA (a_this) &&
+ a_this->priv,
+ -1);
+
+ return a_this->priv->max_visible_events ;
+}
+
+/**********************
+ * </public api>
+ **********************/
+
Added: trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.h
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.h 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/src/today-events-area.h 2007-03-13 16:52:01 UTC (rev 1346)
@@ -0,0 +1,71 @@
+/*
+ * Today - At a glance view of date, time, calender events, todo items and
+ * other images.
+ *
+ * Copyright (C) 2007 by OpenMoko, Inc.
+ * Written by OpenedHand Ltd <info at openedhand.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __TODAY_EVENTS_AREA_H__
+#define __TODAY_EVENTS_AREA_H__
+
+#include <libecal/e-cal-component.h>
+#include <gtk/gtktable.h>
+
+G_BEGIN_DECLS
+
+#define TODAY_TYPE_EVENTS_AREA (today_events_area_get_type ())
+#define TODAY_EVENTS_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TODAY_TYPE_EVENTS_AREA, TodayEventsArea))
+#define TODAY_EVENTS_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TODAY_TYPE_EVENTS_AREA, TodayEventsAreaClass))
+#define TODAY_IS_EVENTS_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TODAY_TYPE_EVENTS_AREA))
+#define TODAY_IS_EVENTS_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TODAY_TYPE_EVENTS_AREA))
+#define TODAY_EVENTS_AREA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TODAY_TYPE_EVENTS_AREATodayEventsAreaClass))
+
+typedef struct _TodayEventsAreaPrivate TodayEventsAreaPrivate;
+typedef struct _TodayEventsAreaClass TodayEventsAreaClass;
+typedef struct _TodayEventsArea TodayEventsArea;
+
+struct _TodayEventsArea {
+ GtkTable table;
+ TodayEventsAreaPrivate *priv;
+};
+
+struct _TodayEventsAreaClass {
+ GtkTableClass parent_class;
+};
+
+GType today_events_area_get_type (void);
+GtkWidget* today_events_area_new ();
+void today_events_area_set_events (TodayEventsArea *a_this,
+ GList *a_events);
+GList* today_events_area_get_events (TodayEventsArea *a_this);
+int today_events_area_get_nb_events (TodayEventsArea *a_this);
+ECalComponent* today_events_area_get_cur_event (TodayEventsArea *a_this);
+int today_events_area_get_cur_event_index (TodayEventsArea *a_this);
+ECalComponent* today_events_area_select_next_event (TodayEventsArea *a_this) ;
+ECalComponent* today_events_area_goto_next_page (TodayEventsArea *a_this) ;
+void today_events_area_set_max_visible_events
+ (TodayEventsArea *a_this,
+ int a_max) ;
+int today_events_area_get_max_visible_events
+ (TodayEventsArea *a_this) ;
+
+G_END_DECLS
+
+#endif /*__TODAY_EVENTS_AREA_H__*/
+
Modified: trunk/src/target/OM-2007/applications/openmoko-today/src/today-main.c
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/src/today-main.c 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/src/today-main.c 2007-03-13 16:52:01 UTC (rev 1346)
@@ -28,6 +28,7 @@
#include <libecal/e-cal-time-util.h>
#include <gtk/gtk.h>
#include <libmokoui/moko-window.h>
+#include "today-events-area.h"
#define LOG_ERROR \
g_warning ("Got error '%s', code '%d'", \
@@ -78,48 +79,13 @@
gtk_label_set_markup (label, time_str);
}
-/*
- * if the timetype is today, then only display it's hour part,
- * without the seconds
- * If it's not today, then only display it's date part, without the year
+/**
+ * e_cal_component_list_free:
+ * @list: the list ECalComooment to free
+ *
+ * Free a list of ECalComponent
*/
-gchar*
-icaltime_to_pretty_string (const icaltimetype *timetype)
-{
-#define TMP_STR_LEN 10
- icaltimetype today ;
- gboolean hour_only = FALSE ;
- gboolean date_only = FALSE ;
- gchar *result = NULL ;
- gchar tmp_str[TMP_STR_LEN+1] ;
- struct tm native_tm ;
-
- g_return_val_if_fail (timetype, NULL) ;
-
- today = icaltime_today () ;
- if (!icaltime_compare_date_only (*timetype, today))
- {
- hour_only = TRUE ;
- }
- else
- {
- date_only = TRUE ;
- }
- if (hour_only)
- {
- result = g_strdup_printf ("%d:%d", timetype->hour, timetype->minute) ;
- }
- else if (date_only)
- {
- native_tm = icaltimetype_to_tm ((icaltimetype*)timetype) ;
- memset (tmp_str, 0, TMP_STR_LEN+1) ;
- strftime (tmp_str, TMP_STR_LEN, "%d/%b", &native_tm) ;
- result = g_strdup (tmp_str) ;
- }
- return result ;
-}
-
-void
+static void
e_cal_component_list_free (GList * list)
{
GList *cur = NULL;
@@ -141,11 +107,13 @@
}
/**
- * returns a list of ECalComponents, of type VEVENT
- * it must freed it with e_cal_component_list_free()
+ * today_get_today_events:
+ *
+ * Return value: a list of ECalComponents, of type VEVENT
+ * must be freed with e_cal_component_list_free()
*/
static GList *
-get_today_events ()
+today_get_today_events ()
{
GList *result = NULL;
GList *ical_comps = NULL;
@@ -169,10 +137,13 @@
goto out;
}
+ /*
query = g_strdup_printf ("(occur-in-time-range? "
"(time-day-begin (time-now)) "
"(time-day-end (time-now)) "
")");
+ */
+ query = g_strdup_printf ("#t");
e_cal_get_object_list (ecal, query, &ical_comps, &error);
if (error)
{
@@ -217,7 +188,13 @@
}
ecal_comps = NULL;
- g_object_unref (G_OBJECT (ecal));
+ /*
+ the calender must stay alive during the app's lifetime
+ if (ecal)
+ {
+ g_object_unref (G_OBJECT (ecal));
+ }
+ */
if (error)
{
@@ -229,6 +206,7 @@
return result;
}
+
/* information lines */
/**
@@ -313,76 +291,33 @@
return button;
}
+/**
+ * today_events_infolines_new:
+ *
+ * Return value: a GtkWidget showing the
+ * events of the day
+ */
GtkWidget *
-get_today_events_infoline ()
+today_events_infolines_new (const gchar *stock_id)
{
- GtkWidget *infoline = NULL ;
- GList *events = NULL ;
- GList *cur = NULL ;
- GString *lines = NULL ;
+ GtkWidget *events_area, *icon, *hbox ;
+ GList *events;
- events = get_today_events () ;
- lines = g_string_new (NULL) ;
- for (cur = events ; cur ; cur = cur->next)
- {
- ECalComponentText text ;
- ECalComponentDateTime start_date ;
- gchar *tmp_str = NULL ;
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 6) ;
- if (!E_IS_CAL_COMPONENT (cur->data)) {
- g_warning ("cur->data is not of type ECalComponent!") ;
- continue ;
- }
- if (e_cal_component_get_vtype (cur->data) != E_CAL_COMPONENT_EVENT)
- {
- g_warning ("Event type is not 'EVENT', but rather %d",
- e_cal_component_get_vtype (cur->data));
- continue;
- }
- /*get the event summary*/
- e_cal_component_get_summary (cur->data, &text) ;
- /*get the event starting date*/
- e_cal_component_get_dtstart (cur->data, &start_date) ;
- /*pretty print the starting date*/
- tmp_str = icaltime_to_pretty_string (start_date.value) ;
- if (tmp_str)
- {
- g_string_append_printf (lines, "%s %s\n", text.value, tmp_str) ;
- g_free (tmp_str) ;
- }
- else
- {
- g_string_append_printf (lines, "%s %s\n", text.value, "No Date") ;
- }
- e_cal_component_free_datetime (&start_date) ;
- }
- if (lines->len)
- {
- infoline = today_infoline_new (GTK_STOCK_NO,
- lines->str) ;
- }
- else
- {
- infoline = today_infoline_new (GTK_STOCK_NO, "No events for today") ;
- }
+ icon = gtk_image_new ();
+ gtk_image_set_from_stock (GTK_IMAGE (icon), stock_id, GTK_ICON_SIZE_MENU);
+ gtk_misc_set_alignment (GTK_MISC (icon), 0, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
- if (lines->len)
- infoline = today_infoline_new (GTK_STOCK_NO, lines->str);
- else
- infoline = today_infoline_new (GTK_STOCK_NO, "No events for today");
+ events = today_get_today_events () ;
+ events_area = today_events_area_new () ;
+ today_events_area_set_events (TODAY_EVENTS_AREA (events_area), events) ;
+ gtk_box_pack_start (GTK_BOX (hbox), events_area, FALSE, FALSE, 0);
- if (events)
- {
- e_cal_component_list_free (events);
- }
-
- if (lines)
- {
- g_string_free (lines, TRUE);
- lines = NULL;
- }
- return infoline;
+ return hbox;
}
static void
@@ -440,7 +375,7 @@
gtk_box_pack_start (GTK_BOX (vbox), infoline, FALSE, FALSE, 0);
/* upcoming events */
- infoline = get_today_events_infoline ();
+ infoline = today_events_infolines_new (GTK_STOCK_NO);
gtk_box_pack_start (GTK_BOX (vbox), infoline, FALSE, FALSE, 0);
/* shurtcut buttons */
Modified: trunk/src/target/OM-2007/applications/openmoko-today/tests/Makefile.am
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/tests/Makefile.am 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/tests/Makefile.am 2007-03-13 16:52:01 UTC (rev 1346)
@@ -1,4 +1,12 @@
-noinst_PROGRAMS = ecaltest
-ecaltest_SOURCES = ecal-test.c
-ecaltest_LDADD = @TODAY_LIBS@
+noinst_PROGRAMS = ecaltest eventsareatest
+
+ecaltest_SOURCES = ecal-test.c
+ecaltest_LDADD = @TODAY_LIBS@
+
+eventsareatest_SOURCES = events-area-test.c \
+$(top_srcdir)/src/today-events-area.c
+
+eventsareatest_LDADD = @TODAY_LIBS@
+
INCLUDES = -I$(top_srcdir) @TODAY_CFLAGS@
+
Added: trunk/src/target/OM-2007/applications/openmoko-today/tests/events-area-test.c
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-today/tests/events-area-test.c 2007-03-13 16:51:55 UTC (rev 1345)
+++ trunk/src/target/OM-2007/applications/openmoko-today/tests/events-area-test.c 2007-03-13 16:52:01 UTC (rev 1346)
@@ -0,0 +1,112 @@
+#include <libecal/e-cal.h>
+#include <libecal/e-cal-component.h>
+#include <gtk/gtk.h>
+#include "src/today-events-area.h"
+
+#define LOG_ERROR \
+g_warning ("Got error '%s', code '%d'", \
+ error->message, error->code);
+
+#define FREE_ERROR g_error_free (error) ; error = NULL ;
+
+static GList* get_calendar_events (ECal *a_cal) ;
+
+static GList*
+get_calendar_events (ECal *a_cal)
+{
+ char *query = NULL ;
+ GError *error = NULL ;
+ GList *objects = NULL ;
+ GList *events = NULL ;
+ GList *cur = NULL ;
+
+
+ if (!e_cal_open (a_cal, TRUE, &error))
+ {
+ g_warning ("failed to open the calendar") ;
+ goto out;
+ }
+ if (error)
+ {
+ LOG_ERROR ;
+ FREE_ERROR ;
+ goto out;
+ }
+ /*
+ query = g_strdup_printf ("(occur-in-time-range? "
+ "(time-day-begin (time-now)) "
+ "(time-day-end (time-now))"
+ ")");
+ */
+ query = g_strdup_printf ("#t");
+
+ if (!e_cal_get_object_list (a_cal, query, &objects, &error))
+ {
+ g_message ("Querying system calendar failed for query '%s'",
+ query) ;
+ goto out ;
+ }
+ if (error)
+ {
+ LOG_ERROR ;
+ FREE_ERROR ;
+ goto out;
+ }
+
+ for (cur = objects ; cur ; cur = cur->next)
+ {
+ ECalComponent *comp ;
+ comp = e_cal_component_new () ;
+ e_cal_component_set_icalcomponent (comp, cur->data) ;
+ events = g_list_prepend (events, comp) ;
+ cur->data = NULL ;
+ }
+ g_list_free (objects) ;
+ objects = NULL ;
+
+out:
+ g_free (query) ;
+ if (objects)
+ {
+ e_cal_free_object_list (objects) ;
+ }
+
+ return events ;
+}
+
+int
+main (int argc, char **argv)
+{
+ ECal *cal = NULL ;
+ GtkWidget *window = NULL ;
+ GtkWidget *ta = NULL ;
+ GList *events = NULL ;
+
+ gtk_init (&argc, &argv) ;
+
+ cal = e_cal_new_system_calendar () ;
+ g_return_val_if_fail (cal, -1) ;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL) ;
+ g_signal_connect (G_OBJECT (window),
+ "destroy",
+ G_CALLBACK (gtk_exit),
+ NULL) ;
+ ta = today_events_area_new () ;
+ today_events_area_set_max_visible_events (TODAY_EVENTS_AREA (ta),
+ 2) ;
+ events = get_calendar_events (cal) ;
+ g_return_val_if_fail (events, -1) ;
+ today_events_area_set_events (TODAY_EVENTS_AREA (ta), events) ;
+ gtk_container_add (GTK_CONTAINER (window), ta) ;
+
+ gtk_widget_show_all (window) ;
+
+ gtk_main () ;
+
+ if (cal)
+ {
+ g_object_unref (G_OBJECT (cal)) ;
+ }
+ return 0 ;
+}
More information about the commitlog
mailing list