mirror of https://github.com/MidnightCommander/mc
1999-02-03 Federico Mena Quintero <federico@nuclecu.unam.mx>
* gdnd.c (gdnd_validate_action): Added an "on_desktop" argument; this specifies that the user is dragging over the desktop. Added cases for drags of desktop icons and URLs. (gdnd_perform_drop): New public function to handle drops. This is now the master function to handle drops -- use this to make all of MC consistent. (drop_on_directory): Made static and renamed from gdnd_drop_on_directory(). Made it fit for use by gdnd_perform_drop(). (drop_url_on_directory): New function to drop an url on a directory, moved over from gdesktop.c. (drop_uri_list_on_directory): New function to handle drops of URI lists on a directory. (drop_on_file): New function to handle drops on a non-directory file entry. This is moved over from gdesktop.c, desktop_icon_drop_uri_list(). This is yet to be finished. * gdesktop.c (desktop_icon_drop_uri_list): Fix memory leak. (desktop_drag_motion): Use gdnd_validate_action(). (dnd_icon_targets): Allow dropping URLs on icons. (icon_drag_motion): Use gdnd_validate_action(). (desktop_drag_data_received): Use gdnd_perform_drop(). (icon_drag_data_received): Use gdnd_perform_drop(). * gscreen.c (panel_icon_list_drag_data_received): Use gdnd_perform_drop(). (panel_clist_drag_data_received): Use gdnd_perform_drop(). (panel_tree_drag_data_received): Use gdnd_perform_drop(). * gcmd.c (gnome_about_cmd): Fixed Foundation typo, and updated the copyright date.
This commit is contained in:
parent
89204b8f1c
commit
04c4abd818
|
@ -1,3 +1,37 @@
|
|||
1999-02-03 Federico Mena Quintero <federico@nuclecu.unam.mx>
|
||||
|
||||
* gdnd.c (gdnd_validate_action): Added an "on_desktop" argument;
|
||||
this specifies that the user is dragging over the desktop. Added
|
||||
cases for drags of desktop icons and URLs.
|
||||
(gdnd_perform_drop): New public function to handle drops. This is
|
||||
now the master function to handle drops -- use this to make all of
|
||||
MC consistent.
|
||||
(drop_on_directory): Made static and renamed from
|
||||
gdnd_drop_on_directory(). Made it fit for use by
|
||||
gdnd_perform_drop().
|
||||
(drop_url_on_directory): New function to drop an url on a
|
||||
directory, moved over from gdesktop.c.
|
||||
(drop_uri_list_on_directory): New function to handle drops of URI
|
||||
lists on a directory.
|
||||
(drop_on_file): New function to handle drops on a non-directory
|
||||
file entry. This is moved over from gdesktop.c,
|
||||
desktop_icon_drop_uri_list(). This is yet to be finished.
|
||||
|
||||
* gdesktop.c (desktop_icon_drop_uri_list): Fix memory leak.
|
||||
(desktop_drag_motion): Use gdnd_validate_action().
|
||||
(dnd_icon_targets): Allow dropping URLs on icons.
|
||||
(icon_drag_motion): Use gdnd_validate_action().
|
||||
(desktop_drag_data_received): Use gdnd_perform_drop().
|
||||
(icon_drag_data_received): Use gdnd_perform_drop().
|
||||
|
||||
* gscreen.c (panel_icon_list_drag_data_received): Use
|
||||
gdnd_perform_drop().
|
||||
(panel_clist_drag_data_received): Use gdnd_perform_drop().
|
||||
(panel_tree_drag_data_received): Use gdnd_perform_drop().
|
||||
|
||||
* gcmd.c (gnome_about_cmd): Fixed Foundation typo, and updated the
|
||||
copyright date.
|
||||
|
||||
1999-02-02 Miguel de Icaza <miguel@nuclecu.unam.mx>
|
||||
|
||||
* gnome-file-property-dialog.c (create_general_properties): Use
|
||||
|
|
239
gnome/gdesktop.c
239
gnome/gdesktop.c
|
@ -73,6 +73,7 @@ static GtkTargetEntry dnd_icon_sources[] = {
|
|||
static GtkTargetEntry dnd_icon_targets[] = {
|
||||
{ TARGET_MC_DESKTOP_ICON_TYPE, 0, TARGET_MC_DESKTOP_ICON },
|
||||
{ TARGET_URI_LIST_TYPE, 0, TARGET_URI_LIST },
|
||||
{ TARGET_URL_TYPE, 0, TARGET_URL }
|
||||
};
|
||||
|
||||
static GtkTargetEntry dnd_desktop_targets[] = {
|
||||
|
@ -1163,8 +1164,7 @@ setup_icon_dnd_source (DesktopIconInfo *dii)
|
|||
dii);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback used when we get a drag_motion event from a desktop icon. We have
|
||||
/* Callback used when we get a drag_motion event from a desktop icon. We have
|
||||
* to decide which operation to perform based on the type of the data the user
|
||||
* is dragging.
|
||||
*/
|
||||
|
@ -1176,27 +1176,25 @@ icon_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, gu
|
|||
char *filename;
|
||||
file_entry *fe;
|
||||
GdkDragAction action;
|
||||
GtkWidget *source_widget;
|
||||
int is_desktop_icon;
|
||||
|
||||
dii = data;
|
||||
|
||||
filename = g_concat_dir_and_file (desktop_directory, dii->filename);
|
||||
fe = file_entry_from_file (filename);
|
||||
g_free (filename);
|
||||
if (!fe)
|
||||
return 0; /* eeek */
|
||||
|
||||
action = 0; /* be pessimistic by defaulting to nothing */
|
||||
gdnd_find_panel_by_drag_context (context, &source_widget);
|
||||
is_desktop_icon = gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON);
|
||||
|
||||
if (dii->selected
|
||||
&& gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON)
|
||||
&& (context->actions & GDK_ACTION_MOVE))
|
||||
action = GDK_ACTION_MOVE;
|
||||
else if (gdnd_drag_context_has_target (context, TARGET_URI_LIST)) {
|
||||
if (S_ISDIR (fe->buf.st_mode) || fe->f.link_to_dir)
|
||||
action = context->suggested_action;
|
||||
else if (is_exe (fe->buf.st_mode)
|
||||
&& if_link_is_exe (fe)
|
||||
&& (context->actions & GDK_ACTION_COPY))
|
||||
action = GDK_ACTION_COPY;
|
||||
}
|
||||
action = gdnd_validate_action (context,
|
||||
TRUE,
|
||||
source_widget != NULL,
|
||||
source_widget && is_desktop_icon,
|
||||
fe,
|
||||
dii->selected);
|
||||
|
||||
gdk_drag_status (context, action, time);
|
||||
return TRUE;
|
||||
|
@ -1245,11 +1243,6 @@ drop_desktop_icons (GdkDragContext *context, GtkSelectionData *data, int x, int
|
|||
GList *l;
|
||||
GSList *sel_icons, *sl;
|
||||
|
||||
/*
|
||||
* FIXME: this needs to do the right thing (what Windows does)
|
||||
* when desktop_auto_placement is enabled.
|
||||
*/
|
||||
|
||||
/* Find the icon that the user is dragging */
|
||||
|
||||
source_dii = find_icon_by_drag_context (context);
|
||||
|
@ -1292,94 +1285,6 @@ drop_desktop_icons (GdkDragContext *context, GtkSelectionData *data, int x, int
|
|||
g_slist_free (sel_icons);
|
||||
}
|
||||
|
||||
/**
|
||||
* drop_on_file_entry
|
||||
*/
|
||||
static void
|
||||
desktop_icon_drop_uri_list (DesktopIconInfo *dii, GdkDragContext *context, GtkSelectionData *data)
|
||||
{
|
||||
char *filename;
|
||||
file_entry *fe;
|
||||
int size;
|
||||
char *buf;
|
||||
const char *mime_type;
|
||||
|
||||
filename = g_concat_dir_and_file (desktop_directory, dii->filename);
|
||||
|
||||
fe = file_entry_from_file (filename);
|
||||
if (!fe)
|
||||
return; /* eek */
|
||||
|
||||
/* 1. If it is a directory, drop the files there */
|
||||
|
||||
if (fe->f.link_to_dir) {
|
||||
gdnd_drop_on_directory (context, data, filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 2. Try to use a metadata-based drop action */
|
||||
|
||||
if (gnome_metadata_get (filename, "drop-action", &size, &buf) == 0) {
|
||||
/*action_drop (filename, buf, context, data);*/ /* Fixme: i'm undefined */
|
||||
g_free (buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 3. Try a drop action from the mime-type */
|
||||
|
||||
mime_type = gnome_mime_type_or_default (filename, NULL);
|
||||
if (mime_type) {
|
||||
char *action;
|
||||
|
||||
action = gnome_mime_get_value (mime_type, "drop-action");
|
||||
|
||||
if (action) {
|
||||
/*action_drop (filename, action, context, data);*/ /* Fixme: i'm undefined */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. Executable. Try metadata keys for "open" */
|
||||
|
||||
if (is_exe (fe->buf.st_mode) && if_link_is_exe (fe)) {
|
||||
GList *names, *l;
|
||||
int len, i;
|
||||
char **drops;
|
||||
|
||||
/* Convert the list of filenames into an array of char */
|
||||
|
||||
names = gnome_uri_list_extract_uris (data->data);
|
||||
len = g_list_length (names);
|
||||
drops = (char **) g_malloc (sizeof (char *) * (len+1));
|
||||
|
||||
for (l = names, i = 0; i < len; i++, l = l->next) {
|
||||
char *text = l->data;
|
||||
|
||||
if (strncmp (text, "file:", 5) == 0)
|
||||
text += 5;
|
||||
|
||||
drops [i] = text;
|
||||
}
|
||||
drops [i] = NULL;
|
||||
|
||||
if (gnome_metadata_get (filename, "open", &size, &buf) == 0) {
|
||||
exec_extension (filename, buf, drops, NULL, 0);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
exec_extension (filename, "%f %q", drops, NULL, 0);
|
||||
|
||||
g_free (drops);
|
||||
out2:
|
||||
gnome_uri_list_free_strings (names);
|
||||
g_free (buf);
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
file_entry_free (fe);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
||||
GtkSelectionData *data, guint info, guint time, gpointer user_data)
|
||||
|
@ -1388,22 +1293,21 @@ icon_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gin
|
|||
|
||||
dii = user_data;
|
||||
|
||||
switch (info) {
|
||||
case TARGET_MC_DESKTOP_ICON:
|
||||
if (dii->selected)
|
||||
drop_desktop_icons (context, data, x + dii->x, y + dii->y);
|
||||
else
|
||||
printf ("FIXME: what do drop?\n"); /* FIXME */
|
||||
if (gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON) && dii->selected)
|
||||
drop_desktop_icons (context, data, x + dii->x, y + dii->y);
|
||||
else {
|
||||
char *full_name;
|
||||
file_entry *fe;
|
||||
|
||||
break;
|
||||
full_name = g_concat_dir_and_file (desktop_directory, dii->filename);
|
||||
fe = file_entry_from_file (full_name);
|
||||
if (!fe)
|
||||
return; /* eeeek */
|
||||
|
||||
case TARGET_URI_LIST:
|
||||
printf ("Wheeeeee!\n");
|
||||
desktop_icon_drop_uri_list (dii, context, data);
|
||||
break;
|
||||
if (gdnd_perform_drop (context, data, fe, full_name))
|
||||
reload_desktop_icons (TRUE, x, y);
|
||||
|
||||
default:
|
||||
break;
|
||||
file_entry_free (fe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1727,73 +1631,27 @@ desktop_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
|||
{
|
||||
GdkDragAction action;
|
||||
GtkWidget *source_widget;
|
||||
int is_desktop_icon;
|
||||
|
||||
action = context->suggested_action; /* this is the default */
|
||||
gdnd_find_panel_by_drag_context (context, &source_widget);
|
||||
is_desktop_icon = gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON);
|
||||
|
||||
if (gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON))
|
||||
action = GDK_ACTION_MOVE;
|
||||
else if (gdnd_drag_context_has_target (context, TARGET_URI_LIST)) {
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
|
||||
/* If it comes from ourselves, make move the default unless the
|
||||
* user is explicitly asking for ASK.
|
||||
*/
|
||||
if (source_widget
|
||||
&& context->suggested_action != GDK_ACTION_ASK
|
||||
&& (context->actions & GDK_ACTION_MOVE))
|
||||
action = GDK_ACTION_MOVE;
|
||||
} else if (gdnd_drag_context_has_target (context, TARGET_URL)) {
|
||||
/* FIXME: right now we only allow links. We should see if we
|
||||
* can move or copy stuff instead (for ftp instead of http
|
||||
* sites, for example).
|
||||
*/
|
||||
if (context->actions & GDK_ACTION_LINK)
|
||||
action = GDK_ACTION_LINK;
|
||||
else
|
||||
action = 0;
|
||||
} else
|
||||
action = 0; /* we cannot handle that type of data */
|
||||
action = gdnd_validate_action (context,
|
||||
TRUE,
|
||||
source_widget != NULL,
|
||||
source_widget && is_desktop_icon,
|
||||
NULL,
|
||||
FALSE);
|
||||
|
||||
gdk_drag_status (context, action, time);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* drop_url: Invoked when we have received an URL from Netscape.
|
||||
* Install the url on the ~/desktop directory
|
||||
*/
|
||||
static void
|
||||
drop_url (GdkDragContext *context, GtkSelectionData *data, gint x, gint y)
|
||||
{
|
||||
char *template;
|
||||
|
||||
template = g_concat_dir_and_file (desktop_directory, "urlXXXXXX");
|
||||
|
||||
if (mktemp (template)) {
|
||||
FILE *f;
|
||||
|
||||
f = fopen (template, "w");
|
||||
if (f){
|
||||
fprintf (f, "URL: %s\n", data->data);
|
||||
fclose (f);
|
||||
|
||||
gnome_metadata_set (template, "desktop-url",
|
||||
strlen (data->data) + 1,
|
||||
data->data);
|
||||
|
||||
reload_desktop_icons (TRUE, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (template);
|
||||
}
|
||||
|
||||
/* Callback used when the root window receives a drop */
|
||||
static void
|
||||
desktop_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
||||
GtkSelectionData *data, guint info, guint time, gpointer user_data)
|
||||
{
|
||||
int retval;
|
||||
gint dx, dy;
|
||||
|
||||
/* Fix the proxy window offsets */
|
||||
|
@ -1802,23 +1660,19 @@ desktop_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x,
|
|||
x += dx;
|
||||
y += dy;
|
||||
|
||||
switch (info) {
|
||||
case TARGET_MC_DESKTOP_ICON:
|
||||
if (gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON))
|
||||
drop_desktop_icons (context, data, x, y);
|
||||
break;
|
||||
else {
|
||||
file_entry *desktop_fe;
|
||||
|
||||
case TARGET_URI_LIST:
|
||||
retval = gdnd_drop_on_directory (context, data, desktop_directory);
|
||||
if (retval)
|
||||
desktop_fe = file_entry_from_file (desktop_directory);
|
||||
if (!desktop_fe)
|
||||
return; /* eeek */
|
||||
|
||||
if (gdnd_perform_drop (context, data, desktop_fe, desktop_directory))
|
||||
reload_desktop_icons (TRUE, x, y);
|
||||
break;
|
||||
|
||||
case TARGET_URL:
|
||||
drop_url (context, data, x, y);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
file_entry_free (desktop_fe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1984,11 +1838,6 @@ icon_is_in_area (DesktopIconInfo *dii, int x1, int y1, int x2, int y2)
|
|||
|
||||
dicon = DESKTOP_ICON (dii->dicon);
|
||||
|
||||
/* FIXME: this only intersects the rectangle with the icon image's
|
||||
* bounds. Doing the "hard" intersection with the actual shape of the
|
||||
* image is left as an exercise to the reader.
|
||||
*/
|
||||
|
||||
x1 -= dii->x;
|
||||
y1 -= dii->y;
|
||||
x2 -= dii->x;
|
||||
|
|
297
gnome/gdnd.c
297
gnome/gdnd.c
|
@ -13,6 +13,7 @@
|
|||
#include "fileopctx.h"
|
||||
#include "main.h"
|
||||
#include "panel.h"
|
||||
#include "ext.h"
|
||||
#include "gscreen.h"
|
||||
#include "../vfs/vfs.h"
|
||||
#include <gdk/gdkprivate.h>
|
||||
|
@ -96,21 +97,20 @@ get_action (GdkDragContext *context)
|
|||
return action;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a drop action on the specified panel. Only supports copy
|
||||
* and move operations. The files are moved or copied to the
|
||||
* specified destination directory.
|
||||
/* Performs a drop action on the specified panel. Only supports copy and move
|
||||
* operations. The files are moved or copied to the specified destination
|
||||
* directory.
|
||||
*/
|
||||
static void
|
||||
perform_action_on_panel (WPanel *source_panel, GdkDragAction action, char *destdir, int ask)
|
||||
perform_action_on_panel (WPanel *source_panel, GdkDragAction action, char *destdir)
|
||||
{
|
||||
switch (action) {
|
||||
case GDK_ACTION_COPY:
|
||||
panel_operate (source_panel, OP_COPY, destdir, ask);
|
||||
panel_operate (source_panel, OP_COPY, destdir, FALSE);
|
||||
break;
|
||||
|
||||
case GDK_ACTION_MOVE:
|
||||
panel_operate (source_panel, OP_MOVE, destdir, ask);
|
||||
panel_operate (source_panel, OP_MOVE, destdir, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -146,11 +146,10 @@ perform_links (GList *names, char *destdir)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a drop action manually, by going through the list of files
|
||||
* to operate on. The files are copied or moved to the specified
|
||||
* directory. This should also encompass symlinking when the file
|
||||
* operations window supports links.
|
||||
/* Performs a drop action manually, by going through the list of files to
|
||||
* operate on. The files are copied or moved to the specified directory. This
|
||||
* should also encompass symlinking when the file operations window supports
|
||||
* links.
|
||||
*/
|
||||
static void
|
||||
perform_action (GList *names, GdkDragAction action, char *destdir)
|
||||
|
@ -226,46 +225,24 @@ perform_action (GList *names, GdkDragAction action, char *destdir)
|
|||
file_op_context_destroy (ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdnd_drop_on_directory:
|
||||
* @context: The drag context received from the drag_data_received callback
|
||||
* @selection_data: The selection data from the drag_data_received callback
|
||||
* @dirname: The name of the directory to drop onto
|
||||
*
|
||||
* Extracts an URI list from the selection data and drops all the files in the
|
||||
* specified directory.
|
||||
*
|
||||
* Return Value: TRUE if the drop was sucessful, FALSE if it was not.
|
||||
**/
|
||||
int
|
||||
gdnd_drop_on_directory (GdkDragContext *context, GtkSelectionData *selection_data, char *destdir)
|
||||
/* Drop a URI list on a directory. If the data comes from a panel, use the nice
|
||||
* MC progress display; otherwise `do it by hand'.
|
||||
*/
|
||||
static void
|
||||
drop_uri_list_on_directory (GdkDragContext *context, GtkSelectionData *selection_data,
|
||||
GdkDragAction action, char *destdir)
|
||||
{
|
||||
GdkDragAction action;
|
||||
WPanel *source_panel;
|
||||
GtkWidget *source_widget;
|
||||
GList *names;
|
||||
|
||||
if (context->action == GDK_ACTION_ASK) {
|
||||
action = get_action (context);
|
||||
|
||||
if (action == GDK_ACTION_ASK)
|
||||
return FALSE;
|
||||
|
||||
} else
|
||||
action = context->action;
|
||||
|
||||
/* If we are dragging from a file panel, we can display a nicer status
|
||||
* display. But if the drag was from the tree, we cannot do this.
|
||||
*/
|
||||
source_panel = gdnd_find_panel_by_drag_context (context, &source_widget);
|
||||
if (source_widget == source_panel->tree)
|
||||
source_panel = NULL;
|
||||
|
||||
/* Symlinks do not use file.c */
|
||||
|
||||
if (source_panel && action != GDK_ACTION_LINK)
|
||||
perform_action_on_panel (source_panel, action, destdir,
|
||||
context->action == GDK_ACTION_ASK);
|
||||
/* We cannot use file.c if we are going to symlink or if we are dragging
|
||||
* from a tree.
|
||||
*/
|
||||
if (source_panel && source_widget != source_panel->tree && action != GDK_ACTION_LINK)
|
||||
perform_action_on_panel (source_panel, action, destdir);
|
||||
else {
|
||||
names = gnome_uri_list_extract_uris (selection_data->data);
|
||||
|
||||
|
@ -276,10 +253,153 @@ gdnd_drop_on_directory (GdkDragContext *context, GtkSelectionData *selection_dat
|
|||
|
||||
gnome_uri_list_free_strings (names);
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop a Netscape URL in a directory */
|
||||
static void
|
||||
drop_url_on_directory (GdkDragContext *context, GtkSelectionData *selection_data, char *destdir)
|
||||
{
|
||||
char *template;
|
||||
|
||||
template = g_concat_dir_and_file (destdir, "urlXXXXXX");
|
||||
|
||||
if (mktemp (template)) {
|
||||
FILE *f;
|
||||
|
||||
f = fopen (template, "w");
|
||||
if (f) {
|
||||
fprintf (f, "URL: %s\n", selection_data->data);
|
||||
fclose (f);
|
||||
|
||||
gnome_metadata_set (template, "desktop-url",
|
||||
strlen (selection_data->data) + 1,
|
||||
selection_data->data);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (template);
|
||||
}
|
||||
|
||||
/* Drop stuff on a directory */
|
||||
static int
|
||||
drop_on_directory (GdkDragContext *context, GtkSelectionData *selection_data, char *destdir)
|
||||
{
|
||||
GdkDragAction action;
|
||||
|
||||
if (context->action == GDK_ACTION_ASK) {
|
||||
action = get_action (context);
|
||||
|
||||
if (action == GDK_ACTION_ASK)
|
||||
return FALSE;
|
||||
} else
|
||||
action = context->action;
|
||||
|
||||
if (gdnd_drag_context_has_target (context, TARGET_URI_LIST))
|
||||
drop_uri_list_on_directory (context, selection_data, action, destdir);
|
||||
else if (gdnd_drag_context_has_target (context, TARGET_URL))
|
||||
drop_url_on_directory (context, selection_data, destdir);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Drop stuff on a non-directory file. This uses metadata and MIME as well. */
|
||||
static int
|
||||
drop_on_file (GdkDragContext *context, GtkSelectionData *selection_data,
|
||||
file_entry *dest_fe, char *dest_name)
|
||||
{
|
||||
int size;
|
||||
char *buf;
|
||||
const char *mime_type;
|
||||
|
||||
/* 1. Try to use a metadata-based drop action */
|
||||
|
||||
if (gnome_metadata_get (dest_name, "drop-action", &size, &buf) == 0) {
|
||||
/*action_drop (dest_name, buf, context, selection_data);*/ /* Fixme: i'm undefined */
|
||||
g_free (buf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* 2. Try a drop action from the MIME-type */
|
||||
|
||||
mime_type = gnome_mime_type_or_default (dest_name, NULL);
|
||||
if (mime_type) {
|
||||
char *action;
|
||||
|
||||
action = gnome_mime_get_value (mime_type, "drop-action");
|
||||
if (action) {
|
||||
/* Fixme: i'm undefined */
|
||||
/*action_drop (dest_name, action, context, selection_data);*/
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. If executable, try metadata keys for "open" */
|
||||
|
||||
if (is_exe (dest_fe->buf.st_mode) && if_link_is_exe (dest_fe)) {
|
||||
GList *names, *l;
|
||||
int len, i;
|
||||
char **drops;
|
||||
|
||||
/* FIXME: handle the case for Netscape URLs */
|
||||
|
||||
/* Convert the data list into an array of strings */
|
||||
|
||||
names = gnome_uri_list_extract_uris (selection_data->data);
|
||||
len = g_list_length (names);
|
||||
drops = g_new (char *, len + 1);
|
||||
|
||||
for (l = names, i = 0; i < len; i++, l = l->next) {
|
||||
char *text = l->data;
|
||||
|
||||
if (strncmp (text, "file:", 5) == 0)
|
||||
text += 5;
|
||||
|
||||
drops[i] = text;
|
||||
}
|
||||
drops[i] = NULL;
|
||||
|
||||
if (gnome_metadata_get (dest_name, "open", &size, &buf) == 0)
|
||||
exec_extension (dest_name, buf, drops, NULL, 0);
|
||||
else
|
||||
exec_extension (dest_name, "%f %q", drops, NULL, 0);
|
||||
|
||||
g_free (drops);
|
||||
gnome_uri_list_free_strings (names);
|
||||
g_free (buf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE; /* could not drop */
|
||||
}
|
||||
|
||||
int
|
||||
gdnd_perform_drop (GdkDragContext *context, GtkSelectionData *selection_data,
|
||||
file_entry *dest_fe, char *dest_name)
|
||||
{
|
||||
GdkDragAction action;
|
||||
|
||||
g_return_val_if_fail (context != NULL, FALSE);
|
||||
g_return_val_if_fail (selection_data != NULL, FALSE);
|
||||
g_return_val_if_fail (dest_fe != NULL, FALSE);
|
||||
|
||||
/* Get action */
|
||||
|
||||
if (context->action == GDK_ACTION_ASK) {
|
||||
action = get_action (context);
|
||||
if (action == GDK_ACTION_ASK)
|
||||
return FALSE;
|
||||
} else
|
||||
action = context->action;
|
||||
|
||||
if (S_ISDIR (dest_fe->buf.st_mode) || dest_fe->f.link_to_dir)
|
||||
return drop_on_directory (context, selection_data, dest_name);
|
||||
else
|
||||
return drop_on_file (context, selection_data, dest_fe, dest_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdnd_drag_context_has_target:
|
||||
* @context: The context to query for a target type
|
||||
|
@ -348,6 +468,7 @@ gdnd_find_panel_by_drag_context (GdkDragContext *context, GtkWidget **source_wid
|
|||
/**
|
||||
* gdnd_validate_action:
|
||||
* @context: The drag context for this drag operation.
|
||||
* @on_desktop: Whether we are dragging onto the desktop or a desktop icon.
|
||||
* @same_process: Whether the drag comes from the same process or not.
|
||||
* @same_source: If same_process, then whether the source and dest widgets are the same.
|
||||
* @dest: The destination file entry, or NULL if dropping on empty space.
|
||||
|
@ -359,48 +480,70 @@ gdnd_find_panel_by_drag_context (GdkDragContext *context, GtkWidget **source_wid
|
|||
* Return value: The computed action, meant to be passed to gdk_drag_action().
|
||||
**/
|
||||
GdkDragAction
|
||||
gdnd_validate_action (GdkDragContext *context, int same_process, int same_source,
|
||||
gdnd_validate_action (GdkDragContext *context,
|
||||
int on_desktop, int same_process, int same_source,
|
||||
file_entry *dest_fe, int dest_selected)
|
||||
{
|
||||
int on_directory;
|
||||
int on_exe;
|
||||
|
||||
if (dest_fe) {
|
||||
on_directory = dest_fe->f.link_to_dir || S_ISDIR (dest_fe->buf.st_mode);
|
||||
on_exe = is_exe (dest_fe->buf.st_mode) && if_link_is_exe (dest_fe);
|
||||
}
|
||||
g_return_val_if_fail (context != NULL, 0);
|
||||
|
||||
if (dest_fe) {
|
||||
if (same_source && dest_selected)
|
||||
return 0;
|
||||
/* If we are dragging a desktop icon onto the desktop or onto a selected
|
||||
* desktop icon, unconditionally specify MOVE.
|
||||
*/
|
||||
if (on_desktop
|
||||
&& gdnd_drag_context_has_target (context, TARGET_MC_DESKTOP_ICON)
|
||||
&& (!dest_fe || dest_selected))
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (on_directory) {
|
||||
if ((same_source || same_process)
|
||||
&& (context->actions & GDK_ACTION_MOVE)
|
||||
&& context->suggested_action != GDK_ACTION_ASK)
|
||||
if (gdnd_drag_context_has_target (context, TARGET_URI_LIST)) {
|
||||
if (dest_fe) {
|
||||
on_directory = S_ISDIR (dest_fe->buf.st_mode) || dest_fe->f.link_to_dir;
|
||||
on_exe = is_exe (dest_fe->buf.st_mode) && if_link_is_exe (dest_fe);
|
||||
}
|
||||
|
||||
if (dest_fe) {
|
||||
if (same_source && dest_selected)
|
||||
return 0;
|
||||
|
||||
if (on_directory) {
|
||||
if ((same_source || same_process)
|
||||
&& (context->actions & GDK_ACTION_MOVE)
|
||||
&& context->suggested_action != GDK_ACTION_ASK)
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
} else if (on_exe) {
|
||||
if (context->actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
} else if (same_source)
|
||||
return 0;
|
||||
else if (same_process
|
||||
&& (context->actions & GDK_ACTION_MOVE)
|
||||
&& context->suggested_action != GDK_ACTION_ASK)
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
} else if (on_exe) {
|
||||
if (context->actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
} else if (same_source)
|
||||
return 0;
|
||||
else if (same_process
|
||||
&& (context->actions & GDK_ACTION_MOVE)
|
||||
&& context->suggested_action != GDK_ACTION_ASK)
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
} else {
|
||||
if (same_source)
|
||||
return 0;
|
||||
else if (same_process
|
||||
&& (context->actions & GDK_ACTION_MOVE)
|
||||
&& context->suggested_action != GDK_ACTION_ASK)
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
} else {
|
||||
if (same_source)
|
||||
return 0;
|
||||
else if (same_process
|
||||
&& (context->actions & GDK_ACTION_MOVE)
|
||||
&& context->suggested_action != GDK_ACTION_ASK)
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
}
|
||||
}
|
||||
|
||||
if (gdnd_drag_context_has_target (context, TARGET_URL)) {
|
||||
/* FIXME: right now we only allow links. We should see if we
|
||||
* can move or copy stuff instead (for ftp instead of http
|
||||
* sites, for example).
|
||||
*/
|
||||
if (context->actions & GDK_ACTION_LINK)
|
||||
return GDK_ACTION_LINK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
11
gnome/gdnd.h
11
gnome/gdnd.h
|
@ -35,8 +35,12 @@ extern GdkAtom dnd_target_atoms[];
|
|||
/* Initializes drag and drop by interning the target convenience atoms */
|
||||
void gdnd_init (void);
|
||||
|
||||
/* Drop the list of URIs in the selection data to the specified directory */
|
||||
int gdnd_drop_on_directory (GdkDragContext *context, GtkSelectionData *selection_data, char *dirname);
|
||||
/* Perform a drop on the specified file entry. This function takes care of
|
||||
* determining how to drop the stuff epending on the type of the file entry.
|
||||
* Returns TRUE if an action was performed, FALSE otherwise (i.e. invalid drop).
|
||||
*/
|
||||
int gdnd_perform_drop (GdkDragContext *context, GtkSelectionData *selection_data,
|
||||
file_entry *dest_fe, char *dest_name);
|
||||
|
||||
/* Test whether the specified context has a certain target type */
|
||||
int gdnd_drag_context_has_target (GdkDragContext *context, TargetType type);
|
||||
|
@ -47,7 +51,8 @@ WPanel *gdnd_find_panel_by_drag_context (GdkDragContext *context, GtkWidget **so
|
|||
/* Computes the final drag action based on the suggested actions and the
|
||||
* specified conditions.
|
||||
*/
|
||||
GdkDragAction gdnd_validate_action (GdkDragContext *context, int same_process, int same_source,
|
||||
GdkDragAction gdnd_validate_action (GdkDragContext *context,
|
||||
int on_desktop, int same_process, int same_source,
|
||||
file_entry *dest_fe, int dest_selected);
|
||||
|
||||
|
||||
|
|
|
@ -776,25 +776,38 @@ panel_icon_list_drag_data_received (GtkWidget *widget,
|
|||
WPanel *panel)
|
||||
{
|
||||
GnomeIconList *gil = GNOME_ICON_LIST (widget);
|
||||
char *dir;
|
||||
file_entry *fe;
|
||||
char *file;
|
||||
int free_file, free_fe;
|
||||
int idx;
|
||||
gboolean reload;
|
||||
|
||||
|
||||
idx = gnome_icon_list_get_icon_at (gil, x, y);
|
||||
if (idx == -1)
|
||||
dir = g_strdup (panel->cwd);
|
||||
else {
|
||||
if (panel->dir.list [idx].f.link_to_dir ||
|
||||
S_ISDIR (panel->dir.list [idx].buf.st_mode))
|
||||
dir = concat_dir_and_file (panel->cwd, panel->dir.list [idx].fname);
|
||||
else
|
||||
dir = g_strdup (panel->cwd);
|
||||
if (idx == -1) {
|
||||
file = panel->cwd;
|
||||
fe = file_entry_from_file (file);
|
||||
if (!fe)
|
||||
return; /* eeeek */
|
||||
|
||||
free_file = FALSE;
|
||||
free_fe = TRUE;
|
||||
} else {
|
||||
file = g_concat_dir_and_file (panel->cwd, panel->dir.list[idx].fname);
|
||||
fe = &panel->dir.list[idx];
|
||||
|
||||
free_file = TRUE;
|
||||
free_fe = FALSE;
|
||||
}
|
||||
|
||||
reload = gdnd_drop_on_directory (context, selection_data, dir);
|
||||
g_free (dir);
|
||||
reload = gdnd_perform_drop (context, selection_data, fe, file);
|
||||
|
||||
if (reload){
|
||||
if (free_file)
|
||||
g_free (file);
|
||||
|
||||
if (free_fe)
|
||||
file_entry_free (fe);
|
||||
|
||||
if (reload) {
|
||||
update_one_panel_widget (panel, 0, UP_KEEPSEL);
|
||||
panel_update_contents (panel);
|
||||
}
|
||||
|
@ -817,26 +830,42 @@ panel_clist_drag_data_received (GtkWidget *widget,
|
|||
WPanel *panel)
|
||||
{
|
||||
GtkCList *clist = GTK_CLIST (widget);
|
||||
char *dir;
|
||||
file_entry *fe;
|
||||
char *file;
|
||||
int free_file, free_fe;
|
||||
int row;
|
||||
int reload;
|
||||
|
||||
if (gtk_clist_get_selection_info (clist, x, y, &row, NULL) == 0)
|
||||
dir = g_strdup (panel->cwd);
|
||||
else {
|
||||
if (gtk_clist_get_selection_info (clist, x, y, &row, NULL) == 0) {
|
||||
file = panel->cwd;
|
||||
fe = file_entry_from_file (file);
|
||||
if (!fe)
|
||||
return; /* eeeek */
|
||||
|
||||
free_file = FALSE;
|
||||
free_fe = TRUE;
|
||||
} else {
|
||||
g_assert (row < panel->count);
|
||||
|
||||
if (S_ISDIR (panel->dir.list [row].buf.st_mode) ||
|
||||
panel->dir.list [row].f.link_to_dir)
|
||||
dir = concat_dir_and_file (panel->cwd, panel->dir.list [row].fname);
|
||||
else
|
||||
dir = g_strdup (panel->cwd);
|
||||
file = g_concat_dir_and_file (panel->cwd, panel->dir.list[row].fname);
|
||||
fe = &panel->dir.list[row];
|
||||
|
||||
free_file = TRUE;
|
||||
free_fe = FALSE;
|
||||
}
|
||||
|
||||
gdnd_drop_on_directory (context, selection_data, dir);
|
||||
g_free (dir);
|
||||
reload = gdnd_perform_drop (context, selection_data, fe, file);
|
||||
|
||||
update_one_panel_widget (panel, 0, UP_KEEPSEL);
|
||||
panel_update_contents (panel);
|
||||
if (free_file)
|
||||
g_free (file);
|
||||
|
||||
if (free_fe)
|
||||
file_entry_free (fe);
|
||||
|
||||
if (reload) {
|
||||
update_one_panel_widget (panel, 0, UP_KEEPSEL);
|
||||
panel_update_contents (panel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -857,6 +886,7 @@ panel_tree_drag_data_received (GtkWidget *widget,
|
|||
GtkDTree *dtree = GTK_DTREE (widget);
|
||||
GtkCTreeNode *node;
|
||||
int row, col;
|
||||
file_entry *fe;
|
||||
char *path;
|
||||
|
||||
if (!gtk_clist_get_selection_info (GTK_CLIST (dtree), x, y, &row, &col))
|
||||
|
@ -866,10 +896,15 @@ panel_tree_drag_data_received (GtkWidget *widget,
|
|||
if (!node)
|
||||
return;
|
||||
gtk_ctree_expand_recursive (GTK_CTREE (dtree), node);
|
||||
|
||||
path = gtk_dtree_get_row_path (dtree, node, 0);
|
||||
fe = file_entry_from_file (path);
|
||||
if (!fe)
|
||||
return; /* eeeek */
|
||||
|
||||
gdnd_drop_on_directory (context, selection_data, path);
|
||||
gdnd_perform_drop (context, selection_data, fe, path);
|
||||
|
||||
file_entry_free (fe);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
|
@ -1073,6 +1108,7 @@ panel_clist_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gin
|
|||
fe = &panel->dir.list[idx];
|
||||
|
||||
action = gdnd_validate_action (context,
|
||||
FALSE,
|
||||
source_widget != NULL,
|
||||
source_widget == widget,
|
||||
fe,
|
||||
|
@ -1187,6 +1223,7 @@ panel_icon_list_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x,
|
|||
fe = (idx == -1) ? NULL : &panel->dir.list[idx];
|
||||
|
||||
action = gdnd_validate_action (context,
|
||||
FALSE,
|
||||
source_widget != NULL,
|
||||
source_widget == widget,
|
||||
fe,
|
||||
|
|
Loading…
Reference in New Issue