gramps/gramps2/src/plugins/ScratchPad.py
Richard Taylor 0b5eeddbd1 2005-03-25 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
* src/ScratchPad.py (ScratchPadWindow): moved content of pad to a
	class attribute so that it is preserved when the pad is closed.
	* src/ScratchPad.py (add_itself_to_menu, remove_itself_from_menu):
	removed large section of commented code.


svn: r4237
2005-03-25 21:20:12 +00:00

472 lines
17 KiB
Python

#
# 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 modiy
# 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$
#------------------------------------------------------------------------
#
# standard python modules
#
#------------------------------------------------------------------------
import pickle
import os
from xml.sax.saxutils import escape
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
import gtk.glade
from gtk.gdk import ACTION_COPY, BUTTON1_MASK
from gnome import help_display
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import Utils
import ListModel
import TreeTips
from DdTargets import DdTargets
#-------------------------------------------------------------------------
#
# ScatchPadWindow class
#
#-------------------------------------------------------------------------
class ScratchPadWindow:
"""
The ScratchPad provides a temporary area to hold objects that can
be reused accross multiple Person records. The pad provides a window
onto which objects can be dropped and then dragged into new Person
dialogs. The objects are stored as the pickles that are built by the
origininating widget. The objects are only unpickled in order to
provide the text in the display.
No attempt is made to ensure that any references contained within
the pickles are valid. Because the pad extends the life time of drag
and drop objects, it is possible that references that were valid
when an object is copied to the pad are invalid by the time they
are dragged to a new Person. For this reason, using the pad places
a responsibility on all '_drag_data_received' methods to check the
references of objects before attempting to use them.
"""
# Class attribute used to hold the content of the
# ScratchPad. A class attribute is used so that the content
# it preserved even when the ScratchPad window is closed.
# As there is only ever one ScratchPad we do not need to
# maintain a list of these.
olist = []
def __init__(self,database,parent):
"""Initializes the ScratchPad class, and displays the window"""
self.db = database
self.parent = parent
if self.parent.child_windows.has_key(self.__class__):
self.parent.child_windows[self.__class__].present(None)
return
self.win_key = self.__class__
self.otitles = [(_('Type'),-1,150),
(_('Title'),-1,150),
(_('Value'),-1,150),
('',-1,0)] # To hold the tooltip text
base = os.path.dirname(__file__)
self.glade_file = "%s/%s" % (base,"scratchpad.glade")
self.top = gtk.glade.XML(self.glade_file,"scratch_pad","gramps")
self.window = self.top.get_widget("scratch_pad")
self.window.set_icon(self.parent.topWindow.get_icon())
self.object_list = self.top.get_widget('objectlist')
self.otree = ListModel.ListModel(self.object_list,self.otitles,
self.on_object_select_row,
self.on_update_object_clicked)
self.treetips = TreeTips.TreeTips(self.object_list,3,True)
self.top.signal_autoconnect({
"on_close_scratchpad" : self.on_close_scratchpad,
"on_clear_clicked": self.on_clear_clicked,
"on_clear_all_clicked": self.on_clear_all_clicked,
"on_help_clicked": self.on_help_clicked,
"on_objectlist_delete_event": self.on_delete_event,
"on_scratchPad_delete_event": self.on_delete_event
})
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)
self.object_list.connect('drag_data_received',
self.object_drag_data_received)
self.add_itself_to_menu()
self.window.show()
self.redraw_object_list()
def on_delete_event(self,obj,b):
self.remove_itself_from_menu()
def add_itself_to_menu(self):
"""Add the ScratchPad window to the list of windows in the
main GRAMPS interface. If this is the first instance to be
created a submenu is created, if it is not the first instance
then an entry is created in the existing sub menu."""
self.parent.child_windows[self.win_key] = self
self.parent_menu_item = gtk.MenuItem(_('Scratch Pad'))
self.parent_menu_item.connect("activate",self.present)
self.parent_menu_item.show()
self.parent.winsmenu.append(self.parent_menu_item)
def remove_itself_from_menu(self):
"""Remove the instance of the pad from the Window menu in the
main GRAMPS window. If this is the last pad then remove the
ScratchPad sub menu as well."""
del self.parent.child_windows[self.win_key]
self.parent_menu_item.destroy()
def present(self,obj):
self.window.present()
def on_help_clicked(self,obj):
"""Display the relevant portion of GRAMPS manual"""
help_display('gramps-manual','tools-util')
def on_close_scratchpad(self,obj):
self.remove_itself_from_menu()
self.window.destroy()
def on_clear_clicked(self,obj):
"""Deletes the selected object from the object list"""
store,node = self.otree.get_selected()
if node:
ScratchPadWindow.olist.remove(self.otree.get_object(node))
self.redraw_object_list()
def on_clear_all_clicked(self,obj):
ScratchPadWindow.olist = []
self.redraw_object_list()
def on_object_select_row(self,obj):
o = self.otree.get_selected_objects()
if len(o):
bits_per = 8; # we're going to pass a string
obj_targets = o[0]['targets']
# union with gramps_types
if len([target for target \
in obj_targets if DdTargets.is_gramps_type(target)]) > 0:
exec 'data = %s' % o[0]['data']
exec 'mytype = "%s"' % data[0]
target = DdTargets.get_dd_type_from_type_name(mytype).target()
# Union with text targets
elif len([target for 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)
def on_update_object_clicked(self, obj):
pass
def object_drag_begin(self, context, a):
return
def object_drag_data_get(self,widget, context, sel_data, info, time):
o = self.otree.get_selected_objects()
if len(o):
bits_per = 8; # we're going to pass a string
obj_targets = o[0]['targets']
# union with gramps_types
if len([target for target \
in obj_targets if DdTargets.is_gramps_type(target)]) > 0:
exec 'data = %s' % o[0]['data']
exec 'mytype = "%s"' % data[0]
exec 'person = "%s"' % data[1]
pickled = data[2]
send_data = str((mytype,person,pickled));
# Union with text targets
elif len([target for target \
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)
def object_drag_data_received(self,widget,context,x,y,sel_data,info,time):
row = self.otree.get_row_at(x,y)
if sel_data and sel_data.data:
ScratchPadWindow.olist.insert(row,{'targets':context.targets,
'data':sel_data.data})
self.redraw_object_list()
def redraw_object_list(self):
"""Redraws the address list"""
self.otree.clear()
for obj in ScratchPadWindow.olist:
obj_targets = obj['targets']
# union with gramps_types
if len([target for target \
in obj_targets if DdTargets.is_gramps_type(target)]) > 0:
exec 'unpack_data = %s' % obj['data']
exec 'mytype = "%s"' % unpack_data[0]
data = pickle.loads(unpack_data[2]);
node = None
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"),
data.get_date(),
location,
self.generate_addr_tooltip(data)],obj)
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 == DdTargets.URL.drag_type:
node = self.otree.add([_("Url"),
data.get_path(),
data.get_description(),
self.generate_url_tooltip(data)],obj)
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 == DdTargets.SOURCEREF.drag_type:
base = self.db.get_source_from_handle(data.get_base_handle())
node = self.otree.add([_("SourceRef"),
base.get_title(),
data.get_text(),
self.generate_srcref_tooltip(data)],obj)
# Union with text targets
elif len([target for target \
in obj_targets if DdTargets.is_text_type(target)]) > 0:
node = self.otree.add([_("Text"),
"",
obj['data'],
self.generate_text_tooltip(obj['data'])],obj)
if ScratchPadWindow.olist:
self.otree.select_row(0)
def generate_event_tooltip(self,event):
global escape
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Event"),
_("Type"),escape(const.display_pevent(event.get_name())),
_("Date"),escape(event.get_date()),
_("Place"),escape(place_title(self.db,event)),
_("Cause"),escape(event.get_cause()),
_("Description"), escape(event.get_description()))
if len(event.get_source_references()) > 0:
psrc_ref = event.get_source_references()[0]
psrc_id = psrc_ref.get_base_handle()
psrc = self.db.get_source_from_handle(psrc_id)
s += "\n<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Primary source"),
_("Name"),
escape(short(psrc.get_title())))
return s
def generate_addr_tooltip(self,addr):
global escape
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\n"\
"\t\t%s\n"\
"\t\t%s\n"\
"\t\t%s\n"\
"\t\t%s\n"\
"\t\t%s\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Address"),
_("Date"), escape(addr.get_date()),
_("Location"),
escape(addr.get_street()),
escape(addr.get_city()),
escape(addr.get_state()),
escape(addr.get_country()),
escape(addr.get_postal_code()),
_("Telephone"), escape(addr.get_phone()))
if len(addr.get_source_references()) > 0:
psrc_ref = addr.get_source_references()[0]
psrc_id = psrc_ref.get_base_handle()
psrc = self.db.get_source_from_handle(psrc_id)
s += "\n<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Sources"),
_("Name"),escape(short(psrc.get_title())))
return s
def generate_url_tooltip(self,url):
global escape
return "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s" % (_("Url"),
_("Path"),
escape(url.get_path()),
_("Description"),
escape(url.get_description()))
def generate_pattr_tooltip(self,attr):
global escape
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s" % (_("Attribute"),
_("Type"),
escape(const.display_pattr(attr.get_type())),
_("Value"),
escape(attr.get_value()))
if len(attr.get_source_references()) > 0:
psrc_ref = attr.get_source_references()[0]
psrc_id = psrc_ref.get_base_handle()
psrc = self.db.get_source_from_handle(psrc_id)
s += "\n<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Sources"),
_("Name"),escape(short(psrc.get_title())))
return s
def generate_srcref_tooltip(self,srcref):
global escape
base = self.db.get_source_from_handle(srcref.get_base_handle())
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s" % (
_("SourceRef"),
_("Title"),escape(base.get_title()),
_("Page"), escape(srcref.get_page()),
_("Text"), escape(srcref.get_text()),
_("Comment"), escape(srcref.get_comments()))
return s
def generate_text_tooltip(self,text):
global escape
return "<big><b>%s</b></big>\n"\
"%s" % (_("Text"),
escape(text))
def short(val,size=60):
if len(val) > size:
return "%s..." % val[0:size]
else:
return val
def place_title(db,event):
pid = event.get_place_handle()
if pid:
return db.get_place_from_handle(pid).get_title()
else:
return u''
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ScratchPad(database,person,callback,parent=None):
ScratchPadWindow(database,parent)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
from PluginMgr import register_tool
register_tool(
ScratchPad,
_("Scratch Pad"),
category=_("Utilities"),
description=_("The Scratch Pad provides a tempory note pad to store "
"objects for easy reuse.")
)