]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-contact-chooser.c
[contact-chooser] Don't reselect the first match if something else is selected
[empathy.git] / libempathy-gtk / empathy-contact-chooser.c
index f6fa59d3b4497be2fc63d560c5016dbbc7d685b0..b16540cf3c88df1e74de18cf8630e9fb17b85fe3 100644 (file)
 G_DEFINE_TYPE (EmpathyContactChooser,
     empathy_contact_chooser, GTK_TYPE_BOX);
 
-enum
-{
-  PROP_TP_CHAT = 1
-};
-
 enum {
   SIG_SELECTION_CHANGED,
+  SIG_ACTIVATE,
   LAST_SIGNAL
 };
 
@@ -36,11 +32,11 @@ typedef struct _AddTemporaryIndividualCtx AddTemporaryIndividualCtx;
 
 struct _EmpathyContactChooserPrivate
 {
-  EmpathyTpChat *tp_chat;
   TpAccountManager *account_mgr;
 
   EmpathyIndividualStore *store;
   EmpathyIndividualView *view;
+  GtkWidget *search_entry;
 
   GPtrArray *search_words;
   gchar *search_str;
@@ -53,47 +49,6 @@ struct _EmpathyContactChooserPrivate
   gpointer filter_data;
 };
 
-static void
-contact_chooser_get_property (GObject *object,
-    guint param_id,
-    GValue *value,
-    GParamSpec *pspec)
-{
-  EmpathyContactChooser *self = (EmpathyContactChooser *)
-    object;
-
-  switch (param_id)
-    {
-    case PROP_TP_CHAT:
-      g_value_set_object (value, self->priv->tp_chat);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    };
-}
-
-static void
-contact_chooser_set_property (GObject *object,
-    guint param_id,
-    const GValue *value,
-    GParamSpec *pspec)
-{
-  EmpathyContactChooser *self = (EmpathyContactChooser *)
-    object;
-
-  switch (param_id)
-    {
-    case PROP_TP_CHAT:
-      g_assert (self->priv->tp_chat == NULL); /* construct-only */
-      self->priv->tp_chat = g_value_dup_object (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    };
-}
-
 struct _AddTemporaryIndividualCtx
 {
   EmpathyContactChooser *self;
@@ -139,7 +94,6 @@ contact_chooser_dispose (GObject *object)
   tp_clear_pointer (&self->priv->add_temp_ctx,
       add_temporary_individual_ctx_free);
 
-  tp_clear_object (&self->priv->tp_chat);
   tp_clear_object (&self->priv->store);
   tp_clear_pointer (&self->priv->search_words, g_ptr_array_unref);
   tp_clear_pointer (&self->priv->search_str, g_free);
@@ -156,27 +110,28 @@ empathy_contact_chooser_class_init (
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->get_property = contact_chooser_get_property;
-  object_class->set_property = contact_chooser_set_property;
   object_class->dispose = contact_chooser_dispose;
 
   g_type_class_add_private (object_class,
       sizeof (EmpathyContactChooserPrivate));
 
-  g_object_class_install_property (object_class,
-      PROP_TP_CHAT,
-      g_param_spec_object ("tp-chat", "EmpathyTpChat", "EmpathyTpChat",
-          EMPATHY_TYPE_TP_CHAT,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-
   signals[SIG_SELECTION_CHANGED] = g_signal_new ("selection-changed",
             G_TYPE_FROM_CLASS (klass),
             G_SIGNAL_RUN_LAST,
             0,
             NULL, NULL,
-            g_cclosure_marshal_VOID__OBJECT,
+            g_cclosure_marshal_generic,
             G_TYPE_NONE,
             1, FOLKS_TYPE_INDIVIDUAL);
+
+  signals[SIG_ACTIVATE] = g_signal_new ("activate",
+            G_TYPE_FROM_CLASS (klass),
+            G_SIGNAL_RUN_LAST,
+            0,
+            NULL, NULL,
+            g_cclosure_marshal_generic,
+            G_TYPE_NONE,
+            0);
 }
 
 static void
@@ -257,7 +212,7 @@ get_contacts_cb (TpConnection *connection,
   if (n_contacts != 1)
     return;
 
-  account = g_object_get_data (G_OBJECT (connection), "account");
+  account = tp_connection_get_account (connection);
 
   store = tpf_persona_store_new (account);
   personas = GEE_SET (
@@ -274,6 +229,12 @@ get_contacts_cb (TpConnection *connection,
 
   individual_store_add_individual_and_connect (self->priv->store, individual);
 
+  /* if nothing is selected, select the first matching node */
+  if (!gtk_tree_selection_get_selected (
+        gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->view)),
+        NULL, NULL))
+    empathy_individual_view_select_first (self->priv->view);
+
   g_clear_object (&persona_new);
   g_clear_object (&personas);
   g_object_unref (store);
@@ -308,10 +269,6 @@ add_temporary_individuals (EmpathyContactChooser *self,
       if (conn == NULL)
         continue;
 
-      /* One day we'll have tp_connection_get_account()... */
-      g_object_set_data_full (G_OBJECT (conn), "account",
-          g_object_ref (account), g_object_unref);
-
       tp_connection_get_contacts_by_id (conn, 1, &id, G_N_ELEMENTS (features),
           features, get_contacts_cb, self->priv->add_temp_ctx, NULL,
           G_OBJECT (self));
@@ -339,13 +296,82 @@ search_text_changed (GtkEntry *entry,
   empathy_individual_view_refilter (self->priv->view);
 }
 
+static void
+search_activate_cb (GtkEntry *entry,
+    EmpathyContactChooser *self)
+{
+  g_signal_emit (self, signals[SIG_ACTIVATE], 0);
+}
+
+static void
+view_activate_cb (GtkTreeView *view,
+    GtkTreePath *path,
+    GtkTreeViewColumn *column,
+    EmpathyContactChooser *self)
+{
+  g_signal_emit (self, signals[SIG_ACTIVATE], 0);
+}
+
+static gboolean
+search_key_press_cb (GtkEntry *entry,
+    GdkEventKey *event,
+    EmpathyContactChooser *self)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  if (event->state != 0)
+    return FALSE;
+
+  switch (event->keyval)
+    {
+      case GDK_KEY_Down:
+      case GDK_KEY_KP_Down:
+      case GDK_KEY_Up:
+      case GDK_KEY_KP_Up:
+        break;
+
+      default:
+        return FALSE;
+    }
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->view));
+
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return TRUE;
+
+  switch (event->keyval)
+    {
+      case GDK_KEY_Down:
+      case GDK_KEY_KP_Down:
+        if (!gtk_tree_model_iter_next (model, &iter))
+          return TRUE;
+
+        break;
+
+      case GDK_KEY_Up:
+      case GDK_KEY_KP_Up:
+        if (!gtk_tree_model_iter_previous (model, &iter))
+          return TRUE;
+
+        break;
+
+      default:
+        g_assert_not_reached ();
+    }
+
+  gtk_tree_selection_select_iter (selection, &iter);
+
+  return TRUE;
+}
+
 static void
 empathy_contact_chooser_init (EmpathyContactChooser *self)
 {
   EmpathyIndividualManager *mgr;
   GtkTreeSelection *selection;
   GtkWidget *scroll;
-  GtkWidget *search_entry;
   GQuark features[] = { TP_ACCOUNT_MANAGER_FEATURE_CORE, 0 };
 
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_CONTACT_CHOOSER,
@@ -360,12 +386,16 @@ empathy_contact_chooser_init (EmpathyContactChooser *self)
   tp_proxy_prepare_async (self->priv->account_mgr, features, NULL, NULL);
 
   /* Search entry */
-  search_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (self), search_entry, FALSE, TRUE, 6);
-  gtk_widget_show (search_entry);
+  self->priv->search_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (self), self->priv->search_entry, FALSE, TRUE, 6);
+  gtk_widget_show (self->priv->search_entry);
 
-  g_signal_connect (search_entry, "changed",
+  g_signal_connect (self->priv->search_entry, "changed",
       G_CALLBACK (search_text_changed), self);
+  g_signal_connect (self->priv->search_entry, "activate",
+      G_CALLBACK (search_activate_cb), self);
+  g_signal_connect (self->priv->search_entry, "key-press-event",
+      G_CALLBACK (search_key_press_cb), self);
 
   /* Add the treeview */
   mgr = empathy_individual_manager_dup_singleton ();
@@ -384,6 +414,8 @@ empathy_contact_chooser_init (EmpathyContactChooser *self)
 
   g_signal_connect (selection, "changed",
       G_CALLBACK (view_selection_changed_cb), self);
+  g_signal_connect (self->priv->view, "row-activated",
+      G_CALLBACK (view_activate_cb), self);
 
   scroll = gtk_scrolled_window_new (NULL, NULL);
 
@@ -395,13 +427,10 @@ empathy_contact_chooser_init (EmpathyContactChooser *self)
 }
 
 GtkWidget *
-empathy_contact_chooser_new (EmpathyTpChat *tp_chat)
+empathy_contact_chooser_new (void)
 {
-  g_return_val_if_fail (EMPATHY_IS_TP_CHAT (tp_chat), NULL);
-
   return g_object_new (EMPATHY_TYPE_CONTACT_CHOOSER,
       "orientation", GTK_ORIENTATION_VERTICAL,
-      "tp-chat", tp_chat,
       NULL);
 }
 
@@ -421,3 +450,10 @@ empathy_contact_chooser_set_filter_func (EmpathyContactChooser *self,
   self->priv->filter_func = func;
   self->priv->filter_data = user_data;
 }
+
+void
+empathy_contact_chooser_show_search_entry (EmpathyContactChooser *self,
+    gboolean show)
+{
+  gtk_widget_set_visible (self->priv->search_entry, show);
+}