import mimetypes import urllib from gettext import gettext as _ from os.path import basename from apostrophe.settings import Settings from gi.repository import Gtk (TARGET_URI, TARGET_TEXT) = range(2) class DragDropHandler: TARGET_URI = None def __init__(self, text_view, *targets): super().__init__() self.settings = Settings.new() self.target_list = Gtk.TargetList.new([]) if TARGET_URI in targets: self.target_list.add_uri_targets(TARGET_URI) if TARGET_TEXT in targets: self.target_list.add_text_targets(TARGET_TEXT) text_view.drag_dest_set_target_list(self.target_list) text_view.connect_after('drag-data-received', self.on_drag_data_received) def on_drag_data_received(self, text_view, drag_context, _x, _y, data, info, time): """Handle drag and drop events""" text_buffer = text_view.get_buffer() if info == TARGET_URI: uris = data.get_uris() for uri in uris: name = basename(urllib.parse.unquote_plus(uri)) mime = mimetypes.guess_type(uri) if mime[0] is not None and mime[0].startswith('image/'): basepath = self.settings.get_string("open-file-path") basepath = urllib.parse.quote(basepath) if uri.startswith("file://"): uri = uri[7:] # for handling local URIs we need to substract the basepath # except when it is "/" (document not saved) if uri.startswith(basepath) and basepath != "/": uri = uri[len(basepath)+1:] text = "![{}]({})".format(name, uri) limit_left = 2 limit_right = len(name) else: text = "[{}]({})".format(name, uri) limit_left = 1 limit_right = len(name) elif info == TARGET_TEXT: text = data.get_text() # delete automatically added DnD text insert_mark = text_buffer.get_insert() cursor_iter_r = text_buffer.get_iter_at_mark(insert_mark) cursor_iter_l = cursor_iter_r.copy() cursor_iter_l.backward_chars(len(data.get_text())) text_buffer.delete(cursor_iter_l, cursor_iter_r) if text.startswith(("http://", "https://", "www.")): text = "[{}]({})".format(_("web page"), text) limit_left = 1 limit_right = len(_("web page")) else: limit_left = 0 limit_right = 0 text_buffer.place_cursor(text_buffer.get_iter_at_mark( text_buffer.get_mark('gtk_drag_target'))) text_buffer.insert_at_cursor(text) insert_mark = text_buffer.get_insert() selection_bound = text_buffer.get_selection_bound() cursor_iter = text_buffer.get_iter_at_mark(insert_mark) cursor_iter.backward_chars(len(text) - limit_left) text_buffer.move_mark(insert_mark, cursor_iter) cursor_iter.forward_chars(limit_right) text_buffer.move_mark(selection_bound, cursor_iter) Gtk.drag_finish(drag_context, True, True, time) text_view.get_toplevel().present_with_time(time) return False