art with code

2008-12-13

Filezoo day 32: drag and drop handling

Added a handler for dealing with data dropped onto the Filezoo window. It copies or moves the source uri list (Konqueror, Nautilus, Firefox and others pass the DnD'd files as \r\n-separated strings of URIs) over to the drag target directory using Gnome-VFS. So now I can drag an image from Firefox onto a Filezoo directory and it'll be copied there.

The implementation was a wee bit challenging, since there was very little documentation for doing DragDrop event handling and perhaps even less for the Gnome.Vfs namespace. Here's what I used:

Handling data dropped on the widget, this is from the widget constructor:

TargetEntry[] target_table = new TargetEntry [] {
new TargetEntry ("text/uri-list", 0, 0),
new TargetEntry ("text/plain", 0, 1),
new TargetEntry ("STRING", 0, 1)
};

DragDataReceived += delegate (object sender, DragDataReceivedArgs e) {
string type = e.SelectionData.Type.Name;
Console.WriteLine(type);
Gdk.DragAction action = e.Context.SuggestedAction;
if (type == "text/uri-list" || (type == "text/plain" && IsURI(e.SelectionData.Text))) {
string data = new System.Text.ASCIIEncoding().GetString(e.SelectionData.Data);
string[] uris = data.Split(new char[] {'\r','\n','\0'},
StringSplitOptions.RemoveEmptyEntries);
string msg = action.ToString() + " " + String.join(", ", uris);
} else {
Console.WriteLine("Got {0}", e.SelectionData.Text);
}
);

Gtk.Drag.DestSet (this, DestDefaults.All, target_table,
Gdk.DragAction.Move
| Gdk.DragAction.Copy
| Gdk.DragAction.Ask
);

Using Gnome-VFS XferUriList to do a copy or move:

public static void XferURIs
(Gnome.Vfs.Uri[] sources, Gnome.Vfs.Uri[] targets, bool removeSources)
{
XferURIs (sources, targets, removeSources, ConsoleXferProgressCallback);
}

public static void XferURIs
(Gnome.Vfs.Uri[] sources, Gnome.Vfs.Uri[] targets, bool removeSources,
Gnome.Vfs.XferProgressCallback callback)
{
Gnome.Vfs.Vfs.Initialize ();
Gnome.Vfs.XferOptions mode = Gnome.Vfs.XferOptions.Recursive;
if (removeSources) mode = mode | Gnome.Vfs.XferOptions.Removesource;
Gnome.Vfs.Xfer.XferUriList (
sources, targets, mode,
Gnome.Vfs.XferErrorMode.Query,
Gnome.Vfs.XferOverwriteMode.Replace,
callback
);
}

public static int ConsoleXferProgressCallback (Gnome.Vfs.XferProgressInfo info)
{
switch (info.Status) {
case Gnome.Vfs.XferProgressStatus.Vfserror:
Console.WriteLine("{0}: {1} in {2} -> {3}",
info.Status, info.VfsStatus, info.SourceName, info.TargetName);
return (int)Gnome.Vfs.XferErrorAction.Abort;
case Gnome.Vfs.XferProgressStatus.Overwrite:
Console.WriteLine("{0}: {1} in {2} -> {3}",
info.Status, info.VfsStatus, info.SourceName, info.TargetName);
return (int)Gnome.Vfs.XferOverwriteAction.Abort;
default:
Console.WriteLine("{0} / {1} {2} -> {3}",
info.BytesCopied, info.BytesTotal, info.SourceName, info.TargetName);
return 1;
}
}

(Now I need a pimpin' progress indicator... maybe an arc to the dir with "incoming $STUFF -." or something with ambient notifications. Maybe just pop up a plain jane Gtk progress dialog :P)

Next features on this path would be dragging things around, navigating while dragging (think Finder's space-to-descend on steroids), and handling cut-copy-paste.

No comments:

Blog Archive