[Xfce4-commits] <xfce-utils:completion> Use XfrunHistory in XfrunDialog.

Jérôme Guelfucci noreply at xfce.org
Wed Nov 3 21:04:08 CET 2010


Updating branch refs/heads/completion
         to a6d41a64f02a8af8e6f5127fa56d45952e164f87 (commit)
       from 588bdc8addf79e66cb53f484982ff28ba9e959a1 (commit)

commit a6d41a64f02a8af8e6f5127fa56d45952e164f87
Author: Jérôme Guelfucci <jeromeg at xfce.org>
Date:   Sun Oct 31 23:26:11 2010 +0100

    Use XfrunHistory in XfrunDialog.
    
    Up and Down arrows are used to cycle through history. Page Up and Page
    Down are used to cycle through the results of history-based completion.

 xfrun/xfrun-dialog.c |  363 ++++++++++++++------------------------------------
 1 files changed, 98 insertions(+), 265 deletions(-)

diff --git a/xfrun/xfrun-dialog.c b/xfrun/xfrun-dialog.c
index 30af751..70ea839 100644
--- a/xfrun/xfrun-dialog.c
+++ b/xfrun/xfrun-dialog.c
@@ -40,21 +40,24 @@
 #include <libxfce4ui/libxfce4ui.h>
 
 #include "xfrun-dialog.h"
+#include "xfrun-history.h"
 
 #define BORDER       8
 #define MAX_ENTRIES 20
 
 struct _XfrunDialogPrivate
 {
-    GtkWidget *comboboxentry;
-    GtkWidget *entry;
-    GtkWidget *terminal_chk;
-    GtkTreeModel *completion_model;
+    GtkWidget    *comboboxentry;
+    GtkWidget    *entry;
+    GtkWidget    *terminal_chk;
+    GtkWidget    *run_button;
 
-    gboolean destroy_on_close;
-    gchar *working_directory;
+    XfrunHistory *history;
+    gboolean      in_history_cycle;
+    gboolean      in_history_completion;
 
-    gchar *entry_val_tmp;
+    gboolean      destroy_on_close;
+    gchar        *working_directory;
 };
 
 enum
@@ -69,12 +72,6 @@ enum
     N_SIGS,
 };
 
-enum
-{
-    XFRUN_COL_COMMAND = 0,
-    XFRUN_COL_IN_TERMINAL,
-    XFRUN_N_COLS,
-};
 
 
 static void xfrun_dialog_set_property(GObject *object,
@@ -94,21 +91,8 @@ static gboolean xfrun_dialog_delete_event(GtkWidget *widget,
 
 static gboolean xfrun_comboboxentry_changed(GtkComboBoxEntry *comboboxentry,
                                             gpointer user_data);
-static gboolean xfrun_entry_check_match(GtkTreeModel *model,
-                                        GtkTreePath *path,
-                                        GtkTreeIter *iter,
-                                        gpointer data);
-static gboolean xfrun_entry_focus_out(GtkWidget *widget,
-                                      GdkEventFocus *evt,
-                                      gpointer user_data);
 static void xfrun_run_clicked(GtkWidget *widget,
                               gpointer user_data);
-static gboolean xfrun_match_selected(GtkEntryCompletion *completion,
-                                     GtkTreeModel *model,
-                                     GtkTreeIter *iter,
-                                     gpointer user_data);
-static void xfrun_setup_entry_completion(XfrunDialog *dialog);
-static GtkTreeModel *xfrun_create_completion_model(XfrunDialog *dialog);
 
 guint __signals[N_SIGS] = { 0, };
 
@@ -151,12 +135,17 @@ static void
 xfrun_dialog_init(XfrunDialog *dialog)
 {
     GtkWidget *entry, *comboboxentry, *chk, *btn, *vbox, *bbox;
-    GtkTreeIter itr;
 
     dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE(dialog, XFRUN_TYPE_DIALOG,
                                                XfrunDialogPrivate);
-    GTK_WINDOW(dialog)->type = GTK_WINDOW_TOPLEVEL;
 
+    /* Initialize the history */
+    dialog->priv->history = xfrun_history_new();
+    dialog->priv->in_history_cycle = FALSE;
+    dialog->priv->in_history_completion = FALSE;
+
+    /* Create the UI */
+    GTK_WINDOW(dialog)->type = GTK_WINDOW_TOPLEVEL;
     gtk_widget_set_size_request(GTK_WIDGET(dialog), 400, -1);
 
     vbox = gtk_vbox_new(FALSE, BORDER/2);
@@ -167,28 +156,16 @@ xfrun_dialog_init(XfrunDialog *dialog)
     dialog->priv->comboboxentry = comboboxentry = gtk_combo_box_entry_new();
     dialog->priv->entry = entry = gtk_bin_get_child(GTK_BIN(comboboxentry));
     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
-    xfrun_setup_entry_completion(dialog);
     gtk_widget_show(comboboxentry);
     gtk_box_pack_start(GTK_BOX(vbox), comboboxentry, FALSE, FALSE, 0);
     g_signal_connect(G_OBJECT(comboboxentry), "changed",
                      G_CALLBACK(xfrun_comboboxentry_changed), dialog);
-    g_signal_connect(G_OBJECT(entry), "focus-out-event",
-                     G_CALLBACK(xfrun_entry_focus_out), dialog);
 
-    dialog->priv->terminal_chk = chk = gtk_check_button_new_with_mnemonic(_("Run in _terminal"));
+    dialog->priv->terminal_chk = chk =
+      gtk_check_button_new_with_mnemonic(_("Run in _terminal"));
     gtk_widget_show(chk);
     gtk_box_pack_start(GTK_BOX(vbox), chk, FALSE, FALSE, 0);
 
-    if(gtk_tree_model_get_iter_first(dialog->priv->completion_model, &itr)) {
-        gboolean in_terminal = FALSE;
-
-        gtk_tree_model_get (dialog->priv->completion_model, &itr,
-                            XFRUN_COL_IN_TERMINAL, &in_terminal, -1);
-
-        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(comboboxentry), &itr);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk), in_terminal);
-    }
-
     bbox = gtk_hbutton_box_new();
     gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
     gtk_box_set_spacing(GTK_BOX(bbox), BORDER);
@@ -201,8 +178,10 @@ xfrun_dialog_init(XfrunDialog *dialog)
     g_signal_connect_swapped(G_OBJECT(btn), "clicked",
                              G_CALLBACK(xfrun_dialog_delete_event), dialog);
 
-    btn = xfce_gtk_button_new_mixed(GTK_STOCK_EXECUTE, _("_Run"));
+    dialog->priv->run_button = btn =
+      xfce_gtk_button_new_mixed(GTK_STOCK_EXECUTE, _("_Run"));
     gtk_widget_show(btn);
+    gtk_widget_set_sensitive(btn, FALSE);
     gtk_box_pack_end(GTK_BOX(bbox), btn, FALSE, FALSE, 0);
     GTK_WIDGET_SET_FLAGS(btn, GTK_CAN_DEFAULT);
     gtk_widget_grab_default(btn);
@@ -256,10 +235,7 @@ xfrun_dialog_finalize(GObject *object)
     XfrunDialog *dialog = XFRUN_DIALOG(object);
 
     g_free(dialog->priv->working_directory);
-    g_free(dialog->priv->entry_val_tmp);
-
-    if(dialog->priv->completion_model)
-        g_object_unref(G_OBJECT(dialog->priv->completion_model));
+    g_object_unref(dialog->priv->history);
 
     G_OBJECT_CLASS(xfrun_dialog_parent_class)->finalize(object);
 }
@@ -268,9 +244,74 @@ static gboolean
 xfrun_dialog_key_press_event(GtkWidget *widget,
                              GdkEventKey *evt)
 {
+    XfrunDialog *dialog = XFRUN_DIALOG(widget);
+
     if(evt->keyval == GDK_Escape) {
         xfrun_dialog_delete_event(widget, NULL);
         return TRUE;
+    } else if(evt->keyval == GDK_Down) {
+        XfrunHistoryItem *item;
+
+        item = xfrun_history_get_previous(dialog->priv->history);
+
+        if(item) {
+            gtk_entry_set_text(GTK_ENTRY(dialog->priv->entry), item->command);
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (dialog->priv->terminal_chk),
+                                         item->in_terminal);
+            dialog->priv->in_history_cycle = TRUE;
+        }
+
+        return TRUE;
+    } else if(evt->keyval == GDK_Up) {
+        XfrunHistoryItem *item;
+
+        item = xfrun_history_get_next(dialog->priv->history);
+
+        if(item) {
+            gtk_entry_set_text(GTK_ENTRY(dialog->priv->entry), item->command);
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (dialog->priv->terminal_chk),
+                                         item->in_terminal);
+        }
+
+        return TRUE;
+    } else if(evt->keyval == GDK_Page_Up) {
+        XfrunHistoryItem *item;
+
+        if(dialog->priv->in_history_completion) {
+            item = xfrun_history_completion_next(dialog->priv->history);
+        } else {
+            item =
+              xfrun_history_completion_start(dialog->priv->history,
+                                             gtk_entry_get_text(GTK_ENTRY(dialog->priv->entry)));
+        }
+
+        if(item) {
+          gtk_entry_set_text(GTK_ENTRY(dialog->priv->entry), item->command);
+          gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (dialog->priv->terminal_chk),
+                                       item->in_terminal);
+          dialog->priv->in_history_completion = TRUE;
+        }
+
+        return TRUE;
+    } else if(evt->keyval == GDK_Page_Down && dialog->priv->in_history_completion) {
+        XfrunHistoryItem *item;
+
+        item = xfrun_history_completion_previous (dialog->priv->history);
+
+        if(item) {
+          gtk_entry_set_text(GTK_ENTRY(dialog->priv->entry), item->command);
+          gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (dialog->priv->terminal_chk),
+                                       item->in_terminal);
+        }
+
+        return TRUE;
+    } else if(dialog->priv->in_history_cycle
+              || dialog->priv->in_history_completion) {
+        /* If the user modifies the entry, start a new cycle and optionnaly a new completion */
+        dialog->priv->in_history_cycle = FALSE;
+        dialog->priv->in_history_completion = FALSE;
+        xfrun_history_reset (dialog->priv->history);
+        xfrun_history_completion_reset (dialog->priv->history);
     }
 
     return GTK_WIDGET_CLASS(xfrun_dialog_parent_class)->key_press_event(widget, evt);
@@ -287,8 +328,6 @@ xfrun_dialog_delete_event(GtkWidget *widget,
     if(dialog->priv->destroy_on_close)
         gtk_widget_destroy(widget);
     else {
-        /* assume we're going to use this again */
-        xfrun_setup_entry_completion(dialog);
         gtk_editable_select_region(GTK_EDITABLE(dialog->priv->entry), 0, -1);
         gtk_widget_grab_focus(dialog->priv->entry);
         gtk_widget_hide(widget);
@@ -297,176 +336,19 @@ xfrun_dialog_delete_event(GtkWidget *widget,
     return TRUE;
 }
 
-static void
-xfrun_setup_entry_completion(XfrunDialog *dialog)
-{
-    GtkComboBoxEntry *comboboxentry = GTK_COMBO_BOX_ENTRY(dialog->priv->comboboxentry);
-    GtkEntryCompletion *completion = gtk_entry_completion_new();
-    GtkTreeModel *completion_model;
-
-    /* clear out the old completion and resources, if any */
-    gtk_entry_set_completion(GTK_ENTRY(dialog->priv->entry), NULL);
-    gtk_combo_box_set_model(GTK_COMBO_BOX(comboboxentry), NULL);
-    if(dialog->priv->completion_model)
-        g_object_unref(dialog->priv->completion_model);
-
-    dialog->priv->completion_model = completion_model = xfrun_create_completion_model(dialog);
-    gtk_combo_box_set_model(GTK_COMBO_BOX(comboboxentry), completion_model);
-    gtk_combo_box_entry_set_text_column(comboboxentry, XFRUN_COL_COMMAND);
-
-    gtk_entry_completion_set_model(completion, completion_model);
-    gtk_entry_completion_set_text_column(completion, XFRUN_COL_COMMAND);
-    gtk_entry_completion_set_popup_completion(completion, TRUE);
-    gtk_entry_completion_set_inline_completion(completion, TRUE);
-    g_signal_connect(G_OBJECT(completion), "match-selected",
-                     G_CALLBACK(xfrun_match_selected), dialog);
-
-    gtk_entry_set_completion(GTK_ENTRY(dialog->priv->entry), completion);
-    g_object_unref(G_OBJECT(completion));
-}
-
-static gchar **
-xfrun_get_histfile_content(void)
-{
-    gchar **lines = NULL, *histfile, *contents = NULL;
-    gsize length = 0;
-
-    histfile = xfce_resource_lookup(XFCE_RESOURCE_CACHE, "xfce4/xfrun4/history");
-    if(histfile && g_file_get_contents(histfile, &contents, &length, NULL)) {
-        lines = g_strsplit(contents, "\n", -1);
-        g_free(contents);
-    }
-
-    g_free(histfile);
-
-    return lines;
-}
-
 static gboolean
 xfrun_comboboxentry_changed(GtkComboBoxEntry *comboboxentry,
                             gpointer user_data)
 {
     XfrunDialog *dialog = XFRUN_DIALOG(user_data);
-    GtkTreeModel *model;
-    GtkTreeIter iter;
-    gboolean in_terminal = FALSE;
-
-    if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(comboboxentry), &iter)) {
-        model = gtk_combo_box_get_model(GTK_COMBO_BOX(comboboxentry));
-        gtk_tree_model_get(model, &iter,
-                           XFRUN_COL_IN_TERMINAL, &in_terminal,
-                           -1);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->priv->terminal_chk),
-                                     in_terminal);
-    }
-
-    return FALSE;
-}
-
-static gboolean
-xfrun_entry_check_match(GtkTreeModel *model,
-                        GtkTreePath *path,
-                        GtkTreeIter *iter,
-                        gpointer data)
-{
-    XfrunDialog *dialog = XFRUN_DIALOG(data);
-    gchar *command = NULL;
-    gboolean in_terminal = FALSE, ret = FALSE;
-
-    gtk_tree_model_get(model, iter,
-                       XFRUN_COL_COMMAND, &command,
-                       XFRUN_COL_IN_TERMINAL, &in_terminal,
-                       -1);
-
-    if(!g_utf8_collate(command, dialog->priv->entry_val_tmp)) {
-        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(dialog->priv->comboboxentry),
-                                      iter);
-        ret = TRUE;
-    }
-
-    g_free(command);
-
-    return ret;
-}
-
-static gboolean
-xfrun_entry_focus_out(GtkWidget *widget,
-                      GdkEventFocus *evt,
-                      gpointer user_data)
-{
-    XfrunDialog *dialog = XFRUN_DIALOG(user_data);
 
-    if(gtk_combo_box_get_active(GTK_COMBO_BOX(dialog->priv->comboboxentry)) < 0) {
-        dialog->priv->entry_val_tmp = gtk_editable_get_chars(GTK_EDITABLE(widget),
-                                                             0, -1);
-        gtk_tree_model_foreach(dialog->priv->completion_model,
-                               xfrun_entry_check_match, dialog);
-        g_free(dialog->priv->entry_val_tmp);
-        dialog->priv->entry_val_tmp = NULL;
-    }
+    gtk_widget_set_sensitive (dialog->priv->run_button,
+      g_strcmp0(gtk_entry_get_text(GTK_ENTRY(dialog->priv->entry)), "") != 0);
 
     return FALSE;
 }
 
 static void
-xfrun_add_to_history(const gchar *command,
-                     gboolean in_terminal)
-{
-    gchar *histfile, *histfile1, **lines = xfrun_get_histfile_content();
-    gint i;
-    FILE *fp = NULL;
-    GList *new_lines = NULL, *l;
-
-    histfile = xfce_resource_save_location(XFCE_RESOURCE_CACHE,
-                                    "xfce4/xfrun4/history.new", TRUE);
-    if(!histfile) {
-        g_critical("Unable to write to history file.");
-        return;
-    }
-
-    if(!lines) {
-        fp = fopen(histfile, "w");
-        if(fp) {
-            fprintf(fp, "%d:%s\n", in_terminal ? 1 : 0, command);
-            fclose(fp);
-        }
-    } else {
-        gchar *new_line;
-
-        for(i = 0; lines[i]; ++i) {
-            if(strlen(lines[i]) < 3 || lines[i][1] != ':')
-                continue;
-
-            if(g_utf8_collate(lines[i] + 2, command))
-                new_lines = g_list_append(new_lines, lines[i]);
-        }
-
-        new_line = g_strdup_printf("%d:%s", in_terminal ? 1 : 0, command);
-        new_lines = g_list_prepend(new_lines, new_line);
-
-        fp = fopen(histfile, "w");
-        if(fp) {
-            for(l = new_lines, i = 0; l && i < MAX_ENTRIES; l = l->next, ++i)
-                fprintf(fp, "%s\n", (char *)l->data);
-            fclose(fp);
-        }
-
-        g_free(new_line);
-    }
-
-    histfile1 = g_strdup(histfile);
-    histfile1[strlen(histfile1)-4] = 0;
-
-    if(rename(histfile, histfile1))
-        g_critical("Unable to rename '%s' to '%s'", histfile, histfile1);
-    unlink(histfile);
-
-    g_free(histfile1);
-    g_free(histfile);
-    g_strfreev(lines);
-}
-
-static void
 xfrun_spawn_child_setup(gpointer data)
 {
 #if !defined(G_OS_WIN32) && defined(HAVE_SETSID)
@@ -490,6 +372,10 @@ xfrun_run_clicked(GtkWidget *widget,
     gint          argc;
 
     cmdline = gtk_editable_get_chars(GTK_EDITABLE(dialog->priv->entry), 0, -1);
+
+    if(g_strcmp0(cmdline, "") == 0)
+      return;
+
     original_cmdline = g_strdup(cmdline);
     in_terminal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->priv->terminal_chk));
 
@@ -530,7 +416,8 @@ xfrun_run_clicked(GtkWidget *widget,
 
     if(result)
     {
-        xfrun_add_to_history(original_cmdline, in_terminal);
+        xfrun_history_add(dialog->priv->history,
+                          original_cmdline, in_terminal);
         xfrun_dialog_delete_event(GTK_WIDGET(dialog), NULL);
     } else {
         gchar    *primary;
@@ -555,7 +442,8 @@ xfrun_run_clicked(GtkWidget *widget,
                                        xfrun_spawn_child_setup, NULL, NULL,
                                        NULL)) {
                     exo_opened = TRUE;
-                    xfrun_add_to_history(original_cmdline, in_terminal);
+                    xfrun_history_add(dialog->priv->history,
+                                      original_cmdline, in_terminal);
                     xfrun_dialog_delete_event(GTK_WIDGET(dialog), NULL);
                     g_error_free(error);
                 }
@@ -596,61 +484,6 @@ xfrun_run_clicked(GtkWidget *widget,
         g_strfreev(argv);
 }
 
-static gboolean
-xfrun_match_selected(GtkEntryCompletion *completion,
-                     GtkTreeModel *model,
-                     GtkTreeIter *iter,
-                     gpointer user_data)
-{
-    XfrunDialog *dialog = XFRUN_DIALOG(user_data);
-    gboolean in_terminal = FALSE;
-
-    gtk_tree_model_get(model, iter,
-                       XFRUN_COL_IN_TERMINAL, &in_terminal,
-                       -1);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->priv->terminal_chk),
-                                 in_terminal);
-
-    return FALSE;
-}
-
-static GtkTreeModel *
-xfrun_create_completion_model(XfrunDialog *dialog)
-{
-    GtkListStore *ls;
-    gchar **lines = NULL;
-    gchar *histfile = NULL;
-
-    ls = gtk_list_store_new(XFRUN_N_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN);
-
-    lines = xfrun_get_histfile_content();
-    if(lines) {
-        GtkTreeIter itr;
-        gint i;
-
-        for(i = 0; lines[i]; ++i) {
-            if(strlen(lines[i]) < 3 || lines[i][1] != ':')
-                continue;
-
-            gtk_list_store_append(ls, &itr);
-            gtk_list_store_set(ls, &itr,
-                               XFRUN_COL_COMMAND, lines[i] + 2,
-                               XFRUN_COL_IN_TERMINAL,
-                               lines[i][0] == '1' ? TRUE : FALSE,
-                               -1);
-        }
-
-        g_strfreev(lines);
-    }
-
-    g_free(histfile);
-
-    return GTK_TREE_MODEL(ls);
-}
-
-
-
-
 GtkWidget *
 xfrun_dialog_new(void)
 {



More information about the Xfce4-commits mailing list