[polari/wip/fmuellner/drop-target-3-20: 1/6] entryArea: Support pasting text/image content from files



commit 3950f45671323d0817ea12c2cd67ce2c83c95a95
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Feb 12 05:30:45 2016 +0100

    entryArea: Support pasting text/image content from files
    
    For users, it is not immediately obvious why they can copy file contents
    in a text/image editor and paste it into Polari for uploading, but trying
    to paste the file itself only inserts a (most likely useless) URI.
    Instead, accept file pastes and upload the contents to the appropriate
    service if possible.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=766066

 src/entryArea.js |   77 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 61 insertions(+), 16 deletions(-)
---
diff --git a/src/entryArea.js b/src/entryArea.js
index 3fc9810..2a32ca1 100644
--- a/src/entryArea.js
+++ b/src/entryArea.js
@@ -23,7 +23,8 @@ const ChatEntry = new Lang.Class({
     Extends: Gtk.Entry,
     Signals: { 'text-pasted': { param_types: [GObject.TYPE_STRING,
                                               GObject.TYPE_INT] },
-               'image-pasted': { param_types: [GdkPixbuf.Pixbuf.$gtype] } },
+               'image-pasted': { param_types: [GdkPixbuf.Pixbuf.$gtype] },
+               'file-pasted': { param_types: [Gio.File.$gtype] } },
 
     _init: function(params) {
         this.parent(params);
@@ -38,21 +39,12 @@ const ChatEntry = new Lang.Class({
         }
 
         let clipboard = Gtk.Clipboard.get_default(this.get_display());
-        clipboard.request_text(Lang.bind(this,
-            function(clipboard, text) {
-                if (text == null)
-                    return;
-               text = text.trim();
-
-                let nLines = text.split('\n').length;
-                if (nLines >= MAX_LINES) {
-                    this.emit('text-pasted', text, nLines);
-                    return;
-                }
-
-                this._useDefaultHandler = true;
-                this.emit('paste-clipboard');
-                this._useDefaultHandler = false;
+        clipboard.request_uris(Lang.bind(this,
+            function(clipboard, uris) {
+                if (uris && uris.length)
+                    this.emit('file-pasted', Gio.File.new_for_uri(uris[0]));
+                else
+                    clipboard.request_text(Lang.bind(this, this._onTextReceived));
             }));
 
         clipboard.request_image(Lang.bind(this,
@@ -62,6 +54,22 @@ const ChatEntry = new Lang.Class({
                 this.emit('image-pasted', pixbuf);
             }));
     },
+
+    _onTextReceived: function(clipboard, text) {
+        if (text == null)
+            return;
+        text = text.trim();
+
+        let nLines = text.split('\n').length;
+        if (nLines >= MAX_LINES) {
+            this.emit('text-pasted', text, nLines);
+            return;
+        }
+
+        this._useDefaultHandler = true;
+        this.emit('paste-clipboard');
+        this._useDefaultHandler = false;
+    }
 });
 
 const EntryArea = new Lang.Class({
@@ -118,6 +126,7 @@ const EntryArea = new Lang.Class({
 
         this._chatEntry.connect('text-pasted', Lang.bind(this, this._onTextPasted));
         this._chatEntry.connect('image-pasted', Lang.bind(this, this._onImagePasted));
+        this._chatEntry.connect('file-pasted', Lang.bind(this, this._onFilePasted));
         this._chatEntry.connect('changed', Lang.bind(this, this._onEntryChanged));
 
         this._chatEntry.connect('activate', Lang.bind(this,
@@ -249,6 +258,42 @@ const EntryArea = new Lang.Class({
         this._setPasteContent(pixbuf);
     },
 
+    _onFilePasted: function(entry, file) {
+        file.query_info_async(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                              Gio.FileQueryInfoFlags.NONE,
+                              GLib.PRIORITY_DEFAULT, null,
+                              Lang.bind(this, this._onFileInfoReady));
+    },
+
+    _onFileInfoReady: function(file, res) {
+        let fileInfo = null;
+        try {
+            fileInfo = file.query_info_finish(res);
+        } catch(e) {
+            return;
+        }
+
+        let contentType = fileInfo.get_content_type();
+
+        if (Gio.content_type_is_a(contentType, 'text/plain'))
+            file.load_contents_async(null, Lang.bind(this,
+                function(f, res) {
+                    let [, contents, ,] = f.load_contents_finish(res);
+                    let text = contents.toString();
+                    this.pasteText(text, text.length);
+                }));
+        else if (Gio.content_type_is_a(contentType, '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);
+                        }));
+                }));
+    },
+
     _onPasteClicked: function() {
         let title;
         let nick = this._room.channel.connection.self_contact.alias;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]