#include <libebook/e-book.h>
#include <libosso-abook/osso-abook.h>
+#include <mce/dbus-names.h>
+#include <mce/mode-names.h>
+
+#define MCE_MATCH_RULE "type='signal',interface='" MCE_SIGNAL_IF "',member='" MCE_DEVICE_ORIENTATION_SIG "'"
+
+#define _HL(str) dgettext("hildon-libs",str)
+
enum
{
COLUMN_AVATAR = 0,
COLUMN_DISPLAY,
COLUMN_FULLNAME,
COLUMN_NEXT_BIRTHDAY,
+ COLUMN_ABOOK_CONTACT,
NUM_COLS
};
+/* Application UI data struct */
+typedef struct _BirthdayData BirthdayData;
+struct _BirthdayData {
+ GtkWidget *window;
+ GtkWidget *label;
+ GtkWidget *view;
+ GtkWidget *search;
+
+ GtkTreeViewColumn *display_column;
+
+ GtkWidget *tree_view;
+ GtkTreeModel *sorted;
+ GtkTreeModel *filter;
+
+ gchar *searched_name;
+ gboolean found;
+
+ guint n_contacts;
+};
+
+static void set_portrait_mode (BirthdayData *priv, gboolean enable);
+
+static gboolean
+is_portrait_mode (osso_context_t *osso_context)
+{
+ osso_rpc_t ret;
+ gboolean result = FALSE;
+
+ if (osso_rpc_run_system (osso_context, MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_DEVICE_ORIENTATION_GET,
+ &ret, DBUS_TYPE_INVALID) == OSSO_OK) {
+
+ if (strcmp (ret.value.s, MCE_ORIENTATION_PORTRAIT) == 0) {
+ result = TRUE;
+ }
+ osso_rpc_free_val (&ret);
+ } else {
+ g_critical ("ERROR: Call do DBus failed\n");
+ }
+ return result;
+}
+
+static DBusHandlerResult
+dbus_handle_mce_message (DBusConnection *connection,
+ DBusMessage *message,
+ gpointer data)
+{
+ DBusMessageIter iter;
+ const gchar *orientation = NULL;
+ BirthdayData *priv;
+
+ g_return_val_if_fail (data, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ priv = (BirthdayData *) data;
+
+ if (dbus_message_is_signal (message, MCE_SIGNAL_IF, MCE_DEVICE_ORIENTATION_SIG)) {
+ if (dbus_message_iter_init (message, &iter)) {
+ dbus_message_iter_get_basic(&iter, &orientation);
+ if (orientation) {
+ if (!strcmp (orientation, MCE_ORIENTATION_PORTRAIT))
+ set_portrait_mode (priv, TRUE);
+ else
+ set_portrait_mode (priv, FALSE);
+ }
+ }
+ }
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean
+birthday_filered_view_visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ BirthdayData *priv;
+ gchar *fullname = NULL, *ascii_searched_name = NULL, *ascii_fullname = NULL;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (data, FALSE);
+ priv = (BirthdayData *) data;
+
+ if (priv->searched_name == NULL) {
+ priv->found = TRUE;
+ return TRUE;
+ }
+
+ ascii_searched_name = g_utf8_strdown (priv->searched_name, strlen (priv->searched_name));
+
+ gtk_tree_model_get (model, iter, COLUMN_FULLNAME, &fullname, -1);
+ if (fullname) {
+ ascii_fullname = g_utf8_strdown (fullname, strlen (fullname));
+ g_free (fullname);
+ }
+
+ if (g_strstr_len (ascii_fullname, strlen (ascii_fullname), ascii_searched_name) != NULL)
+ found = TRUE;
+
+ if (ascii_searched_name)
+ g_free (ascii_searched_name);
+
+ if (ascii_fullname)
+ g_free (ascii_fullname);
+
+ if (found)
+ priv->found = TRUE;
+
+ return found;
+}
+
+static void
+sort_by_name_clicked (GtkButton *button,
+ gpointer data)
+{
+ BirthdayData *priv;
+
+ g_return_if_fail (data);
+ priv = (BirthdayData *) data;
+
+ if (priv->sorted) {
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->sorted),
+ COLUMN_FULLNAME, GTK_SORT_ASCENDING);
+ }
+}
+
+static void
+sort_by_date_clicked (GtkButton *button,
+ gpointer data)
+{
+ BirthdayData *priv;
+
+ g_return_if_fail (data);
+ priv = (BirthdayData *) data;
+
+ if (priv->sorted) {
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->sorted),
+ COLUMN_NEXT_BIRTHDAY, GTK_SORT_ASCENDING);
+ }
+}
+
+static void
+search_menu_clicked (GtkButton *button,
+ gpointer data)
+{
+ BirthdayData *priv;
+ GtkWidget *entry;
+
+ g_return_if_fail (data);
+ priv = (BirthdayData *) data;
+
+ /* show search bar */
+ gtk_widget_show (priv->search);
+
+ /* focus on search entry */
+ entry = g_object_get_data (G_OBJECT (priv->search), "entry");
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+ gtk_widget_grab_focus (GTK_WIDGET (entry));
+
+ /* refilter tree view */
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
+}
+
+static void
+on_search_entry_changed (GtkEditable *editable,
+ gpointer data)
+{
+ GtkTreeSelection *selection;
+ BirthdayData *priv;
+
+ g_return_if_fail (data);
+ priv = (BirthdayData *) data;
+
+ priv->found = FALSE;
+
+ if (priv->searched_name)
+ g_free (priv->searched_name);
+ priv->searched_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (editable)));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+
+ /* ugly hack, set back mode to selection none to not generate "changed"
+ signal during re-filtering */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
+
+ /* refilter tree view */
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
+
+ if (priv->found) {
+ /* hide label */
+ gtk_widget_hide (priv->label);
+
+ /* show tree view */
+ gtk_widget_show (priv->view);
+ } else {
+ /* hide label */
+ gtk_widget_show (priv->label);
+ gtk_label_set_text (GTK_LABEL (priv->label), _("No search results"));
+
+ /* show tree view */
+ gtk_widget_hide (priv->view);
+ }
+
+ /* ugly, but working way how to scroll to the first row */
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->tree_view),
+ gtk_tree_path_new_from_string ("0"), NULL, FALSE, 0, 0);
+
+ /* ugly hack, set back mode to single selection */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ /* unselect selected rows */
+ gtk_tree_selection_unselect_all (selection);
+}
+
+static void
+on_search_close_clicked (GtkButton *button,
+ gpointer data)
+{
+ GtkTreeSelection *selection;
+ BirthdayData *priv;
+
+ g_return_if_fail (data);
+ priv = (BirthdayData *) data;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+
+ /* ugly hack, set back mode to selection none to not generate "changed"
+ signal during re-filtering */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
+
+ /* hide search bar */
+ gtk_widget_hide (priv->search);
+
+ /* hide label */
+ gtk_widget_hide (priv->label);
+
+ /* show tree view */
+ gtk_widget_show (priv->view);
+
+ /* clear searched name */
+ if (priv->searched_name)
+ g_free (priv->searched_name);
+ priv->searched_name = NULL;
+
+ /* refilter tree view */
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
+
+ /* ugly, but working way how to scroll to the first row */
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->tree_view),
+ gtk_tree_path_new_from_string ("0"), NULL, FALSE, 0, 0);
+
+ /* ugly hack, set back mode to single selection */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ /* unselect selected rows */
+ gtk_tree_selection_unselect_all (selection);
+}
+
+
+static gboolean
+on_key_press_event (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
+{
+ BirthdayData *priv;
+
+ g_return_val_if_fail (data, TRUE);
+ priv = (BirthdayData *) data;
+
+ if (priv->n_contacts == 0)
+ return FALSE;
+
+ if ((event->keyval > GDK_space) && (event->keyval <= GDK_stricteq) && !GTK_WIDGET_VISIBLE (priv->search)) {
+ GtkWidget *entry;
+
+ /* show search bar */
+ gtk_widget_show (priv->search);
+
+ /* focus on search entry */
+ entry = g_object_get_data (G_OBJECT (priv->search), "entry");
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+ gtk_widget_grab_focus (GTK_WIDGET (entry));
+
+ /* refilter tree view */
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
+ }
+
+ return FALSE;
+}
+
+static void
+on_selection_changed (GtkTreeSelection *selection,
+ gpointer data)
+{
+ BirthdayData *priv;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *entry;
+
+ g_return_if_fail (data);
+ priv = (BirthdayData *) data;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ OssoABookContact *abook_contact = NULL;
+
+ /* unselect selected rows */
+ gtk_tree_selection_unselect_all (selection);
+
+ gtk_tree_model_get (model, &iter, COLUMN_ABOOK_CONTACT, &abook_contact, -1);
+
+ if (abook_contact) {
+ GtkWidget *starter, *dialog;
+ OssoABookContactDetailStore *store;
+ OssoABookContactAction actions[9] = {OSSO_ABOOK_CONTACT_ACTION_TEL,
+ OSSO_ABOOK_CONTACT_ACTION_SMS,
+ OSSO_ABOOK_CONTACT_ACTION_CHATTO,
+ OSSO_ABOOK_CONTACT_ACTION_VOIPTO,
+ OSSO_ABOOK_CONTACT_ACTION_VOIPTO_AUDIO,
+ OSSO_ABOOK_CONTACT_ACTION_VOIPTO_VIDEO,
+ OSSO_ABOOK_CONTACT_ACTION_MAILTO,
+ OSSO_ABOOK_CONTACT_ACTION_CREATE_ACCOUNT,
+ OSSO_ABOOK_CONTACT_ACTION_BIND};
+
+ store = osso_abook_contact_detail_store_new (abook_contact,
+ OSSO_ABOOK_CONTACT_DETAIL_EMAIL |
+ OSSO_ABOOK_CONTACT_DETAIL_PHONE |
+ OSSO_ABOOK_CONTACT_DETAIL_IM_VOICE |
+ OSSO_ABOOK_CONTACT_DETAIL_IM_VIDEO |
+ OSSO_ABOOK_CONTACT_DETAIL_IM_CHAT |
+ OSSO_ABOOK_CONTACT_DETAIL_OTHERS |
+ OSSO_ABOOK_CONTACT_DETAIL_SMS);
+
+ starter = osso_abook_touch_contact_starter_new_with_store (store,
+ (OssoABookContactAction *) &actions,
+ sizeof (actions));
+
+ dialog = osso_abook_touch_contact_starter_dialog_new (GTK_WINDOW (priv->window),
+ OSSO_ABOOK_TOUCH_CONTACT_STARTER (starter));
+ gtk_widget_show_all (dialog);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ }
+ }
+
+ /* grab focus to search entry */
+ entry = g_object_get_data (G_OBJECT (priv->search), "entry");
+ gtk_widget_grab_focus (GTK_WIDGET (entry));
+
+}
+
static unsigned int
-calc_age (EContactDate *bdate)
+calc_age (EContactDate *bdate, time_t current_date)
{
- struct tm tm_bday;
- struct tm *tm_age;
- time_t t_age;
- int age = 0;
-
- tm_bday.tm_sec = 0;
- tm_bday.tm_min = 0;
- tm_bday.tm_hour = 0;
- tm_bday.tm_mday = bdate->day;
- tm_bday.tm_mon = bdate->month - 1;
- tm_bday.tm_year = bdate->year - 1900;
-
- t_age = time (NULL) - mktime (&tm_bday);
- tm_age = gmtime (&t_age);
- age = tm_age->tm_year - 70;
-
- if (age < 0)
- age = 0;
-
- return age;
+ struct tm *current_date_tm;
+ struct tm bday_tm;
+ int age = 0;
+
+ current_date_tm = gmtime (¤t_date);
+
+ bday_tm.tm_sec = 0;
+ bday_tm.tm_min = 0;
+ bday_tm.tm_hour = 0;
+ bday_tm.tm_mday = bdate->day;
+ bday_tm.tm_mon = bdate->month - 1;
+ bday_tm.tm_year = current_date_tm->tm_year;
+ bday_tm.tm_isdst = current_date_tm->tm_isdst;
+
+ if (mktime (&bday_tm) > current_date) {
+ age = (current_date_tm->tm_year + 1900) - bdate->year - 1;
+ } else {
+ age = (current_date_tm->tm_year + 1900) - bdate->year;
+ }
+
+ if (age < 0)
+ age = 0;
+
+ return age;
}
static unsigned int
-calc_next_bday (EContactDate *bdate)
+calc_next_bday (EContactDate *bdate, time_t current_date)
{
- struct tm tm_current_bday, tm_next_bday;
- struct tm *tm_current_date;
- time_t t_current_date, t_current_bday, t_next_bday, t_next_bday_in;
-
- t_current_date = time (NULL);
- tm_current_date = localtime (&t_current_date);
-
- tm_current_bday.tm_sec = 0;
- tm_current_bday.tm_min = 0;
- tm_current_bday.tm_hour = 0;
- tm_current_bday.tm_mday = bdate->day;
- tm_current_bday.tm_mon = bdate->month - 1;
- tm_current_bday.tm_year = tm_current_date->tm_year;
- t_current_bday = mktime (&tm_current_bday);
-
- if (t_current_date > t_current_bday) {
- tm_next_bday.tm_sec = 0;
- tm_next_bday.tm_min = 0;
- tm_next_bday.tm_hour = 0;
- tm_next_bday.tm_mday = bdate->day;
- tm_next_bday.tm_mon = bdate->month - 1;
- tm_next_bday.tm_year = tm_current_date->tm_year + 1;
- t_next_bday = mktime (&tm_next_bday);
- } else {
- t_next_bday = t_current_bday;
- }
- t_next_bday_in = t_next_bday - t_current_date;
- return (t_next_bday_in / 86400) + 1;
+ struct tm current_bday_tm, next_bday_tm;
+ struct tm *current_date_tm;
+ time_t current_bday, next_bday;
+
+ current_date_tm = gmtime (¤t_date);
+
+ current_bday_tm.tm_sec = 0;
+ current_bday_tm.tm_min = 0;
+ current_bday_tm.tm_hour = 0;
+ current_bday_tm.tm_mday = bdate->day;
+ current_bday_tm.tm_mon = bdate->month - 1;
+ current_bday_tm.tm_year = current_date_tm->tm_year;
+ current_bday_tm.tm_isdst = current_date_tm->tm_isdst;
+ current_bday = mktime (¤t_bday_tm);
+
+ if (current_date > current_bday) {
+ next_bday_tm.tm_sec = 0;
+ next_bday_tm.tm_min = 0;
+ next_bday_tm.tm_hour = 0;
+ next_bday_tm.tm_mday = bdate->day;
+ next_bday_tm.tm_mon = bdate->month - 1;
+ next_bday_tm.tm_year = current_date_tm->tm_year + 1;
+ next_bday_tm.tm_isdst = current_date_tm->tm_isdst;
+ next_bday = mktime (&next_bday_tm);
+ } else {
+ next_bday = current_bday;
+ }
+
+ return (next_bday - current_date) / 86400;
}
static gchar *
return gdk_color_to_string (&color);
}
+static void
+set_portrait_mode (BirthdayData *priv,
+ gboolean enable)
+{
+ g_return_if_fail (priv);
+
+ if (enable) {
+ gtk_tree_view_column_set_fixed_width (priv->display_column, 389);
+ hildon_gtk_window_set_portrait_flags (GTK_WINDOW (priv->window),
+ HILDON_PORTRAIT_MODE_REQUEST);
+ } else {
+ gtk_tree_view_column_set_fixed_width (priv->display_column, 709);
+ hildon_gtk_window_set_portrait_flags (GTK_WINDOW (priv->window),
+ ~HILDON_PORTRAIT_MODE_REQUEST);
+ }
+}
+
static GtkListStore *
-create_bday_liststore(GList *contacts)
+create_bday_liststore (BirthdayData *priv, GList *contacts)
{
GtkListStore *store;
GtkTreeIter iter;
GList *contact;
gchar *text_font = NULL;
gchar *text_color = NULL;
+ guint n_contacts = 0;
+ time_t current_date;
+ struct tm *current_date_tm;
+
+ g_return_val_if_fail (priv, NULL);
text_font = get_text_font_by_name ("SmallSystemFont");
text_color = get_text_color_by_name ("SecondaryTextColor");
+ current_date = time (NULL);
+
+ /* set hour, minute, second to 0 */
+ current_date_tm = gmtime (¤t_date);
+ current_date_tm->tm_sec = 0;
+ current_date_tm->tm_min = 0;
+ current_date_tm->tm_hour = 0;
+ current_date = mktime (current_date_tm);
+
store = gtk_list_store_new(NUM_COLS,
GDK_TYPE_PIXBUF, /* COLUMN_AVATAR */
G_TYPE_STRING, /* COLUMN_DISPLAY */
G_TYPE_STRING, /* COLUMN_FULLNAME */
- G_TYPE_INT); /* COLUMN_NEXT_BIRTHDAY */
+ G_TYPE_INT, /* COLUMN_NEXT_BIRTHDAY */
+ G_TYPE_POINTER); /* COLUMN_ABOOK_CONTACT */
for (contact = contacts; contact != NULL; contact = contact->next) {
- EContactDate *bdate;
+ EContactDate *bdate = NULL;
bdate = e_contact_get (E_CONTACT (contact->data), E_CONTACT_BIRTH_DATE);
if (bdate) {
- EContactPhoto *photo;
+ EContactPhoto *photo = NULL;
GError *error = NULL;
- GdkPixbuf *avatar;
- gchar *avatar_filename = NULL;
+ GdkPixbuf *avatar = NULL;
gchar *fullname = NULL;
guint age = 0, next_birthday = 0;
gchar *display_column = NULL;
gchar *next_birthday_text = NULL;
+ struct tm birthday_tm;
+ gchar birthday_text[11];
+ OssoABookContact *abook_contact;
-#if 0
photo = e_contact_get (E_CONTACT (contact->data), E_CONTACT_PHOTO);
if (photo) {
- avatar_filename = g_filename_from_uri (photo->data.uri, NULL, NULL);
- if (avatar_filename) {
- gint height = 0;
+ if (photo->type == E_CONTACT_PHOTO_TYPE_INLINED) {
+ GdkPixbufLoader *loader;
- avatar = gdk_pixbuf_new_from_file (avatar_filename, &error);
- height = gdk_pixbuf_get_height (avatar);
+ loader = gdk_pixbuf_loader_new ();
+ if (gdk_pixbuf_loader_write (loader, (guchar *) photo->data.inlined.data, photo->data.inlined.length, NULL))
+ avatar = gdk_pixbuf_loader_get_pixbuf (loader);
+
+ } else {
+ gchar *avatar_filename = NULL;
+
+ avatar_filename = g_filename_from_uri (photo->data.uri, NULL, NULL);
+ if (avatar_filename) {
+ avatar = gdk_pixbuf_new_from_file (avatar_filename, &error);
+ g_free (avatar_filename);
+ }
+ }
+
+ if (avatar) {
+ gint height = gdk_pixbuf_get_height (avatar);
if (height != 48) {
gint new_height = 48;
- gint new_width = (int) new_height * gdk_pixbuf_get_width (avatar) / height;
- gdk_pixbuf_scale_simple (avatar, new_width, new_height, GDK_INTERP_BILINEAR);
+ gint new_width = new_height * gdk_pixbuf_get_width (avatar) / height;
+ avatar = gdk_pixbuf_scale_simple (avatar, new_width, new_height, GDK_INTERP_BILINEAR);
}
- g_free (avatar_filename);
}
- avatar_filename = NULL;
+ e_contact_photo_free (photo);
+ photo = NULL;
} else {
avatar = gdk_pixbuf_new_from_file ("/usr/share/icons/hicolor/48x48/hildon/general_default_avatar.png", &error);
}
-#endif
- avatar = gdk_pixbuf_new_from_file ("/usr/share/icons/hicolor/48x48/hildon/general_default_avatar.png", &error);
fullname = e_contact_get (E_CONTACT (contact->data), E_CONTACT_FULL_NAME);
- age = calc_age(bdate);
- next_birthday = calc_next_bday(bdate);
- next_birthday_text = g_strdup_printf(ngettext ("next birthday in %d day", "next birthday in %d days", next_birthday), next_birthday);
- display_column = g_strdup_printf("%s <span font_desc=\"%s\" foreground=\"%s\"><sup>(%d)</sup>\n%02d.%02d.%04d, %s</span>",
- fullname, text_font, text_color, age, bdate->day, bdate->month, bdate->year, next_birthday_text);
+ if (!fullname) {
+ fullname = e_contact_get (E_CONTACT (contact->data), E_CONTACT_GIVEN_NAME);
+ if (!fullname) {
+ fullname = e_contact_get (E_CONTACT (contact->data), E_CONTACT_FAMILY_NAME);
+ if (!fullname) {
+ fullname = e_contact_get (E_CONTACT (contact->data), E_CONTACT_NICKNAME);
+ if (!fullname) {
+ fullname = e_contact_get (E_CONTACT (contact->data), E_CONTACT_ORG);
+ }
+ }
+ }
+ }
+
+ birthday_tm.tm_sec = 0;
+ birthday_tm.tm_min = 0;
+ birthday_tm.tm_hour = 0;
+ birthday_tm.tm_mday = bdate->day;
+ birthday_tm.tm_mon = bdate->month - 1;
+ birthday_tm.tm_year = bdate->year - 1900;
+ strftime (birthday_text, 11, _HL("wdgt_va_date"), &birthday_tm);
+
+ age = calc_age(bdate, current_date);
+ next_birthday = calc_next_bday(bdate, current_date);
+
+ if (next_birthday == 0)
+ next_birthday_text = g_strdup_printf (_("has birthday today"));
+ else
+ next_birthday_text = g_strdup_printf (ngettext ("will have birthday tomorrow",
+ "will have birthday in %d days", next_birthday),
+ next_birthday);
+
+ display_column = g_strdup_printf ("%s <span font_desc=\"%s\" foreground=\"%s\"><sup>(%d)</sup>\n%s, %s</span>",
+ fullname, text_font, text_color, age, birthday_text, next_birthday_text);
+
+ abook_contact = osso_abook_contact_new_from_template (E_CONTACT (contact->data));
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_DISPLAY, display_column,
COLUMN_FULLNAME, fullname,
COLUMN_NEXT_BIRTHDAY, next_birthday,
+ COLUMN_ABOOK_CONTACT, abook_contact,
-1);
+ n_contacts++;
+
+ if (display_column)
+ g_free (display_column);
+ display_column = NULL;
+
+ if (fullname)
+ g_free (fullname);
+ fullname = NULL;
if (next_birthday_text)
g_free (next_birthday_text);
if (text_color)
g_free (text_color);
+ priv->n_contacts = n_contacts;
return store;
}
-static GtkWidget *
-create_main_window(GtkListStore *store)
+static void
+create_search_bar (BirthdayData *priv)
+{
+ GtkWidget *entry, *button;
+ GtkEntryCompletion *completion;
+
+ g_return_if_fail (priv);
+
+ /* search hbox */
+ priv->search = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
+
+ /* search entry */
+ entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT);
+ hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry), HILDON_GTK_INPUT_MODE_FULL);
+ gtk_box_pack_start (GTK_BOX (priv->search), entry, TRUE, TRUE, 0);
+
+ completion = gtk_entry_completion_new ();
+ gtk_entry_completion_set_inline_completion (completion, TRUE);
+ gtk_entry_completion_set_popup_completion (completion, FALSE);
+ gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+
+ /* clear button */
+ button = GTK_WIDGET (gtk_tool_button_new (gtk_image_new_from_icon_name
+ ("general_close", (GtkIconSize) HILDON_ICON_PIXEL_SIZE_FINGER), "Clear"));
+ gtk_box_pack_end (GTK_BOX (priv->search), button, FALSE, TRUE, 0);
+
+ /* search signals */
+ g_signal_connect (entry, "changed", G_CALLBACK (on_search_entry_changed), priv);
+ g_signal_connect (button, "clicked", G_CALLBACK (on_search_close_clicked), priv);
+
+ g_object_set_data (G_OBJECT (priv->search), "entry", entry);
+}
+
+static void
+create_main_menu (BirthdayData *priv)
+{
+ HildonAppMenu *menu;
+ GtkWidget *filter, *item;
+
+ g_return_if_fail (priv);
+
+ menu = HILDON_APP_MENU (hildon_app_menu_new ());
+ hildon_window_set_app_menu (HILDON_WINDOW (priv->window), menu);
+
+ filter = hildon_gtk_radio_button_new (HILDON_SIZE_FINGER_HEIGHT , NULL);
+ gtk_button_set_label (GTK_BUTTON (filter), _("Name"));
+ gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE);
+ g_signal_connect_after (filter, "clicked", G_CALLBACK (sort_by_name_clicked), priv);
+ hildon_app_menu_add_filter (menu, GTK_BUTTON (filter));
+
+ filter = hildon_gtk_radio_button_new_from_widget (HILDON_SIZE_FINGER_HEIGHT , GTK_RADIO_BUTTON (filter));
+ gtk_button_set_label (GTK_BUTTON (filter), _("Date"));
+ gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter), TRUE);
+ g_signal_connect_after (filter, "clicked", G_CALLBACK (sort_by_date_clicked), priv);
+ hildon_app_menu_add_filter (menu, GTK_BUTTON (filter));
+
+ item = hildon_gtk_button_new (HILDON_SIZE_AUTO);
+ gtk_button_set_label (GTK_BUTTON (item), _("Search"));
+ hildon_app_menu_append (menu, GTK_BUTTON (item));
+ g_signal_connect (item, "clicked", G_CALLBACK (search_menu_clicked), priv);
+
+ if (priv->n_contacts > 0)
+ gtk_widget_show_all (GTK_WIDGET (menu));
+}
+
+static void
+create_main_window (BirthdayData *priv, GtkListStore *store)
{
HildonProgram *program = NULL;
- GtkWidget *window, *main_vbox, *alignment, *label, *pannable, *tree_view;
+ GtkWidget *main_vbox, *alignment, *pannable, *tree_view;
+ GtkTreeModel *filter;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+
+ g_return_if_fail (priv);
program = hildon_program_get_instance ();
g_set_application_name (_("Birthday"));
/* main window */
- window = hildon_stackable_window_new ();
- hildon_program_add_window (program, HILDON_WINDOW (window));
+ priv->window = hildon_stackable_window_new ();
+ hildon_program_add_window (program, HILDON_WINDOW (priv->window));
+
+ /* create main menu */
+ create_main_menu (priv);
/* aligment */
alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
HILDON_MARGIN_HALF, 0, HILDON_MARGIN_DEFAULT, HILDON_MARGIN_DEFAULT);
- gtk_container_add (GTK_CONTAINER (window), alignment);
+ gtk_container_add (GTK_CONTAINER (priv->window), alignment);
/* main vbox */
main_vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (alignment), main_vbox);
/* no_search_result label */
- label = gtk_label_new (_("No contacts with set birthdate"));
- hildon_helper_set_logical_color (label, GTK_RC_FG,
+ priv->label = gtk_label_new (_("No contacts with birthday"));
+ hildon_helper_set_logical_color (priv->label, GTK_RC_FG,
GTK_STATE_NORMAL, "SecondaryTextColor");
- hildon_helper_set_logical_font (label, "LargeSystemFont");
- gtk_box_pack_start (GTK_BOX (main_vbox), label, TRUE, TRUE, 0);
+ hildon_helper_set_logical_font (priv->label, "LargeSystemFont");
+ gtk_box_pack_start (GTK_BOX (main_vbox), priv->label, TRUE, TRUE, 0);
/* alignment for pannable area */
- alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
- 0, 0, HILDON_MARGIN_DEFAULT, HILDON_MARGIN_DEFAULT);
- gtk_box_pack_start (GTK_BOX (main_vbox), alignment, TRUE, TRUE, 0);
+ priv->view = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (priv->view),
+ 0, 0, HILDON_MARGIN_DEFAULT, 0);
+ gtk_box_pack_start (GTK_BOX (main_vbox), priv->view, TRUE, TRUE, 0);
/* pannable for tree view */
pannable = hildon_pannable_area_new ();
g_object_set (G_OBJECT (pannable), "mov-mode", HILDON_MOVEMENT_MODE_VERT, NULL);
- gtk_container_add (GTK_CONTAINER (alignment), pannable);
+ gtk_container_add (GTK_CONTAINER (priv->view), pannable);
- /* tree view */
- tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
- gtk_container_add (GTK_CONTAINER (pannable), tree_view);
+ /* sort list by next birthdays */
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
COLUMN_NEXT_BIRTHDAY, GTK_SORT_ASCENDING);
+ priv->sorted = GTK_TREE_MODEL (store);
+
+ /* filtered view */
+ filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+ birthday_filered_view_visible_func,
+ priv,
+ NULL);
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
+ priv->filter = GTK_TREE_MODEL (filter);
+
+ /* tree view */
+ priv->tree_view = hildon_gtk_tree_view_new_with_model (HILDON_UI_MODE_EDIT, filter);
+ gtk_container_add (GTK_CONTAINER (pannable), priv->tree_view);
/* display column */
column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_fixed_width (column, 696);
+ gtk_tree_view_column_set_fixed_width (column, 709);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, TRUE);
"markup", COLUMN_DISPLAY,
NULL);
g_object_set (G_OBJECT (renderer), "xpad", 10, NULL);
-
- gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), column);
+ priv->display_column = column;
/* avatar column */
column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_fixed_width (column, 64);
+ gtk_tree_view_column_set_fixed_width (column, 48);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_end (column, renderer, FALSE);
gtk_tree_view_column_set_attributes (column, renderer,
"pixbuf", COLUMN_AVATAR,
NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), column);
+
+ /* search bar */
+ create_search_bar(priv);
+ gtk_box_pack_end (GTK_BOX (main_vbox), priv->search, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (GTK_WIDGET (priv->window));
+ gtk_widget_hide (GTK_WIDGET (priv->search));
+
+ if (priv->n_contacts > 0) {
+ gtk_widget_hide (GTK_WIDGET (priv->label));
+ gtk_widget_show (GTK_WIDGET (priv->view));
+ } else {
+ gtk_widget_show (GTK_WIDGET (priv->label));
+ gtk_widget_hide (GTK_WIDGET (priv->view));
+ }
+
+ /* enable portrait mode support */
+ hildon_gtk_window_set_portrait_flags (GTK_WINDOW (priv->window),
+ HILDON_PORTRAIT_MODE_SUPPORT);
+
+ /* tree view signals */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+ gtk_tree_selection_unselect_all (selection);
+ g_signal_connect (selection, "changed", G_CALLBACK (on_selection_changed), priv);
/* window signals */
- g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ g_signal_connect (G_OBJECT (priv->window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ g_signal_connect (G_OBJECT (priv->window), "key-press-event", G_CALLBACK (on_key_press_event), priv);
+}
+
+static GList *
+get_all_contacts (EBook *ebook)
+{
+ GError *error = NULL;
+ EBookQuery *query;
+ GList *contacts;
+
+ ebook = e_book_new_system_addressbook (&error);
+ if (!ebook) {
+ g_warning ("Error opening system address book: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ if (!e_book_open (ebook, TRUE, &error)) {
+ g_warning ("Error opening system address book: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ query = e_book_query_any_field_contains ("");
- gtk_widget_show_all (GTK_WIDGET(window));
- gtk_widget_hide (GTK_WIDGET(label));
- return window;
+ if (!e_book_get_contacts (ebook, query, &contacts, &error)) {
+ g_warning ("Error getting contacts: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ return contacts;
}
int main (int argc, char **argv)
{
+ BirthdayData *data;
osso_context_t *osso_context;
EBook *ebook;
- EBookQuery *query;
- GError *error = NULL;
GtkWidget *window;
GtkListStore *store;
GList *contacts;
hildon_gtk_init (&argc, &argv);
+ /* create application data */
+ data = g_new0 (BirthdayData, 1);
+ data->searched_name = NULL;
+ data->found = TRUE;
+ data->n_contacts = 0;
+
/* initialize localization */
setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
goto exit;
}
- ebook = e_book_new_system_addressbook (&error);
- if (!ebook) {
- g_warning ("Error opening system address book: %s", error->message);
- g_error_free (error);
- goto exit;
- }
+ contacts = get_all_contacts (ebook);
+ store = create_bday_liststore (data, contacts);
- if (!e_book_open (ebook, TRUE, &error)) {
- g_warning ("Error opening system address book: %s", error->message);
- g_error_free (error);
- goto exit;
- }
+ /* create main widow */
+ create_main_window (data, store);
- query = e_book_query_any_field_contains ("");
+ /* get the system dbus connection */
+ DBusConnection *dbus_connection = osso_get_sys_dbus_connection (osso_context);
- if (!e_book_get_contacts (ebook, query, &contacts, &error)) {
- g_warning ("Error getting contacts: %s", error->message);
- g_error_free (error);
- goto exit;
- }
+ /* add the callback, which should be called, once the device is rotated */
+ dbus_bus_add_match (dbus_connection, MCE_MATCH_RULE, NULL);
+ dbus_connection_add_filter (dbus_connection, dbus_handle_mce_message, data, NULL);
- store = create_bday_liststore (contacts);
- window = create_main_window (store);
+ /* check if device is not already in portrait orientation */
+ if (is_portrait_mode (osso_context))
+ set_portrait_mode (data, TRUE);
gtk_main ();