[polari/gnome-3-20] pasteManager: Turn drop target support into a GObject interface
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [polari/gnome-3-20] pasteManager: Turn drop target support into a GObject interface
- Date: Tue, 10 May 2016 19:56:26 +0000 (UTC)
commit 0c5518b4b73bb65078f84906e03a62d6bf3e1406
Author: Florian Müllner <fmuellner gnome org>
Date: Fri Feb 12 00:54:07 2016 +0100
pasteManager: Turn drop target support into a GObject interface
The paste manager has some old support for turning widgets into
drop targets for supported types and upload dropped data to the
appropriate paste service. While sometimes useful, without any
confirmation we ended up with accidental uploads more often than
not and disabled it.
With the re-enabled paste support from last cycle we now have a
confirmation UI that we can leverage for processing drops as
well - however this requires separating drop handling from doing
the actual upload, and a singleton like PasteManager is fairly
ill-suited to connect the widget receiving the drop with the one
asking for confirmation.
So instead, turn drop target support into an interface that objects
can implement to have appropriate signals emitted for each drop on
any widget set up as drop destination via addTargets().
https://bugzilla.gnome.org/show_bug.cgi?id=766068
src/pasteManager.js | 176 ++++++++++++++++-----------------------------------
1 files changed, 55 insertions(+), 121 deletions(-)
---
diff --git a/src/pasteManager.js b/src/pasteManager.js
index 848d0a7..a7d4ccf 100644
--- a/src/pasteManager.js
+++ b/src/pasteManager.js
@@ -2,6 +2,7 @@ const Gdk = imports.gi.Gdk;
const GdkPixbuf = imports.gi.GdkPixbuf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Polari = imports.gi.Polari;
const Tp = imports.gi.TelepathyGLib;
@@ -18,25 +19,54 @@ const DndTargetType = {
IMAGE: 3,
};
+function _getTargetForContentType(contentType) {
+ if (Gio.content_type_is_a(contentType, 'text/plain'))
+ return DndTargetType.TEXT;
+ else if (Gio.content_type_is_a(contentType, 'image/*'))
+ return DndTargetType.IMAGE;
+ else
+ return 0;
+}
+
+
const PasteManager = new Lang.Class({
Name: 'PasteManager',
_init: function() {
- this._widgets = [];
-
- this._dragHighlight = false;
- this._dragDataReceived = false;
- this._dragPending = false;
-
- this._roomManager = ChatroomManager.getDefault();
},
addWidget: function(widget) {
// auto-paste needs some design; disable for now
return;
+ },
- if (this._widgets.indexOf(widget) != -1)
- return;
+ pasteContent: function(content, title, callback) {
+ if (typeof content == 'string') {
+ Utils.gpaste(content, title, callback);
+ } else if (content instanceof GdkPixbuf.Pixbuf) {
+ Utils.imgurPaste(content, title, callback);
+ } else {
+ throw new Error('Unhandled content type');
+ }
+ }
+});
+
+const DropTargetIface = new Lang.Interface({
+ Name: 'DropTargetIface',
+ Requires: [GObject.Object],
+ Properties: {
+ 'can-drop': GObject.ParamSpec.boolean('can-drop', '', '',
+ GObject.ParamFlags.READABLE,
+ false)
+ },
+ Signals: {
+ 'text-dropped': { param_types: [GObject.TYPE_STRING] },
+ 'image-dropped': { param_types: [GdkPixbuf.Pixbuf.$gtype] },
+ 'file-dropped': { param_types: [Gio.File.$gtype] }
+ },
+
+ addTargets: function(widget) {
+ this._dragHighlight = false;
widget.drag_dest_set(0, [], Gdk.DragAction.COPY);
@@ -55,30 +85,12 @@ const PasteManager = new Lang.Class({
widget.connect('drag-motion', Lang.bind(this, this._onDragMotion));
widget.connect('drag-data-received',
Lang.bind(this, this._onDragDataReceived));
-
- widget.connect('destroy', Lang.bind(this,
- function(w) {
- for (let i = 0; i < this._widgets.length; i++)
- if (this._widgets[i] == w) {
- this._widgets.slice(i, 1);
- break;
- }
- }));
-
- this._widgets.push(widget);
- },
-
- pasteContent: function(content, title, callback) {
- if (typeof content == 'string') {
- Utils.gpaste(content, title, callback);
- } else if (content instanceof GdkPixbuf.Pixbuf) {
- Utils.imgurPaste(content, title, callback);
- } else {
- throw new Error('Unhandled content type');
- }
},
_onDragDrop: function(widget, context, x, y, time) {
+ if (!this.can_drop)
+ return Gdk.EVENT_PROPAGATE;
+
if (!Polari.drag_dest_supports_target(widget, context, null))
return Gdk.EVENT_PROPAGATE;
@@ -89,34 +101,22 @@ const PasteManager = new Lang.Class({
_onDragLeave: function(widget, context, time) {
widget.drag_unhighlight();
this._dragHighlight = false;
- this._dragDataReceived = false;
- this._dragPending = false;
},
_onDragMotion: function(widget, context, x, y, time) {
+ if (!this.can_drop)
+ return Gdk.EVENT_PROPAGATE;
+
if (!Polari.drag_dest_supports_target(widget, context, null))
return Gdk.EVENT_PROPAGATE;
let info = Polari.drag_dest_find_target(widget, context);
switch (info) {
case DndTargetType.TEXT:
- //case DndTargetType.IMAGE:
- Gdk.drag_status(context, Gdk.DragAction.COPY, time);
- break;
+ case DndTargetType.IMAGE:
case DndTargetType.URI_LIST:
- /* FIXME: the latter doesn't seem to work, pretend to support
- all drops */
Gdk.drag_status(context, Gdk.DragAction.COPY, time);
break;
-
- let action = 0;
- if (!this._dragDataReceived) {
- this._dragPending = true;
- Polari.drag_dest_request_data(widget, context, time);
- } else {
- Gdk.drag_status(context, action, time);
- }
- break;
default:
return Gdk.EVENT_PROPAGATE;
}
@@ -131,28 +131,6 @@ const PasteManager = new Lang.Class({
_onDragDataReceived: function(widget, context, x, y, data, info, time) {
- if (this._dragPending) {
- this._dragPending = false;
-
- if (info != DndTargetType.URI_LIST) {
- Gdk.drag_status(context, 0, time);
- return;
- }
-
- let uris = data.get_uris();
- this._dragDataReceived = true;
- // TODO: handle multiple files ...
- let file = Gio.File.new_for_uri(uris[0]);
- this._lookupFileInfo(file, Lang.bind(this,
- function(name, targetType) {
- let action = 0;
- if (targetType == DndTargetType.TEXT)
- action = Gdk.DragAction.COPY;
- Gdk.drag_status(context, action, time);
- }));
- return;
- }
-
if (info == DndTargetType.URI_LIST) {
let uris = data.get_uris();
if (!uris) {
@@ -163,43 +141,30 @@ const PasteManager = new Lang.Class({
// TODO: handle multiple files ...
let file = Gio.File.new_for_uri(uris[0]);
this._lookupFileInfo(file, Lang.bind(this,
- function(name, targetType) {
- let canHandle = // targetType != 0;
- targetType == DndTargetType.TEXT;
-
+ function(targetType) {
+ let canHandle = targetType != 0;
if (canHandle)
- this._handleFileContent(file, displayName, targetType);
+ this.emit('file-dropped', file);
Gtk.drag_finish(context, canHandle, false, time);
}));
} else {
let success = false;
switch(info) {
case DndTargetType.TEXT:
- this.pasteText(data.get_text());
+ this.emit('text-dropped', data.get_text());
success = true;
break;
case DndTargetType.IMAGE:
- // not implemented
- //this._pasteImage(data.get_pixbuf());
+ this.emit('image-dropped', data.get_pixbuf());
+ success = true;
break;
}
Gtk.drag_finish(context, success, false, time);
}
},
- _getTargetForContentType: function(contentType) {
- if (Gio.content_type_is_a(contentType, 'text/plain'))
- return DndTargetType.TEXT;
- else if (Gio.content_type_is_a(contentType, 'image/*'))
- return DndTargetType.IMAGE;
- else
- return 0;
- },
-
_lookupFileInfo: function(file, callback) {
- let attr = Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE + ',' +
- Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME;
- file.query_info_async(attr,
+ file.query_info_async(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT,
null, Lang.bind(this,
@@ -208,43 +173,12 @@ const PasteManager = new Lang.Class({
try {
fileInfo = file.query_info_finish(res);
} catch(e) {
- logError(e);
- callback(null, 0);
+ callback(0);
Gtk.drag_finish(context, false, false, time);
}
- let displayName = fileInfo.get_display_name();
let contentType = fileInfo.get_content_type();
- let targetType = this._getTargetForContentType(contentType);
- callback(displayName, targetType);
+ callback(_getTargetForContentType(contentType));
}))
- },
-
-
- _handleFileContent: function(file, name, type) {
- let app = Gio.Application.get_default();
- let n = new UploadNotification(name);
- app.notificationQueue.addNotification(n);
-
- if (type == DndTargetType.TEXT) {
- file.load_contents_async(null, Lang.bind(this,
- function(f, res) {
- let [, contents, ,] = f.load_contents_finish(res);
- this._pasteText(contents.toString(), n);
- }));
- } else if (type == DndTargetType.IMAGE) {
- file.read_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this,
- function(f, res) {
- let stream = f.read_finish(res);
- GdkPixbuf.Pixbuf.new_from_stream_async(stream, null,
- Lang.bind(this, function(stream, res) {
- let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(res);
- this._pasteImage(pixbuf, n);
- }));
- }));
- } else {
- log('Unhandled type');
- n.close();
- }
}
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]