2005-03-24 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
* src/DdTargets.py: new module to manage drag and drop target data. * src/Makefile.am: added DdTargets.py * src/ScratchPad.py: modified to use DdTargets.py. This is the first stage. I will look at modifying EditPersons.py to use DdTargets.py next svn: r4231
This commit is contained in:
		
							
								
								
									
										187
									
								
								src/DdTargets.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/DdTargets.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
# -*- python -*-
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
# Gramps - a GTK+/GNOME based genealogy program
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2000-2005  Donald N. Allingham
 | 
			
		||||
#
 | 
			
		||||
# This program is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# $Id$
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
   This module provides management of all the drag and drop target information
 | 
			
		||||
   required by gramps widgets.
 | 
			
		||||
 | 
			
		||||
   Adding a new drag and drop target.
 | 
			
		||||
   ==================================
 | 
			
		||||
 | 
			
		||||
   To add a new target: add a new _DdType to in _DdTargets.__init__ and
 | 
			
		||||
   then add this new type to the list returned from either all_text_types()
 | 
			
		||||
   and all_text_targets() or  or all_gramps_targets() and all_gramps_types().
 | 
			
		||||
 | 
			
		||||
   Usage
 | 
			
		||||
   =====
 | 
			
		||||
 | 
			
		||||
   The module defines a singleton instance of _DdTargets called DdTargets.
 | 
			
		||||
 | 
			
		||||
   from DdTargets import DdTargets
 | 
			
		||||
 | 
			
		||||
   drag_dest_set(gtk.DEST_DEFAULT_ALL,
 | 
			
		||||
                 DdTargets.all_targets(),
 | 
			
		||||
                 ACTION_COPY)
 | 
			
		||||
   
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
class _DdType:
 | 
			
		||||
    """Represents the fields needed by a drag and drop traget."""
 | 
			
		||||
    
 | 
			
		||||
    _APP_ID_OFFSET = 40  # Starting value of app_ids
 | 
			
		||||
    
 | 
			
		||||
    def __init__(self,container,drag_type,target_flags=0,app_id=None):
 | 
			
		||||
        """Create a new DdType:
 | 
			
		||||
 | 
			
		||||
        drag_type: string holding the name of the type.
 | 
			
		||||
        target_flags: int value that will be passed to drop target.
 | 
			
		||||
        app_id: integer target id passed to drop target.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.drag_type = drag_type
 | 
			
		||||
        self.target_flags = target_flags
 | 
			
		||||
        self.app_id = app_id or self._calculate_id()
 | 
			
		||||
        container.insert(self)
 | 
			
		||||
 | 
			
		||||
    def _calculate_id(self):
 | 
			
		||||
        """return the next available app_id."""
 | 
			
		||||
        
 | 
			
		||||
        id = _DdType._APP_ID_OFFSET
 | 
			
		||||
        _DdType._APP_ID_OFFSET += 1
 | 
			
		||||
        return id
 | 
			
		||||
 | 
			
		||||
    def target(self):
 | 
			
		||||
        """return the full target information in the format
 | 
			
		||||
        required by the Gtk functions."""
 | 
			
		||||
        return (self.drag_type,self.target_flags,self.app_id)
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
class _DdTargets(object):
 | 
			
		||||
    """A single class that manages all the drag and drop targets."""
 | 
			
		||||
    
 | 
			
		||||
    _instance = None # Singleton instance
 | 
			
		||||
 | 
			
		||||
    def __new__(cls):
 | 
			
		||||
        """Ensure that we never have more than one instance."""
 | 
			
		||||
        
 | 
			
		||||
        if _DdTargets._instance is not None:
 | 
			
		||||
            return _DdTargets._instance
 | 
			
		||||
        _DdTargets._instance = object.__new__(cls)
 | 
			
		||||
        return _DdTargets._instance        
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        """Set up the drag and drop targets."""
 | 
			
		||||
        
 | 
			
		||||
        self._type_map = {}
 | 
			
		||||
        self._app_id_map = {}
 | 
			
		||||
        
 | 
			
		||||
        self.URL       = _DdType(self,'url',0,0)
 | 
			
		||||
        self.EVENT     = _DdType(self,'pevent',0,1)
 | 
			
		||||
        self.ATTRIBUTE = _DdType(self,'pattr',0,2)
 | 
			
		||||
        self.ADDRESS   = _DdType(self,'paddr',0,3)
 | 
			
		||||
        self.SOURCEREF = _DdType(self,'srcref',0,4)
 | 
			
		||||
 | 
			
		||||
        self.TEXT          = _DdType(self,'TEXT',0,1)
 | 
			
		||||
        self.TEXT_MIME     = _DdType(self,'text/plain',0,0)
 | 
			
		||||
        self.STRING        = _DdType(self,'STRING', 0, 2)
 | 
			
		||||
        self.COMPOUND_TEXT = _DdType(self,'COMPOUND_TEXT', 0, 3)
 | 
			
		||||
        self.UTF8_STRING   = _DdType(self,'UTF8_STRING', 0, 4)
 | 
			
		||||
 | 
			
		||||
    def insert(self,dd_type):
 | 
			
		||||
        """Add a target to the lookup lists. These lists are
 | 
			
		||||
        used purely for performance reasons."""
 | 
			
		||||
        
 | 
			
		||||
        self._type_map[dd_type.drag_type] = dd_type
 | 
			
		||||
        self._app_id_map[dd_type.app_id] = dd_type
 | 
			
		||||
 | 
			
		||||
    def get_dd_type_from_type_name(self,type_name):
 | 
			
		||||
        return self._type_map.get(type_name,None)
 | 
			
		||||
 | 
			
		||||
    def get_dd_type_from_app_id(self,app_id):
 | 
			
		||||
        return self._app_id_map.get(app_id,None)
 | 
			
		||||
 | 
			
		||||
    def is_text_type(self,type_name):
 | 
			
		||||
        return type_name in self.all_text_types()
 | 
			
		||||
 | 
			
		||||
    def all_text_types(self):
 | 
			
		||||
        """return a list of all the type names that could be
 | 
			
		||||
        used as the type of a string."""
 | 
			
		||||
        
 | 
			
		||||
        return (self.TEXT.drag_type,
 | 
			
		||||
                self.TEXT_MIME.drag_type,
 | 
			
		||||
                self.STRING.drag_type,
 | 
			
		||||
                self.COMPOUND_TEXT.drag_type,
 | 
			
		||||
                self.UTF8_STRING.drag_type)
 | 
			
		||||
    
 | 
			
		||||
    def is_gramps_type(self,type_name):
 | 
			
		||||
        return type_name in self.all_gramps_types()
 | 
			
		||||
 | 
			
		||||
    def all_gramps_types(self):
 | 
			
		||||
        """return a list of all the type names that are internal
 | 
			
		||||
        to gramps."""
 | 
			
		||||
        
 | 
			
		||||
        return (self.URL.drag_type,
 | 
			
		||||
                self.EVENT.drag_type,
 | 
			
		||||
                self.ATTRIBUTE.drag_type,
 | 
			
		||||
                self.ADDRESS.drag_type,
 | 
			
		||||
                self.SOURCEREF.drag_type)
 | 
			
		||||
 | 
			
		||||
    def all_text_targets(self):
 | 
			
		||||
        """return a list of all the targets that could be used
 | 
			
		||||
        for text."""
 | 
			
		||||
        
 | 
			
		||||
        return (self.TEXT.target(),
 | 
			
		||||
                self.TEXT_MIME.target(),
 | 
			
		||||
                self.STRING.target(),
 | 
			
		||||
                self.COMPOUND_TEXT.target(),
 | 
			
		||||
                self.UTF8_STRING.target())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def all_gramps_targets(self):
 | 
			
		||||
        """return a list off the internal gramps targets."""
 | 
			
		||||
        
 | 
			
		||||
        return (self.URL.target(),
 | 
			
		||||
                self.EVENT.target(),
 | 
			
		||||
                self.ATTRIBUTE.target(),
 | 
			
		||||
                self.ADDRESS.target(),
 | 
			
		||||
                self.SOURCEREF.target())
 | 
			
		||||
 | 
			
		||||
    def all_targets(self):
 | 
			
		||||
        """return a list of all the known targets."""
 | 
			
		||||
        return self.all_gramps_targets() + self.all_text_targets()
 | 
			
		||||
 | 
			
		||||
# Create the singleton instance.
 | 
			
		||||
 | 
			
		||||
DdTargets = _DdTargets()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Below here is test code.
 | 
			
		||||
#
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
 | 
			
		||||
    print repr(DdTargets.all_text_types())
 | 
			
		||||
    print repr(DdTargets.URL)
 | 
			
		||||
    print DdTargets.is_gramps_type('pevent')
 | 
			
		||||
@@ -40,6 +40,7 @@ gdir_PYTHON = \
 | 
			
		||||
	DateHandler.py\
 | 
			
		||||
	DateDisplay.py\
 | 
			
		||||
	DbPrompter.py\
 | 
			
		||||
	DdTargets.py\
 | 
			
		||||
	DisplayModels.py\
 | 
			
		||||
	DisplayTrace.py\
 | 
			
		||||
	EditPerson.py\
 | 
			
		||||
 
 | 
			
		||||
@@ -54,39 +54,41 @@ from gtk.gdk import ACTION_COPY, BUTTON1_MASK
 | 
			
		||||
#
 | 
			
		||||
#-------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
text_targets =  ['text/plain',
 | 
			
		||||
                 'TEXT',
 | 
			
		||||
                 'STRING',
 | 
			
		||||
                 'COMPOUND_TEXT',
 | 
			
		||||
                 'UTF8_STRING']
 | 
			
		||||
from DdTargets import DdTargets
 | 
			
		||||
 | 
			
		||||
text_tgts = [('text/plain',0,0),
 | 
			
		||||
             ('TEXT', 0, 1),
 | 
			
		||||
             ('STRING', 0, 2),
 | 
			
		||||
             ('COMPOUND_TEXT', 0, 3),
 | 
			
		||||
             ('UTF8_STRING', 0, 4)]
 | 
			
		||||
##text_targets =  ['text/plain',
 | 
			
		||||
##                 'TEXT',
 | 
			
		||||
##                 'STRING',
 | 
			
		||||
##                 'COMPOUND_TEXT',
 | 
			
		||||
##                 'UTF8_STRING']
 | 
			
		||||
 | 
			
		||||
gramps_targets = ['url',
 | 
			
		||||
                  'pevent',
 | 
			
		||||
                  'pattr',
 | 
			
		||||
                  'paddr',
 | 
			
		||||
                  'srcref']
 | 
			
		||||
##text_tgts = [('text/plain',0,0),
 | 
			
		||||
##             ('TEXT', 0, 1),
 | 
			
		||||
##             ('STRING', 0, 2),
 | 
			
		||||
##             ('COMPOUND_TEXT', 0, 3),
 | 
			
		||||
##             ('UTF8_STRING', 0, 4)]
 | 
			
		||||
 | 
			
		||||
pycode_tgts = [('url', 0, 0),
 | 
			
		||||
               ('pevent', 0, 1),
 | 
			
		||||
               ('pattr', 0, 2),
 | 
			
		||||
               ('paddr', 0, 3),
 | 
			
		||||
               ('srcref', 0, 4)] + text_tgts
 | 
			
		||||
##gramps_targets = ['url',
 | 
			
		||||
##                  'pevent',
 | 
			
		||||
##                  'pattr',
 | 
			
		||||
##                  'paddr',
 | 
			
		||||
##                  'srcref']
 | 
			
		||||
 | 
			
		||||
##pycode_tgts = [('url', 0, 0),
 | 
			
		||||
##               ('pevent', 0, 1),
 | 
			
		||||
##               ('pattr', 0, 2),
 | 
			
		||||
##               ('paddr', 0, 3),
 | 
			
		||||
##               ('srcref', 0, 4)] + text_tgts
 | 
			
		||||
               
 | 
			
		||||
 | 
			
		||||
TEXT_TARGET = 'TEXT'
 | 
			
		||||
##TEXT_TARGET = 'TEXT'
 | 
			
		||||
 | 
			
		||||
target_map = {'url':[('url', 0, 0)],
 | 
			
		||||
              'pevent': [('pevent', 0, 1)],
 | 
			
		||||
              'pattr': [('pattr', 0, 2)],
 | 
			
		||||
              'paddr': [('paddr', 0, 3)],
 | 
			
		||||
              'srcref': [('srcref', 0, 4)],
 | 
			
		||||
              TEXT_TARGET: text_tgts}
 | 
			
		||||
##target_map = {'url':[('url', 0, 0)],
 | 
			
		||||
##              'pevent': [('pevent', 0, 1)],
 | 
			
		||||
##              'pattr': [('pattr', 0, 2)],
 | 
			
		||||
##              'paddr': [('paddr', 0, 3)],
 | 
			
		||||
##              'srcref': [('srcref', 0, 4)],
 | 
			
		||||
##              TEXT_TARGET: text_tgts}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -149,8 +151,9 @@ class ScratchPadWindow:
 | 
			
		||||
            "on_scratchPad_delete_event": self.on_delete_event
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        self.object_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, pycode_tgts,
 | 
			
		||||
                                           ACTION_COPY)
 | 
			
		||||
        self.object_list.drag_dest_set(gtk.DEST_DEFAULT_ALL,
 | 
			
		||||
                                       DdTargets.all_targets(),
 | 
			
		||||
                                       ACTION_COPY)
 | 
			
		||||
 | 
			
		||||
        self.object_list.connect('drag_data_get', self.object_drag_data_get)
 | 
			
		||||
        self.object_list.connect('drag_begin', self.object_drag_begin)
 | 
			
		||||
@@ -259,8 +262,6 @@ class ScratchPadWindow:
 | 
			
		||||
        self.redraw_object_list()
 | 
			
		||||
 | 
			
		||||
    def on_object_select_row(self,obj):
 | 
			
		||||
        global target_map
 | 
			
		||||
        global TEXT_TARGET
 | 
			
		||||
        
 | 
			
		||||
        o = self.otree.get_selected_objects()
 | 
			
		||||
        
 | 
			
		||||
@@ -271,19 +272,19 @@ class ScratchPadWindow:
 | 
			
		||||
 | 
			
		||||
            # union with gramps_types
 | 
			
		||||
            if len([target for target \
 | 
			
		||||
                    in obj_targets if target in gramps_targets]) > 0:
 | 
			
		||||
                    in obj_targets if DdTargets.is_gramps_type(target)]) > 0:
 | 
			
		||||
 | 
			
		||||
                exec 'data = %s' % o[0]['data']
 | 
			
		||||
                exec 'mytype = "%s"' % data[0]
 | 
			
		||||
                target = target_map[mytype]
 | 
			
		||||
                target = DdTargets.get_dd_type_from_type_name(mytype).target()
 | 
			
		||||
            
 | 
			
		||||
            # Union with text targets
 | 
			
		||||
            elif len([target for target \
 | 
			
		||||
                      in obj_targets if target in text_targets]) > 0:
 | 
			
		||||
                target = target_map[TEXT_TARGET]
 | 
			
		||||
                      in obj_targets if DdTargets.is_text_type(target)]) > 0:
 | 
			
		||||
                target = DdTargets.TEXT.target()
 | 
			
		||||
 | 
			
		||||
            self.object_list.drag_source_unset()
 | 
			
		||||
            self.object_list.drag_source_set(BUTTON1_MASK, target, ACTION_COPY)
 | 
			
		||||
            self.object_list.drag_source_set(BUTTON1_MASK, [target], ACTION_COPY)
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
    def on_update_object_clicked(self, obj):
 | 
			
		||||
@@ -293,9 +294,6 @@ class ScratchPadWindow:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    def object_drag_data_get(self,widget, context, sel_data, info, time):
 | 
			
		||||
 | 
			
		||||
        global gramps_targets
 | 
			
		||||
        global text_targets
 | 
			
		||||
        
 | 
			
		||||
        o = self.otree.get_selected_objects()
 | 
			
		||||
        
 | 
			
		||||
@@ -306,7 +304,7 @@ class ScratchPadWindow:
 | 
			
		||||
 | 
			
		||||
            # union with gramps_types
 | 
			
		||||
            if len([target for target \
 | 
			
		||||
                    in obj_targets if target in gramps_targets]) > 0:
 | 
			
		||||
                    in obj_targets if DdTargets.is_gramps_type(target)]) > 0:
 | 
			
		||||
 | 
			
		||||
                exec 'data = %s' % o[0]['data']
 | 
			
		||||
                exec 'mytype = "%s"' % data[0]
 | 
			
		||||
@@ -317,7 +315,7 @@ class ScratchPadWindow:
 | 
			
		||||
            
 | 
			
		||||
            # Union with text targets
 | 
			
		||||
            elif len([target for target \
 | 
			
		||||
                      in obj_targets if target in text_targets]) > 0:
 | 
			
		||||
                      in obj_targets if DdTargets.is_text_type(target)]) > 0:
 | 
			
		||||
                send_data = str(o[0]['data'])
 | 
			
		||||
 | 
			
		||||
            sel_data.set(sel_data.target, bits_per, send_data)
 | 
			
		||||
@@ -335,9 +333,6 @@ class ScratchPadWindow:
 | 
			
		||||
    def redraw_object_list(self):
 | 
			
		||||
        """Redraws the address list"""
 | 
			
		||||
 | 
			
		||||
        global gramps_targets
 | 
			
		||||
        global text_targets
 | 
			
		||||
 | 
			
		||||
        self.otree.clear()
 | 
			
		||||
        
 | 
			
		||||
        for obj in self.olist:
 | 
			
		||||
@@ -345,7 +340,7 @@ class ScratchPadWindow:
 | 
			
		||||
 | 
			
		||||
            # union with gramps_types
 | 
			
		||||
            if len([target for target \
 | 
			
		||||
                    in obj_targets if target in gramps_targets]) > 0:
 | 
			
		||||
                    in obj_targets if DdTargets.is_gramps_type(target)]) > 0:
 | 
			
		||||
                
 | 
			
		||||
                exec 'unpack_data = %s' % obj['data']
 | 
			
		||||
                exec 'mytype = "%s"' % unpack_data[0]
 | 
			
		||||
@@ -353,7 +348,7 @@ class ScratchPadWindow:
 | 
			
		||||
 | 
			
		||||
                node = None
 | 
			
		||||
 | 
			
		||||
                if mytype == 'paddr':                
 | 
			
		||||
                if mytype == DdTargets.ADDRESS.drag_type:                
 | 
			
		||||
                    location = "%s %s %s %s" % (data.get_street(),data.get_city(),
 | 
			
		||||
                                                data.get_state(),data.get_country())
 | 
			
		||||
                    node = self.otree.add([_("Address"),
 | 
			
		||||
@@ -361,23 +356,23 @@ class ScratchPadWindow:
 | 
			
		||||
                                           location,
 | 
			
		||||
                                           self.generate_addr_tooltip(data)],obj)
 | 
			
		||||
 | 
			
		||||
                elif mytype == 'pevent':
 | 
			
		||||
                elif mytype == DdTargets.EVENT.drag_type:
 | 
			
		||||
                    node = self.otree.add([_("Event"),
 | 
			
		||||
                                           const.display_pevent(data.get_name()),
 | 
			
		||||
                                           data.get_description(),
 | 
			
		||||
                                           self.generate_event_tooltip(data)],obj)
 | 
			
		||||
 | 
			
		||||
                elif mytype == 'url':
 | 
			
		||||
                elif mytype == DdTargets.URL.drag_type:
 | 
			
		||||
                    node = self.otree.add([_("Url"),
 | 
			
		||||
                                           data.get_path(),
 | 
			
		||||
                                           data.get_description(),
 | 
			
		||||
                                           self.generate_url_tooltip(data)],obj)
 | 
			
		||||
                elif mytype == 'pattr':
 | 
			
		||||
                elif mytype == DdTargets.ATTRIBUTE.drag_type:
 | 
			
		||||
                    node = self.otree.add([_("Attribute"),
 | 
			
		||||
                                           const.display_pattr(data.get_type()),
 | 
			
		||||
                                           data.get_value(),
 | 
			
		||||
                                           self.generate_pattr_tooltip(data)],obj)
 | 
			
		||||
                elif mytype == 'srcref':
 | 
			
		||||
                elif mytype == DdTargets.SOURCEREF.drag_type:
 | 
			
		||||
                    base = self.db.get_source_from_handle(data.get_base_handle())
 | 
			
		||||
                    node = self.otree.add([_("SourceRef"),
 | 
			
		||||
                                           base.get_title(),
 | 
			
		||||
@@ -386,7 +381,7 @@ class ScratchPadWindow:
 | 
			
		||||
 | 
			
		||||
            # Union with text targets
 | 
			
		||||
            elif len([target for target \
 | 
			
		||||
                      in obj_targets if target in text_targets]) > 0:
 | 
			
		||||
                      in obj_targets if DdTargets.is_text_type(target)]) > 0:
 | 
			
		||||
                node = self.otree.add([_("Text"),
 | 
			
		||||
                                       "",
 | 
			
		||||
                                       obj['data'],
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user