]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-irc-network-chooser-dialog.c
Use double quotes for all internal headers
[empathy.git] / libempathy-gtk / empathy-irc-network-chooser-dialog.c
index 4f0b618b55010f418d91038b3be6e61cd6f1e6fd..c4c8e830f84714e72a5e574e4276f8701fedd21c 100644 (file)
 
 #include "config.h"
 
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
 #include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
 
-#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-irc-network-manager.h>
+#include "libempathy/empathy-utils.h"
+#include "libempathy/empathy-irc-network-manager.h"
 
 #include "empathy-irc-network-dialog.h"
-#include "empathy-ui-utils.h"
 #include "empathy-live-search.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC
-#include <libempathy/empathy-debug.h>
+#include "libempathy/empathy-debug.h"
 
 #include "empathy-irc-network-chooser-dialog.h"
 
@@ -47,6 +41,10 @@ enum {
     PROP_NETWORK
 };
 
+enum {
+       RESPONSE_RESET = 0
+};
+
 typedef struct {
     EmpathyAccountSettings *settings;
     EmpathyIrcNetwork *network;
@@ -58,8 +56,10 @@ typedef struct {
     GtkListStore *store;
     GtkTreeModelFilter *filter;
     GtkWidget *search;
+    GtkWidget *select_button;
 
     gulong search_sig;
+    gulong activate_sig;
 } EmpathyIrcNetworkChooserDialogPriv;
 
 enum {
@@ -126,6 +126,9 @@ dup_selected_network (EmpathyIrcNetworkChooserDialog *self,
   GtkTreeModel *model;
 
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
+  if (selection == NULL)
+    return NULL;
+
   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
     return NULL;
 
@@ -151,7 +154,7 @@ treeview_changed_cb (GtkTreeView *treeview,
   network = dup_selected_network (self, NULL);
   if (network == priv->network)
     {
-      g_object_unref (network);
+      g_clear_object (&network);
       return;
     }
 
@@ -189,6 +192,7 @@ select_iter (EmpathyIrcNetworkChooserDialog *self,
 {
   EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
   GtkTreeSelection *selection;
+  GtkTreePath *path;
 
   /* Select the network */
   selection = gtk_tree_view_get_selection (
@@ -196,6 +200,15 @@ select_iter (EmpathyIrcNetworkChooserDialog *self,
 
   gtk_tree_selection_select_iter (selection, filter_iter);
 
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter), filter_iter);
+  if (path != NULL)
+    {
+      gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->treeview), path,
+          NULL, FALSE);
+
+      gtk_tree_path_free (path);
+    }
+
   /* Scroll to the selected network */
   scroll_to_iter (self, filter_iter);
 
@@ -207,6 +220,19 @@ select_iter (EmpathyIrcNetworkChooserDialog *self,
     }
 }
 
+static GtkTreeIter
+iter_to_filter_iter (EmpathyIrcNetworkChooserDialog *self,
+    GtkTreeIter *iter)
+{
+  EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+  GtkTreeIter filter_iter;
+
+  g_assert (gtk_tree_model_filter_convert_child_iter_to_iter (priv->filter,
+        &filter_iter, iter));
+
+  return filter_iter;
+}
+
 static void
 fill_store (EmpathyIrcNetworkChooserDialog *self)
 {
@@ -228,11 +254,7 @@ fill_store (EmpathyIrcNetworkChooserDialog *self)
 
       if (network == priv->network)
         {
-          GtkTreeIter filter_iter;
-
-          /* Convert to a filter iter */
-          gtk_tree_model_filter_convert_child_iter_to_iter (priv->filter,
-              &filter_iter, &iter);
+          GtkTreeIter filter_iter = iter_to_filter_iter (self, &iter);
 
           select_iter (self, &filter_iter, FALSE);
         }
@@ -261,11 +283,10 @@ irc_network_dialog_destroy_cb (GtkWidget *widget,
   gtk_list_store_set (GTK_LIST_STORE (priv->store), &iter,
       COL_NETWORK_NAME, empathy_irc_network_get_name (network), -1);
 
-  /* Convert to a filter iter */
-  gtk_tree_model_filter_convert_child_iter_to_iter (priv->filter, &filter_iter,
-      &iter);
+  filter_iter = iter_to_filter_iter (self, &iter);
+  scroll_to_iter (self, &filter_iter);
 
-  scroll_to_iter (self, &iter);
+  gtk_widget_grab_focus (priv->treeview);
 
   g_object_unref (network);
 }
@@ -276,7 +297,7 @@ display_irc_network_dialog (EmpathyIrcNetworkChooserDialog *self,
 {
   GtkWidget *dialog;
 
-  dialog = empathy_irc_network_dialog_show (network, NULL);
+  dialog = empathy_irc_network_dialog_show (network, GTK_WIDGET (self));
 
   g_signal_connect (dialog, "destroy",
       G_CALLBACK (irc_network_dialog_destroy_cb), self);
@@ -303,6 +324,8 @@ add_network (EmpathyIrcNetworkChooserDialog *self)
   EmpathyIrcNetwork *network;
   GtkTreeIter iter, filter_iter;
 
+  gtk_widget_hide (priv->search);
+
   network = empathy_irc_network_new (_("New Network"));
   empathy_irc_network_manager_add (priv->network_manager, network);
 
@@ -311,10 +334,7 @@ add_network (EmpathyIrcNetworkChooserDialog *self)
       COL_NETWORK_NAME, empathy_irc_network_get_name (network),
       -1);
 
-  /* Convert to a filter iter */
-  gtk_tree_model_filter_convert_child_iter_to_iter (priv->filter, &filter_iter,
-      &iter);
-
+  filter_iter = iter_to_filter_iter (self, &iter);
   select_iter (self, &filter_iter, TRUE);
 
   display_irc_network_dialog (self, network);
@@ -333,29 +353,76 @@ remove_network (EmpathyIrcNetworkChooserDialog *self)
   if (network == NULL)
     return;
 
+  /* Hide the search after picking the network to get the right one */
+  gtk_widget_hide (priv->search);
+
   DEBUG ("Remove network %s", empathy_irc_network_get_name (network));
 
-  gtk_list_store_remove (priv->store, &iter);
-  empathy_irc_network_manager_remove (priv->network_manager, network);
+  /* Delete network and select next network */
+  if (gtk_list_store_remove (priv->store, &iter))
+    {
+      GtkTreeIter filter_iter = iter_to_filter_iter (self, &iter);
+
+      select_iter (self, &filter_iter, TRUE);
+    }
+  else
+    {
+      /* this should only happen if the last network was deleted */
+      GtkTreeIter last, filter_iter;
+      gint n_elements;
 
-  /* Select next network */
-  if (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter))
-    select_iter (self, &iter, TRUE);
+      n_elements = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->store),
+          NULL);
+
+      if (n_elements > 0)
+        {
+          gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (priv->store), &last,
+              NULL, (n_elements-1));
+          filter_iter = iter_to_filter_iter (self, &last);
+
+          select_iter (self, &filter_iter, TRUE);
+        }
+    }
+
+  empathy_irc_network_manager_remove (priv->network_manager, network);
+  gtk_widget_grab_focus (priv->treeview);
 
   g_object_unref (network);
 }
 
+static void
+reset_networks (EmpathyIrcNetworkChooserDialog *self)
+{
+  EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+  GSList *networks, *l;
+
+  networks = empathy_irc_network_manager_get_dropped_networks (
+      priv->network_manager);
+
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      EmpathyIrcNetwork *network;
+      GtkTreeIter iter;
+
+      network = EMPATHY_IRC_NETWORK (l->data);
+      empathy_irc_network_activate (network);
+
+      gtk_list_store_insert_with_values (priv->store, &iter, -1,
+          COL_NETWORK_OBJ, network,
+          COL_NETWORK_NAME, empathy_irc_network_get_name (network),
+          -1);
+    }
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+}
+
 static void
 dialog_response_cb (GtkDialog *dialog,
     gint response,
     EmpathyIrcNetworkChooserDialog *self)
 {
-  if (response == GTK_RESPONSE_OK)
-    add_network (self);
-  else if (response == GTK_RESPONSE_APPLY)
-    edit_network (self);
-  else if (response == GTK_RESPONSE_REJECT)
-    remove_network (self);
+  if (response == RESPONSE_RESET)
+    reset_networks (self);
 }
 
 static gboolean
@@ -376,6 +443,13 @@ filter_visible_func (GtkTreeModel *model,
   return visible;
 }
 
+static void
+search_activate_cb (GtkWidget *search,
+  EmpathyIrcNetworkChooserDialog *self)
+{
+  gtk_widget_hide (search);
+  gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CLOSE);
+}
 
 static void
 search_text_notify_cb (EmpathyLiveSearch *search,
@@ -383,17 +457,60 @@ search_text_notify_cb (EmpathyLiveSearch *search,
     EmpathyIrcNetworkChooserDialog *self)
 {
   EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+  GtkTreeIter filter_iter;
+  gboolean sensitive = FALSE;
 
   gtk_tree_model_filter_refilter (priv->filter);
+
+  /* Is there at least one network in the view ? */
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->filter),
+        &filter_iter))
+    {
+      const gchar *text;
+
+      text = empathy_live_search_get_text (EMPATHY_LIVE_SEARCH (priv->search));
+      if (!EMP_STR_EMPTY (text))
+        {
+          /* We are doing a search, select the first matching network */
+          select_iter (self, &filter_iter, TRUE);
+        }
+      else
+        {
+          /* Search has been cancelled. Scroll to the selected network */
+          GtkTreeSelection *selection;
+
+          selection = gtk_tree_view_get_selection (
+              GTK_TREE_VIEW (priv->treeview));
+
+          if (gtk_tree_selection_get_selected (selection, NULL, &filter_iter))
+            scroll_to_iter (self, &filter_iter);
+        }
+
+      sensitive = TRUE;
+    }
+
+  gtk_widget_set_sensitive (priv->select_button, sensitive);
 }
 
 static void
-dialog_destroy_cb (GtkWidget *widget,
+add_clicked_cb (GtkToolButton *button,
     EmpathyIrcNetworkChooserDialog *self)
 {
-  EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+  add_network (self);
+}
 
-  g_signal_handler_disconnect (priv->search, priv->search_sig);
+static void
+remove_clicked_cb (GtkToolButton *button,
+    EmpathyIrcNetworkChooserDialog *self)
+{
+  remove_network (self);
+}
+
+static void
+edit_clicked_cb (GtkToolButton *button,
+    EmpathyIrcNetworkChooserDialog *self)
+{
+  edit_network (self);
 }
 
 static void
@@ -406,10 +523,13 @@ empathy_irc_network_chooser_dialog_constructed (GObject *object)
   GtkWidget *vbox;
   GtkTreeViewColumn *column;
   GtkWidget *scroll;
+  GtkWidget *toolbar;
+  GtkToolItem *item;
+  GtkStyleContext *context;
 
   g_assert (priv->settings != NULL);
 
-  gtk_window_set_title (GTK_WINDOW (self), _("IRC Networks"));
+  gtk_window_set_title (GTK_WINDOW (self), _("Choose an IRC network"));
 
   /* Create store and treeview */
   priv->store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING);
@@ -442,6 +562,35 @@ empathy_irc_network_chooser_dialog_constructed (GObject *object)
   gtk_container_add (GTK_CONTAINER (scroll), priv->treeview);
   gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 6);
 
+  /* Treeview toolbar */
+  toolbar = gtk_toolbar_new ();
+  gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
+  gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
+
+  item = gtk_tool_button_new (NULL, "");
+  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), "list-add-symbolic");
+  g_signal_connect (item, "clicked", G_CALLBACK (add_clicked_cb), self);
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
+
+  item = gtk_tool_button_new (NULL, "");
+  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item),
+      "list-remove-symbolic");
+  g_signal_connect (item, "clicked", G_CALLBACK (remove_clicked_cb), self);
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
+
+  item = gtk_tool_button_new (NULL, "");
+  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item),
+      "preferences-system-symbolic");
+  g_signal_connect (item, "clicked", G_CALLBACK (edit_clicked_cb), self);
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
+
+  context = gtk_widget_get_style_context (scroll);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+
+  context = gtk_widget_get_style_context (toolbar);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+
   /* Live search */
   priv->search = empathy_live_search_new (priv->treeview);
 
@@ -458,14 +607,18 @@ empathy_irc_network_chooser_dialog_constructed (GObject *object)
   priv->search_sig = g_signal_connect (priv->search, "notify::text",
       G_CALLBACK (search_text_notify_cb), self);
 
+  priv->activate_sig = g_signal_connect (priv->search, "activate",
+      G_CALLBACK (search_activate_cb), self);
+
   /* Add buttons */
   gtk_dialog_add_buttons (dialog,
-      GTK_STOCK_ADD, GTK_RESPONSE_OK,
-      GTK_STOCK_EDIT, GTK_RESPONSE_APPLY,
-      GTK_STOCK_REMOVE, GTK_RESPONSE_REJECT,
-      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+      _("Reset _Networks List"), RESPONSE_RESET,
       NULL);
 
+  priv->select_button = gtk_dialog_add_button (dialog,
+      C_("verb displayed on a button to select an IRC network", "Select"),
+      GTK_RESPONSE_CLOSE);
+
   fill_store (self);
 
   g_signal_connect (priv->treeview, "cursor-changed",
@@ -473,11 +626,11 @@ empathy_irc_network_chooser_dialog_constructed (GObject *object)
 
   g_signal_connect (self, "response",
       G_CALLBACK (dialog_response_cb), self);
-  g_signal_connect (self, "destroy",
-      G_CALLBACK (dialog_destroy_cb), self);
 
   /* Request a side ensuring to display at least some networks */
   gtk_widget_set_size_request (GTK_WIDGET (self), -1, 300);
+
+  gtk_window_set_modal (GTK_WINDOW (self), TRUE);
 }
 
 static void
@@ -486,6 +639,26 @@ empathy_irc_network_chooser_dialog_dispose (GObject *object)
   EmpathyIrcNetworkManager *self = (EmpathyIrcNetworkManager *) object;
   EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
 
+  if (priv->search_sig != 0)
+    {
+      g_signal_handler_disconnect (priv->search, priv->search_sig);
+      priv->search_sig = 0;
+    }
+
+  if (priv->activate_sig != 0)
+    {
+      g_signal_handler_disconnect (priv->search, priv->activate_sig);
+      priv->activate_sig = 0;
+    }
+
+  if (priv->search != NULL)
+    {
+      empathy_live_search_set_hook_widget (EMPATHY_LIVE_SEARCH (priv->search),
+          NULL);
+
+      priv->search = NULL;
+    }
+
   tp_clear_object (&priv->settings);
   tp_clear_object (&priv->network);
   tp_clear_object (&priv->network_manager);
@@ -538,11 +711,13 @@ empathy_irc_network_chooser_dialog_init (EmpathyIrcNetworkChooserDialog *self)
 
 GtkWidget *
 empathy_irc_network_chooser_dialog_new (EmpathyAccountSettings *settings,
-    EmpathyIrcNetwork *network)
+    EmpathyIrcNetwork *network,
+    GtkWindow *parent)
 {
   return g_object_new (EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG,
       "settings", settings,
       "network", network,
+      "transient-for", parent,
       NULL);
 }