[hotssh] Hook GNOME Shell search provider up to tab hostnames



commit e5bcc7b38780cbc53e4a0a9ec3d67104c42ff971
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Thu Nov 14 22:15:34 2013 -0500

    Hook GNOME Shell search provider up to tab hostnames
    
    Search windows and tabs for a tab with a hostname that matches the
    search string, and switch to that tab and window when the search
    result is activated.
    
    Currently, when multiple tabs match, only one search result is shown
    and a random tab is selected; it's probably best to switch to the
    last-active tab for that hostname rather than a random one.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=712345

 Makefile-src.am                |    1 +
 src/hotssh-search-provider.c   |  148 +++++++++++++++++++++++++++++-----------
 src/hotssh-search-provider.ini |    5 ++
 src/hotssh-tab.c               |   11 +++
 src/hotssh-tab.h               |    2 +
 src/hotssh-win.c               |   25 +++++++
 src/hotssh-win.h               |    6 ++
 7 files changed, 159 insertions(+), 39 deletions(-)
---
diff --git a/Makefile-src.am b/Makefile-src.am
index a041221..98615fb 100644
--- a/Makefile-src.am
+++ b/Makefile-src.am
@@ -13,6 +13,7 @@ hotssh_dbus_h_files += hotssh-search-glue.h
 hotssh_dbus_c_files += hotssh-search-glue.c
 
 BUILT_SOURCES += $(hotssh_dbus_h_files) $(hotssh_dbus_c_files)
+CLEANFILES += hotssh-search-glue.h hotssh-search-glue.c
 
 hotssh_headers = $(addprefix src/, \
        hotssh-app.h \
diff --git a/src/hotssh-search-provider.c b/src/hotssh-search-provider.c
index 285e5a3..b7efd7f 100644
--- a/src/hotssh-search-provider.c
+++ b/src/hotssh-search-provider.c
@@ -23,6 +23,10 @@
 
 #include "hotssh-search-provider.h"
 #include "hotssh-search-glue.h"
+#include "hotssh-tab.h"
+#include "hotssh-win.h"
+
+#include "libgsystem.h"
 
 struct _HotSshSearchProvider
 {
@@ -46,28 +50,78 @@ struct _HotSshSearchProviderPrivate
 G_DEFINE_TYPE_WITH_PRIVATE(HotSshSearchProvider, hotssh_search_provider, G_TYPE_OBJECT)
 
 static char **
-get_results (HotSshSearchProvider *search_provider,
-             char                **terms)
+get_open_servers (HotSshSearchProvider *search_provider)
 {
-  char **term;
-  gboolean match = TRUE;
-
-  for (term = terms; *term; term++)
+  HotSshSearchProviderPrivate *priv = hotssh_search_provider_get_instance_private (search_provider);
+  gs_unref_hashtable GHashTable *servers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  GList *windows;
+  GList *l;
+  gchar **result;
+  GHashTableIter iter;
+  gpointer key;
+  int i;
+
+  windows = gtk_application_get_windows (GTK_APPLICATION (priv->app));
+  for (l = windows; l; l = l->next)
     {
-      if (strstr ("foo.example.com", *term) == NULL)
-        match = FALSE;
+      if (HOTSSH_IS_WINDOW (l->data))
+        {
+          HotSshWindow *window = l->data;
+          GList *tabs = hotssh_window_get_tabs (window);
+          GList *ll;
+
+          for (ll = tabs; ll; ll = ll->next)
+            {
+              HotSshTab *tab = ll->data;
+              const char *hostname = hotssh_tab_get_hostname (tab);
+              if (hostname != NULL)
+                g_hash_table_replace (servers, g_strdup (hostname), GUINT_TO_POINTER (1));
+            }
+
+          g_list_free (tabs);
+        }
     }
 
-  if (match)
+  result = g_new (char *, g_hash_table_size (servers) + 1);
+
+  i = 0;
+  g_hash_table_iter_init (&iter, servers);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
     {
-      const char * const results[] = { "foo.example.com", NULL };
-      return g_strdupv ((char **)results);
+      result[i] = g_strdup (key);
+      i++;
     }
-  else
+  result[i] = NULL;
+
+  return result;
+}
+
+static char **
+get_results (HotSshSearchProvider *search_provider,
+             char                **terms)
+{
+  gs_strfreev char **open_servers = get_open_servers (search_provider);
+  GPtrArray *matches = g_ptr_array_new ();
+  char **server;
+
+  for (server = open_servers; *server; server++)
     {
-      const char * const results[] = { NULL };
-      return g_strdupv ((char **)results);
+      char **term;
+      gboolean match = TRUE;
+
+      for (term = terms; *term; term++)
+        {
+          if (strstr (*server, *term) == NULL)
+            match = FALSE;
+        }
+
+      if (match)
+        g_ptr_array_add (matches, g_strdup (*server));
     }
+
+  g_ptr_array_add (matches, NULL);
+
+  return (char **)g_ptr_array_free (matches, FALSE);
 }
 
 static gboolean
@@ -76,9 +130,8 @@ handle_get_initial_result_set (HotSshSearchShellSearchProvider2 *skeleton,
                                char                            **terms,
                                HotSshSearchProvider             *search_provider)
 {
-  char **results = get_results (search_provider, terms);
+  gs_strfreev char **results = get_results (search_provider, terms);
   hot_ssh_search_shell_search_provider2_complete_get_initial_result_set (skeleton, invocation, (const char * 
const *)results);
-  g_strfreev (results);
 
   return TRUE;
 }
@@ -90,9 +143,8 @@ handle_get_subsearch_result_set (HotSshSearchShellSearchProvider2 *skeleton,
                                  char                            **terms,
                                  HotSshSearchProvider             *search_provider)
 {
-  char **results = get_results (search_provider, terms);
+  gs_strfreev char **results = get_results (search_provider, terms);
   hot_ssh_search_shell_search_provider2_complete_get_subsearch_result_set (skeleton, invocation, (const char 
* const *)results);
-  g_strfreev (results);
 
   return TRUE;
 }
@@ -111,30 +163,23 @@ handle_get_result_metas (HotSshSearchShellSearchProvider2 *skeleton,
   for (p = identifiers; *p; p++)
     {
       const char *id = *p;
-      if (g_strcmp0 (id, "foo.example.com") == 0)
-        {
-          GVariantBuilder *b2 = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
-          GIcon *icon;
-          GVariant *serialized_icon;
-          gchar *string_icon;
-
-          g_variant_builder_add (b2, "{sv}", "id", g_variant_new_string (id));
-          g_variant_builder_add (b2, "{sv}", "name", g_variant_new_string ("foo.example.com"));
+      GVariantBuilder *b2 = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+      gs_unref_object GIcon *icon;
+      gs_unref_variant GVariant *serialized_icon;
+      gs_free gchar *string_icon;
 
-          icon = g_themed_icon_new ("gnome-terminal");
+      g_variant_builder_add (b2, "{sv}", "id", g_variant_new_string (id));
+      g_variant_builder_add (b2, "{sv}", "name", g_variant_new_string (id));
 
-          serialized_icon = g_icon_serialize (icon);
-          g_variant_builder_add (b2, "{sv}", "icon", serialized_icon);
-          g_variant_unref (serialized_icon);
-          string_icon = g_icon_to_string (icon);
-          g_variant_builder_add (b2, "{sv}", "gicon", g_variant_new_string (string_icon));
-          g_free (string_icon);
+      icon = g_themed_icon_new ("hotssh");
 
-          g_object_unref (icon);
+      serialized_icon = g_icon_serialize (icon);
+      g_variant_builder_add (b2, "{sv}", "icon", serialized_icon);
 
-          g_variant_builder_add_value (b1, g_variant_builder_end (b2));
-        }
+      string_icon = g_icon_to_string (icon);
+      g_variant_builder_add (b2, "{sv}", "gicon", g_variant_new_string (string_icon));
 
+      g_variant_builder_add_value (b1, g_variant_builder_end (b2));
     }
 
   metas = g_variant_builder_end (b1);
@@ -151,9 +196,34 @@ handle_activate_result (HotSshSearchShellSearchProvider2 *skeleton,
                         guint                             timestamp,
                         HotSshSearchProvider             *search_provider)
 {
-  if (g_strcmp0 (identifier, "foo.example.com") == 0)
+  HotSshSearchProviderPrivate *priv = hotssh_search_provider_get_instance_private (search_provider);
+  GList *windows;
+  GList *l;
+  gboolean found = FALSE;
+
+  windows = gtk_application_get_windows (GTK_APPLICATION (priv->app));
+  for (l = windows; l && !found; l = l->next)
     {
-      g_print ("Open up the Foo server!\n");
+      if (HOTSSH_IS_WINDOW (l->data))
+        {
+          HotSshWindow *window = l->data;
+          GList *tabs = hotssh_window_get_tabs (window);
+          GList *ll;
+
+          for (ll = tabs; ll && !found; ll = ll->next)
+            {
+              HotSshTab *tab = ll->data;
+              const char *hostname = hotssh_tab_get_hostname (tab);
+              if (g_strcmp0 (hostname, identifier) == 0)
+                {
+                  hotssh_window_activate_tab (window, tab);
+                  gtk_window_present_with_time ((GtkWindow *)window, timestamp);
+                  found = TRUE;
+                }
+            }
+
+          g_list_free (tabs);
+        }
     }
 
   hot_ssh_search_shell_search_provider2_complete_activate_result (skeleton, invocation);
diff --git a/src/hotssh-search-provider.ini b/src/hotssh-search-provider.ini
new file mode 100644
index 0000000..5ad7459
--- /dev/null
+++ b/src/hotssh-search-provider.ini
@@ -0,0 +1,5 @@
+[Shell Search Provider]
+DesktopId=hotssh.desktop
+BusName=org.gnome.HotSSH
+ObjectPath=/org/gnome/hotssh/SearchProvider
+Version=2
diff --git a/src/hotssh-tab.c b/src/hotssh-tab.c
index 1fc630f..1fb0b54 100644
--- a/src/hotssh-tab.c
+++ b/src/hotssh-tab.c
@@ -79,6 +79,7 @@ struct _HotSshTabPrivate
   HotSshTabPage active_page;
   guint authmechanism_index;
 
+  char *hostname;
   GSocketConnectable *address;
   GSshConnection *connection;
   GSshChannel *channel;
@@ -119,6 +120,7 @@ state_reset_for_new_connection (HotSshTab                *self)
 {
   HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
   g_debug ("reset state");
+  g_clear_pointer (&priv->hostname, g_free);
   g_clear_object (&priv->address);
   g_clear_object (&priv->connection);
   g_clear_object (&priv->cancellable);
@@ -442,6 +444,8 @@ on_connect (GtkButton     *button,
       return;
     }
 
+  priv->hostname = g_strdup (hostname);
+
   g_clear_object (&priv->connection);
   priv->connection = gssh_connection_new (priv->address, username); 
   gssh_connection_set_interaction (priv->connection, (GTlsInteraction*)priv->password_interaction);
@@ -746,3 +750,10 @@ hotssh_tab_disconnect  (HotSshTab *self)
   page_transition (self, HOTSSH_TAB_PAGE_NEW_CONNECTION);
   gtk_notebook_set_current_page ((GtkNotebook*)self, 0);
 }
+
+const char *
+hotssh_tab_get_hostname (HotSshTab *self)
+{
+  HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
+  return priv->hostname;
+}
diff --git a/src/hotssh-tab.h b/src/hotssh-tab.h
index 4a5634c..5d31760 100644
--- a/src/hotssh-tab.h
+++ b/src/hotssh-tab.h
@@ -34,3 +34,5 @@ HotSshTab              *hotssh_tab_new          (void);
 HotSshTab              *hotssh_tab_new_channel  (HotSshTab *source);
 
 void                    hotssh_tab_disconnect  (HotSshTab *source);
+
+const char *            hotssh_tab_get_hostname (HotSshTab *self);
diff --git a/src/hotssh-win.c b/src/hotssh-win.c
index 09b6a9b..0712c9c 100644
--- a/src/hotssh-win.c
+++ b/src/hotssh-win.c
@@ -244,3 +244,28 @@ hotssh_window_new (HotSshApp *app)
 {
   return g_object_new (HOTSSH_TYPE_WINDOW, "application", app, NULL);
 }
+
+GList *
+hotssh_window_get_tabs (HotSshWindow *self)
+{
+  HotSshWindowPrivate *priv = hotssh_window_get_instance_private (self);
+  GList *tabs = NULL;
+  gint n_pages, i;
+
+  n_pages = gtk_notebook_get_n_pages ((GtkNotebook*)priv->main_notebook);
+  for (i = 0; i < n_pages; i++)
+    tabs = g_list_prepend (tabs, gtk_notebook_get_nth_page ((GtkNotebook*)priv->main_notebook, i));
+
+  return g_list_reverse (tabs);
+}
+
+void
+hotssh_window_activate_tab (HotSshWindow *self,
+                            HotSshTab    *tab)
+{
+  HotSshWindowPrivate *priv = hotssh_window_get_instance_private (self);
+  guint index;
+
+  index = find_tab_index (self, tab);
+  gtk_notebook_set_current_page ((GtkNotebook*)priv->main_notebook, index);
+}
diff --git a/src/hotssh-win.h b/src/hotssh-win.h
index 031d3eb..bf8ce45 100644
--- a/src/hotssh-win.h
+++ b/src/hotssh-win.h
@@ -21,9 +21,11 @@
 #pragma once
 
 #include "hotssh-app.h"
+#include "hotssh-tab.h"
 
 #define HOTSSH_TYPE_WINDOW (hotssh_window_get_type ())
 #define HOTSSH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HOTSSH_TYPE_WINDOW, HotSshWindow))
+#define HOTSSH_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HOTSSH_TYPE_WINDOW))
 
 typedef struct _HotSshWindow         HotSshWindow;
 typedef struct _HotSshWindowClass    HotSshWindowClass;
@@ -31,3 +33,7 @@ typedef struct _HotSshWindowClass    HotSshWindowClass;
 
 GType                   hotssh_window_get_type     (void);
 HotSshWindow       *hotssh_window_new          (HotSshApp *app);
+
+GList *hotssh_window_get_tabs     (HotSshWindow *self);
+void   hotssh_window_activate_tab (HotSshWindow *self,
+                                   HotSshTab    *tab);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]