[Xfce4-commits] <design:master> Add spawning.

Nick Schermer noreply at xfce.org
Thu Jun 2 18:34:01 CEST 2011


Updating branch refs/heads/master
         to ffe975f45f55522520bf6050180025e81fe93449 (commit)
       from 90c7e1988188c36b6df779f0f71076054b590208 (commit)

commit ffe975f45f55522520bf6050180025e81fe93449
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Jun 2 18:31:55 2011 +0200

    Add spawning.

 .../merge-with-xfrun/demo-code/c/appfinder-model.c |  170 ++++++++--
 .../merge-with-xfrun/demo-code/c/appfinder-model.h |   18 +-
 .../demo-code/c/appfinder-window.c                 |  344 +++++++++++++++++---
 .../merge-with-xfrun/demo-code/c/main.c            |    3 +
 4 files changed, 455 insertions(+), 80 deletions(-)

diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c
index 4bdc7d9..9e6f104 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c
@@ -5,6 +5,7 @@
 #include <memory.h>
 #include <string.h>
 #include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
 #include <garcon/garcon.h>
 
 #include "appfinder-model.h"
@@ -176,6 +177,8 @@ xfce_appfinder_model_finalize (GObject *object)
   g_free (model->filter_category);
   g_free (model->filter_string);
 
+  g_message ("model cleared");
+
   (*G_OBJECT_CLASS (xfce_appfinder_model_parent_class)->finalize) (object);
 }
 
@@ -204,7 +207,6 @@ xfce_appfinder_model_get_column_type (GtkTreeModel *tree_model,
   switch (column)
     {
     case XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT:
-    case XFCE_APPFINDER_MODEL_COLUMN_KEY:
     case XFCE_APPFINDER_MODEL_COLUMN_ICON_NAME:
       return G_TYPE_STRING;
 
@@ -274,10 +276,15 @@ xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
   g_return_if_fail (iter->stamp == model->stamp);
 
   item = ITER_GET_DATA (iter);
-  g_return_if_fail (item->item == NULL || GARCON_IS_MENU_ITEM (item->item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item->item));
 
   switch (column)
     {
+    case XFCE_APPFINDER_MODEL_COLUMN_VISIBLE:
+      g_value_init (value, G_TYPE_BOOLEAN);
+      g_value_set_boolean (value, item->visible);
+      break;
+
     case XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT:
       if (item->abstract == NULL
           && item->item != NULL)
@@ -304,27 +311,11 @@ xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
       g_value_set_object (value, item->pixbuf);
       break;
 
-    case XFCE_APPFINDER_MODEL_COLUMN_KEY:
-      if (item->key == NULL
-          && item->item)
-        {
-          name = garcon_menu_item_get_name (item->item);
-          item->key = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
-        }
-
-      g_value_init (value, G_TYPE_STRING);
-      g_value_set_static_string (value, item->key);
-      break;
-
     case XFCE_APPFINDER_MODEL_COLUMN_ICON_NAME:
       g_value_init (value, G_TYPE_STRING);
       g_value_set_static_string (value, garcon_menu_item_get_icon_name (item->item));
       break;
 
-    case XFCE_APPFINDER_MODEL_COLUMN_VISIBLE:
-      g_value_init (value, G_TYPE_BOOLEAN);
-      g_value_set_boolean (value, item->visible);
-      break;
 
     default:
       g_assert_not_reached ();
@@ -533,6 +524,36 @@ xfce_appfinder_model_item_free (gpointer data)
 
 
 
+static gchar *
+xfce_appfinder_model_item_key (GarconMenuItem *item)
+{
+  const gchar *value;
+  GString     *str;
+  gchar       *normalized;
+  gchar       *casefold;
+
+  str = g_string_sized_new (128);
+
+  value = garcon_menu_item_get_name (item);
+  if (value != NULL)
+    g_string_append (str, value);
+  g_string_append_c (str, '\n');
+
+  value = garcon_menu_item_get_comment (item);
+  if (value != NULL)
+    g_string_append (str, value);
+
+  normalized = g_utf8_normalize (str->str, str->len, G_NORMALIZE_ALL);
+  casefold = g_utf8_casefold (normalized, -1);
+  g_free (normalized);
+
+  g_string_free (str, TRUE);
+
+  return casefold;
+}
+
+
+
 static gboolean
 xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
                                     GarconMenu         *menu,
@@ -542,6 +563,7 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
   GarconMenuDirectory *directory;
   ModelItem           *item;
   gboolean             has_items = FALSE;
+  gchar               *category_collated = NULL;
 
   g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE);
 
@@ -552,7 +574,11 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
         return FALSE;
 
       if (category == NULL)
-        category = garcon_menu_directory_get_name (directory);
+        {
+          category = garcon_menu_directory_get_name (directory);
+          category_collated = g_utf8_collate_key (category, -1);
+          category = category_collated;
+        }
     }
 
   /* collect all the elements in this menu and its sub menus */
@@ -567,8 +593,7 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
           item = g_slice_new0 (ModelItem);
           item->visible = TRUE;
           item->item = li->data;
-          if (category != NULL)
-            item->category = g_utf8_collate_key (category, -1);
+          item->category = g_strdup (category);
 
           model->collect_items = g_slist_prepend (model->collect_items, item);
 
@@ -582,6 +607,8 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
     }
   g_list_free (elements);
 
+  g_free (category_collated);
+
   if (directory != NULL
       && has_items)
     model->collect_categories = g_slist_prepend (model->collect_categories, directory);
@@ -651,12 +678,18 @@ xfce_appfinder_model_filter_idle (gpointer data)
       visible = TRUE;
 
       if (model->filter_category != NULL
-          && g_strcmp0 (model->filter_category, item->category) != 0)
-        visible = FALSE;
+          && (item->category == NULL
+              || strcmp (model->filter_category, item->category) != 0))
+        {
+          visible = FALSE;
+        }
+      else if (model->filter_string != NULL)
+        {
+          if (item->key == NULL)
+            item->key = xfce_appfinder_model_item_key (item->item);
 
-      /*if (visible
-          && model->filter_string != NULL)
-        visible = FALSE;*/
+          visible = strstr (item->key, model->filter_string) != NULL;
+        }
 
       if (item->visible != visible)
         {
@@ -728,16 +761,99 @@ void
 xfce_appfinder_model_filter_string (XfceAppfinderModel *model,
                                     const gchar        *seach_string)
 {
+  gchar *normalized;
+
   g_return_if_fail (XFCE_IS_APPFINDER_MODEL (model));
 
   g_free (model->filter_string);
-  model->filter_string = g_strdup (seach_string);
+
+  if (seach_string != NULL && *seach_string != '\0')
+    {
+      normalized = g_utf8_normalize (seach_string, -1, G_NORMALIZE_ALL);
+      model->filter_string = g_utf8_casefold (normalized, -1);
+      g_free (normalized);
+    }
+  else
+    {
+      model->filter_string = NULL;
+    }
 
   xfce_appfinder_model_filter (model);
 }
 
 
 
+gboolean
+xfce_appfinder_model_execute (XfceAppfinderModel  *model,
+                              GtkTreeIter         *iter,
+                              GdkScreen           *screen,
+                              GError             **error)
+{
+  const gchar     *command, *p;
+  GarconMenuItem  *item;
+  ModelItem       *mitem;
+  GString         *string;
+  gboolean         succeed = FALSE;
+  gchar          **argv;
+
+  g_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
+  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+
+  mitem = ITER_GET_DATA (iter);
+  item = mitem->item;
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
+
+  command = garcon_menu_item_get_command (item);
+  if (command == NULL || *command == '\0')
+    {
+      g_set_error_literal (error, 0, 0, _("Application has no command"));
+      return FALSE;
+    }
+
+  string = g_string_sized_new (100);
+
+  if (garcon_menu_item_requires_terminal (item))
+    g_string_append (string, "exo-open --launch TerminalEmulator ");
+
+  /* expand the field codes */
+  for (p = command; *p != '\0'; ++p)
+    {
+      if (G_UNLIKELY (p[0] == '%' && p[1] != '\0'))
+        {
+          switch (*++p)
+            {
+            case '%':
+              g_string_append_c (string, '%');
+              break;
+
+            /* skip all the other %? values for now we don't have dnd anyways */
+            }
+        }
+      else
+        {
+          g_string_append_c (string, *p);
+        }
+    }
+
+  if (g_shell_parse_argv (string->str, NULL, &argv, error))
+    {
+      succeed = xfce_spawn_on_screen (screen, garcon_menu_item_get_path (item),
+                                      argv, NULL, G_SPAWN_SEARCH_PATH,
+                                      garcon_menu_item_supports_startup_notification (item),
+                                      gtk_get_current_event_time (),
+                                      garcon_menu_item_get_icon_name (item),
+                                      error);
+
+      g_strfreev (argv);
+    }
+
+  g_string_free (string, TRUE);
+
+  return succeed;
+}
+
+
 GdkPixbuf *
 xfce_appfinder_model_load_pixbuf (const gchar *icon_name,
                                   gint         size)
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h
index 2cf37e9..b54ca13 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h
@@ -26,7 +26,6 @@ enum
 {
   XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT,
   XFCE_APPFINDER_MODEL_COLUMN_ICON,
-  XFCE_APPFINDER_MODEL_COLUMN_KEY,
   XFCE_APPFINDER_MODEL_COLUMN_ICON_NAME,
   XFCE_APPFINDER_MODEL_COLUMN_VISIBLE,
   XFCE_APPFINDER_MODEL_N_COLUMNS,
@@ -38,14 +37,19 @@ GType               xfce_appfinder_model_get_type             (void) G_GNUC_CONS
 
 XfceAppfinderModel *xfce_appfinder_model_new                  (void) G_GNUC_MALLOC;
 
-void                xfce_appfinder_model_filter_category      (XfceAppfinderModel *model,
-                                                               const gchar        *category);
+void                xfce_appfinder_model_filter_category      (XfceAppfinderModel  *model,
+                                                               const gchar         *category);
 
-void                xfce_appfinder_model_filter_string        (XfceAppfinderModel *model,
-                                                               const gchar        *seach_string);
+void                xfce_appfinder_model_filter_string        (XfceAppfinderModel  *model,
+                                                               const gchar         *seach_string);
 
-GdkPixbuf          *xfce_appfinder_model_load_pixbuf          (const gchar        *icon_name,
-                                                               gint                size) G_GNUC_MALLOC;
+gboolean            xfce_appfinder_model_execute              (XfceAppfinderModel  *model,
+                                                               GtkTreeIter         *iter,
+                                                               GdkScreen           *screen,
+                                                               GError             **error);
+
+GdkPixbuf          *xfce_appfinder_model_load_pixbuf          (const gchar         *icon_name,
+                                                               gint                 size) G_GNUC_MALLOC;
 
 G_END_DECLS
 
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c
index 397b122..f203667 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c
@@ -4,6 +4,8 @@
 
 #include <string.h>
 #include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <gdk/gdkkeysyms.h>
 
 #include "appfinder-window.h"
 #include "appfinder-model.h"
@@ -12,15 +14,29 @@
 
 
 static void       xfce_appfinder_window_finalize                 (GObject                     *object);
+static gboolean   xfce_appfinder_window_key_press_event          (GtkWidget                   *widget,
+                                                                  GdkEventKey                 *event);
+static gboolean   xfce_appfinder_window_delete_event             (GtkWidget                   *widget,
+                                                                  GdkEventAny                 *event);
 static void       xfce_appfinder_window_set_padding              (GtkWidget                   *entry,
                                                                   GtkWidget                   *align);
-static GtkWidget *xfce_appfinder_window_buttonbox                (void);
+static void       xfce_appfinder_window_entry_changed            (XfceAppfinderWindow         *window);
+static void       xfce_appfinder_window_entry_activate           (GtkEditable                 *entry,
+                                                                  XfceAppfinderWindow         *window);
+static gboolean   xfce_appfinder_window_entry_key_press_event    (GtkWidget                   *entry,
+                                                                  GdkEventKey                 *event,
+                                                                  XfceAppfinderWindow         *window);
 static void       xfce_appfinder_window_entry_icon_released      (GtkEntry                    *entry,
                                                                   GtkEntryIconPosition         icon_pos,
                                                                   GdkEvent                    *event,
                                                                   XfceAppfinderWindow         *window);
 static void       xfce_appfinder_window_category_changed         (GtkTreeSelection            *selection,
                                                                   XfceAppfinderWindow         *window);
+static void       xfce_appfinder_window_item_changed             (XfceAppfinderWindow         *window);
+static void       xfce_appfinder_window_row_activated            (XfceAppfinderWindow         *window);
+static void       xfce_appfinder_window_execute                  (XfceAppfinderWindow         *window);
+
+
 
 struct _XfceAppfinderWindowClass
 {
@@ -37,10 +53,13 @@ struct _XfceAppfinderWindow
 
   GtkWidget *paned;
   GtkWidget *entry;
-  GtkWidget *vbox;
-  GtkWidget *bbox1;
-  GtkWidget *bbox2;
   GtkWidget *image;
+  GtkWidget *treeview;
+
+  GtkWidget *bbox;
+  GtkWidget *button_launch;
+  GtkWidget *bin_collapsed;
+  GtkWidget *bin_expanded;
 };
 
 
@@ -52,10 +71,15 @@ G_DEFINE_TYPE (XfceAppfinderWindow, xfce_appfinder_window, GTK_TYPE_WINDOW)
 static void
 xfce_appfinder_window_class_init (XfceAppfinderWindowClass *klass)
 {
-  GObjectClass *gobject_class;
+  GObjectClass   *gobject_class;
+  GtkWidgetClass *gtkwidget_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = xfce_appfinder_window_finalize;
+
+  gtkwidget_class = GTK_WIDGET_CLASS (klass);
+  gtkwidget_class->key_press_event = xfce_appfinder_window_key_press_event;
+  gtkwidget_class->delete_event = xfce_appfinder_window_delete_event;
 }
 
 
@@ -76,6 +100,9 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   GtkCellRenderer    *renderer;
   GtkTreeModel       *filter_model;
   GtkTreeSelection   *selection;
+  GtkWidget          *bbox;
+  GtkWidget          *button;
+  GtkTreePath        *path;
 
   window->model = xfce_appfinder_model_new ();
   window->category_model = xfce_appfinder_category_model_new ();
@@ -86,9 +113,8 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   gtk_window_set_title (GTK_WINDOW (window), _("Application Finder"));
   gtk_window_set_default_size (GTK_WINDOW (window), 500 /* todo, remember */, -1);
   gtk_window_set_icon_name (GTK_WINDOW (window), GTK_STOCK_EXECUTE);
-  g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
 
-  window->vbox = vbox = gtk_vbox_new (FALSE, 6);
+  vbox = gtk_vbox_new (FALSE, 6);
   gtk_container_add (GTK_CONTAINER (window), vbox);
   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
   gtk_widget_show (vbox);
@@ -117,10 +143,15 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   gtk_container_add (GTK_CONTAINER (align), entry);
   g_signal_connect (G_OBJECT (entry), "icon-release", G_CALLBACK (xfce_appfinder_window_entry_icon_released), window);
   g_signal_connect (G_OBJECT (entry), "realize", G_CALLBACK (xfce_appfinder_window_set_padding), align);
+  g_signal_connect_swapped (G_OBJECT (entry), "changed", G_CALLBACK (xfce_appfinder_window_entry_changed), window);
+  g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (xfce_appfinder_window_entry_activate), window);
+  g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK (xfce_appfinder_window_entry_key_press_event), window);
+  gtk_entry_set_icon_tooltip_text (GTK_ENTRY (window->entry), GTK_ENTRY_ICON_SECONDARY, _("Toggle view mode"));
   gtk_widget_show (entry);
 
-  window->bbox1 = xfce_appfinder_window_buttonbox ();
-  gtk_box_pack_start (GTK_BOX (vbox2), window->bbox1, FALSE, TRUE, 0);
+  window->bin_collapsed = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+  gtk_box_pack_start (GTK_BOX (vbox2), window->bin_collapsed, FALSE, TRUE, 0);
+  gtk_widget_show (window->bin_collapsed);
 
   window->paned = pane = gtk_hpaned_new ();
   gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
@@ -134,12 +165,19 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
 
   sidepane = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window->category_model));
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (sidepane), FALSE);
+  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (sidepane), FALSE);
+  g_signal_connect_swapped (GTK_TREE_VIEW (sidepane), "start-interactive-search", G_CALLBACK (gtk_widget_grab_focus), entry);
   gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (sidepane),
       xfce_appfinder_category_model_row_separator_func, NULL, NULL);
   gtk_container_add (GTK_CONTAINER (scroll), sidepane);
   gtk_widget_show (sidepane);
 
+  path = gtk_tree_path_new_first ();
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (sidepane), path, NULL, FALSE);
+  gtk_tree_path_free (path);
+
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidepane));
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
   g_signal_connect (G_OBJECT (selection), "changed",
       G_CALLBACK (xfce_appfinder_window_category_changed), window);
 
@@ -160,34 +198,57 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   scroll = gtk_scrolled_window_new (NULL, NULL);
   gtk_paned_add2 (GTK_PANED (pane), scroll);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_ETCHED_IN);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
   gtk_widget_show (scroll);
 
   filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (window->model), NULL);
   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), XFCE_APPFINDER_MODEL_COLUMN_VISIBLE);
 
-  treeview = gtk_tree_view_new_with_model (filter_model);
+  window->treeview = treeview = gtk_tree_view_new_with_model (filter_model);
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), FALSE);
+  g_signal_connect_swapped (GTK_TREE_VIEW (treeview), "row-activated", G_CALLBACK (xfce_appfinder_window_row_activated), window);
+  g_signal_connect_swapped (GTK_TREE_VIEW (treeview), "start-interactive-search", G_CALLBACK (gtk_widget_grab_focus), entry);
   /* gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), XFCE_RUN_MODEL_COLUMN_TOOLTIP); */
   gtk_container_add (GTK_CONTAINER (scroll), treeview);
   gtk_widget_show (treeview);
   g_object_unref (G_OBJECT (filter_model));
 
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+  g_signal_connect_swapped (G_OBJECT (selection), "changed",
+      G_CALLBACK (xfce_appfinder_window_item_changed), window);
+
   renderer = gtk_cell_renderer_pixbuf_new ();
-  column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
-                                                     "pixbuf", XFCE_APPFINDER_MODEL_COLUMN_ICON,
-                                                     NULL);
+  column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "pixbuf", XFCE_APPFINDER_MODEL_COLUMN_ICON, NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), GTK_TREE_VIEW_COLUMN (column));
 
   renderer = gtk_cell_renderer_text_new ();
-  g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-  column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
-                                                     "markup", XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT,
-                                                     NULL);
+  column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "markup", XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT, NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), GTK_TREE_VIEW_COLUMN (column));
 
-  window->bbox2 = xfce_appfinder_window_buttonbox ();
-  gtk_box_pack_start (GTK_BOX (vbox), window->bbox2, FALSE, TRUE, 0);
+  window->bin_expanded = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+  gtk_box_pack_start (GTK_BOX (vbox), window->bin_expanded, FALSE, TRUE, 0);
+  gtk_widget_show (window->bin_expanded);
+
+  window->bbox = bbox = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
+  gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 6);
+  gtk_widget_show (bbox);
+
+  button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+  gtk_container_add (GTK_CONTAINER (bbox), button);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_widget_show (button);
+
+  window->button_launch = button = gtk_button_new_with_mnemonic ("La_unch");
+  gtk_container_add (GTK_CONTAINER (bbox), button);
+  g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (xfce_appfinder_window_execute), window);
+  gtk_widget_set_sensitive (button, FALSE);
+  gtk_widget_show (button);
+
+  image = gtk_image_new_from_stock (GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_image (GTK_BUTTON (button), image);
+  gtk_widget_show (image);
 
   g_message ("constructed window");
 }
@@ -207,6 +268,32 @@ xfce_appfinder_window_finalize (GObject *object)
 
 
 
+static gboolean
+xfce_appfinder_window_key_press_event (GtkWidget   *widget,
+                                       GdkEventKey *event)
+{
+  if (event->keyval == GDK_Escape)
+    {
+      gtk_main_quit ();
+      return TRUE;
+    }
+
+  return  (*GTK_WIDGET_CLASS (xfce_appfinder_window_parent_class)->key_press_event) (widget, event);
+}
+
+
+
+static gboolean
+xfce_appfinder_window_delete_event (GtkWidget   *widget,
+                                    GdkEventAny *event)
+{
+  /* destroy the window after the main loop */
+  gtk_main_quit ();
+  return TRUE;
+}
+
+
+
 static void
 xfce_appfinder_window_set_padding (GtkWidget *entry,
                                    GtkWidget *align)
@@ -219,32 +306,64 @@ xfce_appfinder_window_set_padding (GtkWidget *entry,
 
 
 
-static GtkWidget *
-xfce_appfinder_window_buttonbox (void)
+/* TODO idle */
+static void
+xfce_appfinder_window_entry_changed (XfceAppfinderWindow *window)
 {
+  const gchar *text;
 
-  GtkWidget *image;
-  GtkWidget *button;
-  GtkWidget *bbox;
+  text = gtk_entry_get_text (GTK_ENTRY (window->entry));
 
-  bbox = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
-  gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 6);
+  if (gtk_widget_get_visible (window->paned))
+    xfce_appfinder_model_filter_string (window->model, text);
+  else
+    gtk_widget_set_sensitive (window->button_launch, text != NULL && *text != '\0');
+}
 
-  button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
-  gtk_container_add (GTK_CONTAINER (bbox), button);
-  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (gtk_main_quit), NULL);
-  gtk_widget_show (button);
 
-  button = gtk_button_new_with_mnemonic ("La_unch");
-  gtk_container_add (GTK_CONTAINER (bbox), button);
-  gtk_widget_show (button);
 
-  image = gtk_image_new_from_stock (GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON);
-  gtk_button_set_image (GTK_BUTTON (button), image);
-  gtk_widget_show (image);
+static void
+xfce_appfinder_window_entry_activate (GtkEditable         *entry,
+                                      XfceAppfinderWindow *window)
+{
+  GtkTreePath *path;
 
-  return bbox;
+  if (gtk_widget_get_visible (window->paned))
+    {
+      if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (window->treeview), &path, NULL))
+        {
+          gtk_tree_view_set_cursor (GTK_TREE_VIEW (window->treeview), path, NULL, FALSE);
+          gtk_tree_path_free (path);
+        }
+
+      gtk_widget_grab_focus (window->treeview);
+    }
+  else if (gtk_widget_get_sensitive (window->button_launch))
+    {
+      gtk_button_clicked (GTK_BUTTON (window->button_launch));
+    }
+}
+
+
+
+static gboolean
+xfce_appfinder_window_entry_key_press_event (GtkWidget           *entry,
+                                             GdkEventKey         *event,
+                                             XfceAppfinderWindow *window)
+{
+  gboolean expand;
+
+  if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down)
+    {
+      expand = (event->keyval == GDK_KEY_Down);
+      if (gtk_widget_get_visible (window->paned) != expand)
+        {
+          xfce_appfinder_window_set_expanded (window, expand);
+          return TRUE;
+        }
+    }
+
+  return FALSE;
 }
 
 
@@ -284,6 +403,120 @@ xfce_appfinder_window_category_changed (GtkTreeSelection    *selection,
 
 
 
+static void
+xfce_appfinder_window_item_changed (XfceAppfinderWindow *window)
+{
+  GtkTreeIter       iter;
+  GtkTreeModel     *model;
+  gboolean          can_launch;
+  GtkTreeSelection *selection;
+
+  if (!gtk_widget_get_visible (window->paned))
+    return;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->treeview));
+  can_launch = gtk_tree_selection_get_selected (selection, &model, &iter);
+  gtk_widget_set_sensitive (window->button_launch, can_launch);
+  if (can_launch)
+    {
+      /* TODO? */
+    }
+}
+
+
+
+
+static void
+xfce_appfinder_window_row_activated (XfceAppfinderWindow *window)
+{
+  if (gtk_widget_get_sensitive (window->button_launch))
+    gtk_button_clicked (GTK_BUTTON (window->button_launch));
+}
+
+
+
+static void
+xfce_appfinder_window_execute (XfceAppfinderWindow *window)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel     *model;
+  GtkTreeIter       iter, orig;
+  GError           *error = NULL;
+  gboolean          result = FALSE;
+  GdkScreen        *screen;
+  const gchar      *text;
+  GdkModifierType   state;
+  gboolean          in_terminal = FALSE;
+  gchar            *cmdline, *tmp;
+  const gchar      *exo_open_prefix[] = { "file://", "http://", "https://" };
+  guint             i;
+
+  if (!gtk_widget_get_sensitive (window->button_launch))
+    return;
+
+  screen = gtk_window_get_screen (GTK_WINDOW (window));
+  if (gtk_widget_get_visible (window->paned))
+    {
+      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->treeview));
+      if (gtk_tree_selection_get_selected (selection, &model, &iter))
+        {
+          gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &orig, &iter);
+          result = xfce_appfinder_model_execute (window->model, &orig, screen, &error);
+        }
+    }
+  else
+    {
+      if (gtk_get_current_event_state (&state)
+          && (state & GDK_CONTROL_MASK) != 0)
+        in_terminal = TRUE;
+
+      text = gtk_entry_get_text (GTK_ENTRY (window->entry));
+      cmdline = xfce_expand_variables (text, NULL);
+
+      if (g_str_has_prefix (text, "#"))
+        {
+          /* open manual page in the terminal */
+          tmp = g_strconcat ("man ", cmdline + 1, NULL);
+          g_free (cmdline);
+          cmdline = tmp;
+          in_terminal = TRUE;
+        }
+
+      result = xfce_spawn_command_line_on_screen (screen, cmdline, in_terminal, FALSE, &error);
+      if (!result)
+        {
+          /* TODO instead check the exo exit code */
+          /* check if this is something exo-open can handle */
+          for (i = 0; !result && i < G_N_ELEMENTS (exo_open_prefix); i++)
+            if (g_str_has_prefix (cmdline, exo_open_prefix[i]))
+              result = TRUE;
+
+          if (result)
+            {
+              /* try to spawn again */
+              tmp = g_strconcat ("exo-open ", cmdline, NULL);
+              result = xfce_spawn_command_line_on_screen (screen, tmp, FALSE, FALSE, &error);
+              g_free (tmp);
+            }
+        }
+
+      g_free (cmdline);
+    }
+
+  gtk_entry_set_icon_from_stock (GTK_ENTRY (window->entry), GTK_ENTRY_ICON_PRIMARY,
+                                 result ? NULL : GTK_STOCK_DIALOG_ERROR);
+  gtk_entry_set_icon_tooltip_text (GTK_ENTRY (window->entry), GTK_ENTRY_ICON_PRIMARY,
+                                   error != NULL ? error->message : NULL);
+
+  if (error != NULL)
+    g_error_free (error);
+
+  if (result)
+    gtk_main_quit ();
+}
+
+
+
 GtkWidget *
 xfce_appfinder_window_new (void)
 {
@@ -296,9 +529,13 @@ void
 xfce_appfinder_window_set_expanded (XfceAppfinderWindow *window,
                                     gboolean             expanded)
 {
-  GdkGeometry hints;
-  gint        width;
+  GdkGeometry  hints;
+  gint         width;
+  GtkWidget   *parent;
 
+  g_message ("set expand = %s", expanded ? "true" : "false");
+
+  /* force window geomentry */
   if (expanded)
     {
       gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL, NULL, 0);
@@ -312,12 +549,27 @@ xfce_appfinder_window_set_expanded (XfceAppfinderWindow *window,
       gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL, &hints, GDK_HINT_MAX_SIZE);
     }
 
+  /* repack the button box */
+  g_object_ref (G_OBJECT (window->bbox));
+  parent = gtk_widget_get_parent (window->bbox);
+  if (parent != NULL)
+    gtk_container_remove (GTK_CONTAINER (parent), window->bbox);
+  if (expanded)
+    gtk_container_add (GTK_CONTAINER (window->bin_expanded), window->bbox);
+  else
+    gtk_container_add (GTK_CONTAINER (window->bin_collapsed), window->bbox);
+  gtk_widget_set_visible (window->bin_expanded, expanded);
+  gtk_widget_set_visible (window->bin_collapsed, !expanded);
+  g_object_unref (G_OBJECT (window->bbox));
+
+  /* show/hide pane with treeviews */
   gtk_widget_set_visible (window->paned, expanded);
-  gtk_widget_set_visible (window->bbox1, !expanded);
-  gtk_widget_set_visible (window->bbox2, expanded);
+
+  /* toggle icon */
   gtk_entry_set_icon_from_icon_name (GTK_ENTRY (window->entry), GTK_ENTRY_ICON_SECONDARY,
                                      expanded ? GTK_STOCK_GO_UP : GTK_STOCK_GO_DOWN);
-  gtk_entry_set_icon_tooltip_text (GTK_ENTRY (window->entry), GTK_ENTRY_ICON_SECONDARY,
-                                   expanded ? _("Collapse the icon views")
-                                            : _("Show all applications"));
+
+  /* update state */
+  xfce_appfinder_window_entry_changed (window);
+  xfce_appfinder_window_item_changed (window);
 }
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/main.c b/xfce4-appfinder/merge-with-xfrun/demo-code/c/main.c
index f847999..d7a8fa1 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/main.c
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/main.c
@@ -78,5 +78,8 @@ main (gint argc, gchar **argv)
 
   gtk_main ();
 
+  gtk_widget_hide (window);
+  gtk_widget_destroy (window);
+
   return EXIT_SUCCESS;
 }



More information about the Xfce4-commits mailing list