46
46
from collections import abc , deque
47
47
import gi
48
48
from gi .repository import Gtk , Gdk , GdkPixbuf , GLib , Pango
49
- import pickle
50
49
51
50
#-------------------------------------------------------------------------
52
51
#
71
70
from gramps .gen .utils .libformatting import FormattingHelper
72
71
from gramps .gen .utils .thumbnails import get_thumbnail_path
73
72
74
- from gramps .gui .ddtargets import DdTargets
75
73
from gramps .gui .dialog import (OptionDialog , ErrorDialog , QuestionDialog2 ,
76
74
WarningDialog )
77
75
from gramps .gui .display import display_url
137
135
sys .path .append (os .path .abspath (os .path .dirname (__file__ )))
138
136
from search_widget import SearchWidget , Popover , ListBoxRow , get_person_tooltip
139
137
from avatars import Avatars
138
+ from drag_n_drop import DragAndDrop
140
139
141
140
142
141
#-------------------------------------------------------------------------
@@ -983,13 +982,11 @@ def __init__(self, view, dbstate, uistate):
983
982
self ._last_x = 0
984
983
self ._last_y = 0
985
984
self ._in_move = False
986
- self ._in_drag = False
987
985
self .view = view
988
986
self .dbstate = dbstate
989
987
self .uistate = uistate
990
988
self .parser = None
991
989
self .active_person_handle = None
992
- self .drag_person = None
993
990
994
991
self .actions = Actions (dbstate , uistate , self .view .bookmarks )
995
992
self .actions .connect ('rebuild-graph' , self .view .build_tree )
@@ -1157,10 +1154,7 @@ def __init__(self, view, dbstate, uistate):
1157
1154
self .bold_size = self .norm_size = 0 # font sizes to send to dot
1158
1155
1159
1156
# setup drag and drop
1160
- drag_widget = self .get_widget ()
1161
- drag_widget .connect ("drag_data_get" , self .cb_drag_data_get )
1162
- drag_widget .connect ("drag_begin" , self .cb_drag_begin )
1163
- drag_widget .connect ("drag_end" , self .cb_drag_end )
1157
+ self .dnd = DragAndDrop (self .get_widget (), self .dbstate )
1164
1158
1165
1159
def add_popover (self , widget , container ):
1166
1160
"""
@@ -1175,7 +1169,7 @@ def add_popover(self, widget, container):
1175
1169
def build_spinner (self , icon , start , end , tooltip , conf_const ):
1176
1170
"""
1177
1171
Build spinner with icon and pack it into box.
1178
- Chenges apply to config with delay.
1172
+ Changes apply to config with delay.
1179
1173
"""
1180
1174
box = Gtk .Box (orientation = Gtk .Orientation .HORIZONTAL )
1181
1175
img = Gtk .Image .new_from_icon_name (icon , Gtk .IconSize .MENU )
@@ -1480,8 +1474,8 @@ def populate(self, active_person):
1480
1474
if self .uistate .window .get_window ().is_visible ():
1481
1475
process_pending_events ()
1482
1476
1483
- self ._in_drag = False # True - when drag can be started
1484
- self . _do_drag = False # True - when drag is started
1477
+ self .dnd . stop ()
1478
+
1485
1479
self .clear ()
1486
1480
self .active_person_handle = active_person
1487
1481
@@ -1632,7 +1626,7 @@ def button_release(self, item, target, event):
1632
1626
"""
1633
1627
Exit from scroll mode when button release.
1634
1628
"""
1635
- self ._in_drag = False
1629
+ self .dnd . stop ()
1636
1630
button = event .get_button ()[1 ]
1637
1631
if ((button == 1 or button == 2 ) and
1638
1632
event .type == getattr (Gdk .EventType , "BUTTON_RELEASE" )):
@@ -1665,7 +1659,7 @@ def motion_notify_event(self, _item, _target, event):
1665
1659
if not (event .type == Gdk .EventType .MOTION_NOTIFY ):
1666
1660
return False
1667
1661
1668
- if self ._in_drag and ( not self . _do_drag ):
1662
+ if self .dnd . is_ready ( ):
1669
1663
# start drag when cursor moved more then 5
1670
1664
# to separate it from simple click
1671
1665
if ((abs (self ._last_x - event .x_root ) > 5 )
@@ -1682,32 +1676,8 @@ def motion_notify_event(self, _item, _target, event):
1682
1676
x = self ._last_x * scale_coef - self .hadjustment .get_value ()
1683
1677
y = self ._last_y * scale_coef - self .vadjustment .get_value ()
1684
1678
1685
- # setup targets
1686
- tglist = Gtk .TargetList .new ([])
1687
- if self .drag_person is not None :
1688
- tglist .add (DdTargets .PERSON_LINK .atom_drag_type ,
1689
- DdTargets .PERSON_LINK .target_flags ,
1690
- DdTargets .PERSON_LINK .app_id ,
1691
- )
1692
- # allow drag to a text document, info on drag_get will be 0
1693
- tglist .add_text_targets (0 )
1694
- if self .drag_family is not None :
1695
- tglist .add (DdTargets .FAMILY_LINK .atom_drag_type ,
1696
- DdTargets .FAMILY_LINK .target_flags ,
1697
- DdTargets .FAMILY_LINK .app_id ,
1698
- )
1699
- # allow drag to a text document, info on drag_get will be 1
1700
- tglist .add_text_targets (1 )
1701
-
1702
- # start drag
1703
- drag_widget = self .get_widget ()
1704
- drag_widget .drag_begin_with_coordinates (
1705
- tglist ,
1706
- Gdk .DragAction .COPY ,
1707
- 1 , # left mouse button = 1
1708
- event ,
1709
- x , y )
1710
- return True
1679
+ self .dnd .start_drag (x , y , event )
1680
+
1711
1681
return False
1712
1682
1713
1683
def set_zoom (self , value ):
@@ -1750,16 +1720,8 @@ def select_node(self, item, target, event):
1750
1720
return False
1751
1721
1752
1722
if button == 1 and node_class : # left mouse
1753
- # set drag mode, it will be applyed on motion event
1754
- self .drag_person = None
1755
- self .drag_family = None
1756
- if node_class == 'node' :
1757
- self .drag_person = self .dbstate .db .get_person_from_handle (
1758
- handle )
1759
- if node_class == 'familynode' :
1760
- self .drag_family = self .dbstate .db .get_family_from_handle (
1761
- handle )
1762
- self ._in_drag = True
1723
+ # set drag mode, it will be applied on motion event
1724
+ self .dnd .set_ready (node_class , handle )
1763
1725
self ._last_x = event .x_root
1764
1726
self ._last_y = event .y_root
1765
1727
@@ -1797,62 +1759,6 @@ def select_node(self, item, target, event):
1797
1759
1798
1760
return True
1799
1761
1800
- def cb_drag_begin (self , widget , context ):
1801
- """
1802
- Called on start drag.
1803
- """
1804
- self ._do_drag = True
1805
- tgs = [x .name () for x in context .list_targets ()]
1806
- # set icon depending on person or family drag
1807
- if DdTargets .PERSON_LINK .drag_type in tgs :
1808
- Gtk .drag_set_icon_name (context , 'gramps-person' , 0 , 0 )
1809
- if DdTargets .FAMILY_LINK .drag_type in tgs :
1810
- Gtk .drag_set_icon_name (context , 'gramps-family' , 0 , 0 )
1811
-
1812
- def cb_drag_end (self , widget , context ):
1813
- """
1814
- Called when drag is end.
1815
- """
1816
- self ._in_drag = False
1817
- self ._do_drag = False
1818
-
1819
- def cb_drag_data_get (self , widget , context , sel_data , info , time ):
1820
- """
1821
- Returned parameters after drag.
1822
- Specified for 'person-link' and 'family-link',
1823
- also to return text info about person or family.
1824
- """
1825
- tgs = [x .name () for x in context .list_targets ()]
1826
-
1827
- if info == DdTargets .PERSON_LINK .app_id :
1828
- data = (DdTargets .PERSON_LINK .drag_type ,
1829
- id (widget ), self .drag_person .handle , 0 )
1830
- sel_data .set (sel_data .get_target (), 8 , pickle .dumps (data ))
1831
- elif info == DdTargets .FAMILY_LINK .app_id :
1832
- data = (DdTargets .FAMILY_LINK .drag_type ,
1833
- id (widget ), self .drag_family .handle , 0 )
1834
- sel_data .set (sel_data .get_target (), 8 , pickle .dumps (data ))
1835
- elif ('TEXT' in tgs or 'text/plain' in tgs ):
1836
- if info == 0 :
1837
- format_helper = FormattingHelper (self .dbstate )
1838
- sel_data .set_text (
1839
- format_helper .format_person (self .drag_person , 11 ),- 1 )
1840
- if info == 1 :
1841
- f_handle = self .drag_family .get_father_handle ()
1842
- m_handle = self .drag_family .get_mother_handle ()
1843
- if f_handle :
1844
- father = self .dbstate .db .get_person_from_handle (f_handle )
1845
- father = displayer .display (father )
1846
- else :
1847
- father = '...'
1848
- if m_handle :
1849
- mother = self .dbstate .db .get_person_from_handle (m_handle )
1850
- mother = displayer .display (mother )
1851
- else :
1852
- mother = '...'
1853
- sel_data .set_text (
1854
- _ ('Family of %s and %s' ) % (father , mother ), - 1 )
1855
-
1856
1762
def find_a_parent (self , handle ):
1857
1763
"""
1858
1764
Locate a parent from the first family that the selected person is a
0 commit comments