From 4f086da18ecdc8aeb762508801f21ca19fcd9fdf Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Mon, 15 May 2000 10:47:02 +0000 Subject: [PATCH] r278: Changed the type-setting system. Now you open a new type of minibuffer and enter a shell command. Doesn't support dragging yet. Minibuffers are now labelled. --- ROX-Filer/src/filer.c | 14 +++++-- ROX-Filer/src/filer.h | 4 +- ROX-Filer/src/menu.c | 37 ++++------------- ROX-Filer/src/minibuffer.c | 101 +++++++++++++++++++++++++++++++++++++++++---- ROX-Filer/src/minibuffer.h | 4 +- ROX-Filer/src/type.c | 56 +++++++++++++++++++++++++ ROX-Filer/src/type.h | 1 + 7 files changed, 174 insertions(+), 43 deletions(-) diff --git a/ROX-Filer/src/filer.c b/ROX-Filer/src/filer.c index c42c8879..ac81318d 100644 --- a/ROX-Filer/src/filer.c +++ b/ROX-Filer/src/filer.c @@ -1079,6 +1079,12 @@ void filer_openitem(FilerWindow *filer_window, int item_number, OpenFlags flags) minibuffer_add(filer_window, item->leafname); return; } + else if (filer_window->mini_type == MINI_RUN_ACTION) + { + collection_set_cursor_item(filer_window->collection, + item_number); + return; + } full_path = make_path(filer_window->path, item->leafname)->str; @@ -1529,6 +1535,8 @@ FilerWindow *filer_opendir(char *path, PanelType panel_type) filer_window = g_new(FilerWindow, 1); filer_window->minibuffer = NULL; + filer_window->minibuffer_label = NULL; + filer_window->minibuffer_area = NULL; filer_window->path = real_path; filer_window->scanning = FALSE; filer_window->had_cursor = FALSE; @@ -1669,9 +1677,9 @@ FilerWindow *filer_opendir(char *path, PanelType panel_type) gtk_box_pack_start(GTK_BOX(vbox), collection, TRUE, TRUE, 0); - filer_window->minibuffer = create_minibuffer(filer_window); - gtk_box_pack_start(GTK_BOX(vbox), filer_window->minibuffer, - FALSE, TRUE, 0); + create_minibuffer(filer_window); + gtk_box_pack_start(GTK_BOX(vbox), filer_window->minibuffer_area, + FALSE, TRUE, 0); scrollbar = gtk_vscrollbar_new(COLLECTION(collection)->vadj); gtk_box_pack_start(GTK_BOX(hbox), scrollbar, FALSE, TRUE, 0); diff --git a/ROX-Filer/src/filer.h b/ROX-Filer/src/filer.h index 08d62662..1ca77804 100644 --- a/ROX-Filer/src/filer.h +++ b/ROX-Filer/src/filer.h @@ -55,7 +55,9 @@ struct _FilerWindow gboolean had_cursor; /* (before changing directory) */ char *auto_select; /* If it we find while scanning */ - GtkWidget *minibuffer; + GtkWidget *minibuffer_area; /* The hbox to show/hide */ + GtkWidget *minibuffer_label; /* The operation name */ + GtkWidget *minibuffer; /* The text entry */ int mini_cursor_base; MiniType mini_type; }; diff --git a/ROX-Filer/src/menu.c b/ROX-Filer/src/menu.c index c59f6a3e..2a3fca11 100644 --- a/ROX-Filer/src/menu.c +++ b/ROX-Filer/src/menu.c @@ -90,7 +90,6 @@ static void refresh(gpointer data, guint action, GtkWidget *widget); static void copy_item(gpointer data, guint action, GtkWidget *widget); static void rename_item(gpointer data, guint action, GtkWidget *widget); static void link_item(gpointer data, guint action, GtkWidget *widget); -static void run_action(gpointer data, guint action, GtkWidget *widget); static void open_file(gpointer data, guint action, GtkWidget *widget); static void help(gpointer data, guint action, GtkWidget *widget); static void show_file_info(gpointer data, guint action, GtkWidget *widget); @@ -117,6 +116,7 @@ static void new_window(gpointer data, guint action, GtkWidget *widget); static void close_window(gpointer data, guint action, GtkWidget *widget); static void enter_path(gpointer data, guint action, GtkWidget *widget); static void shell_command(gpointer data, guint action, GtkWidget *widget); +static void run_action(gpointer data, guint action, GtkWidget *widget); static void rox_help(gpointer data, guint action, GtkWidget *widget); static void open_as_dir(gpointer data, guint action, GtkWidget *widget); @@ -173,7 +173,6 @@ static GtkItemFactoryEntry filer_menu_def[] = { {">" N_("Copy..."), NULL, copy_item, 0, NULL}, {">" N_("Rename..."), NULL, rename_item, 0, NULL}, {">" N_("Link..."), NULL, link_item, 0, NULL}, -{">" N_("Run Action..."), NULL, run_action, 0, NULL}, {">" N_("Shift Open"), NULL, open_file, 0, NULL}, {">" N_("Help"), NULL, help, 0, NULL}, {">" N_("Info"), NULL, show_file_info, 0, NULL}, @@ -199,6 +198,7 @@ static GtkItemFactoryEntry filer_menu_def[] = { {">" N_("Close Window"), NULL, close_window, 0, NULL}, {">" N_("Enter Path"), NULL, enter_path, 0, NULL}, {">" N_("Shell Command"), NULL, shell_command, 0, NULL}, +{">" N_("Set Run Action"), NULL, run_action, 0, NULL}, {">", NULL, NULL, 0, ""}, {">" N_("Show ROX-Filer help"), NULL, rox_help, 0, NULL}, }; @@ -867,32 +867,6 @@ static void link_item(gpointer data, guint action, GtkWidget *widget) SHOW_SAVEBOX(_("Symlink"), link_cb); } -static void run_action(gpointer data, guint action, GtkWidget *widget) -{ - Collection *collection; - - g_return_if_fail(window_with_focus != NULL); - - collection = window_with_focus->collection; - if (collection->number_selected > 1) - { - report_error(PROJECT, _("You cannot do this to more than " - "one item at a time")); - return; - } - else if (collection->number_selected != 1) - collection_target(collection, target_callback, run_action); - else - { - DirItem *item; - - item = selected_item(collection); - g_return_if_fail(item->mime_type != NULL); - - show_set_run_action(item->mime_type); - } -} - static void open_file(gpointer data, guint action, GtkWidget *widget) { Collection *collection; @@ -1411,6 +1385,13 @@ static void shell_command(gpointer data, guint action, GtkWidget *widget) minibuffer_show(window_with_focus, MINI_SHELL); } +static void run_action(gpointer data, guint action, GtkWidget *widget) +{ + g_return_if_fail(window_with_focus != NULL); + + minibuffer_show(window_with_focus, MINI_RUN_ACTION); +} + static void rox_help(gpointer data, guint action, GtkWidget *widget) { g_return_if_fail(window_with_focus != NULL); diff --git a/ROX-Filer/src/minibuffer.c b/ROX-Filer/src/minibuffer.c index d9d70f9e..db17603a 100644 --- a/ROX-Filer/src/minibuffer.c +++ b/ROX-Filer/src/minibuffer.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -56,18 +57,28 @@ static guchar *mini_contents(FilerWindow *filer_window); ****************************************************************/ -GtkWidget *create_minibuffer(FilerWindow *filer_window) +/* Creates the minibuffer widgets, setting the appropriate fields + * in filer_window. + */ +void create_minibuffer(FilerWindow *filer_window) { - GtkWidget *mini; + GtkWidget *hbox, *label, *mini; + + hbox = gtk_hbox_new(FALSE, 0); + label = gtk_label_new(NULL); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2); mini = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), mini, TRUE, TRUE, 0); gtk_widget_set_style(mini, fixed_style); gtk_signal_connect(GTK_OBJECT(mini), "key_press_event", GTK_SIGNAL_FUNC(key_press_event), filer_window); gtk_signal_connect(GTK_OBJECT(mini), "changed", GTK_SIGNAL_FUNC(changed), filer_window); - return mini; + filer_window->minibuffer = mini; + filer_window->minibuffer_label = label; + filer_window->minibuffer_area = hbox; } void minibuffer_show(FilerWindow *filer_window, MiniType mini_type) @@ -81,6 +92,11 @@ void minibuffer_show(FilerWindow *filer_window, MiniType mini_type) mini = GTK_ENTRY(filer_window->minibuffer); filer_window->mini_type = MINI_NONE; + gtk_label_set_text(GTK_LABEL(filer_window->minibuffer_label), + mini_type == MINI_PATH ? "Goto:" : + mini_type == MINI_SHELL ? "Shell:" : + mini_type == MINI_RUN_ACTION ? "Run Action:" : + "?"); switch (mini_type) { @@ -92,6 +108,7 @@ void minibuffer_show(FilerWindow *filer_window, MiniType mini_type) make_path(filer_window->path, "")->str); break; case MINI_SHELL: + case MINI_RUN_ACTION: filer_window->mini_cursor_base = -1; /* History */ gtk_entry_set_text(mini, ""); break; @@ -104,7 +121,7 @@ void minibuffer_show(FilerWindow *filer_window, MiniType mini_type) gtk_entry_set_position(mini, -1); - gtk_widget_show(filer_window->minibuffer); + gtk_widget_show_all(filer_window->minibuffer_area); gtk_window_set_focus(GTK_WINDOW(filer_window->window), filer_window->minibuffer); @@ -114,13 +131,13 @@ void minibuffer_hide(FilerWindow *filer_window) { filer_window->mini_type = MINI_NONE; - gtk_widget_hide(filer_window->minibuffer); + gtk_widget_hide(filer_window->minibuffer_area); gtk_window_set_focus(GTK_WINDOW(filer_window->window), GTK_WIDGET(filer_window->collection)); } /* Insert this leafname at the cursor (replacing the selection, if any). - * Must be in SHELL mode. + * Must be in SHELL or RUN_ACTION mode. */ void minibuffer_add(FilerWindow *filer_window, guchar *leafname) { @@ -129,7 +146,8 @@ void minibuffer_add(FilerWindow *filer_window, guchar *leafname) GtkEntry *entry = GTK_ENTRY(edit); int pos; - g_return_if_fail(filer_window->mini_type == MINI_SHELL); + g_return_if_fail(filer_window->mini_type == MINI_SHELL || + filer_window->mini_type == MINI_RUN_ACTION); esc = shell_escape(leafname); @@ -532,6 +550,64 @@ static void shell_tab(FilerWindow *filer_window) g_string_free(leaf, TRUE); } +/* This is called from shell_return_pressed() so that the command is already + * in the history. Returns TRUE if the buffer should be closed. + */ +gboolean set_run_action(FilerWindow *filer_window, guchar *command) +{ + Collection *collection = filer_window->collection; + int n = collection->cursor_item; + DirItem *item; + guchar *path, *tmp; + FILE *file; + int error = 0, len; + + if (!strchr(command, '$')) + { + delayed_error(PROJECT, + _("To set the run action for a file, either:\n" + "- Drag a file to an application directory (eg drag an image to the " + "Gimp), or\n" "- Enter a shell command which contains a \"$1\"" + "where the name of the file should go (eg ` gimp \"$1\" ')")); + return FALSE; + } + + if (n < 0 || n >= collection->number_of_items) + { + delayed_error(PROJECT, + _("You must have the cursor on the item to use for '$1'. Clicking " + "on an item will select it.")); + return FALSE; + } + + item = (DirItem *) collection->items[n].data; + path = type_ask_which_action(item->mime_type); + + if (!path) + return TRUE; + + report_error("Setting action!", path); + + tmp = g_strdup_printf("#! /bin/sh\nexec %s\n", command); + len = strlen(tmp); + + file = fopen(path, "wb"); + if (fwrite(tmp, 1, len, file) < len) + error = errno; + if (fclose(file) && error == 0) + error = errno; + if (chmod(path, 0777)) + error = errno; + + if (error) + report_error(PROJECT, g_strerror(errno)); + + g_free(tmp); + + return TRUE; +} + +/* Either execute the command or make it the default run action */ static void shell_return_pressed(FilerWindow *filer_window, GdkEventKey *event) { GPtrArray *argv; @@ -546,6 +622,14 @@ static void shell_return_pressed(FilerWindow *filer_window, GdkEventKey *event) goto out; add_to_history(entry); + + if (filer_window->mini_type == MINI_RUN_ACTION) + { + if (set_run_action(filer_window, entry)) + goto out; + else + return; + } argv = g_ptr_array_new(); g_ptr_array_add(argv, "sh"); @@ -665,6 +749,7 @@ static gint key_press_event(GtkWidget *widget, break; case MINI_SHELL: + case MINI_RUN_ACTION: switch (event->keyval) { case GDK_Up: @@ -698,8 +783,6 @@ static void changed(GtkEditable *mini, FilerWindow *filer_window) case MINI_PATH: path_changed(mini, filer_window); return; - case MINI_SHELL: - break; default: break; } diff --git a/ROX-Filer/src/minibuffer.h b/ROX-Filer/src/minibuffer.h index 4a57ecce..64da5036 100644 --- a/ROX-Filer/src/minibuffer.h +++ b/ROX-Filer/src/minibuffer.h @@ -8,12 +8,12 @@ #ifndef _MINIBUFFER_H #define _MINIBUFFER_H -typedef enum {MINI_NONE, MINI_PATH, MINI_SHELL} MiniType; +typedef enum {MINI_NONE, MINI_PATH, MINI_SHELL, MINI_RUN_ACTION} MiniType; #include #include "filer.h" -GtkWidget *create_minibuffer(FilerWindow *filer_window); +void create_minibuffer(FilerWindow *filer_window); void minibuffer_show(FilerWindow *filer_window, MiniType mini_type); void minibuffer_hide(FilerWindow *filer_window); void minibuffer_add(FilerWindow *filer_window, guchar *leafname); diff --git a/ROX-Filer/src/type.c b/ROX-Filer/src/type.c index a3ddfa08..3958b502 100644 --- a/ROX-Filer/src/type.c +++ b/ROX-Filer/src/type.c @@ -464,3 +464,59 @@ void show_set_run_action(MIME_type *type) gtk_widget_show_all(box); } + +/* The user wants to set a new default action for files of this type. + * Ask the user if they want to set eg 'text/plain' or just 'text'. + * Removes the current binding if possible and returns the path to + * save the new one to. NULL means cancel. + */ +char *type_ask_which_action(MIME_type *type) +{ + int r; + guchar *tmp, *type_name, *path; + + g_return_val_if_fail(type != NULL, NULL); + + if (!choices_find_path_save("", PROJECT, FALSE)) + { + report_error(PROJECT, + _("Choices saving is disabled by CHOICESPATH variable")); + return NULL; + } + + type_name = g_strconcat(type->media_type, "/", type->subtype, NULL); + tmp = g_strdup_printf( + _("You can choose to set the action for just '%s' files, or " + "the default action for all '%s' files which don't already " + "have a run action:"), type_name, type->media_type); + r = get_choice(PROJECT, tmp, 3, type_name, type->media_type, "Cancel"); + g_free(tmp); + g_free(type_name); + + if (r == 0) + { + type_name = g_strconcat(type->media_type, "_", + type->subtype, NULL); + path = choices_find_path_save(type_name, "MIME-types", TRUE); + g_free(type_name); + } + else if (r == 1) + path = choices_find_path_save(type->media_type, + "MIME-types", TRUE); + else + return NULL; + + if (access(path, F_OK) == 0) + { + if (unlink(path)) + { + tmp = g_strdup_printf( _("Can't remove %s: %s"), + path, g_strerror(errno)); + report_error(PROJECT, tmp); + g_free(tmp); + return NULL; + } + } + + return path; +} diff --git a/ROX-Filer/src/type.h b/ROX-Filer/src/type.h index b90ed0a9..9cadf990 100644 --- a/ROX-Filer/src/type.h +++ b/ROX-Filer/src/type.h @@ -31,5 +31,6 @@ gboolean type_open(char *path, MIME_type *type); MaskedPixmap *type_to_icon(MIME_type *type); GdkAtom type_to_atom(MIME_type *type); void show_set_run_action(MIME_type *type); +char *type_ask_which_action(MIME_type *type); #endif /* _TYPE_H */ -- 2.11.4.GIT