r1992 - in trunk/src/target/OM-2007/applications/openmoko-contacts: . src

thomas at sita.openmoko.org thomas at sita.openmoko.org
Thu May 17 11:55:56 CEST 2007


Author: thomas
Date: 2007-05-17 11:55:54 +0200 (Thu, 17 May 2007)
New Revision: 1992

Modified:
   trunk/src/target/OM-2007/applications/openmoko-contacts/ChangeLog
   trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-contact-pane.c
   trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-omoko.h
Log:
Patch by: Neil J Patel <njp at o-hand.com>

* src/contacts-contact-pane.c:
* src/contacts-omoko.h:

- Uses colours from the theme instead of hard-coded values.
- Correct alignments for the GtkLabel.
- When a entry is in focus, its combobox will turn to an 'active' state.
- When a combobox is active, its entry will turn to an 'active' state.
- If you change the value of the combobox, it will automatically make
  the corresponding entry take focus (so you don't have to click twice).
- Added a h-sep between the picture/title/org and the rest of the
  fields, like in the mockups. It does need to be themed, however.
- Fixed a bug where selecting the 'mobile' field when the entry was 
  blank would crash contacts.
- Adding/removing fields works all the time now, and never removes the
  last field of its type.
- Updated the icon names for open-moko.
- When in 'view-mode', the field labels will show the corresponding icon
  for each type.


Modified: trunk/src/target/OM-2007/applications/openmoko-contacts/ChangeLog
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-contacts/ChangeLog	2007-05-17 02:22:23 UTC (rev 1991)
+++ trunk/src/target/OM-2007/applications/openmoko-contacts/ChangeLog	2007-05-17 09:55:54 UTC (rev 1992)
@@ -1,3 +1,27 @@
+2007-05-17  Thomas Wood  <thomas at openedhand.com>
+
+	Patch by: Neil J Patel <njp at o-hand.com>
+
+	* src/contacts-contact-pane.c:
+	* src/contacts-omoko.h:
+
+	- Uses colours from the theme instead of hard-coded values.
+	- Correct alignments for the GtkLabel.
+	- When a entry is in focus, its combobox will turn to an 'active' state.
+	- When a combobox is active, its entry will turn to an 'active' state.
+	- If you change the value of the combobox, it will automatically make
+	  the corresponding entry take focus (so you don't have to click twice).
+	- Added a h-sep between the picture/title/org and the rest of the
+	  fields, like in the mockups. It does need to be themed, however.
+	- Fixed a bug where selecting the 'mobile' field when the entry was 
+	  blank would crash contacts.
+	- Adding/removing fields works all the time now, and never removes the
+	  last field of its type.
+	- Updated the icon names for open-moko.
+	- When in 'view-mode', the field labels will show the corresponding icon
+	  for each type.
+
+
 2007-05-14  Thomas Wood  <thomas at openedhand.com>
 
 	Patch by: Neil J Patel <njp at o-hand.com>

Modified: trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-contact-pane.c
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-contact-pane.c	2007-05-17 02:22:23 UTC (rev 1991)
+++ trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-contact-pane.c	2007-05-17 09:55:54 UTC (rev 1992)
@@ -24,6 +24,7 @@
 #include "contacts-contact-pane.h"
 #include "contacts-utils.h"
 #include "contacts-callbacks-ebook.h"
+#include "contacts-omoko.h"
 
 G_DEFINE_TYPE (ContactsContactPane, contacts_contact_pane, GTK_TYPE_VBOX);
 
@@ -94,15 +95,16 @@
 static GQuark attr_quark = 0;
 static GQuark field_quark = 0;
 static GQuark entry_quark = 0;
+static GQuark combo_quark = 0;
 
 static FieldInfo fields[] = {
   { EVC_FN, "Name", NULL, FIELD_UNIQUE | FIELD_NOLABEL,  "<big><b>%s</b></big>", NULL },
   { EVC_ORG, "Organization", NULL, FIELD_UNIQUE | FIELD_NOLABEL, "<span size=\"small\">%s</span>", NULL },
 
-  { EVC_EMAIL, "E-Mail", "stock_mail", 0, NULL, email_types },
-  { EVC_TEL, "Telephone", "stock_telephone", 0, NULL, phone_types },
-  { EVC_BDAY, "Birthday", "stock_birthday", FIELD_UNIQUE, NULL, NULL },
-  { EVC_ADR, "Address", "stock_address", FIELD_MULTILINE, NULL, email_types },
+  { EVC_EMAIL, "E-Mail", MOKO_STOCK_CONTACT_EMAIL, 0, NULL, email_types },
+  { EVC_TEL, "Telephone", MOKO_STOCK_CONTACT_PHONE, 0, NULL, phone_types },
+  { EVC_BDAY, "Birthday", "moko-stock-contact-birthday", FIELD_UNIQUE, NULL, NULL },
+  { EVC_ADR, "Address", MOKO_STOCK_CONTACT_ADDRESS, FIELD_MULTILINE, NULL, email_types },
 
   { EVC_NOTE, "Notes", NULL, FIELD_UNIQUE | FIELD_MULTILINE, NULL, NULL },
 };
@@ -186,11 +188,10 @@
 static void
 field_set_blank (GtkEntry *entry, FieldInfo *info)
 {
-  /* TODO: use some colour from the theme */
-  GdkColor gray;
-  gdk_color_parse ("LightGray", &gray);
   gtk_entry_set_text (GTK_ENTRY (entry), info->display_name);
-  gtk_widget_modify_text (GTK_WIDGET (entry), GTK_STATE_NORMAL, &gray);
+  gtk_widget_modify_text (GTK_WIDGET (entry), 
+                          GTK_STATE_NORMAL, 
+                          &(GTK_WIDGET (entry)->style->dark[GTK_STATE_NORMAL]));
 }
 
 /*
@@ -202,7 +203,7 @@
   EVCardAttribute *attr;
   FieldInfo *info;
   const char *value;
-
+  
   attr = g_object_get_qdata (G_OBJECT (entry), attr_quark);
   g_assert (attr);
 
@@ -211,7 +212,7 @@
 
 
   value = gtk_entry_get_text (GTK_ENTRY (entry));
-
+  
   /* don't save the value if we're just displaying the field name */
   if (value && !strcmp (info->display_name, value))
     return;
@@ -235,33 +236,77 @@
   {
     g_signal_emit (pane, contacts_contact_pane_signals[FULLNAME_CHANGED], 0, pane->priv->contact);
   }
-  else if (info->vcard_field == EVC_TEL)
+  else if (info->vcard_field == EVC_TEL && (g_utf8_strlen (value, -1) > 0))
   {
     g_signal_emit (pane, contacts_contact_pane_signals[CELL_CHANGED], 0, pane->priv->contact);
   }
   pane->priv->dirty = TRUE;
 }
 
+static void
+make_entry_visible (GtkWidget *entry, gboolean visible)
+{
+  GtkWidget *parent = NULL;
+  
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+  
+  if (visible) {
+    /* Restore the frame & set the base colour to normal */
+    gtk_entry_set_has_frame (GTK_ENTRY (entry), TRUE);
+    gtk_widget_modify_base (entry, GTK_STATE_NORMAL, NULL); 
+    
+  } else {
+    /* Remove the frame & set the base colour to the background of the parent */
+    gtk_entry_set_has_frame (GTK_ENTRY (entry), FALSE);  
+  
+    parent = gtk_widget_get_parent (entry);
+    if (parent)
+      gtk_widget_modify_base (entry, 
+                            GTK_STATE_NORMAL,
+    			    &(parent->style->bg[GTK_STATE_NORMAL]));       
+  }
+}
+
+static void
+change_state_cb (GtkWidget *widget, gpointer bool)
+{
+  if (GPOINTER_TO_INT  (bool)) {
+    /* We want to 'active' the widget */
+    gtk_widget_set_state (widget, GTK_STATE_PRELIGHT);
+  } else {
+    /* We want to return its state to normal */
+    gtk_widget_set_state (widget, GTK_STATE_NORMAL);
+  }
+}
+
 /*
  * Callback for when a field entry recieves focus
  */
 static gboolean
 field_focus_in (GtkWidget *entry, GdkEventFocus *event, FieldInfo *info)
 {
+  GtkWidget *combo;
+  
   if (!strcmp (gtk_entry_get_text (GTK_ENTRY (entry)), info->display_name)) {
-    /* TODO: use some colour from the theme */
-    GdkColor gray;
-    gdk_color_parse ("Black", &gray);
-    gtk_entry_set_text (GTK_ENTRY (entry), info->display_name);
-    gtk_widget_modify_text (GTK_WIDGET (entry), GTK_STATE_NORMAL, &gray);
+    gtk_widget_modify_text (GTK_WIDGET (entry), 
+                            GTK_STATE_NORMAL, 
+                            NULL);
 
     gtk_entry_set_text (GTK_ENTRY (entry), "");
     
   }
   
+  /* Set the combo to 'active' */
+  combo = (GtkWidget*)g_object_get_qdata (G_OBJECT (entry), combo_quark);
+  if (GTK_IS_CONTAINER (combo)) {
+    gtk_container_forall (GTK_CONTAINER (combo), 
+                          (GtkCallback)change_state_cb,
+                          GINT_TO_POINTER (1));    
+    gtk_widget_queue_draw (combo);
+  }
+  
   /* Restore the frame & set the base colour to normal */
-  gtk_entry_set_has_frame (GTK_ENTRY (entry), TRUE);
-  gtk_widget_modify_base (entry, GTK_STATE_NORMAL, NULL);  
+  make_entry_visible (entry, TRUE);  
   
   return FALSE;
 }
@@ -272,20 +317,22 @@
 static gboolean
 field_focus_out (GtkWidget *entry, GdkEventFocus *event, FieldInfo *info)
 {
-  GtkWidget *parent = NULL;
+  GtkWidget *combo;
   
   if (!strcmp (gtk_entry_get_text (GTK_ENTRY (entry)), "")) {
     field_set_blank (GTK_ENTRY (entry), info);
   }
   
+  /* Set the combo to 'normal' */
+  combo = (GtkWidget*)g_object_get_qdata (G_OBJECT (entry), combo_quark);
+  if (GTK_IS_CONTAINER (combo)) {
+    gtk_container_forall (GTK_CONTAINER (combo), 
+                          (GtkCallback)change_state_cb,
+                          GINT_TO_POINTER (0));
+    gtk_widget_queue_draw (combo);
+  }
   /* Remove the frame & set the base colour to the background of the parent */
-  gtk_entry_set_has_frame (GTK_ENTRY (entry), FALSE);  
-  
-  parent = gtk_widget_get_parent (entry);
-  if (parent)
-    gtk_widget_modify_base (entry, 
-                            GTK_STATE_NORMAL,
-    			    &(parent->style->bg[GTK_STATE_NORMAL]));    
+  make_entry_visible (entry, FALSE);     
   return FALSE;
 }
 
@@ -415,7 +462,8 @@
   gchar *vcard_type = NULL;
   GtkWidget *box;
   FieldInfo *info;
-
+  gpointer entry;
+  
   /* TODO: use quarks here */
   gchar *display_type = gtk_combo_box_get_active_text (GTK_COMBO_BOX (widget));
   ContactsContactPane *pane = g_object_get_data (G_OBJECT (widget), "contact-pane");
@@ -429,6 +477,8 @@
 
   for (i = 0; &(info->types[i]); i++)
   {
+     if (!info->types[i].display)
+       continue;
      /* search the types array */
      if (!strcmp (info->types[i].display, display_type))
      {
@@ -439,6 +489,12 @@
 
   set_type (attr, vcard_type);
   pane->priv->dirty = TRUE;
+  
+  /* Finally, activate the associated entry */  
+  entry = g_object_get_data (G_OBJECT (widget), "entry");
+  if (GTK_IS_ENTRY (entry)) {
+    gtk_widget_grab_focus (GTK_WIDGET (entry));
+  }
 }
 
 static void
@@ -478,9 +534,10 @@
   GtkWidget *box, *entry;
   EVCardAttribute *attr;
   FieldInfo *info;
-  GList *attrs;
-  gboolean remove = FALSE;
-  gchar *type, *old_type;
+  GList *rows = gtk_container_get_children (GTK_CONTAINER (pane));
+  GList *r;
+  gint res = 0;
+  
 
   box = button->parent->parent;
   if (!GTK_IS_HBOX (box))
@@ -490,21 +547,18 @@
   entry = g_object_get_qdata (G_OBJECT (box), entry_quark);
   info = g_object_get_qdata (G_OBJECT (box), field_quark);
 
-  /* check this wasn't the last attribute of it's type before removing it */
-  old_type = get_type (attr);
-  if (old_type) {
-    for (attrs = e_vcard_get_attributes (E_VCARD (pane->priv->contact));
-         (attrs = g_list_next (attrs)); ) {
-      type = get_type (attrs->data);
-      if (type && !strcmp (type, old_type)) {
-        remove = TRUE;
-        break;
-      }
-
+  /* Check this isn't the last field of this type */
+  for (r = rows; r != NULL; r = r->next) {
+    GtkWidget *row = r->data;
+    FieldInfo *i = g_object_get_qdata (G_OBJECT (row), field_quark);
+    
+    if (GTK_IS_HBOX (row) && i != NULL) {
+      if (strcmp (info->vcard_field, i->vcard_field) == 0)
+        res++;
     }
   }
-
-  if (remove) {
+  
+  if (res > 1) {
     gtk_container_remove (GTK_CONTAINER (pane), box);
     e_vcard_remove_attribute (E_VCARD (pane->priv->contact), attr);
   }
@@ -516,10 +570,29 @@
 
 }
 
+static void
+combo_popup_changed_cb (GObject *gobject, GParamSpec *arg1, GtkWidget *entry)
+{
+  g_return_if_fail (GTK_IS_COMBO_BOX (gobject));
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  gboolean shown = FALSE;
+  g_object_get (gobject, "popup-shown", &shown, NULL);
+  
+  if (shown) {
+    make_entry_visible (entry, TRUE);
+  } else {
+    make_entry_visible (entry, FALSE);
+  }  
+}
+
 static GtkWidget *
 make_widget (ContactsContactPane *pane, EVCardAttribute *attr, FieldInfo *info)
 {
-  GtkWidget *box, *type_label = NULL, *value;
+#define BUTTON_WIDTH 24
+#define BUTTON_HEIGHT 21
+
+  GtkWidget *box, *type_label = NULL, *key = NULL, *value;
   gchar *attr_value = NULL, *escaped_str, *type, *s;
   gint i = 0;
 
@@ -544,14 +617,14 @@
     btn = gtk_button_new ();
     gtk_widget_set_name (btn, "addbutton");
     alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
-    gtk_widget_set_size_request (btn, 24, 21);
+    gtk_widget_set_size_request (btn, BUTTON_WIDTH, BUTTON_HEIGHT);
     gtk_container_add (GTK_CONTAINER (alignment), btn);
     gtk_box_pack_start (GTK_BOX (box), alignment, FALSE, FALSE, 0);
     g_signal_connect (G_OBJECT (btn), "clicked", G_CALLBACK (field_button_add_cb), pane);
 
     btn = gtk_button_new ();
     gtk_widget_set_name (btn, "removebutton");
-    gtk_widget_set_size_request (btn, 24, 21);
+    gtk_widget_set_size_request (btn, BUTTON_WIDTH, BUTTON_HEIGHT);
     alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
     gtk_container_add (GTK_CONTAINER (alignment), btn);
     gtk_box_pack_start (GTK_BOX (box), alignment, FALSE, FALSE, 0);
@@ -563,7 +636,8 @@
   if (!FIELD_IS_NOLABEL (info) && (!pane->priv->editable || FIELD_IS_UNIQUE(info)))
   {
     s = NULL;
-
+    GtkWidget *align;
+    
     /* Unique fields don't have different types, so just use the display name
      * for the label */
     if (FIELD_IS_UNIQUE (info))
@@ -587,13 +661,22 @@
         s = g_strdup_printf ("%s:", type);
       }
     }
+    /* Pack into an alignment with a left padding of twice the BUTTON_WIDTH size
+       so we take into account the missing buttons-width, which the comboboxes
+       will have */
+    align  = gtk_alignment_new (0.5, 0.5, 1, 1);
+    gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, BUTTON_WIDTH *2, 0);
 
-
     type_label = gtk_label_new (s);
+    key = type_label;
     gtk_widget_set_name (type_label, "fieldlabel");
+    gtk_widget_set_size_request (type_label, -1, 46);
+    gtk_misc_set_alignment (GTK_MISC (type_label), 0.0, 0.5);
+    
     if (pane->priv->size_group)
       gtk_size_group_add_widget (pane->priv->size_group, type_label);
-    gtk_box_pack_start (GTK_BOX (box), type_label, FALSE, FALSE, 4);
+    gtk_container_add (GTK_CONTAINER (align), type_label);
+    gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 4);
     g_free (s);
   }
 
@@ -603,6 +686,7 @@
     GtkWidget *combo;
     gboolean is_custom_type = TRUE;
     combo = gtk_combo_box_new_text ();
+    key = combo;
     gtk_widget_set_size_request (combo, -1, 46);
     i = 0;
 
@@ -622,9 +706,9 @@
        gtk_combo_box_append_text (GTK_COMBO_BOX (combo), type);
        gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i);
     }
-
     g_object_set_data (G_OBJECT (combo), "contact-pane", pane);
     g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (set_type_cb), attr);
+    g_object_notify (G_OBJECT (combo), "popup-shown");
     if (pane->priv->size_group)
       gtk_size_group_add_widget (pane->priv->size_group, combo);
     gtk_box_pack_start (GTK_BOX (box), combo, FALSE, FALSE, 4);
@@ -655,6 +739,8 @@
 
   if (pane->priv->editable) {
     value = gtk_entry_new ();
+    gtk_widget_set_size_request (value, -1, 34);
+    
     /* Make the entry "transparent" by setting the base colour to that of
        the parent, and removing the frame */
     gtk_entry_set_has_frame (GTK_ENTRY (value), FALSE);
@@ -666,28 +752,67 @@
       gtk_entry_set_text (GTK_ENTRY (value), attr_value);
     else
     {
-      /* this is a field that doesn't have a value yet */
-      field_set_blank (GTK_ENTRY (value), info);
+      gtk_entry_set_text (GTK_ENTRY (value), info->display_name);
+      gtk_widget_modify_text (GTK_WIDGET (value), 
+                          GTK_STATE_NORMAL, 
+                          &(GTK_WIDGET (pane)->style->dark[GTK_STATE_NORMAL]));
     }
 
     g_object_set_qdata (G_OBJECT (value), attr_quark, attr);
     g_object_set_qdata (G_OBJECT (value), field_quark, (gpointer)info);
+    if (key) {
+      g_object_set_qdata (G_OBJECT (value), combo_quark, (gpointer)key);
+      if (GTK_IS_COMBO_BOX (key)) {
+        g_signal_connect (G_OBJECT (key), "notify", 
+                          G_CALLBACK (combo_popup_changed_cb), (gpointer)value);
+        g_object_set_data (G_OBJECT (key), "entry", (gpointer)value);
+      }
+    }
     g_signal_connect (value, "changed", G_CALLBACK (field_changed), pane);
     g_signal_connect (value, "focus-in-event", G_CALLBACK (field_focus_in), info);
     g_signal_connect (value, "focus-out-event", G_CALLBACK (field_focus_out), info);
+  
   } else {
+    GtkWidget *label, *image;
+    GdkPixbuf *pixbuf = NULL;
+    gchar *icon = NULL;
+    
     if (!attr_value)
       attr_value = g_strdup ("");
     if (info->format)
     {
       escaped_str = g_markup_printf_escaped (info->format, attr_value);
-      value = gtk_label_new (NULL);
-      gtk_label_set_markup (GTK_LABEL (value), escaped_str);
+      label = gtk_label_new (NULL);
+      gtk_label_set_markup (GTK_LABEL (label), escaped_str);
       g_free (escaped_str);
     }
     else
-      value = gtk_label_new (attr_value);
-    gtk_misc_set_alignment (GTK_MISC (value), 0.0, 0.5);
+      label = gtk_label_new (attr_value);
+    
+    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+    
+    /* Load the correct pixbuf */
+    icon = info->icon;
+    if (icon)
+      pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                         icon,
+                                         24,
+                                         0, NULL);
+    if (pixbuf) {
+      value = gtk_hbox_new (FALSE, 10);
+      
+      image = gtk_image_new_from_pixbuf (pixbuf);
+      gtk_box_pack_start (GTK_BOX (value), image, FALSE, FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (value), label, TRUE, TRUE, 0);
+      
+    } else
+      value = label;
+    
+    /* We want to remove any size-requests as we are in viewmode */
+    if (key) {
+      gtk_widget_set_size_request (key, -1, 24);
+      gtk_misc_set_alignment (GTK_MISC (key), 1, 0.5);
+    }
   }
   gtk_box_pack_start (GTK_BOX (box), value, TRUE, TRUE, 4);
 
@@ -723,6 +848,7 @@
   g_assert (CONTACTS_IS_CONTACT_PANE (pane));
 
   /* First, clear the pane */
+  gtk_container_set_border_width (GTK_CONTAINER (pane), 6);
   gtk_container_foreach (GTK_CONTAINER (pane),
                          (GtkCallback)gtk_widget_destroy, NULL);
   
@@ -768,7 +894,7 @@
     gtk_table_attach_defaults (GTK_TABLE (table), w, 1, 2, 1, 2);
     has_org_field = TRUE;
   }
-
+  
   /* Add Photo */
   GtkImage *photo = contacts_load_photo (pane->priv->contact);
   if (pane->priv->editable)
@@ -788,8 +914,12 @@
     gtk_table_attach (GTK_TABLE (table), w, 0, 1, 0, 1, 0, 0, 0, 0);
 
   gtk_widget_show_all (table);
+  
+  /* The HSep between the name/org and the fields */
+  GtkWidget *sep = gtk_hseparator_new ();
+  gtk_widget_show (sep);
+  gtk_box_pack_start (GTK_BOX (pane), sep, FALSE, FALSE, 5);
 
-
   for (i = 2; i < G_N_ELEMENTS (fields); i++) {
     FieldInfo *info;
 
@@ -879,8 +1009,8 @@
   attr_quark = g_quark_from_static_string("contact-pane-attribute");
   field_quark = g_quark_from_static_string("contact-pane-fieldinfo");
   entry_quark = g_quark_from_static_string("contact-pane-entry");
+  combo_quark = g_quark_from_static_string("contact-pane-combo");
 
-
   contacts_contact_pane_signals[FULLNAME_CHANGED] = g_signal_new (("fullname-changed"),
       G_OBJECT_CLASS_TYPE (klass),
       G_SIGNAL_RUN_LAST,

Modified: trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-omoko.h
===================================================================
--- trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-omoko.h	2007-05-17 02:22:23 UTC (rev 1991)
+++ trunk/src/target/OM-2007/applications/openmoko-contacts/src/contacts-omoko.h	2007-05-17 09:55:54 UTC (rev 1992)
@@ -29,6 +29,7 @@
 #include <libmokoui/moko-tool-box.h>
 #include <libmokoui/moko-navigation-list.h>
 #include <libmokoui/moko-scrolled-pane.h>
+#include <libmokoui/moko-stock.h>
 
 
 #ifndef OMOKO_H





More information about the commitlog mailing list