[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