From 55fa99e27d77b31907c67d105d657ceaa83870f4 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Mon, 15 May 2000 12:57:44 +0000 Subject: [PATCH] r279: Can now set run actions by dragging. --- ROX-Filer/src/dnd.c | 93 +++++++++++++++++++++++++++- ROX-Filer/src/dnd.h | 2 +- ROX-Filer/src/filer.c | 6 -- ROX-Filer/src/minibuffer.c | 8 +-- ROX-Filer/src/type.c | 150 +++------------------------------------------ ROX-Filer/src/type.h | 3 +- 6 files changed, 104 insertions(+), 158 deletions(-) diff --git a/ROX-Filer/src/dnd.c b/ROX-Filer/src/dnd.c index bf98ac4b..5ef189dc 100644 --- a/ROX-Filer/src/dnd.c +++ b/ROX-Filer/src/dnd.c @@ -120,10 +120,12 @@ enum { TARGET_RAW, TARGET_URI_LIST, + TARGET_RUN_ACTION, TARGET_XDS, }; GdkAtom XdndDirectSave0; +GdkAtom _rox_run_action; GdkAtom xa_text_plain; GdkAtom text_uri_list; GdkAtom application_octet_stream; @@ -131,6 +133,7 @@ GdkAtom application_octet_stream; void dnd_init() { XdndDirectSave0 = gdk_atom_intern("XdndDirectSave0", FALSE); + _rox_run_action = gdk_atom_intern("_ROX_RUN_ACTION", FALSE); xa_text_plain = gdk_atom_intern("text/plain", FALSE); text_uri_list = gdk_atom_intern("text/uri-list", FALSE); application_octet_stream = gdk_atom_intern("application/octet-stream", @@ -337,11 +340,14 @@ static void create_uri_list(GString *string, * * We always provide text/uri-list. If we are dragging a single, regular file * then we also offer application/octet-stream and the type of the file. + * + * If the RUN_ACTION minibuffer is open then only drags to other executables + * shown in our windows are allowed. */ void drag_selection(Collection *collection, GdkEventMotion *event, gint number_selected, - gpointer user_data) + FilerWindow *filer_window) { GtkWidget *widget; MaskedPixmap *image; @@ -363,7 +369,18 @@ void drag_selection(Collection *collection, widget = GTK_WIDGET(collection); - if (item && item->mime_type) + if (filer_window->mini_type == MINI_RUN_ACTION) + { + GtkTargetEntry target_table[] = { + {"_ROX_RUN_ACTION", 0, TARGET_RUN_ACTION}, + }; + + if (collection->number_selected != 1) + return; + + target_list = gtk_target_list_new(target_table, 1); + } + else if (item && item->mime_type) { MIME_type *t = item->mime_type; @@ -401,6 +418,8 @@ static void drag_end(GtkWidget *widget, FilerWindow *filer_window) { collection_clear_selection(filer_window->collection); + if (filer_window->mini_type == MINI_RUN_ACTION) + minibuffer_hide(filer_window); } /* Called when a remote app wants us to send it some data. @@ -445,6 +464,19 @@ void drag_data_get(GtkWidget *widget, delete_once_sent = TRUE; g_string_free(string, FALSE); break; + case TARGET_RUN_ACTION: + item = selected_item(filer_window->collection); + if (item && item->mime_type) + { + MIME_type *type = item->mime_type; + to_send = g_strconcat(type->media_type, "/", + type->subtype, NULL); + to_send_length = strlen(to_send); + delete_once_sent = TRUE; + break; + } + g_warning("drag_data_get: Can't find MIME-type\n"); + return; default: delayed_error("drag_data_get", _("Internal error - bad info type")); @@ -474,6 +506,7 @@ void drag_set_dest(FilerWindow *filer_window) {"text/uri-list", 0, TARGET_URI_LIST}, {"XdndDirectSave0", 0, TARGET_XDS}, {"application/octet-stream", 0, TARGET_RAW}, + {"_ROX_RUN_ACTION", 0, TARGET_RUN_ACTION}, }; gtk_drag_dest_set(widget, @@ -522,7 +555,25 @@ static gboolean drag_motion(GtkWidget *widget, ? (DirItem *) filer_window->collection->items[item_number].data : NULL; - if (item) + if (provides(context, _rox_run_action)) + { + /* This is a special internal type. The user is dragging + * to an executable item to set the run action. + */ + if (!item) + goto out; + + if (item->flags & (ITEM_FLAG_APPDIR | ITEM_FLAG_EXEC_FILE)) + { + type = drop_dest_prog; + new_path = make_path(filer_window->path, + item->leafname)->str; + } + else + goto out; + + } + else if (item) { /* If we didn't drop onto a directory, application or * executable file then act as though the drop is to the @@ -678,6 +729,9 @@ static gboolean drag_drop(GtkWidget *widget, target = text_uri_list; else if (provides(context, application_octet_stream)) target = application_octet_stream; + else if (dest_type == drop_dest_prog && + provides(context, _rox_run_action)) + target = _rox_run_action; else { if (dest_type == drop_dest_dir) @@ -700,6 +754,36 @@ static gboolean drag_drop(GtkWidget *widget, return TRUE; } +static void got_run_action(GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint32 time) +{ + char *type = selection_data->data; + char *media, *sub; + char *dest_path, *link; + + g_return_if_fail(type != NULL); + + dest_path = g_dataset_get_data(context, "drop_dest_path"); + + gtk_drag_finish(context, TRUE, FALSE, time); /* Success! */ + + sub = strchr(type, '/'); + g_return_if_fail(sub != NULL); + + media = g_strndup(type, sub - type); + sub++; + + link = type_ask_which_action(media, sub); + g_free(media); + if (!link) + return; + + if (symlink(dest_path, link)) + delayed_error(PROJECT, g_strerror(errno)); +} + /* Called when some data arrives from the remote app (which we asked for * in drag_drop). */ @@ -732,6 +816,9 @@ static void drag_data_received(GtkWidget *widget, case TARGET_URI_LIST: got_uri_list(widget, context, selection_data, time); break; + case TARGET_RUN_ACTION: + got_run_action(widget, context, selection_data, time); + break; default: gtk_drag_finish(context, FALSE, FALSE, time); delayed_error("drag_data_received", diff --git a/ROX-Filer/src/dnd.h b/ROX-Filer/src/dnd.h index 70756e36..3a325b5e 100644 --- a/ROX-Filer/src/dnd.h +++ b/ROX-Filer/src/dnd.h @@ -15,7 +15,7 @@ void drag_selection(Collection *collection, GdkEventMotion *event, gint number_selected, - gpointer user_data); + FilerWindow *filer_window); void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, diff --git a/ROX-Filer/src/filer.c b/ROX-Filer/src/filer.c index ac81318d..12e2ae57 100644 --- a/ROX-Filer/src/filer.c +++ b/ROX-Filer/src/filer.c @@ -1079,12 +1079,6 @@ 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; diff --git a/ROX-Filer/src/minibuffer.c b/ROX-Filer/src/minibuffer.c index db17603a..f4dd95a2 100644 --- a/ROX-Filer/src/minibuffer.c +++ b/ROX-Filer/src/minibuffer.c @@ -575,19 +575,17 @@ gboolean set_run_action(FilerWindow *filer_window, guchar *command) 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.")); + _("You must have the cursor on the item to use for '$1'.")); return FALSE; } item = (DirItem *) collection->items[n].data; - path = type_ask_which_action(item->mime_type); + path = type_ask_which_action(item->mime_type->media_type, + item->mime_type->subtype); if (!path) return TRUE; - report_error("Setting action!", path); - tmp = g_strdup_printf("#! /bin/sh\nexec %s\n", command); len = strlen(tmp); diff --git a/ROX-Filer/src/type.c b/ROX-Filer/src/type.c index 3958b502..014c6ad1 100644 --- a/ROX-Filer/src/type.c +++ b/ROX-Filer/src/type.c @@ -198,7 +198,7 @@ char *basetype_name(DirItem *item) /* MIME-type guessing */ -/* Returns a pointer to the MIME-type string, or NULL if we have +/* Returns a pointer to the MIME-type. Defaults to text/plain if we have * no opinion. */ MIME_type *type_from_path(char *path) @@ -334,148 +334,18 @@ GdkAtom type_to_atom(MIME_type *type) return retval; } -/* Display a box allowing the user to set the run action for this type */ -void show_set_run_action(MIME_type *type) -{ - static GtkWidget *box = NULL; - static GtkWidget *pixmap = NULL, *link_path, *explain_label; - guchar *type_name, *path; - struct stat info; - static MaskedPixmap *drop = NULL; - MaskedPixmap *pic; - guchar *tmp; - - if (!box) - { - GtkWidget *vbox, *event, *hbox, *button, *frame; - GtkWidget *link_box; - GtkTargetEntry targets[] = { - {"text/uri-list", 0, 0}, - }; - - box = gtk_window_new(GTK_WINDOW_DIALOG); - gtk_container_set_border_width(GTK_CONTAINER(box), 4); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(box), vbox); - - explain_label = gtk_label_new(""); - gtk_box_pack_start(GTK_BOX(vbox), explain_label, - FALSE, TRUE, 4); - - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - event = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(frame), event); - gtk_drag_dest_set(event, GTK_DEST_DEFAULT_ALL, targets, - sizeof(targets) / sizeof(*targets), - GDK_ACTION_COPY | GDK_ACTION_PRIVATE); - - tmp = g_strconcat(getenv("APP_DIR"), "/pixmaps/drop.xpm", NULL); - drop = g_fscache_lookup(pixmap_cache, tmp); - g_free(tmp); - - link_box = gtk_vbox_new(FALSE, 4); - gtk_container_add(GTK_CONTAINER(event), link_box); - - pixmap = gtk_pixmap_new(drop->pixmap, drop->mask); - gtk_box_pack_start(GTK_BOX(link_box), pixmap, FALSE, TRUE, 4); - link_path = gtk_label_new(""); - gtk_misc_set_padding(GTK_MISC(link_path), 4, 0); - gtk_box_pack_start(GTK_BOX(link_box), - link_path, FALSE, TRUE, 4); - - hbox = gtk_hbox_new(TRUE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 4); - - button = gtk_button_new_with_label(_("Save")); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 4); - button = gtk_button_new_with_label(_("Cancel")); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(gtk_widget_hide), GTK_OBJECT(box)); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 4); - } - - if (GTK_WIDGET_VISIBLE(box)) - gtk_widget_hide(box); - - type_name = g_strconcat(type->media_type, "/", type->subtype, NULL); - gtk_window_set_title(GTK_WINDOW(box), type_name); - tmp = g_strdup_printf( - _("Default run action for files of type '%s':"), - type_name); - gtk_label_set_text(GTK_LABEL(explain_label), tmp); - g_free(tmp); - g_free(type_name); - - type_name = g_strconcat(type->media_type, "_", type->subtype, NULL); - path = choices_find_path_load(type_name, "MIME-types"); - if (!path) - path = choices_find_path_load(type->media_type, "MIME-types"); - - pic = NULL; - if (path && stat(path, &info) == 0) - { - if (S_ISDIR(info.st_mode)) - { - tmp = g_strconcat(path, "/AppIcon.xpm", NULL); - pic = g_fscache_lookup(pixmap_cache, tmp); - g_free(tmp); - if (!pic) - { - pic = default_pixmap[TYPE_APPDIR]; - pixmap_ref(pic); - } - } - else - { - pic = default_pixmap[TYPE_EXEC_FILE]; - pixmap_ref(pic); - } - } - - if (!pic) - { - pic = drop; - gtk_label_set_text(GTK_LABEL(link_path), - _("No run action set")); - } - else - { - char buffer[MAXPATHLEN + 1]; - int got; - - got = readlink(path, buffer, sizeof(buffer) - 1); - if (got > 0) - { - buffer[got] = '\0'; - gtk_label_set_text(GTK_LABEL(link_path), buffer); - } - else - gtk_label_set_text(GTK_LABEL(link_path), path); - } - - gtk_pixmap_set(GTK_PIXMAP(pixmap), pic->pixmap, pic->mask); - if (pic != drop) - g_fscache_data_unref(pixmap_cache, pic); - - g_free(path); - - 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) +char *type_ask_which_action(guchar *media_type, guchar *subtype) { int r; guchar *tmp, *type_name, *path; - g_return_val_if_fail(type != NULL, NULL); + g_return_val_if_fail(media_type != NULL, NULL); + g_return_val_if_fail(subtype != NULL, NULL); if (!choices_find_path_save("", PROJECT, FALSE)) { @@ -484,25 +354,23 @@ char *type_ask_which_action(MIME_type *type) return NULL; } - type_name = g_strconcat(type->media_type, "/", type->subtype, NULL); + type_name = g_strconcat(media_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"); + "have a run action:"), type_name, media_type); + r = get_choice(PROJECT, tmp, 3, type_name, media_type, "Cancel"); g_free(tmp); g_free(type_name); if (r == 0) { - type_name = g_strconcat(type->media_type, "_", - type->subtype, NULL); + type_name = g_strconcat(media_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); + path = choices_find_path_save(media_type, "MIME-types", TRUE); else return NULL; diff --git a/ROX-Filer/src/type.h b/ROX-Filer/src/type.h index 9cadf990..64570d4f 100644 --- a/ROX-Filer/src/type.h +++ b/ROX-Filer/src/type.h @@ -30,7 +30,6 @@ MIME_type *type_from_path(char *path); 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); +char *type_ask_which_action(guchar *media_type, guchar *subtype); #endif /* _TYPE_H */ -- 2.11.4.GIT