Skip to content

Commit d1aa42b

Browse files
committed
add drag and drop function
1 parent 8639564 commit d1aa42b

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

GraphView/graphview.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
from collections import abc, deque
4747
import gi
4848
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib, Pango
49+
import pickle
4950

5051
#-------------------------------------------------------------------------
5152
#
@@ -70,6 +71,7 @@
7071
from gramps.gen.utils.libformatting import FormattingHelper
7172
from gramps.gen.utils.thumbnails import get_thumbnail_path
7273

74+
from gramps.gui.ddtargets import DdTargets
7375
from gramps.gui.dialog import (OptionDialog, ErrorDialog, QuestionDialog2,
7476
WarningDialog)
7577
from gramps.gui.display import display_url
@@ -981,11 +983,13 @@ def __init__(self, view, dbstate, uistate):
981983
self._last_x = 0
982984
self._last_y = 0
983985
self._in_move = False
986+
self._in_drag = False
984987
self.view = view
985988
self.dbstate = dbstate
986989
self.uistate = uistate
987990
self.parser = None
988991
self.active_person_handle = None
992+
self.drag_person = None
989993

990994
self.actions = Actions(dbstate, uistate, self.view.bookmarks)
991995
self.actions.connect('rebuild-graph', self.view.build_tree)
@@ -1152,6 +1156,22 @@ def __init__(self, view, dbstate, uistate):
11521156
self.retest_font = True # flag indicates need to resize font
11531157
self.bold_size = self.norm_size = 0 # font sizes to send to dot
11541158

1159+
# setup drag and drop
1160+
drag_widget = self.get_widget()
1161+
drag_widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [],
1162+
Gdk.DragAction.COPY)
1163+
drag_widget.connect("drag_data_get", self.cb_drag_data_get)
1164+
drag_widget.connect("drag_begin", self.cb_drag_begin)
1165+
drag_widget.connect("drag_end", self.cb_drag_end)
1166+
1167+
tglist = Gtk.TargetList.new([])
1168+
tglist.add(DdTargets.PERSON_LINK.atom_drag_type,
1169+
DdTargets.PERSON_LINK.target_flags,
1170+
DdTargets.PERSON_LINK.app_id)
1171+
# allow drag to a text document, info on drag_get will be 0L !
1172+
tglist.add_text_targets(0)
1173+
drag_widget.drag_source_set_target_list(tglist)
1174+
11551175
def add_popover(self, widget, container):
11561176
"""
11571177
Add popover for button.
@@ -1470,6 +1490,7 @@ def populate(self, active_person):
14701490
if self.uistate.window.get_window().is_visible():
14711491
process_pending_events()
14721492

1493+
self._in_drag = False
14731494
self.clear()
14741495
self.active_person_handle = active_person
14751496

@@ -1620,6 +1641,7 @@ def button_release(self, item, target, event):
16201641
"""
16211642
Exit from scroll mode when button release.
16221643
"""
1644+
self._in_drag = False
16231645
button = event.get_button()[1]
16241646
if((button == 1 or button == 2) and
16251647
event.type == getattr(Gdk.EventType, "BUTTON_RELEASE")):
@@ -1648,6 +1670,35 @@ def motion_notify_event(self, _item, _target, event):
16481670
(event.y_root - self._last_y) * scale_coef)
16491671
self.vadjustment.set_value(new_y)
16501672
return True
1673+
1674+
if self._in_drag and (event.type == Gdk.EventType.MOTION_NOTIFY):
1675+
# start drag when cursor moved more then 5
1676+
# to separate it from simple click
1677+
if ((abs(self._last_x - event.x) > 5)
1678+
or (abs(self._last_x - event.x) > 5)):
1679+
self.uistate.set_busy_cursor(False)
1680+
# Remove all single click events
1681+
for click_item in self.click_events:
1682+
if not click_item.is_destroyed():
1683+
GLib.source_remove(click_item.get_id())
1684+
self.click_events.clear()
1685+
1686+
# translate to drag_widget coords
1687+
drag_widget = self.get_widget()
1688+
scale_coef = self.canvas.get_scale()
1689+
bounds = self.canvas.get_root_item().get_bounds()
1690+
height_canvas = bounds.y2 - bounds.y1
1691+
x = self._last_x * scale_coef - self.hadjustment.get_value()
1692+
y = ((height_canvas + self._last_y) * scale_coef -
1693+
self.vadjustment.get_value())
1694+
1695+
drag_widget.drag_begin_with_coordinates(
1696+
drag_widget.drag_source_get_target_list(),
1697+
Gdk.DragAction.COPY,
1698+
Gdk.ModifierType.BUTTON1_MASK,
1699+
event,
1700+
x, y)
1701+
return True
16511702
return False
16521703

16531704
def set_zoom(self, value):
@@ -1708,6 +1759,11 @@ def select_node(self, item, target, event):
17081759
context = GLib.main_context_default()
17091760
self.click_events.append(context.find_source_by_id(click_event_id))
17101761

1762+
# go to drag mode, applyed on motion event
1763+
self._in_drag = True
1764+
self._last_x = event.x
1765+
self._last_y = event.y
1766+
17111767
elif button == 3 and node_class: # right mouse
17121768
if node_class == 'node':
17131769
self.menu = PopupMenu(self, 'person', handle)
@@ -1723,6 +1779,30 @@ def select_node(self, item, target, event):
17231779

17241780
return True
17251781

1782+
def cb_drag_begin(self, widget, data):
1783+
"""Set up some inital conditions for drag. Set up icon."""
1784+
self._in_drag = True
1785+
widget.drag_source_set_icon_name('gramps-person')
1786+
1787+
def cb_drag_end(self, widget, data):
1788+
"""Set up some inital conditions for drag. Set up icon."""
1789+
self._in_drag = False
1790+
1791+
def cb_drag_data_get(self, widget, context, sel_data, info, time):
1792+
"""
1793+
Returned parameters after drag.
1794+
Specified for 'person-link', for others return text info about person.
1795+
"""
1796+
tgs = [x.name() for x in context.list_targets()]
1797+
if info == DdTargets.PERSON_LINK.app_id:
1798+
data = (DdTargets.PERSON_LINK.drag_type,
1799+
id(self), self.drag_person.handle, 0)
1800+
sel_data.set(sel_data.get_target(), 8, pickle.dumps(data))
1801+
elif ('TEXT' in tgs or 'text/plain' in tgs) and info == 0:
1802+
format_helper = FormattingHelper(self.dbstate)
1803+
sel_data.set_text(
1804+
format_helper.format_person(self.drag_person, 11),-1)
1805+
17261806
def find_a_parent(self, handle):
17271807
"""
17281808
Locate a parent from the first family that the selected person is a

0 commit comments

Comments
 (0)