split UI and DB state

svn: r5049
This commit is contained in:
Don Allingham
2005-08-10 23:53:24 +00:00
parent 363e219af7
commit b39a328f9a
10 changed files with 772 additions and 502 deletions

View File

@ -1,3 +1,15 @@
2005-08-10 Don Allingham <don@gramps-project.org>
* src/DbState.py: separate database class from display class
* src/EditPerson.py: separate database class from display class
* src/GrampsDbBase.py: separate database class from display class
* src/PageView.py: separate database class from display class
* src/PedView.py: separate database class from display class
* src/PersonView.py: separate database class from display class
* src/RelLib.py: separate database class from display class
* src/ViewManager.py: separate database class from display class
* src/gramps_main.py: separate database class from display class
* src/Navigation.py: provides navigation ability for the history menu
2005-08-10 Martin Hawlisch <Martin.Hawlisch@gmx.de> 2005-08-10 Martin Hawlisch <Martin.Hawlisch@gmx.de>
* src/PedView.py: Better autoscaling; better ui management * src/PedView.py: Better autoscaling; better ui management

View File

@ -44,9 +44,15 @@ import GrampsDBCallback
import GrampsKeys import GrampsKeys
import NameDisplay import NameDisplay
class History: class History(GrampsDBCallback.GrampsDBCallback):
__signals__ = {
'changed' : (list,),
'menu-changed' : (list,),
}
def __init__(self): def __init__(self):
GrampsDBCallback.GrampsDBCallback.__init__(self)
self.history = [] self.history = []
self.mhistory = [] self.mhistory = []
self.index = -1 self.index = -1
@ -73,22 +79,33 @@ class History:
mhc = self.mhistory.count(del_id) mhc = self.mhistory.count(del_id)
for c in range(mhc): for c in range(mhc):
self.mhistory.remove(del_id) self.mhistory.remove(del_id)
self.emit('changed',(self.history,))
self.emit('menu-changed',(self.mhistory,))
def push(self,person_handle): def push(self,person_handle):
self.prune() self.prune()
if len(self.history) == 0 or person_handle != self.history[-1]: if len(self.history) == 0 or person_handle != self.history[-1]:
self.history.append(person_handle) self.history.append(person_handle)
if person_handle not in self.mhistory:
self.mhistory.append(person_handle) self.mhistory.append(person_handle)
self.emit('menu-changed',(self.mhistory,))
self.index += 1 self.index += 1
self.emit('changed',(self.history,))
def forward(self,step=1): def forward(self,step=1):
self.index += step self.index += step
self.mhistory.append(self.history[self.index]) person_handle = self.history[self.index]
if person_handle not in self.mhistory:
self.mhistory.append(person_handle)
self.emit('menu-changed',(self.mhistory,))
return str(self.history[self.index]) return str(self.history[self.index])
def back(self,step=1): def back(self,step=1):
self.index -= step self.index -= step
self.mhistory.append(self.history[self.index]) person_handle = self.history[self.index]
if person_handle not in self.mhistory:
self.mhistory.append(person_handle)
self.emit('menu-changed',(self.mhistory,))
return str(self.history[self.index]) return str(self.history[self.index])
def at_end(self): def at_end(self):
@ -109,21 +126,10 @@ class DbState(GrampsDBCallback.GrampsDBCallback):
'no-database' : None, 'no-database' : None,
} }
def __init__(self,window,status,uimanager): def __init__(self):
self.uimanager = uimanager
self.window = window
GrampsDBCallback.GrampsDBCallback.__init__(self) GrampsDBCallback.GrampsDBCallback.__init__(self)
self.db = GrampsDbBase.GrampsDbBase() self.db = GrampsDbBase.GrampsDbBase()
self.active = None self.active = None
self.status = status
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): def change_active_person(self,person):
self.active = person self.active = person
@ -147,15 +153,28 @@ class DbState(GrampsDBCallback.GrampsDBCallback):
self.db = GrampsDbBase.GrampsDbBase() self.db = GrampsDbBase.GrampsDbBase()
self.emit('no-database') self.emit('no-database')
def modify_statusbar(self): class DisplayState(GrampsDBCallback.GrampsDBCallback):
__signals__ = {
}
def __init__(self,window,status,uimanager,dbstate):
self.dbstate = dbstate
self.uimanager = uimanager
self.window = window
GrampsDBCallback.GrampsDBCallback.__init__(self)
self.status = status
self.status_id = status.get_context_id('GRAMPS')
self.phistory = History()
def modify_statusbar(self,active=None):
self.status.pop(self.status_id) self.status.pop(self.status_id)
if self.active == None: if self.dbstate.active == None:
self.status.push(self.status_id,"") self.status.push(self.status_id,"")
else: else:
if GrampsKeys.get_statusbar() <= 1: if GrampsKeys.get_statusbar() <= 1:
pname = NameDisplay.displayer.display(self.active) pname = NameDisplay.displayer.display(self.dbstate.active)
name = "[%s] %s" % (self.active.get_gramps_id(),pname) name = "[%s] %s" % (self.dbstate.active.get_gramps_id(),pname)
else: else:
name = self.display_relationship() name = self.display_relationship()
self.status.push(self.status_id,name) self.status.push(self.status_id,name)

View File

@ -88,10 +88,11 @@ class EditPerson:
use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic use_patronymic = locale.getlocale(locale.LC_TIME)[0] in _use_patronymic
def __init__(self,state,person,callback=None): def __init__(self,state,uistate,person,callback=None):
"""Creates an edit window. Associates a person with the window.""" """Creates an edit window. Associates a person with the window."""
self.state = state self.state = state
self.uistate = uistate
self.retval = const.UPDATE_PERSON self.retval = const.UPDATE_PERSON
self.dp = DateHandler.parser self.dp = DateHandler.parser
@ -462,7 +463,7 @@ class EditPerson:
self.win_menu_item = gtk.MenuItem(win_menu_label) self.win_menu_item = gtk.MenuItem(win_menu_label)
self.win_menu_item.set_submenu(gtk.Menu()) self.win_menu_item.set_submenu(gtk.Menu())
self.win_menu_item.show() self.win_menu_item.show()
self.state.winsmenu.append(self.win_menu_item) self.uistate.winsmenu.append(self.win_menu_item)
self.winsmenu = self.win_menu_item.get_submenu() self.winsmenu = self.win_menu_item.get_submenu()
self.menu_item = gtk.MenuItem(_('Edit Person')) self.menu_item = gtk.MenuItem(_('Edit Person'))
self.menu_item.connect("activate",self.present) self.menu_item.connect("activate",self.present)

View File

@ -312,26 +312,24 @@ class GrampsDbBase(GrampsDBCallback.GrampsDBCallback):
update_list.append((handle,obj.serialize())) update_list.append((handle,obj.serialize()))
else: else:
add_list.append((handle,obj.serialize())) add_list.append((handle,obj.serialize()))
return old_data
# committing person, do gender stats here
if key == PERSON_KEY:
if old_data:
old_person = Person(old_data)
if (old_data[2] != person.gender or
old_data[3].first_name != obj.primary_name.first_name):
self.genderStats.uncount_person(old_person)
self.genderStats.count_person(obj,self)
else:
self.genderStats.count_person(obj,self)
def commit_person(self,person,transaction,change_time=None): def commit_person(self,person,transaction,change_time=None):
""" """
Commits the specified Person to the database, storing the changes Commits the specified Person to the database, storing the changes
as part of the transaction. as part of the transaction.
""" """
self._commit_base(person, self.person_map, PERSON_KEY, old_data = self._commit_base(
transaction.person_update, transaction.person_add, person, self.person_map, PERSON_KEY, transaction.person_update,
transaction, change_time) transaction.person_add, transaction, change_time)
if old_data:
old_person = Person(old_data)
if (old_data[2] != person.gender or
old_data[3].first_name != person.primary_name.first_name):
self.genderStats.uncount_person(old_person)
self.genderStats.count_person(person,self)
else:
self.genderStats.count_person(person,self)
def commit_media_object(self,obj,transaction,change_time=None): def commit_media_object(self,obj,transaction,change_time=None):
""" """

154
src/Navigation.py Normal file
View File

@ -0,0 +1,154 @@
#
# 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
#
_top = '<ui><menubar name="MenuBar"><menu action="GoMenu"><placeholder name="CommonHistory">'
_btm = '</placeholder></menu></menubar></ui>'
import gtk
import sys
import NameDisplay
DISABLED = -1
class BaseNavigation:
"""
Base history navigation class. Builds the action group and ui for the
uimanager. Changes to the associated history objects are tracked. When
the history changes, the UI XML string and the action groups are updated.
Import variables:
self.title - name used for Action group name and Actions
self.ui - XML string used to build menu items for UIManager
self.action_group - associate action group for selecting items
self.active - merge ID for the action group. DISABLED if not active
self.items - history handles associated with the menu
self.func - array of functions to take action based off of.
"""
def __init__(self,uistate,history,title):
self.title = title
self.ui = _top+_btm
history.connect('menu-changed', self.update_menu)
self.action_group = gtk.ActionGroup(self.title)
self.active = DISABLED
self.uistate = uistate
self.items = []
def disable(self):
"""
Removes the UI and action groups if the navigation is enabled
"""
if self.active != DISABLED:
self.uistate.uimanager.remove_ui(self.active)
self.uistate.uimanager.remove_action_group(self.action_group)
self.active = DISABLED
def enable(self):
"""
Enables the UI and action groups
"""
self.uistate.uimanager.insert_action_group(self.action_group, 1)
self.active = self.uistate.uimanager.add_ui_from_string(self.ui)
def build_item_name(self,handle):
"""
Builds a string from the passed handle. Must be overridden by the
derrived class.
"""
return "ERROR"
def update_menu(self,items):
"""
Builds the UI and action group.
"""
self.items = items
self.disable()
data = map(lambda x: '<menuitem action="%s%02d"/>' % (self.title,x), range(0,len(items)))
self.ui = _top + "".join(data) + _btm
self.action_group = gtk.ActionGroup(self.title)
data = []
index = 0
for item in items:
name = self.build_item_name(item)
f = self.func[index]
data.append(('%s%02d'%(self.title,index), None, name, "<alt>%d" % index, None, f))
index +=1
self.action_group.add_actions(data)
if self.active != DISABLED:
self.enable()
class PersonNavigation(BaseNavigation):
"""
Builds a navigation item for the Person class.
"""
def __init__(self,uistate):
"""
Associates the functions with the associated items. Builds the function
array so that there are unique functions for each possible index (0-9)
The callback simply calls change_active_handle
"""
BaseNavigation.__init__(self,uistate,uistate.phistory,'PersonHistory')
self.func = [ self.f0, self.f1, self.f2, self.f3, self.f4,
self.f5, self.f6, self.f7, self.f8, self.f9 ]
def build_item_name(self, item):
"""
Builds a name in the format of 'NAME [GRAMPSID]'
"""
person = self.uistate.dbstate.db.get_person_from_handle(item)
name = "%s [%s]" % (NameDisplay.displayer.display(person),
person.gramps_id)
def f0(self,obj):
self.uistate.dbstate.change_active_handle(self.items[0])
def f1(self,obj):
self.uistate.dbstate.change_active_handle(self.items[1])
def f2(self,obj):
self.uistate.dbstate.change_active_handle(self.items[2])
def f3(self,obj):
self.uistate.dbstate.change_active_handle(self.items[3])
def f4(self,obj):
self.uistate.dbstate.change_active_handle(self.items[4])
def f5(self,obj):
self.uistate.dbstate.change_active_handle(self.items[5])
def f6(self,obj):
self.uistate.dbstate.change_active_handle(self.items[6])
def f7(self,obj):
self.uistate.dbstate.change_active_handle(self.items[7])
def f8(self,obj):
self.uistate.dbstate.change_active_handle(self.items[8])
def f9(self,obj):
self.uistate.dbstate.change_active_handle(self.items[9])

View File

@ -22,19 +22,34 @@
import gtk import gtk
NAVIGATION_NONE = -1
NAVIGATION_PERSON = 0
class PageView: class PageView:
def __init__(self,title,state): def __init__(self,title,dbstate,uistate):
self.title = title self.title = title
self.state = state self.dbstate = dbstate
self.uistate = uistate
self.action_list = [] self.action_list = []
self.action_toggle_list = [] self.action_toggle_list = []
self.action_group = None self.action_group = None
self.additional_action_groups = [] self.additional_action_groups = []
self.additional_uis = []
self.widget = None self.widget = None
self.ui = "" self.ui = '<ui></ui>'
self.state.connect('no-database',self.disable_action_group) self.dbstate.connect('no-database',self.disable_action_group)
self.state.connect('database-changed',self.enable_action_group) self.dbstate.connect('database-changed',self.enable_action_group)
def navigation_type(self):
return NAVIGATION_NONE
def ui_definition(self):
return self.ui
def additional_ui_definitions(self):
return self.additional_uis
def disable_action_group(self): def disable_action_group(self):
if self.action_group: if self.action_group:
@ -50,9 +65,6 @@ class PageView:
except AttributeError: except AttributeError:
return gtk.STOCK_MISSING_IMAGE return gtk.STOCK_MISSING_IMAGE
def get_ui(self):
return self.ui
def get_title(self): def get_title(self):
return self.title return self.title
@ -88,3 +100,5 @@ class PageView:
def add_action_group(self,group): def add_action_group(self,group):
self.additional_action_groups.append(group) self.additional_action_groups.append(group)

View File

@ -41,10 +41,12 @@ import gtk.gdk
# Gramps Modules # Gramps Modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import RelLib
import PageView import PageView
import EditPerson import const
import GrampsCfg
import Relationship
import NameDisplay import NameDisplay
import RelLib
import Utils import Utils
import DateHandler import DateHandler
@ -53,6 +55,8 @@ import DateHandler
# Constants # Constants
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
_PAD = 3
_CANVASPAD = 3
_PERSON = "p" _PERSON = "p"
_BORN = _('b.') _BORN = _('b.')
_DIED = _('d.') _DIED = _('d.')
@ -69,17 +73,19 @@ _CREM = _('crem.')
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class PedView(PageView.PageView): class PedView(PageView.PageView):
def __init__(self,state): def __init__(self,dbstate,uistate):
PageView.PageView.__init__(self,'Pedigree View',state) PageView.PageView.__init__(self,'Pedigree View',dbstate,uistate)
self.inactive = False self.inactive = False
state.connect('database-changed',self.change_db) dbstate.connect('database-changed',self.change_db)
state.connect('active-changed',self.goto_active_person) dbstate.connect('active-changed',self.goto_active_person)
self.force_size = 0 # Automatic resize self.force_size = 0 # Automatic resize
def navigation_type(self):
return PageView.NAVIGATION_PERSON
def build_widget(self): def build_widget(self):
self.notebook = gtk.Notebook() self.notebook = gtk.Notebook()
self.notebook.connect("button-press-event", self.on_show_option_menu_cb) self.notebook.connect("button-press-event", self.on_show_option_menu_cb)
self.bootstrap_handler = self.notebook.connect("expose-event", self.init_parent_signals_cb)
self.notebook.set_show_border(False) self.notebook.set_show_border(False)
self.notebook.set_show_tabs(False) self.notebook.set_show_tabs(False)
@ -99,16 +105,10 @@ class PedView(PageView.PageView):
self.table_5.connect("button-press-event", self.on_show_option_menu_cb) self.table_5.connect("button-press-event", self.on_show_option_menu_cb)
self.add_table_to_notebook( self.table_5) self.add_table_to_notebook( self.table_5)
self.rebuild_trees(None) #self.parent_container.connect("size-allocate", self.size_request_cb)
return self.notebook return self.notebook
def init_parent_signals_cb(self, widget, event):
print "PedView.init_parent_signals_cb"
self.notebook.disconnect(self.bootstrap_handler)
self.notebook.parent.connect("size-allocate", self.size_request_cb)
self.size_request_cb(widget.parent,event)
def add_table_to_notebook( self, table): def add_table_to_notebook( self, table):
frame = gtk.ScrolledWindow(None,None) frame = gtk.ScrolledWindow(None,None)
frame.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) frame.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
@ -123,49 +123,10 @@ class PedView(PageView.PageView):
#self.add_action('Add', gtk.STOCK_ADD, "_Add", callback=self.add) #self.add_action('Add', gtk.STOCK_ADD, "_Add", callback=self.add)
#self.add_action('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit) #self.add_action('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit)
#self.add_action('Remove', gtk.STOCK_REMOVE, "_Remove", callback=self.remove) #self.add_action('Remove', gtk.STOCK_REMOVE, "_Remove", callback=self.remove)
self.add_action('Forward',gtk.STOCK_GO_FORWARD,"_Forward", callback=self.home)#callback=self.fwd_clicked) #self.add_action('Forward',gtk.STOCK_GO_FORWARD,"_Forward", callback=self.fwd_clicked)
self.add_action('Back', gtk.STOCK_GO_BACK, "_Back", callback=self.home)#callback=self.back_clicked) #self.add_action('Back', gtk.STOCK_GO_BACK, "_Back", callback=self.back_clicked)
self.add_action('HomePerson', gtk.STOCK_HOME, "_Home", callback=self.home) self.add_action('HomePerson', gtk.STOCK_HOME, "_Home", callback=self.home)
#self.add_toggle_action('Filter', None, '_Filter', callback=self.filter_toggle) #self.add_toggle_action('Filter', None, '_Filter', callback=self.filter_toggle)
# add the Forward action group to handle the Forward button
self.fwd_action = gtk.ActionGroup(self.title + '/Forward')
self.fwd_action.add_actions([
('Forward',gtk.STOCK_GO_FORWARD,"_Forward", None, None, self.home)#callback=self.fwd_clicked)
])
# add the Backward action group to handle the Forward button
self.back_action = gtk.ActionGroup(self.title + '/Backward')
self.back_action.add_actions([
('Back',gtk.STOCK_GO_BACK,"_Back", None, None, self.home)#callback=self.back_clicked)
])
self.add_action_group(self.back_action)
self.add_action_group(self.fwd_action)
def disable_action_group(self):
"""
Normally, this would not be overridden from the base class. However,
in this case, we have additional action groups that need to be
handled correctly.
"""
PageView.PageView.disable_action_group(self)
self.fwd_action.set_visible(False)
self.back_action.set_visible(False)
def enable_action_group(self,obj):
"""
Normally, this would not be overridden from the base class. However,
in this case, we have additional action groups that need to be
handled correctly.
"""
PageView.PageView.enable_action_group(self,obj)
self.fwd_action.set_visible(True)
self.back_action.set_visible(True)
hobj = self.state.phistory
self.fwd_action.set_sensitive(not hobj.at_end())
self.back_action.set_sensitive(not hobj.at_front())
def ui_definition(self): def ui_definition(self):
return '''<ui> return '''<ui>
@ -178,8 +139,6 @@ class PedView(PageView.PageView):
</menubar> </menubar>
<toolbar name="ToolBar"> <toolbar name="ToolBar">
<placeholder name="CommonNavigation"> <placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
<toolitem action="HomePerson"/> <toolitem action="HomePerson"/>
</placeholder> </placeholder>
</toolbar> </toolbar>
@ -195,32 +154,26 @@ class PedView(PageView.PageView):
db.connect('person-update', self.person_updated_cb) db.connect('person-update', self.person_updated_cb)
db.connect('person-delete', self.person_updated_cb) db.connect('person-delete', self.person_updated_cb)
db.connect('person-rebuild', self.person_rebuild) db.connect('person-rebuild', self.person_rebuild)
self.rebuild_trees(None) self.active_person = None
def person_updated_cb(self,handle_list): def person_updated_cb(self,handle_list):
print "PedView.person_updated_cb" self.rebuild_trees(self.active_person)
self.rebuild_trees(self.state.active)
def person_rebuild(self): def person_rebuild(self):
print "PedView.person_rebuild" self.rebuild_trees(self.active_person)
self.rebuild_trees(self.state.active)
def person_edited_cb(self, p1=None, p2=None):
print "PedView.person_edited_cb"
def goto_active_person(self,handle): def goto_active_person(self,handle):
print "PedView.goto_active_person" print "PedView.goto_active_person"
if handle: if handle:
self.rebuild_trees(self.db.get_person_from_handle(handle)) self.active_person = self.db.get_person_from_handle(handle)
self.rebuild_trees(self.active_person)
else: else:
self.rebuild_trees(None) self.rebuild_trees(None)
def request_resize(self): def request_resize(self):
print "PedView.request_resize"
self.size_request_cb(self.notebook.parent,None,None) self.size_request_cb(self.notebook.parent,None,None)
def size_request_cb(self, widget, event, data=None): def size_request_cb(self, widget, event, data=None):
print "PedView.size_request_cb"
if self.force_size == 0: if self.force_size == 0:
v = widget.get_allocation() v = widget.get_allocation()
page_list = range(0,self.notebook.get_n_pages()) page_list = range(0,self.notebook.get_n_pages())
@ -295,14 +248,13 @@ class PedView(PageView.PageView):
self.rebuild( self.table_4, pos_4, person) self.rebuild( self.table_4, pos_4, person)
self.rebuild( self.table_5, pos_5, person) self.rebuild( self.table_5, pos_5, person)
#gobject.idle_add(self.request_resize) gobject.idle_add(self.request_resize)
def rebuild( self, table_widget, positions, active_person): def rebuild( self, table_widget, positions, active_person):
print "PedView.rebuild" print "PedView.rebuild"
# Build ancestor tree # Build ancestor tree
lst = [None]*31 lst = [None]*31
self.find_tree(active_person,0,1,lst) self.find_tree(self.active_person,0,1,lst)
# Purge current table content # Purge current table content
for child in table_widget.get_children(): for child in table_widget.get_children():
@ -429,17 +381,17 @@ class PedView(PageView.PageView):
def home(self,obj): def home(self,obj):
print "PedView.home" print "PedView.home"
defperson = self.state.db.get_default_person() defperson = self.dbstate.db.get_default_person()
if defperson: if defperson:
self.state.change_active_person(defperson) self.dbstate.change_active_person(defperson)
def edit_person_cb(self,obj): def edit_person_cb(self,obj):
person_handle = obj.get_data(_PERSON) person_handle = obj.get_data(_PERSON)
person = self.db.get_person_from_handle(person_handle) person = self.db.get_person_from_handle(person_handle)
if person: if person:
EditPerson.EditPerson(self.state, person, self.person_edited_cb) self.edit_person(person)
return True return True
return False return 0
def on_show_option_menu_cb(self,obj,data=None): def on_show_option_menu_cb(self,obj,data=None):
myMenu = gtk.Menu() myMenu = gtk.Menu()
@ -450,16 +402,16 @@ class PedView(PageView.PageView):
def on_show_child_menu(self,obj): def on_show_child_menu(self,obj):
"""User clicked button to move to child of active person""" """User clicked button to move to child of active person"""
if self.state.active: if self.active_person:
# Build and display the menu attached to the left pointing arrow # Build and display the menu attached to the left pointing arrow
# button. The menu consists of the children of the current root # button. The menu consists of the children of the current root
# person of the tree. Attach a child to each menu item. # person of the tree. Attach a child to each menu item.
childlist = find_children(self.db,self.state.active) childlist = find_children(self.db,self.active_person)
if len(childlist) == 1: if len(childlist) == 1:
child = self.db.get_person_from_handle(childlist[0]) child = self.db.get_person_from_handle(childlist[0])
if child: if child:
self.state.change_active_person(child) self.parent.change_active_person(child)
elif len(childlist) > 1: elif len(childlist) > 1:
myMenu = gtk.Menu() myMenu = gtk.Menu()
for child_handle in childlist: for child_handle in childlist:
@ -488,7 +440,7 @@ class PedView(PageView.PageView):
person_handle = obj.get_data(_PERSON) person_handle = obj.get_data(_PERSON)
if person_handle: if person_handle:
self.state.change_active_handle(person_handle) self.dbstate.change_active_handle(person_handle)
return True return True
return False return False

View File

@ -42,6 +42,7 @@ from gtk.gdk import ACTION_COPY, BUTTON1_MASK
# GRAMPS modules # GRAMPS modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import RelLib
import PeopleModel import PeopleModel
import PageView import PageView
import GenericFilter import GenericFilter
@ -68,38 +69,90 @@ column_names = [
class PersonView(PageView.PageView): class PersonView(PageView.PageView):
def __init__(self,state): def __init__(self,dbstate,uistate):
PageView.PageView.__init__(self,'Person View',state) PageView.PageView.__init__(self,'Person View',dbstate,uistate)
self.inactive = False self.inactive = False
state.connect('database-changed',self.change_db) dbstate.connect('database-changed',self.change_db)
state.connect('active-changed',self.goto_active_person) dbstate.connect('active-changed',self.goto_active_person)
def setup_filter(self): def navigation_type(self):
all = GenericFilter.GenericFilter() return PageView.NAVIGATION_PERSON
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
self.DataFilter = None
self.init_filters()
def define_actions(self): def define_actions(self):
"""
Required define_actions function for PageView. Builds the action
group information required. We extend beyond the normal here,
since we want to have more than one action group for the PersonView.
Most PageViews really won't care about this.
Special action groups for Forward and Back are created to allow the
handling of navigation buttons. Forward and Back allow the user to
advance or retreat throughout the history, and we want to have these
be able to toggle these when you are at the end of the history or
at the beginning of the history.
"""
self.add_action('Add', gtk.STOCK_ADD, "_Add", callback=self.add) self.add_action('Add', gtk.STOCK_ADD, "_Add", callback=self.add)
self.add_action('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit) self.add_action('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit)
self.add_action('Remove', gtk.STOCK_REMOVE,"_Remove",callback=self.remove) self.add_action('Remove', gtk.STOCK_REMOVE,"_Remove",callback=self.remove)
self.add_action('Forward',gtk.STOCK_GO_FORWARD,"_Forward", callback=self.fwd_clicked)
self.add_action('Back', gtk.STOCK_GO_BACK, "_Back", callback=self.back_clicked)
self.add_action('HomePerson',gtk.STOCK_HOME, "_Home", callback=self.home) self.add_action('HomePerson',gtk.STOCK_HOME, "_Home", callback=self.home)
self.add_toggle_action('Filter', None, '_Filter', callback=self.filter_toggle) self.add_toggle_action('Filter', None, '_Filter', callback=self.filter_toggle)
# add the Forward action group to handle the Forward button
self.fwd_action = gtk.ActionGroup(self.title + '/Forward')
self.fwd_action.add_actions([
('Forward',gtk.STOCK_GO_FORWARD,"_Forward", None, None, self.fwd_clicked)
])
# add the Backward action group to handle the Forward button
self.back_action = gtk.ActionGroup(self.title + '/Backward')
self.back_action.add_actions([
('Back',gtk.STOCK_GO_BACK,"_Back", None, None, self.back_clicked)
])
self.add_action_group(self.back_action)
self.add_action_group(self.fwd_action)
def disable_action_group(self):
"""
Normally, this would not be overridden from the base class. However,
in this case, we have additional action groups that need to be
handled correctly.
"""
PageView.PageView.disable_action_group(self)
self.fwd_action.set_visible(False)
self.back_action.set_visible(False)
def enable_action_group(self,obj):
"""
Normally, this would not be overridden from the base class. However,
in this case, we have additional action groups that need to be
handled correctly.
"""
PageView.PageView.enable_action_group(self,obj)
self.fwd_action.set_visible(True)
self.back_action.set_visible(True)
hobj = self.uistate.phistory
self.fwd_action.set_sensitive(not hobj.at_end())
self.back_action.set_sensitive(not hobj.at_front())
def get_stock(self): def get_stock(self):
"""
Returns the name of the stock icon to use for the display.
This assumes that this icon has already been registered with
GNOME as a stock icon.
"""
return 'gramps-person' return 'gramps-person'
def build_tree(self):
self.person_model = PeopleModel.PeopleModel(
self.state.db, self.DataFilter, self.filter_invert.get_active())
self.person_tree.set_model(self.person_model)
def build_widget(self): def build_widget(self):
"""
Builds the interface and returns a gtk.Container type that
contains the interface. This containter will be inserted into
a gtk.Notebook page.
"""
self.vbox = gtk.VBox() self.vbox = gtk.VBox()
self.vbox.set_border_width(4) self.vbox.set_border_width(4)
self.vbox.set_spacing(4) self.vbox.set_spacing(4)
@ -133,8 +186,6 @@ class PersonView(PageView.PageView):
self.vbox.pack_start(self.filterbar,False) self.vbox.pack_start(self.filterbar,False)
self.vbox.pack_start(scrollwindow,True) self.vbox.pack_start(scrollwindow,True)
# temporary hack
self.renderer = gtk.CellRendererText() self.renderer = gtk.CellRendererText()
self.inactive = False self.inactive = False
@ -153,14 +204,14 @@ class PersonView(PageView.PageView):
self.vbox.set_focus_chain([self.person_tree,self.filter_list, self.filter_text, self.vbox.set_focus_chain([self.person_tree,self.filter_list, self.filter_text,
self.filter_invert, self.filter_button]) self.filter_invert, self.filter_button])
a = gtk.ListStore(str,str)
self.person_tree.set_model(a)
self.setup_filter() self.setup_filter()
return self.vbox return self.vbox
def ui_definition(self): def ui_definition(self):
"""
Specifies the UIManager XML code that defines the menus and buttons
associated with the interface.
"""
return '''<ui> return '''<ui>
<menubar name="MenuBar"> <menubar name="MenuBar">
<menu action="ViewMenu"> <menu action="ViewMenu">
@ -197,175 +248,54 @@ class PersonView(PageView.PageView):
</toolbar> </toolbar>
</ui>''' </ui>'''
def filter_toggle(self,obj): def change_db(self,db):
if obj.get_active(): """
self.filterbar.show() Callback associated with DbState. Whenenver the database
else: changes, this task is called. In this case, we rebuild the
self.filterbar.hide() columns, and connect signals to the connected database. Tere
is no need to store the database, since we will get the value
def add(self,obj): from self.state.db
person = RelLib.Person() """
EditPerson.EditPerson(self, person, self.state.db, self.build_columns()
None) db.connect('person-add', self.person_added)
db.connect('person-update', self.person_updated)
def edit(self,obj): db.connect('person-delete', self.person_removed)
EditPerson.EditPerson(self, self.state.active, self.state.db, db.connect('person-rebuild', self.build_tree)
None)
def remove(self,obj):
mlist = self.get_selected_objects()
if len(mlist) == 0:
return
for sel in mlist:
p = self.state.db.get_person_from_handle(sel)
self.active_person = p
name = NameDisplay.displayer.display(p)
msg = _('Deleting the person will remove the person '
'from the database.')
msg = "%s %s" % (msg,Utils.data_recover_msg)
QuestionDialog.QuestionDialog(_('Delete %s?') % name,msg,
_('_Delete Person'),
self.delete_person_response)
def delete_person_response(self):
#self.disable_interface()
trans = self.state.db.transaction_begin()
n = NameDisplay.displayer.display(self.active_person)
if self.state.db.get_default_person() == self.active_person:
self.state.db.set_default_person_handle(None)
for family_handle in self.active_person.get_family_handle_list():
if not family_handle:
continue
family = self.state.db.get_family_from_handle(family_handle)
family_to_remove = False
if self.active_person.get_handle() == family.get_father_handle():
if family.get_mother_handle():
family.set_father_handle(None)
else:
family_to_remove = True
else:
if family.get_father_handle():
family.set_mother_handle(None)
else:
family_to_remove = True
if family_to_remove:
for child_handle in family.get_child_handle_list():
child = self.state.db.get_person_from_handle(child_handle)
child.remove_parent_family_handle(family_handle)
self.db.commit_person(child,trans)
self.state.db.remove_family(family_handle,trans)
else:
self.state.db.commit_family(family,trans)
for (family_handle,mrel,frel) in self.active_person.get_parent_family_handle_list():
if family_handle:
family = self.db.get_family_from_handle(family_handle)
family.remove_child_handle(self.active_person.get_handle())
self.db.commit_family(family,trans)
handle = self.active_person.get_handle()
person = self.active_person
self.remove_from_person_list(person)
self.people_view.remove_from_history(handle)
self.state.db.remove_person(handle, trans)
if self.state.phistory.index >= 0:
self.active_person = self.state.db.get_person_from_handle(self.state.phistory.history[self.index])
else:
self.state.change_active_person(None)
self.state.db.transaction_commit(trans,_("Delete Person (%s)") % n)
#self.redraw_histmenu()
#self.enable_interface()
def build_columns(self):
for column in self.columns:
self.person_tree.remove_column(column)
column = gtk.TreeViewColumn(_('Name'), self.renderer,text=0)
column.set_resizable(True)
#column.set_clickable(True)
#column.connect('clicked',self.sort_clicked)
column.set_min_width(225)
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
self.person_tree.append_column(column)
self.columns = [column]
for pair in self.state.db.get_person_column_order():
if not pair[0]:
continue
name = column_names[pair[1]]
column = gtk.TreeViewColumn(name, self.renderer, markup=pair[1])
column.set_resizable(True)
column.set_min_width(60)
column.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY)
self.columns.append(column)
self.person_tree.append_column(column)
def row_changed(self,obj):
"""Called with a row is changed. Check the selected objects from
the person_tree to get the IDs of the selected objects. Set the
active person to the first person in the list. If no one is
selected, set the active person to None"""
selected_ids = self.get_selected_objects()
try:
person = self.state.db.get_person_from_handle(selected_ids[0])
self.state.change_active_person(person)
self.goto_active_person()
except:
self.state.change_active_person(None)
if len(selected_ids) == 1:
self.person_tree.drag_source_set(BUTTON1_MASK,
[DdTargets.PERSON_LINK.target()],
ACTION_COPY)
elif len(selected_ids) > 1:
self.person_tree.drag_source_set(BUTTON1_MASK,
[DdTargets.PERSON_LINK_LIST.target()],
ACTION_COPY)
self.state.modify_statusbar()
def alpha_event(self,*obj):
pass
#self.parent.load_person(self.parent.active_person)
def on_plist_button_press(self,obj,event):
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
self.build_people_context_menu(event)
def person_drag_data_get(self, widget, context, sel_data, info, time):
selected_ids = self.get_selected_objects()
if len(selected_ids) == 1:
sel_data.set(sel_data.target, 8, selected_ids[0])
elif len(selected_ids) > 1:
sel_data.set(DdTargets.PERSON_LINK_LIST.drag_type,8,
pickle.dumps(selected_ids))
def apply_filter_clicked(self):
index = self.filter_list.get_active()
self.DataFilter = self.filter_model.get_filter(index)
if self.DataFilter.need_param:
qual = unicode(self.filter_text.get_text())
self.DataFilter.set_parameter(qual)
self.apply_filter() self.apply_filter()
self.goto_active_person()
def goto_active_person(self,obj=None): def goto_active_person(self,obj=None):
if not self.state.active or self.inactive: """
Callback (and usable function) that selects the active person
in the display tree.
We have a bit of a problem due to the nature of how GTK works.
We have unselect the previous path and select the new path. However,
these cause a row change, which calls the row_change callback, which
can end up calling change_active_person, which can call
goto_active_person, causing a bit of recusion. Confusing, huh?
Unforunately, we row_change has to be able to call change_active_person,
because the can occur from the interface in addition to programatically.
TO handle this, we set the self.inactive variable that we can check
in row_change to look for this particular condition.
"""
# if there is no active person, or if we have been marked inactive,
# simply return
if not self.dbstate.active or self.inactive:
return return
# mark inactive to prevent recusion
self.inactive = True self.inactive = True
p = self.state.active
# select the active person in the person view
p = self.dbstate.active
try: try:
path = self.person_model.on_get_path(p.get_handle()) path = self.person_model.on_get_path(p.get_handle())
group_name = p.get_primary_name().get_group_name() group_name = p.get_primary_name().get_group_name()
top_name = self.state.db.get_name_group_mapping(group_name) top_name = self.dbstate.db.get_name_group_mapping(group_name)
top_path = self.person_model.on_get_path(top_name) top_path = self.person_model.on_get_path(top_name)
self.person_tree.expand_row(top_path,0) self.person_tree.expand_row(top_path,0)
@ -378,117 +308,29 @@ class PersonView(PageView.PageView):
except KeyError: except KeyError:
self.person_selection.unselect_all() self.person_selection.unselect_all()
print "Person not currently available due to filter" print "Person not currently available due to filter"
self.state.active = p self.dbstate.active = p
# disable the inactive flag
self.inactive = False self.inactive = False
def redisplay_person_list(self): # update history
self.build_tree() self.handle_history(p.handle)
def person_added(self,handle_list): def handle_history(self, handle):
for node in handle_list: """
person = self.state.db.get_person_from_handle(node) Updates the person history information
top = person.get_primary_name().get_group_name() """
self.person_model.rebuild_data(self.DataFilter) hobj = self.uistate.phistory
if not self.person_model.is_visable(node): if handle and not hobj.lock:
continue hobj.push(handle)
if (not self.person_model.sname_sub.has_key(top) or #self.redraw_histmenu()
len(self.person_model.sname_sub[top]) == 1): self.fwd_action.set_sensitive(not hobj.at_end())
path = self.person_model.on_get_path(top) self.back_action.set_sensitive(not hobj.at_front())
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
path = self.person_model.on_get_path(node)
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
def person_removed(self,handle_list): def setup_filter(self):
for node in handle_list: """
person = self.state.db.get_person_from_handle(node) Builds the default filters and add them to the filter menu.
if not self.person_model.is_visable(node): """
continue
top = person.get_primary_name().get_group_name()
mylist = self.person_model.sname_sub.get(top,[])
if mylist:
try:
path = self.person_model.on_get_path(node)
self.person_model.row_deleted(path)
if len(mylist) == 1:
path = self.person_model.on_get_path(top)
self.person_model.row_deleted(path)
except KeyError:
pass
self.person_model.rebuild_data(self.DataFilter,skip=node)
def person_updated(self,handle_list):
for node in handle_list:
person = self.state.db.get_person_from_handle(node)
try:
oldpath = self.person_model.iter2path[node]
except:
return
pathval = self.person_model.on_get_path(node)
pnode = self.person_model.get_iter(pathval)
# calculate the new data
if person.primary_name.group_as:
surname = person.primary_name.group_as
else:
surname = self.state.db.get_name_group_mapping(person.primary_name.surname)
if oldpath[0] == surname:
self.person_model.build_sub_entry(surname)
else:
self.person_model.calculate_data(self.DataFilter)
# find the path of the person in the new data build
newpath = self.person_model.temp_iter2path[node]
# if paths same, just issue row changed signal
if oldpath == newpath:
self.person_model.row_changed(pathval,pnode)
else:
# paths different, get the new surname list
mylist = self.person_model.temp_sname_sub.get(oldpath[0],[])
path = self.person_model.on_get_path(node)
# delete original
self.person_model.row_deleted(pathval)
# delete top node of original if necessar
if len(mylist)==0:
self.person_model.row_deleted(pathval[0])
# determine if we need to insert a new top node',
insert = not self.person_model.sname_sub.has_key(newpath[0])
# assign new data
self.person_model.assign_data()
# insert new row if needed
if insert:
path = self.person_model.on_get_path(newpath[0])
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
# insert new person
path = self.person_model.on_get_path(node)
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
self.goto_active_person()
def change_db(self,db):
self.build_columns()
db.connect('person-add', self.person_added)
db.connect('person-update', self.person_updated)
db.connect('person-delete', self.person_removed)
db.connect('person-rebuild', self.redisplay_person_list)
self.apply_filter()
def init_filters(self):
cell = gtk.CellRendererText() cell = gtk.CellRendererText()
self.filter_list.clear() self.filter_list.clear()
@ -497,6 +339,12 @@ class PersonView(PageView.PageView):
filter_list = [] filter_list = []
self.DataFilter = None
all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
all = GenericFilter.GenericFilter() all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database")) all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([])) all.add_rule(GenericFilter.Everyone([]))
@ -611,7 +459,270 @@ class PersonView(PageView.PageView):
self.filter_list.set_model(self.filter_model) self.filter_list.set_model(self.filter_model)
self.filter_list.set_active(self.filter_model.default_index()) self.filter_list.set_active(self.filter_model.default_index())
self.filter_list.connect('changed',self.on_filter_name_changed) self.filter_list.connect('changed',self.on_filter_name_changed)
self.filter_text.set_sensitive(0) self.filter_text.set_sensitive(False)
def build_tree(self):
"""
Creates a new PeopleModel instance. Essentially creates a complete
rebuild of the data.
"""
self.person_model = PeopleModel.PeopleModel(
self.dbstate.db, self.DataFilter, self.filter_invert.get_active())
self.person_tree.set_model(self.person_model)
def filter_toggle(self,obj):
if obj.get_active():
self.filterbar.show()
else:
self.filterbar.hide()
def add(self,obj):
person = RelLib.Person()
EditPerson.EditPerson(self.dbstate, self.uistate, person)
def edit(self,obj):
EditPerson.EditPerson(self.dbstate, self.uistate, self.dbstate.active)
def remove(self,obj):
mlist = self.get_selected_objects()
if len(mlist) == 0:
return
for sel in mlist:
p = self.dbstate.db.get_person_from_handle(sel)
self.active_person = p
name = NameDisplay.displayer.display(p)
msg = _('Deleting the person will remove the person '
'from the database.')
msg = "%s %s" % (msg,Utils.data_recover_msg)
QuestionDialog.QuestionDialog(_('Delete %s?') % name,msg,
_('_Delete Person'),
self.delete_person_response)
def delete_person_response(self):
#self.disable_interface()
trans = self.dbstate.db.transaction_begin()
n = NameDisplay.displayer.display(self.active_person)
if self.dbstate.db.get_default_person() == self.active_person:
self.dbstate.db.set_default_person_handle(None)
for family_handle in self.active_person.get_family_handle_list():
if not family_handle:
continue
family = self.dbstate.db.get_family_from_handle(family_handle)
family_to_remove = False
if self.active_person.get_handle() == family.get_father_handle():
if family.get_mother_handle():
family.set_father_handle(None)
else:
family_to_remove = True
else:
if family.get_father_handle():
family.set_mother_handle(None)
else:
family_to_remove = True
if family_to_remove:
for child_handle in family.get_child_handle_list():
child = self.dbstate.db.get_person_from_handle(child_handle)
child.remove_parent_family_handle(family_handle)
self.db.commit_person(child,trans)
self.dbstate.db.remove_family(family_handle,trans)
else:
self.dbstate.db.commit_family(family,trans)
for (family_handle,mrel,frel) in self.active_person.get_parent_family_handle_list():
if family_handle:
family = self.db.get_family_from_handle(family_handle)
family.remove_child_handle(self.active_person.get_handle())
self.db.commit_family(family,trans)
handle = self.active_person.get_handle()
person = self.active_person
self.remove_from_person_list(person)
self.people_view.remove_from_history(handle)
self.dbstate.db.remove_person(handle, trans)
if self.uistate.phistory.index >= 0:
handle = self.uistate.phistory.history[self.index]
self.active_person = self.dbstate.db.get_person_from_handle(handle)
else:
self.dbstate.change_active_person(None)
self.dbstate.db.transaction_commit(trans,_("Delete Person (%s)") % n)
#self.redraw_histmenu()
#self.enable_interface()
def build_columns(self):
for column in self.columns:
self.person_tree.remove_column(column)
column = gtk.TreeViewColumn(_('Name'), self.renderer,text=0)
column.set_resizable(True)
#column.set_clickable(True)
#column.connect('clicked',self.sort_clicked)
column.set_min_width(225)
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
self.person_tree.append_column(column)
self.columns = [column]
for pair in self.dbstate.db.get_person_column_order():
if not pair[0]:
continue
name = column_names[pair[1]]
column = gtk.TreeViewColumn(name, self.renderer, markup=pair[1])
column.set_resizable(True)
column.set_min_width(60)
column.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY)
self.columns.append(column)
self.person_tree.append_column(column)
def row_changed(self,obj):
"""Called with a row is changed. Check the selected objects from
the person_tree to get the IDs of the selected objects. Set the
active person to the first person in the list. If no one is
selected, set the active person to None"""
selected_ids = self.get_selected_objects()
if not self.inactive:
try:
person = self.dbstate.db.get_person_from_handle(selected_ids[0])
self.dbstate.change_active_person(person)
except:
self.dbstate.change_active_person(None)
if len(selected_ids) == 1:
self.person_tree.drag_source_set(BUTTON1_MASK,
[DdTargets.PERSON_LINK.target()],
ACTION_COPY)
elif len(selected_ids) > 1:
self.person_tree.drag_source_set(BUTTON1_MASK,
[DdTargets.PERSON_LINK_LIST.target()],
ACTION_COPY)
self.uistate.modify_statusbar()
def alpha_event(self,*obj):
EditPerson.EditPerson(self.dbstate, self.dbstate.active)
def on_plist_button_press(self,obj,event):
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
self.build_people_context_menu(event)
def person_drag_data_get(self, widget, context, sel_data, info, time):
selected_ids = self.get_selected_objects()
if len(selected_ids) == 1:
sel_data.set(sel_data.target, 8, selected_ids[0])
elif len(selected_ids) > 1:
sel_data.set(DdTargets.PERSON_LINK_LIST.drag_type,8,
pickle.dumps(selected_ids))
def apply_filter_clicked(self):
index = self.filter_list.get_active()
self.DataFilter = self.filter_model.get_filter(index)
if self.DataFilter.need_param:
qual = unicode(self.filter_text.get_text())
self.DataFilter.set_parameter(qual)
self.apply_filter()
self.goto_active_person()
def person_added(self,handle_list):
for node in handle_list:
person = self.dbstate.db.get_person_from_handle(node)
top = person.get_primary_name().get_group_name()
self.person_model.rebuild_data(self.DataFilter)
if not self.person_model.is_visable(node):
continue
if (not self.person_model.sname_sub.has_key(top) or
len(self.person_model.sname_sub[top]) == 1):
path = self.person_model.on_get_path(top)
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
path = self.person_model.on_get_path(node)
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
def person_removed(self,handle_list):
for node in handle_list:
person = self.dbstate.db.get_person_from_handle(node)
if not self.person_model.is_visable(node):
continue
top = person.get_primary_name().get_group_name()
mylist = self.person_model.sname_sub.get(top,[])
if mylist:
try:
path = self.person_model.on_get_path(node)
self.person_model.row_deleted(path)
if len(mylist) == 1:
path = self.person_model.on_get_path(top)
self.person_model.row_deleted(path)
except KeyError:
pass
self.person_model.rebuild_data(self.DataFilter,skip=node)
def person_updated(self,handle_list):
for node in handle_list:
person = self.dbstate.db.get_person_from_handle(node)
try:
oldpath = self.person_model.iter2path[node]
except:
return
pathval = self.person_model.on_get_path(node)
pnode = self.person_model.get_iter(pathval)
# calculate the new data
if person.primary_name.group_as:
surname = person.primary_name.group_as
else:
base = person.primary_name.surname
surname = self.dbstate.db.get_name_group_mapping(base)
if oldpath[0] == surname:
self.person_model.build_sub_entry(surname)
else:
self.person_model.calculate_data(self.DataFilter)
# find the path of the person in the new data build
newpath = self.person_model.temp_iter2path[node]
# if paths same, just issue row changed signal
if oldpath == newpath:
self.person_model.row_changed(pathval,pnode)
else:
# paths different, get the new surname list
mylist = self.person_model.temp_sname_sub.get(oldpath[0],[])
path = self.person_model.on_get_path(node)
# delete original
self.person_model.row_deleted(pathval)
# delete top node of original if necessar
if len(mylist)==0:
self.person_model.row_deleted(pathval[0])
# determine if we need to insert a new top node',
insert = not self.person_model.sname_sub.has_key(newpath[0])
# assign new data
self.person_model.assign_data()
# insert new row if needed
if insert:
path = self.person_model.on_get_path(newpath[0])
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
# insert new person
path = self.person_model.on_get_path(node)
pnode = self.person_model.get_iter(path)
self.person_model.row_inserted(path,pnode)
self.goto_active_person()
def on_filter_name_changed(self,obj): def on_filter_name_changed(self,obj):
index = self.filter_list.get_active() index = self.filter_list.get_active()
@ -628,9 +739,9 @@ class PersonView(PageView.PageView):
self.filter_label.hide() self.filter_label.hide()
def apply_filter(self,current_model=None): def apply_filter(self,current_model=None):
#self.parent.status_text(_('Updating display...')) self.uistate.status_text(_('Updating display...'))
self.build_tree() self.build_tree()
#self.parent.modify_statusbar() self.uistate.modify_statusbar()
def get_selected_objects(self): def get_selected_objects(self):
(mode,paths) = self.person_selection.get_selected_rows() (mode,paths) = self.person_selection.get_selected_rows()
@ -652,7 +763,7 @@ class PersonView(PageView.PageView):
def build_backhistmenu(self,event): def build_backhistmenu(self,event):
"""Builds and displays the menu with the back portion of the history""" """Builds and displays the menu with the back portion of the history"""
hobj = self.state.phistory hobj = self.uistate.phistory
if hobj.index > 0: if hobj.index > 0:
backhistmenu = gtk.Menu() backhistmenu = gtk.Menu()
backhistmenu.set_title(_('Back Menu')) backhistmenu.set_title(_('Back Menu'))
@ -667,7 +778,7 @@ class PersonView(PageView.PageView):
hotkey = "_%s" % chr(ord('a')+num-11) hotkey = "_%s" % chr(ord('a')+num-11)
elif num >= 21: elif num >= 21:
break break
person = self.state.db.get_person_from_handle(pid) person = self.dbstate.db.get_person_from_handle(pid)
item = gtk.MenuItem("%s. %s [%s]" % item = gtk.MenuItem("%s. %s [%s]" %
(hotkey, (hotkey,
NameDisplay.displayer.display(person), NameDisplay.displayer.display(person),
@ -713,71 +824,50 @@ class PersonView(PageView.PageView):
self.build_fwdhistmenu(event) self.build_fwdhistmenu(event)
def fwd_clicked(self,obj,step=1): def fwd_clicked(self,obj,step=1):
print "fwd clicked" hobj = self.uistate.phistory
hobj = self.state.phistory
hobj.lock = True hobj.lock = True
print hobj.history if not hobj.at_end():
if hobj.index+1 < len(hobj.history):
try: try:
hobj.index += step handle = hobj.forward()
handle = str(hobj.history[hobj.index]) self.dbstate.active = self.dbstate.db.get_person_from_handle(handle)
self.state.active = self.state.db.get_person_from_handle(handle) self.uistate.modify_statusbar()
self.state.modify_statusbar() self.dbstate.change_active_handle(handle)
self.state.change_active_handle(handle) hobj.mhistory.append(hobj.history[hobj.index])
hobj.mhistory.append(self.history[hobj.index])
#self.redraw_histmenu() #self.redraw_histmenu()
self.set_buttons(True) self.fwd_action.set_sensitive(not hobj.at_end())
if hobj.index == len(hobj.history)-1: self.back_action.set_sensitive(True)
self.fwdbtn.set_sensitive(False)
self.forward.set_sensitive(False)
else:
self.fwdbtn.set_sensitive(True)
self.forward.set_sensitive(True)
self.backbtn.set_sensitive(True)
self.back.set_sensitive(True)
except: except:
self.clear_history() hobj.clear()
self.fwd_action.set_sensitive(False)
self.back_action.set_sensitive(False)
else: else:
self.fwdbtn.set_sensitive(False) self.fwd_action.set_sensitive(False)
self.forward.set_sensitive(False) self.back_action.set_sensitive(True)
self.backbtn.set_sensitive(True)
self.back.set_sensitive(True)
self.goto_active_person()
hobj.lock = False hobj.lock = False
def back_clicked(self,obj,step=1): def back_clicked(self,obj,step=1):
hobj = self.state.phistory hobj = self.uistate.phistory
hobj.lock = True hobj.lock = True
if hobj.index > 0: if not hobj.at_front():
try: try:
hobj.index -= step handle = hobj.back()
handle = str(hobj.history[hobj.hindex]) self.active = self.dbstate.db.get_person_from_handle(handle)
self.active = self.db.get_person_from_handle(handle) self.uistate.modify_statusbar()
self.modify_statusbar() self.dbstate.change_active_handle(handle)
self.change_active_handle(handle)
hobj.mhistory.append(hobj.history[hobj.index]) hobj.mhistory.append(hobj.history[hobj.index])
self.redraw_histmenu() # self.redraw_histmenu()
self.set_buttons(1) self.back_action.set_sensitive(not hobj.at_front())
if hobj.index == 0: self.fwd_action.set_sensitive(True)
self.backbtn.set_sensitive(False)
self.back.set_sensitive(False)
else:
self.backbtn.set_sensitive(True)
self.back.set_sensitive(True)
self.fwdbtn.set_sensitive(True)
self.forward.set_sensitive(True)
except: except:
hobj.clear_history() hobj.clear()
self.fwd_action.set_sensitive(False)
self.back_action.set_sensitive(False)
else: else:
self.backbtn.set_sensitive(False) self.back_action.set_sensitive(False)
self.back.set_sensitive(False) self.fwd_action.set_sensitive(True)
self.fwdbtn.set_sensitive(True)
self.forward.set_sensitive(True)
self.goto_active_person()
hobj.lock = False hobj.lock = False
def home(self,obj): def home(self,obj):
defperson = self.state.db.get_default_person() defperson = self.dbstate.db.get_default_person()
if defperson: if defperson:
self.state.change_active_person(defperson) self.dbstate.change_active_person(defperson)
self.goto_active_person()

View File

@ -57,6 +57,9 @@ import GrampsCfg
import Errors import Errors
import DisplayTrace import DisplayTrace
import Utils import Utils
import QuestionDialog
import PageView
import Navigation
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -99,6 +102,7 @@ uidefault = '''<ui>
</menu> </menu>
<menu action="GoMenu"> <menu action="GoMenu">
<placeholder name="CommonGo"/> <placeholder name="CommonGo"/>
<placeholder name="CommonHistory"/>
</menu> </menu>
<menu action="BookMenu"> <menu action="BookMenu">
<menuitem action="AddBook"/> <menuitem action="AddBook"/>
@ -132,8 +136,14 @@ uidefault = '''<ui>
class ViewManager: class ViewManager:
def __init__(self): def __init__(self,state):
self.navigation_type = {
PageView.NAVIGATION_NONE: (None, None),
PageView.NAVIGATION_PERSON: (None,None),
}
self.state = state
self.active_page = None self.active_page = None
self.views = [] self.views = []
self.window = gtk.Window() self.window = gtk.Window()
@ -160,14 +170,17 @@ class ViewManager:
hbox.pack_start(self.notebook,True) hbox.pack_start(self.notebook,True)
self.menubar = self.uimanager.get_widget('/MenuBar') self.menubar = self.uimanager.get_widget('/MenuBar')
self.toolbar = self.uimanager.get_widget('/ToolBar') self.toolbar = self.uimanager.get_widget('/ToolBar')
print self.uimanager.get_widget('/MenuBar/GoMenu')
vbox.pack_start(self.menubar, False) vbox.pack_start(self.menubar, False)
vbox.pack_start(self.toolbar, False) vbox.pack_start(self.toolbar, False)
vbox.add(hbox) vbox.add(hbox)
vbox.pack_end(self.statusbar,False) vbox.pack_end(self.statusbar,False)
self.notebook.connect('switch-page',self.change_page) self.notebook.connect('switch-page',self.change_page)
self.state = DbState.DbState(self.window,self.statusbar,self.uimanager) self.uistate = DbState.DisplayState(self.window, self.statusbar,
self.uimanager, self.state)
person_nav = Navigation.PersonNavigation(self.uistate)
self.navigation_type[PageView.NAVIGATION_PERSON] = (person_nav,None)
self.window.show_all() self.window.show_all()
def init_interface(self): def init_interface(self):
@ -187,7 +200,7 @@ class ViewManager:
obj.set_style(style) obj.set_style(style)
def build_ui_manager(self): def build_ui_manager(self):
self.merge_id = 0 self.merge_ids = []
self.uimanager = gtk.UIManager() self.uimanager = gtk.UIManager()
accelgroup = self.uimanager.get_accel_group() accelgroup = self.uimanager.get_accel_group()
@ -259,10 +272,12 @@ class ViewManager:
def create_pages(self): def create_pages(self):
self.pages = [] self.pages = []
self.prev_nav = PageView.NAVIGATION_NONE
index = 0 index = 0
self.set_color(self.ebox) self.set_color(self.ebox)
for page_def in self.views: for page_def in self.views:
page = page_def(self.state) page = page_def(self.state,self.uistate)
# create icon/label for notebook # create icon/label for notebook
hbox = gtk.HBox() hbox = gtk.HBox()
@ -291,8 +306,8 @@ class ViewManager:
self.bbox.pack_start(button,False) self.bbox.pack_start(button,False)
def change_page(self,obj,page,num): def change_page(self,obj,page,num):
if self.merge_id: for mergeid in self.merge_ids:
self.uimanager.remove_ui(self.merge_id) self.uimanager.remove_ui(mergeid)
if self.active_page: if self.active_page:
groups = self.active_page.get_actions() groups = self.active_page.get_actions()
for grp in groups: for grp in groups:
@ -300,16 +315,28 @@ class ViewManager:
if len(self.pages) > 0: if len(self.pages) > 0:
self.active_page = self.pages[num] self.active_page = self.pages[num]
old_nav = self.navigation_type[self.prev_nav]
if old_nav[0] != None:
old_nav[0].disable
nav_type = self.navigation_type[self.active_page.navigation_type()]
if nav_type[0] != None:
nav_type[0].enable()
groups = self.active_page.get_actions() groups = self.active_page.get_actions()
for grp in groups: for grp in groups:
self.uimanager.insert_action_group(grp,1) self.uimanager.insert_action_group(grp,1)
self.merge_id = self.uimanager.add_ui_from_string(self.active_page.ui_definition()) self.merge_ids = [self.uimanager.add_ui_from_string(self.active_page.ui_definition())]
for ui in self.active_page.additional_ui_definitions():
mergeid = self.uimanager.add_ui_from_string(ui)
self.merge_ids.append(mergeid)
def on_open_activate(self,obj): def on_open_activate(self,obj):
choose = gtk.FileChooserDialog(_('GRAMPS: Open database'), choose = gtk.FileChooserDialog(_('GRAMPS: Open database'),
self.state.window, self.uistate.window,
gtk.FILE_CHOOSER_ACTION_OPEN, gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, (gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL, gtk.RESPONSE_CANCEL,
@ -396,7 +423,7 @@ class ViewManager:
def on_new_activate(self,obj): def on_new_activate(self,obj):
choose = gtk.FileChooserDialog(_('GRAMPS: Create GRAMPS database'), choose = gtk.FileChooserDialog(_('GRAMPS: Create GRAMPS database'),
self.state.window, self.uistate.window,
gtk.FILE_CHOOSER_ACTION_SAVE, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, (gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL, gtk.RESPONSE_CANCEL,
@ -501,9 +528,9 @@ class ViewManager:
return 0 return 0
elif not os.access(filename,os.W_OK): elif not os.access(filename,os.W_OK):
mode = "r" mode = "r"
WarningDialog(_('Read only database'), QuestionDialog.WarningDialog(_('Read only database'),
_('You do not have write access to the selected ' _('You do not have write access '
'file.')) 'to the selected file.'))
try: try:
if self.load_database(filename,callback,mode=mode) == 1: if self.load_database(filename,callback,mode=mode) == 1:
@ -511,19 +538,19 @@ class ViewManager:
filename = filename[:-1] filename = filename[:-1]
name = os.path.basename(filename) name = os.path.basename(filename)
if self.state.db.readonly: if self.state.db.readonly:
self.state.window.set_title("%s (%s) - GRAMPS" % (name,_('Read Only'))) self.uistate.window.set_title("%s (%s) - GRAMPS" % (name,_('Read Only')))
else: else:
self.state.window.set_title("%s - GRAMPS" % name) self.uistate.window.set_title("%s - GRAMPS" % name)
else: else:
GrampsKeys.save_last_file("") GrampsKeys.save_last_file("")
ErrorDialog(_('Cannot open database'), QuestionDialog.ErrorDialog(_('Cannot open database'),
_('The database file specified could not be opened.')) _('The database file specified could not be opened.'))
return 0 return 0
except ( IOError, OSError, Errors.FileVersionError), msg: except ( IOError, OSError, Errors.FileVersionError), msg:
ErrorDialog(_('Cannot open database'),str(msg)) QuestionDialog.ErrorDialog(_('Cannot open database'),str(msg))
return 0 return 0
except (db.DBAccessError,db.DBError), msg: except (db.DBAccessError,db.DBError), msg:
ErrorDialog(_('Cannot open database'), QuestionDialog.ErrorDialog(_('Cannot open database'),
_('%s could not be opened.' % filename) + '\n' + msg[1]) _('%s could not be opened.' % filename) + '\n' + msg[1])
return 0 return 0
except Exception: except Exception:
@ -588,9 +615,8 @@ class ViewManager:
ScratchPad.ScratchPadWindow(self.state, self) ScratchPad.ScratchPadWindow(self.state, self)
def on_import(self,obj): def on_import(self,obj):
print "import"
choose = gtk.FileChooserDialog(_('GRAMPS: Import database'), choose = gtk.FileChooserDialog(_('GRAMPS: Import database'),
self.state.window, self.uistate.window,
gtk.FILE_CHOOSER_ACTION_OPEN, gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, (gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL, gtk.RESPONSE_CANCEL,

View File

@ -32,6 +32,7 @@ import const
import Errors import Errors
import PluginMgr import PluginMgr
import TipOfDay import TipOfDay
import DbState
from GrampsMime import mime_type_is_defined from GrampsMime import mime_type_is_defined
from QuestionDialog import ErrorDialog from QuestionDialog import ErrorDialog
@ -39,7 +40,7 @@ from QuestionDialog import ErrorDialog
import gnome import gnome
iconpaths = [".","/usr/share/gramps","~/devel/srcx"] iconpaths = [".","/usr/share/gramps"]
def register_stock_icons (): def register_stock_icons ():
import os import os
@ -183,7 +184,10 @@ class Gramps:
# self.date_format_key_update) # self.date_format_key_update)
register_stock_icons() register_stock_icons()
a = ViewManager.ViewManager()
state = DbState.DbState()
a = ViewManager.ViewManager(state)
a.register_view(PersonView.PersonView) a.register_view(PersonView.PersonView)
a.register_view(PedView.PedView) a.register_view(PedView.PedView)
a.init_interface() a.init_interface()