* src/ScratchPad.py: added

* src/stock_link.png: added
* src/DbState.py: better ui management, history management
* src/EditPerson.py: better ui management
* src/GrampsDbBase.py: better ui management
* src/PageView.py: better ui management
* src/PersonView.py: better ui management, history management
* src/ViewManager.py: better ui management


svn: r5044
This commit is contained in:
Alex Roitman 2005-08-10 14:28:16 +00:00
parent d955c08548
commit bad1414dfc
7 changed files with 1098 additions and 40 deletions

View File

@ -1,3 +1,13 @@
2005-08-09 Don Allingham <don@gramps-project.org>
* src/ScratchPad.py: added
* src/stock_link.png: added
* src/DbState.py: better ui management, history management
* src/EditPerson.py: better ui management
* src/GrampsDbBase.py: better ui management
* src/PageView.py: better ui management
* src/PersonView.py: better ui management, history management
* src/ViewManager.py: better ui management
2005-08-09 Alex Roitman <shura@gramps-project.org>
* src/const.py.in: Remove obsolete constants.

View File

@ -44,7 +44,6 @@ import GrampsDBCallback
import GrampsKeys
import NameDisplay
class History:
def __init__(self):
@ -75,14 +74,43 @@ class History:
for c in range(mhc):
self.mhistory.remove(del_id)
def push(self,person_handle):
self.prune()
if len(self.history) == 0 or person_handle != self.history[-1]:
self.history.append(person_handle)
self.mhistory.append(person_handle)
self.index += 1
def forward(self,step=1):
self.index += step
self.mhistory.append(self.history[self.index])
return str(self.history[self.index])
def back(self,step=1):
self.index -= step
self.mhistory.append(self.history[self.index])
return str(self.history[self.index])
def at_end(self):
return self.index+1 == len(self.history)
def at_front(self):
return self.index == 0
def prune(self):
if not self.at_end():
self.history = self.history[0:self.index+1]
class DbState(GrampsDBCallback.GrampsDBCallback):
__signals__ = {
'database-changed' : (GrampsDbBase.GrampsDbBase,),
'active-changed' : (str,),
'active-changed' : (str,),
'no-database' : None,
}
def __init__(self,window,status):
def __init__(self,window,status,uimanager):
self.uimanager = uimanager
self.window = window
GrampsDBCallback.GrampsDBCallback.__init__(self)
self.db = GrampsDbBase.GrampsDbBase()
@ -91,15 +119,19 @@ class DbState(GrampsDBCallback.GrampsDBCallback):
self.status_id = status.get_context_id('GRAMPS')
self.phistory = History()
def get_widget(self,path):
return self.uimanager.get_widget(path)
def clear_history(self):
self.phistory.clear()
def change_active_person(self,person):
self.active = person
try:
self.emit('active-changed',(person.handle,))
except:
self.emit('active-changed',(None,))
if person:
try:
self.emit('active-changed',(person.handle,))
except:
self.emit('active-changed',("",))
def change_active_handle(self,handle):
self.change_active_person(self.db.get_person_from_handle(handle))
@ -111,6 +143,10 @@ class DbState(GrampsDBCallback.GrampsDBCallback):
self.db = db
self.emit('database-changed',(self.db,))
def no_database(self):
self.db = GrampsDbBase.GrampsDbBase()
self.emit('no-database')
def modify_statusbar(self):
self.status.pop(self.status_id)

View File

@ -88,9 +88,10 @@ class EditPerson:
use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic
def __init__(self,parent,person,db,callback=None):
def __init__(self,state,person,callback=None):
"""Creates an edit window. Associates a person with the window."""
self.state = state
self.retval = const.UPDATE_PERSON
self.dp = DateHandler.parser
@ -100,17 +101,16 @@ class EditPerson:
# done to ensure that the person object is not stale, as it could
# have been changed by something external (merge, tool, etc).
if self.orig_handle:
person = db.get_person_from_handle(self.orig_handle)
person = self.state.db.get_person_from_handle(self.orig_handle)
self.person = person
self.orig_surname = self.person.get_primary_name().get_group_name()
self.parent = parent
if self.parent.child_windows.has_key(self.orig_handle):
self.parent.child_windows[self.orig_handle].present(None)
return
self.db = db
#if self.parent_window.child_windows.has_key(self.orig_handle):
# self.parent_window.child_windows[self.orig_handle].present(None)
# return
self.db = self.state.db
self.callback = callback
self.child_windows = {}
self.path = db.get_save_path()
self.path = self.db.get_save_path()
self.not_loaded = True
self.lds_not_loaded = True
self.lists_changed = False
@ -121,8 +121,8 @@ class EditPerson:
person.get_gender () ==
RelLib.Person.UNKNOWN)
for key in db.get_place_handles():
p = db.get_place_from_handle(key).get_display_info()
for key in self.db.get_place_handles():
p = self.db.get_place_from_handle(key).get_display_info()
self.pdmap[p[0]] = key
mod = not self.db.readonly
@ -454,14 +454,15 @@ class EditPerson:
self.window.destroy()
def add_itself_to_winsmenu(self):
self.parent.child_windows[self.orig_handle] = self
return
self.parent_window.child_windows[self.orig_handle] = self
win_menu_label = self.name_display.display(self.person)
if not win_menu_label.strip():
win_menu_label = _("New Person")
self.win_menu_item = gtk.MenuItem(win_menu_label)
self.win_menu_item.set_submenu(gtk.Menu())
self.win_menu_item.show()
self.parent.winsmenu.append(self.win_menu_item)
self.state.winsmenu.append(self.win_menu_item)
self.winsmenu = self.win_menu_item.get_submenu()
self.menu_item = gtk.MenuItem(_('Edit Person'))
self.menu_item.connect("activate",self.present)
@ -469,7 +470,8 @@ class EditPerson:
self.winsmenu.append(self.menu_item)
def remove_itself_from_winsmenu(self):
del self.parent.child_windows[self.orig_handle]
return
del self.parent_window.child_windows[self.orig_handle]
self.menu_item.destroy()
self.winsmenu.destroy()
self.win_menu_item.destroy()

View File

@ -30,8 +30,19 @@ class PageView:
self.action_list = []
self.action_toggle_list = []
self.action_group = None
self.additional_action_groups = []
self.widget = None
self.ui = ""
self.state.connect('no-database',self.disable_action_group)
self.state.connect('database-changed',self.enable_action_group)
def disable_action_group(self):
if self.action_group:
self.action_group.set_visible(False)
def enable_action_group(self,obj):
if self.action_group:
self.action_group.set_visible(True)
def get_stock(self):
try:
@ -73,4 +84,7 @@ class PageView:
if not self.action_group:
self.define_actions()
self._build_action_group()
return self.action_group
return [self.action_group] + self.additional_action_groups
def add_action_group(self,group):
self.additional_action_groups.append(group)

902
gramps2/src/ScratchPad.py Normal file
View File

@ -0,0 +1,902 @@
#
# 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 cPickle as 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 TreeTips
from DdTargets import DdTargets
#-------------------------------------------------------------------------
#
# icons used in the object listing
#
#-------------------------------------------------------------------------
LINK_PIC = gtk.gdk.pixbuf_new_from_file( "%s/%s" % (os.path.dirname(__file__),
'stock_link.png'))
BLANK_PIC = gtk.gdk.Pixbuf(0,0,8,1,1)
#-------------------------------------------------------------------------
#
# wrapper classes to provide object specific listing in the ListView
#
#-------------------------------------------------------------------------
class ScratchPadWrapper(object):
def __init__(self,model,obj):
self._gramps_model = model
self.database_changed(model.db)
self._gramps_model.connect('database-changed', self.database_changed)
self._obj = obj
self._type = _("Unknown")
self._title = ''
self._value = ''
def database_changed(self,db):
self._db = db
def get_type(self):
return self._type
def get_title(self):
return self._title
def get_value(self):
return self._value
def pack(self):
return str(self._obj)
class ScratchPadGrampsTypeWrapper(ScratchPadWrapper):
def __init__(self,model,obj):
ScratchPadWrapper.__init__(self,model,obj)
#unpack object
exec 'unpack_data = %s' % self._obj
exec 'o_type = "%s"' % unpack_data[0]
self._obj = pickle.loads(unpack_data[2])
self._pickle = obj
def pack(self):
return self._pickle
class ScratchPadAddress(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.ADDRESS]
DRAG_TARGET = DdTargets.ADDRESS
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Address")
self._title = self._obj.get_date()
self._value = "%s %s %s %s" % (self._obj.get_street(),self._obj.get_city(),
self._obj.get_state(),self._obj.get_country())
def tooltip(self):
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(self._obj.get_date()),
_("Location"),
escape(self._obj.get_street()),
escape(self._obj.get_city()),
escape(self._obj.get_state()),
escape(self._obj.get_country()),
escape(self._obj.get_postal_code()),
_("Telephone"), escape(self._obj.get_phone()))
if len(self._obj.get_source_references()) > 0:
psrc_ref = self._obj.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
class ScratchPadEvent(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.EVENT]
DRAG_TARGET = DdTargets.EVENT
ICON = LINK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Event")
self._title = const.display_pevent(self._obj.get_name())
self._value = self._obj.get_description()
def tooltip(self):
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(self._obj.get_name())),
_("Date"),escape(self._obj.get_date()),
_("Place"),escape(place_title(self._db,self._obj)),
_("Cause"),escape(self._obj.get_cause()),
_("Description"), escape(self._obj.get_description()))
if len(self._obj.get_source_references()) > 0:
psrc_ref = self._obj.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
class ScratchPadFamilyEvent(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.FAMILY_EVENT]
DRAG_TARGET = DdTargets.FAMILY_EVENT
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Family Event")
self._title = const.display_fevent(self._obj.get_name())
self._value = self._obj.get_description()
def tooltip(self):
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" % (
_("Family Event"),
_("Type"),escape(const.display_fevent(self._obj.get_name())),
_("Date"),escape(self._obj.get_date()),
_("Place"),escape(place_title(self.db,self._obj)),
_("Cause"),escape(self._obj.get_cause()),
_("Description"), escape(self._obj.get_description()))
if len(self._obj.get_source_references()) > 0:
psrc_ref = self._obj.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
class ScratchPadUrl(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.URL]
DRAG_TARGET = DdTargets.URL
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Url")
self._title = self._obj.get_path()
self._value = self._obj.get_description()
def tooltip(self):
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(self._obj.get_path()),
_("Description"),
escape(self._obj.get_description()))
class ScratchPadAttribute(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.ATTRIBUTE]
DRAG_TARGET = DdTargets.ATTRIBUTE
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Attribute")
self._title = const.display_pattr(self._obj.get_type())
self._value = self._obj.get_value()
def tooltip(self):
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(self._obj.get_type())),
_("Value"),
escape(self._obj.get_value()))
if len(self._obj.get_source_references()) > 0:
psrc_ref = self._obj.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
class ScratchPadFamilyAttribute(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.FAMILY_ATTRIBUTE]
DRAG_TARGET = DdTargets.FAMILY_ATTRIBUTE
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Family Attribute")
self._title = const.display_fattr(self._obj.get_type())
self._value = self._obj.get_value()
def tooltip(self):
global escape
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s" % (_("Family Attribute"),
_("Type"),
escape(const.display_fattr(self._obj.get_type())),
_("Value"),
escape(self._obj.get_value()))
if len(self._obj.get_source_references()) > 0:
psrc_ref = self._obj.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
class ScratchPadSourceRef(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.SOURCEREF]
DRAG_TARGET = DdTargets.SOURCEREF
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("SourceRef")
base = self._db.get_source_from_handle(self._obj.get_base_handle())
self._title = base.get_title()
self._value = self._obj.get_text(),
def tooltip(self):
global escape
base = self._db.get_source_from_handle(self._obj.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(self._obj.get_page()),
_("Text"), escape(self._obj.get_text()),
_("Comment"), escape(self._obj.get_note()))
return s
class ScratchPadName(ScratchPadGrampsTypeWrapper):
DROP_TARGETS = [DdTargets.NAME]
DRAG_TARGET = DdTargets.NAME
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadGrampsTypeWrapper.__init__(self,model,obj)
self._type = _("Name")
self._title = self._obj.get_name()
self._value = self._obj.get_type()
def tooltip(self):
global escape
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Name"),
_("Name"),escape(self._obj.get_name()),
_("Type"),escape(self._obj.get_type()))
if len(self._obj.get_source_references()) > 0:
psrc_ref = self._obj.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
class ScratchPadText(ScratchPadWrapper):
DROP_TARGETS = DdTargets.all_text()
DRAG_TARGET = DdTargets.TEXT
ICON = BLANK_PIC
def __init__(self,model,obj):
ScratchPadWrapper.__init__(self,model,obj)
self._type = _("Text")
self._title = ""
self._value = self._obj
def tooltip(self):
global escape
return "<big><b>%s</b></big>\n"\
"%s" % (_("Text"),
escape(self._obj))
class ScratchMediaObj(ScratchPadWrapper):
DROP_TARGETS = [DdTargets.MEDIAOBJ]
DRAG_TARGET = DdTargets.MEDIAOBJ
ICON = LINK_PIC
def __init__(self,model,obj):
ScratchPadWrapper.__init__(self,model,obj)
self._type = _("Media Object")
self._title = ""
self._value = ""
def tooltip(self):
global escape
return "<big><b>%s</b></big>\n"\
"%s" % (_("Media Object"),
escape(self._obj))
class ScratchPersonLink(ScratchPadWrapper):
DROP_TARGETS = [DdTargets.PERSON_LINK]
DRAG_TARGET = DdTargets.PERSON_LINK
ICON = LINK_PIC
def __init__(self,model,obj):
ScratchPadWrapper.__init__(self,model,obj)
self._type = _("Person Link")
person = self._db.get_person_from_handle(self._obj)
self._title = person.get_primary_name().get_name()
birth_handle = person.get_birth_handle()
if birth_handle:
birth = self._db.get_event_from_handle(birth_handle)
if birth.get_date() and birth.get_date() != "":
self._value = escape(birth.get_date())
def tooltip(self):
global escape
person = self._db.get_person_from_handle(self._obj)
s = "<big><b>%s</b></big>\n\n"\
"\t<b>%s:</b>\t%s\n"\
"\t<b>%s:</b>\t%s\n" % (
_("Person Link"),
_("Name"),escape(self._title),
_("Birth"),escape(self._value))
if len(person.get_source_references()) > 0:
psrc_ref = person.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
#-------------------------------------------------------------------------
#
# Wrapper classes to deal with lists of objects
#
#-------------------------------------------------------------------------
class ScratchDropList(object):
def __init__(self,model,obj_list):
self._model = model
self._obj_list = pickle.loads(obj_list)
def get_objects(self):
return [self._cls(self._model,obj) for obj in self._obj_list]
class ScratchPersonLinkList(ScratchDropList):
DROP_TARGETS = [DdTargets.PERSON_LINK_LIST]
DRAG_TARGET = None
def __init__(self,model,obj_list):
ScratchDropList.__init__(self,model,obj_list)
self._cls = ScratchPersonLink
#-------------------------------------------------------------------------
#
# ScratchPadListModel class
#
#-------------------------------------------------------------------------
class ScratchPadListModel(gtk.ListStore):
def __init__(self):
gtk.ListStore.__init__(self,
str, # object type
object, # object
object # tooltip callback
)
#-------------------------------------------------------------------------
#
# ScratchPadListView class
#
#-------------------------------------------------------------------------
class ScratchPadListView:
LOCAL_DRAG_TARGET = ('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)
LOCAL_DRAG_TYPE = 'MY_TREE_MODEL_ROW'
def __init__(self, model, widget):
self._gramps_model = model
self.database_changed(self._gramps_model.db)
self._gramps_model.connect('database-changed', self.database_changed)
self._widget = widget
self._target_type_to_wrapper_class_map = {}
self._previous_drop_time = 0
self.otitles = [(_('Type'),-1,150),
(_('Title'),-1,150),
(_('Value'),-1,150),
('',-1,0)] # To hold the tooltip text
# Create the tree columns
self._col1 = gtk.TreeViewColumn(_("Type"))
self._col2 = gtk.TreeViewColumn(_("Title"))
self._col3 = gtk.TreeViewColumn(_("Value"))
# Add columns
self._widget.append_column(self._col1)
self._widget.append_column(self._col2)
self._widget.append_column(self._col3)
# Create cell renders
self._col1_cellpb = gtk.CellRendererPixbuf()
self._col1_cell = gtk.CellRendererText()
self._col2_cell = gtk.CellRendererText()
self._col3_cell = gtk.CellRendererText()
# Add cells to view
self._col1.pack_start(self._col1_cellpb, False)
self._col1.pack_start(self._col1_cell, True)
self._col2.pack_start(self._col2_cell, True)
self._col3.pack_start(self._col3_cell, True)
# Setup the cell data callback funcs
self._col1.set_cell_data_func(self._col1_cellpb, self.object_pixbuf)
self._col1.set_cell_data_func(self._col1_cell, self.object_type)
self._col2.set_cell_data_func(self._col2_cell, self.object_title)
self._col3.set_cell_data_func(self._col3_cell, self.object_value)
self.treetips = TreeTips.TreeTips(self._widget,2,True)
# Set the column that inline searching will use.
# The search does not appear to work properly so I am disabling it for now.
self._widget.set_enable_search(False)
#self._widget.set_search_column(1)
self._widget.drag_dest_set(gtk.DEST_DEFAULT_ALL,
(ScratchPadListView.LOCAL_DRAG_TARGET,) + \
DdTargets.all_targets(),
ACTION_COPY)
self._widget.connect('drag_data_get', self.object_drag_data_get)
self._widget.connect('drag_begin', self.object_drag_begin)
self._widget.connect('drag_data_received',
self.object_drag_data_received)
self.register_wrapper_classes()
def database_changed(self,db):
self._db = db
# Method to manage the wrapper classes.
def register_wrapper_classes(self):
self.register_wrapper_class(ScratchPadAddress)
self.register_wrapper_class(ScratchPadEvent)
self.register_wrapper_class(ScratchPadFamilyEvent)
self.register_wrapper_class(ScratchPadUrl)
self.register_wrapper_class(ScratchPadAttribute)
self.register_wrapper_class(ScratchPadFamilyAttribute)
self.register_wrapper_class(ScratchPadSourceRef)
self.register_wrapper_class(ScratchPadName)
self.register_wrapper_class(ScratchPadText)
self.register_wrapper_class(ScratchMediaObj)
self.register_wrapper_class(ScratchPersonLink)
self.register_wrapper_class(ScratchPersonLinkList)
def register_wrapper_class(self,wrapper_class):
for drop_target in wrapper_class.DROP_TARGETS:
self._target_type_to_wrapper_class_map[drop_target.drag_type] = wrapper_class
# Methods for rendering the cells.
def object_pixbuf(self, column, cell, model, iter, user_data=None):
o = model.get_value(iter, 1)
cell.set_property('pixbuf', o.__class__.ICON)
def object_type(self, column, cell, model, iter, user_data=None):
o = model.get_value(iter, 1)
cell.set_property('text', o.get_type())
def object_title(self, column, cell, model, iter, user_data=None):
o = model.get_value(iter, 1)
cell.set_property('text', o.get_title())
def object_value(self, column, cell, model, iter, user_data=None):
o = model.get_value(iter, 1)
cell.set_property('text', o.get_value())
# handlers for the drag and drop events.
def on_object_select_row(self,obj):
tree_selection = self._widget.get_selection()
model,iter = tree_selection.get_selected()
self._widget.unset_rows_drag_source()
if iter != None:
o = model.get_value(iter,1)
targets = [ScratchPadListView.LOCAL_DRAG_TARGET] + \
[target.target() for target in o.__class__.DROP_TARGETS]
self._widget.enable_model_drag_source(BUTTON1_MASK, targets, ACTION_COPY)
def object_drag_begin(self, context, a):
return
def object_drag_data_get(self, widget, context, sel_data, info, time):
tree_selection = widget.get_selection()
model,iter = tree_selection.get_selected()
o = model.get_value(iter,1)
sel_data.set(sel_data.target, 8, o.pack())
def object_drag_data_received(self,widget,context,x,y,selection,info,time):
# Ignore drops from the same widget.
if ScratchPadListView.LOCAL_DRAG_TYPE in context.targets:
return
model = widget.get_model()
sel_data = selection.data
# There is a strange bug that means that if there is a selection
# in the list we get multiple drops of the same object. Luckily
# the time values are the same so we can drop all but the first.
if time == self._previous_drop_time:
return
# Find a wrapper class
possible_wrappers = [target for target in context.targets \
if target in self._target_type_to_wrapper_class_map.keys()]
if len(possible_wrappers) == 0:
# No wrapper for this class
return
# Just select the first match.
wrapper_class = self._target_type_to_wrapper_class_map[str(possible_wrappers[0])]
o = wrapper_class(self._gramps_model,sel_data)
# If the wrapper object is a subclass of ScratchDropList then
# the drag data was a list of objects and we need to decode
# all of them.
if isinstance(o,ScratchDropList):
o_list = o.get_objects()
else:
o_list = [o]
for o in o_list:
drop_info = widget.get_dest_row_at_pos(x, y)
if drop_info:
path, position = drop_info
iter = model.get_iter(path)
if (position == gtk.TREE_VIEW_DROP_BEFORE
or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
model.insert_before(iter,[o.__class__.DRAG_TARGET.drag_type,o,o.tooltip])
else:
model.insert_after(iter,[o.__class__.DRAG_TARGET.drag_type,o,o.tooltip])
else:
model.append([o.__class__.DRAG_TARGET.drag_type,o,o.tooltip])
# remember time for double drop workaround.
self._previous_drop_time = time
# proxy methods to provide access to the real widget functions.
def set_model(self,model=None):
self._widget.set_model(model)
self._widget.get_selection().connect('changed',self.on_object_select_row)
def get_model(self):
return self._widget.get_model()
def get_selection(self):
return self._widget.get_selection()
#-------------------------------------------------------------------------
#
# 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.
otree = None
def __init__(self,database,parent):
"""Initializes the ScratchPad class, and displays the window"""
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.database_changed(database)
self.parent.connect('database-changed', self.database_changed)
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.clear_all_btn = self.top.get_widget("btn_clear_all")
self.clear_btn = self.top.get_widget("btn_clear")
self.object_list = ScratchPadListView(self.parent,self.top.get_widget('objectlist'))
self.object_list.get_selection().connect('changed',self.set_clear_btn_sensitivity)
self.set_clear_btn_sensitivity(sel=self.object_list.get_selection())
if not ScratchPadWindow.otree:
ScratchPadWindow.otree = ScratchPadListModel()
self.set_clear_all_btn_sensitivity(treemodel=ScratchPadWindow.otree)
ScratchPadWindow.otree.connect('row-deleted',self.set_clear_all_btn_sensitivity)
ScratchPadWindow.otree.connect('row-inserted',self.set_clear_all_btn_sensitivity)
self.object_list.set_model(ScratchPadWindow.otree)
self.top.signal_autoconnect({
"on_close_scratchpad" : self.on_close_scratchpad,
"on_clear_clicked": self.on_clear_clicked,
"on_help_clicked": self.on_help_clicked,
"on_objectlist_delete_event": self.on_delete_event,
"on_scratch_pad_delete_event": self.on_delete_event
})
self.clear_all_btn.connect_object('clicked', gtk.ListStore.clear, ScratchPadWindow.otree)
self.parent.connect('database-changed', lambda x: ScratchPadWindow.otree.clear())
self.add_itself_to_menu()
self.window.show()
def database_changed(self,database):
self.db = database
def set_clear_all_btn_sensitivity(self, treemodel=None, path=None, iter=None, user_param1=None):
if len(treemodel) == 0:
self.clear_all_btn.set_sensitive(False)
else:
self.clear_all_btn.set_sensitive(True)
def set_clear_btn_sensitivity(self, sel=None, user_param1=None):
if sel.count_selected_rows() == 0:
self.clear_btn.set_sensitive(False)
else:
self.clear_btn.set_sensitive(True)
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-scratch-pad')
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"""
selection = self.object_list.get_selection()
model, iter = selection.get_selected()
if iter:
model.remove(iter)
return
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(state,person,callback,parent=None):
ScratchPadWindow(state.db,parent)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
from PluginMgr import register_tool
register_tool(
ScratchPad,
_("Scratch Pad"),
category=_("Utilities"),
description=_("The Scratch Pad provides a temporary note pad to store "
"objects for easy reuse.")
)

View File

@ -141,7 +141,6 @@ class ViewManager:
self.window.set_size_request(775,500)
self.statusbar = gtk.Statusbar()
self.state = DbState.DbState(self.window,self.statusbar)
self.RelClass = PluginMgr.relationship_class
@ -161,18 +160,21 @@ class ViewManager:
hbox.pack_start(self.notebook,True)
self.menubar = self.uimanager.get_widget('/MenuBar')
self.toolbar = self.uimanager.get_widget('/ToolBar')
print self.uimanager.get_widget('/MenuBar/GoMenu')
vbox.pack_start(self.menubar, False)
vbox.pack_start(self.toolbar, False)
vbox.add(hbox)
vbox.pack_end(self.statusbar,False)
self.notebook.connect('switch-page',self.change_page)
self.state = DbState.DbState(self.window,self.statusbar,self.uimanager)
self.window.show_all()
def init_interface(self):
self.create_pages()
self.change_page(None,None,0)
self.state.no_database()
self.actiongroup.set_visible(False)
def set_color(self,obj):
style = obj.get_style().copy()
@ -192,28 +194,34 @@ class ViewManager:
self.window.add_accel_group(accelgroup)
self.actiongroup = gtk.ActionGroup('MainWindow')
self.fileactions = gtk.ActionGroup('FileWindow')
self.fileactions.add_actions([
('FileMenu', None, '_File'),
('New', gtk.STOCK_NEW, '_New', "<control>n", None, self.on_new_activate),
('Open', gtk.STOCK_OPEN, '_Open', "<control>o", None, self.on_open_activate),
('OpenRecent', gtk.STOCK_OPEN, 'Open _Recent'),
('Quit', gtk.STOCK_QUIT, '_Quit', '<control>q', None, gtk.main_quit),
('ViewMenu', None, '_View'),
('Preferences',gtk.STOCK_PREFERENCES,'_Preferences'),
('ColumnEdit', gtk.STOCK_PROPERTIES, '_Column Editor'),
('HelpMenu', None, '_Help'),
('About', gtk.STOCK_ABOUT, '_About'),
])
self.actiongroup.add_actions([
# Name Stock Icon Label
('FileMenu', None, '_File'),
('New', gtk.STOCK_NEW, '_New', "<control>n", None, self.on_new_activate),
('Open', gtk.STOCK_OPEN, '_Open', "<control>o", None, self.on_open_activate),
('OpenRecent', gtk.STOCK_OPEN, 'Open _Recent'),
('Import', gtk.STOCK_CONVERT, '_Import'),
('SaveAs', gtk.STOCK_SAVE_AS, '_Save As'),
('Export', gtk.STOCK_SAVE_AS, '_Export'),
('Abandon', gtk.STOCK_REVERT_TO_SAVED, '_Abandon changes and quit'),
('Quit', gtk.STOCK_QUIT, '_Quit', '<control>q', None, gtk.main_quit),
('Undo', gtk.STOCK_UNDO, '_Undo', '<control>z' ),
('Preferences',gtk.STOCK_PREFERENCES, '_Preferences'),
('ColumnEdit', gtk.STOCK_PROPERTIES, '_Column Editor'),
('CmpMerge', None, '_Compare and merge'),
('FastMerge', None, '_Fast merge'),
('ScratchPad', gtk.STOCK_PASTE, '_ScratchPad', None, None, self.on_scratchpad),
('Import', gtk.STOCK_CONVERT, '_Import', None, None, self.on_import),
('Reports', gtk.STOCK_DND_MULTIPLE, '_Reports'),
('Tools', gtk.STOCK_EXECUTE, '_Tools'),
('EditMenu', None, '_Edit'),
('GoMenu', None, '_Go'),
('ViewMenu', None, '_View'),
('BookMenu', None, '_Bookmarks'),
('AddBook', gtk.STOCK_INDEX, '_Add bookmark', '<control>d'),
('EditBook', None, '_Edit bookmarks', '<control>b'),
@ -221,16 +229,15 @@ class ViewManager:
('ReportsMenu',None, '_Reports'),
('ToolsMenu', None, '_Tools'),
('WindowsMenu',None, '_Windows'),
('HelpMenu', None, '_Help'),
('About', gtk.STOCK_ABOUT, '_About'),
])
self.actiongroup.add_toggle_actions([
self.fileactions.add_toggle_actions([
('Sidebar', None, '_Sidebar', None, None, self.sidebar_toggle),
('Toolbar', None, '_Toolbar', None, None, self.toolbar_toggle),
])
merge_id = self.uimanager.add_ui_from_string(uidefault)
self.uimanager.insert_action_group(self.fileactions,1)
self.uimanager.insert_action_group(self.actiongroup,1)
def sidebar_toggle(self,obj):
@ -287,12 +294,16 @@ class ViewManager:
if self.merge_id:
self.uimanager.remove_ui(self.merge_id)
if self.active_page:
self.uimanager.remove_action_group(self.active_page.get_actions())
groups = self.active_page.get_actions()
for grp in groups:
self.uimanager.remove_action_group(grp)
if len(self.pages) > 0:
self.active_page = self.pages[num]
groups = self.active_page.get_actions()
self.uimanager.insert_action_group(self.active_page.get_actions(),1)
for grp in groups:
self.uimanager.insert_action_group(grp,1)
self.merge_id = self.uimanager.add_ui_from_string(self.active_page.ui_definition())
def on_open_activate(self,obj):
@ -523,6 +534,7 @@ class ViewManager:
#self.undo_callback(None)
#self.redo_callback(None)
#self.goto_active_person()
self.actiongroup.set_visible(True)
return 1
def load_database(self,name,callback=None,mode="w"):
@ -573,7 +585,89 @@ class ViewManager:
def on_scratchpad(self,obj):
import ScratchPad
ScratchPad.ScratchPadWindow(self.db, self)
ScratchPad.ScratchPadWindow(self.state, self)
def on_import(self,obj):
print "import"
choose = gtk.FileChooserDialog(_('GRAMPS: Import database'),
self.state.window,
gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
choose.set_local_only(False)
# Always add automatic (macth all files) filter
add_all_files_filter(choose)
add_grdb_filter(choose)
add_xml_filter(choose)
add_gedcom_filter(choose)
format_list = [const.app_gramps,const.app_gramps_xml,const.app_gedcom]
# Add more data type selections if opening existing db
for (importData,mime_filter,mime_type,native_format,format_name) in PluginMgr.import_list:
if not native_format:
choose.add_filter(mime_filter)
format_list.append(mime_type)
_KNOWN_FORMATS[mime_type] = format_name
(box,type_selector) = format_maker(format_list)
choose.set_extra_widget(box)
# Suggested folder: try last open file, import, then last export,
# then home.
default_dir = GrampsKeys.get_last_import_dir()
if len(default_dir)<=1:
default_dir = os.path.split(GrampsKeys.get_lastfile())[0] + os.path.sep
if len(default_dir)<=1:
default_dir = GrampsKeys.get_last_export_dir()
if len(default_dir)<=1:
default_dir = '~/'
choose.set_current_folder(default_dir)
response = choose.run()
if response == gtk.RESPONSE_OK:
filename = choose.get_filename()
filetype = type_selector.get_value()
if filetype == 'auto':
try:
filetype = get_mime_type(filename)
except RuntimeError,msg:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
str(msg))
return False
if filetype == const.app_gramps:
choose.destroy()
ReadGrdb.importData(self.state.db,filename)
self.parent.import_tool_callback()
return True
elif filetype == const.app_gramps_xml:
choose.destroy()
import ReadXML
ReadXML.importData(self.state.db,filename)
return True
elif filetype == const.app_gedcom:
choose.destroy()
import ReadGedcom
ReadGedcom.importData(self.state.db,filename)
return True
(the_path,the_file) = os.path.split(filename)
GrampsKeys.save_last_import_dir(the_path)
for (importData,mime_filter,mime_type,native_format,format_name) in PluginMgr.import_list:
if filetype == mime_type or the_file == mime_type:
choose.destroy()
importData(self.state.db,filename)
self.parent.import_tool_callback()
return True
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_('File type "%s" is unknown to GRAMPS.\n\nValid types are: GRAMPS database, GRAMPS XML, GRAMPS package, and GEDCOM.') % filetype)
choose.destroy()
return False
def add_all_files_filter(chooser):
"""

BIN
gramps2/src/stock_link.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B