apostrophe/apostrophe/text_view_drag_drop_handler.py

93 lines
3.3 KiB
Python

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