diff --git a/ChangeLog b/ChangeLog index 657c80b54..ebb7722e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-08-10 Don Allingham + * 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 * src/PedView.py: Better autoscaling; better ui management diff --git a/src/DbState.py b/src/DbState.py index 557cd97c9..6a18080f4 100644 --- a/src/DbState.py +++ b/src/DbState.py @@ -44,9 +44,15 @@ import GrampsDBCallback import GrampsKeys import NameDisplay -class History: +class History(GrampsDBCallback.GrampsDBCallback): + + __signals__ = { + 'changed' : (list,), + 'menu-changed' : (list,), + } def __init__(self): + GrampsDBCallback.GrampsDBCallback.__init__(self) self.history = [] self.mhistory = [] self.index = -1 @@ -73,22 +79,33 @@ class History: mhc = self.mhistory.count(del_id) for c in range(mhc): self.mhistory.remove(del_id) + self.emit('changed',(self.history,)) + self.emit('menu-changed',(self.mhistory,)) 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) + if person_handle not in self.mhistory: + self.mhistory.append(person_handle) + self.emit('menu-changed',(self.mhistory,)) self.index += 1 + self.emit('changed',(self.history,)) def forward(self,step=1): 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]) def back(self,step=1): 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]) def at_end(self): @@ -109,21 +126,10 @@ class DbState(GrampsDBCallback.GrampsDBCallback): 'no-database' : None, } - def __init__(self,window,status,uimanager): - self.uimanager = uimanager - self.window = window + def __init__(self): GrampsDBCallback.GrampsDBCallback.__init__(self) self.db = GrampsDbBase.GrampsDbBase() 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): self.active = person @@ -147,15 +153,28 @@ class DbState(GrampsDBCallback.GrampsDBCallback): self.db = GrampsDbBase.GrampsDbBase() 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) - if self.active == None: + if self.dbstate.active == None: self.status.push(self.status_id,"") else: if GrampsKeys.get_statusbar() <= 1: - pname = NameDisplay.displayer.display(self.active) - name = "[%s] %s" % (self.active.get_gramps_id(),pname) + pname = NameDisplay.displayer.display(self.dbstate.active) + name = "[%s] %s" % (self.dbstate.active.get_gramps_id(),pname) else: name = self.display_relationship() self.status.push(self.status_id,name) diff --git a/src/EditPerson.py b/src/EditPerson.py index f905a18c2..464ae8a29 100644 --- a/src/EditPerson.py +++ b/src/EditPerson.py @@ -88,10 +88,11 @@ class EditPerson: 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.""" self.state = state + self.uistate = uistate self.retval = const.UPDATE_PERSON self.dp = DateHandler.parser @@ -462,7 +463,7 @@ class EditPerson: self.win_menu_item = gtk.MenuItem(win_menu_label) self.win_menu_item.set_submenu(gtk.Menu()) 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.menu_item = gtk.MenuItem(_('Edit Person')) self.menu_item.connect("activate",self.present) diff --git a/src/GrampsDbBase.py b/src/GrampsDbBase.py index d2e329cff..712e45e3c 100644 --- a/src/GrampsDbBase.py +++ b/src/GrampsDbBase.py @@ -312,26 +312,24 @@ class GrampsDbBase(GrampsDBCallback.GrampsDBCallback): update_list.append((handle,obj.serialize())) else: add_list.append((handle,obj.serialize())) - - # 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) + return old_data def commit_person(self,person,transaction,change_time=None): """ Commits the specified Person to the database, storing the changes as part of the transaction. """ - self._commit_base(person, self.person_map, PERSON_KEY, - transaction.person_update, transaction.person_add, - transaction, change_time) + old_data = self._commit_base( + person, self.person_map, PERSON_KEY, transaction.person_update, + 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): """ diff --git a/src/Navigation.py b/src/Navigation.py new file mode 100644 index 000000000..cb45eab9b --- /dev/null +++ b/src/Navigation.py @@ -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 = '' +_btm = '' + +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: '' % (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, "%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]) + diff --git a/src/PageView.py b/src/PageView.py index 033bf8b73..974e544ab 100644 --- a/src/PageView.py +++ b/src/PageView.py @@ -22,19 +22,34 @@ import gtk +NAVIGATION_NONE = -1 +NAVIGATION_PERSON = 0 + + class PageView: - def __init__(self,title,state): + def __init__(self,title,dbstate,uistate): self.title = title - self.state = state + self.dbstate = dbstate + self.uistate = uistate self.action_list = [] self.action_toggle_list = [] self.action_group = None self.additional_action_groups = [] + self.additional_uis = [] self.widget = None - self.ui = "" - self.state.connect('no-database',self.disable_action_group) - self.state.connect('database-changed',self.enable_action_group) + self.ui = '' + self.dbstate.connect('no-database',self.disable_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): if self.action_group: @@ -50,9 +65,6 @@ class PageView: except AttributeError: return gtk.STOCK_MISSING_IMAGE - def get_ui(self): - return self.ui - def get_title(self): return self.title @@ -88,3 +100,5 @@ class PageView: def add_action_group(self,group): self.additional_action_groups.append(group) + + diff --git a/src/PedView.py b/src/PedView.py index 4d3e8f1ce..6b06ce899 100644 --- a/src/PedView.py +++ b/src/PedView.py @@ -41,10 +41,12 @@ import gtk.gdk # Gramps Modules # #------------------------------------------------------------------------- -import RelLib import PageView -import EditPerson +import const +import GrampsCfg +import Relationship import NameDisplay +import RelLib import Utils import DateHandler @@ -53,6 +55,8 @@ import DateHandler # Constants # #------------------------------------------------------------------------- +_PAD = 3 +_CANVASPAD = 3 _PERSON = "p" _BORN = _('b.') _DIED = _('d.') @@ -69,17 +73,19 @@ _CREM = _('crem.') #------------------------------------------------------------------------- class PedView(PageView.PageView): - def __init__(self,state): - PageView.PageView.__init__(self,'Pedigree View',state) + def __init__(self,dbstate,uistate): + PageView.PageView.__init__(self,'Pedigree View',dbstate,uistate) self.inactive = False - state.connect('database-changed',self.change_db) - state.connect('active-changed',self.goto_active_person) + dbstate.connect('database-changed',self.change_db) + dbstate.connect('active-changed',self.goto_active_person) self.force_size = 0 # Automatic resize + def navigation_type(self): + return PageView.NAVIGATION_PERSON + def build_widget(self): self.notebook = gtk.Notebook() 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_tabs(False) @@ -99,16 +105,10 @@ class PedView(PageView.PageView): self.table_5.connect("button-press-event", self.on_show_option_menu_cb) 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 - 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): frame = gtk.ScrolledWindow(None,None) 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('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit) #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('Back', gtk.STOCK_GO_BACK, "_Back", callback=self.home)#callback=self.back_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.back_clicked) self.add_action('HomePerson', gtk.STOCK_HOME, "_Home", callback=self.home) #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): return ''' @@ -178,8 +139,6 @@ class PedView(PageView.PageView): - - @@ -195,32 +154,26 @@ class PedView(PageView.PageView): db.connect('person-update', self.person_updated_cb) db.connect('person-delete', self.person_updated_cb) db.connect('person-rebuild', self.person_rebuild) - self.rebuild_trees(None) - + self.active_person = None + def person_updated_cb(self,handle_list): - print "PedView.person_updated_cb" - self.rebuild_trees(self.state.active) + self.rebuild_trees(self.active_person) def person_rebuild(self): - print "PedView.person_rebuild" - self.rebuild_trees(self.state.active) - - def person_edited_cb(self, p1=None, p2=None): - print "PedView.person_edited_cb" + self.rebuild_trees(self.active_person) def goto_active_person(self,handle): print "PedView.goto_active_person" 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: self.rebuild_trees(None) def request_resize(self): - print "PedView.request_resize" self.size_request_cb(self.notebook.parent,None,None) def size_request_cb(self, widget, event, data=None): - print "PedView.size_request_cb" if self.force_size == 0: v = widget.get_allocation() 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_5, pos_5, person) - #gobject.idle_add(self.request_resize) - + gobject.idle_add(self.request_resize) def rebuild( self, table_widget, positions, active_person): print "PedView.rebuild" # Build ancestor tree lst = [None]*31 - self.find_tree(active_person,0,1,lst) + self.find_tree(self.active_person,0,1,lst) # Purge current table content for child in table_widget.get_children(): @@ -429,17 +381,17 @@ class PedView(PageView.PageView): def home(self,obj): print "PedView.home" - defperson = self.state.db.get_default_person() + defperson = self.dbstate.db.get_default_person() if defperson: - self.state.change_active_person(defperson) + self.dbstate.change_active_person(defperson) def edit_person_cb(self,obj): person_handle = obj.get_data(_PERSON) person = self.db.get_person_from_handle(person_handle) if person: - EditPerson.EditPerson(self.state, person, self.person_edited_cb) + self.edit_person(person) return True - return False + return 0 def on_show_option_menu_cb(self,obj,data=None): myMenu = gtk.Menu() @@ -450,16 +402,16 @@ class PedView(PageView.PageView): def on_show_child_menu(self,obj): """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 # button. The menu consists of the children of the current root # 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: child = self.db.get_person_from_handle(childlist[0]) if child: - self.state.change_active_person(child) + self.parent.change_active_person(child) elif len(childlist) > 1: myMenu = gtk.Menu() for child_handle in childlist: @@ -488,7 +440,7 @@ class PedView(PageView.PageView): person_handle = obj.get_data(_PERSON) if person_handle: - self.state.change_active_handle(person_handle) + self.dbstate.change_active_handle(person_handle) return True return False diff --git a/src/PersonView.py b/src/PersonView.py index 8f7c61cb5..7a11fb51e 100644 --- a/src/PersonView.py +++ b/src/PersonView.py @@ -42,6 +42,7 @@ from gtk.gdk import ACTION_COPY, BUTTON1_MASK # GRAMPS modules # #------------------------------------------------------------------------- +import RelLib import PeopleModel import PageView import GenericFilter @@ -68,38 +69,90 @@ column_names = [ class PersonView(PageView.PageView): - def __init__(self,state): - PageView.PageView.__init__(self,'Person View',state) + def __init__(self,dbstate,uistate): + PageView.PageView.__init__(self,'Person View',dbstate,uistate) self.inactive = False - state.connect('database-changed',self.change_db) - state.connect('active-changed',self.goto_active_person) + dbstate.connect('database-changed',self.change_db) + dbstate.connect('active-changed',self.goto_active_person) - def setup_filter(self): - all = GenericFilter.GenericFilter() - all.set_name(_("Entire Database")) - all.add_rule(GenericFilter.Everyone([])) - - self.DataFilter = None - self.init_filters() + def navigation_type(self): + return PageView.NAVIGATION_PERSON def define_actions(self): - 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('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_toggle_action('Filter', None, '_Filter', callback=self.filter_toggle) + """ + 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('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit) + self.add_action('Remove', gtk.STOCK_REMOVE,"_Remove",callback=self.remove) + self.add_action('HomePerson',gtk.STOCK_HOME, "_Home", callback=self.home) + + 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): + """ + 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' - 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): + """ + 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.set_border_width(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(scrollwindow,True) - # temporary hack - self.renderer = gtk.CellRendererText() 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.filter_invert, self.filter_button]) - a = gtk.ListStore(str,str) - self.person_tree.set_model(a) - self.setup_filter() - return self.vbox def ui_definition(self): + """ + Specifies the UIManager XML code that defines the menus and buttons + associated with the interface. + """ return ''' @@ -197,175 +248,54 @@ class PersonView(PageView.PageView): ''' - 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, person, self.state.db, - None) - - def edit(self,obj): - EditPerson.EditPerson(self, self.state.active, self.state.db, - 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) + def change_db(self,db): + """ + Callback associated with DbState. Whenenver the database + changes, this task is called. In this case, we rebuild the + columns, and connect signals to the connected database. Tere + is no need to store the database, since we will get the value + from self.state.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.build_tree) self.apply_filter() - self.goto_active_person() 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 + + # mark inactive to prevent recusion self.inactive = True - p = self.state.active + + # select the active person in the person view + p = self.dbstate.active try: path = self.person_model.on_get_path(p.get_handle()) 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) self.person_tree.expand_row(top_path,0) @@ -378,118 +308,30 @@ class PersonView(PageView.PageView): except KeyError: self.person_selection.unselect_all() print "Person not currently available due to filter" - self.state.active = p + self.dbstate.active = p + + # disable the inactive flag self.inactive = False - def redisplay_person_list(self): - self.build_tree() - - def person_added(self,handle_list): - for node in handle_list: - person = self.state.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.state.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.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): + # update history + self.handle_history(p.handle) + def handle_history(self, handle): + """ + Updates the person history information + """ + hobj = self.uistate.phistory + if handle and not hobj.lock: + hobj.push(handle) + #self.redraw_histmenu() + self.fwd_action.set_sensitive(not hobj.at_end()) + self.back_action.set_sensitive(not hobj.at_front()) + + def setup_filter(self): + """ + Builds the default filters and add them to the filter menu. + """ + cell = gtk.CellRendererText() self.filter_list.clear() self.filter_list.pack_start(cell,True) @@ -497,6 +339,12 @@ class PersonView(PageView.PageView): filter_list = [] + self.DataFilter = None + + all = GenericFilter.GenericFilter() + all.set_name(_("Entire Database")) + all.add_rule(GenericFilter.Everyone([])) + all = GenericFilter.GenericFilter() all.set_name(_("Entire Database")) all.add_rule(GenericFilter.Everyone([])) @@ -611,8 +459,271 @@ class PersonView(PageView.PageView): self.filter_list.set_model(self.filter_model) self.filter_list.set_active(self.filter_model.default_index()) 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): index = self.filter_list.get_active() mime_filter = self.filter_model.get_filter(index) @@ -628,9 +739,9 @@ class PersonView(PageView.PageView): self.filter_label.hide() def apply_filter(self,current_model=None): - #self.parent.status_text(_('Updating display...')) + self.uistate.status_text(_('Updating display...')) self.build_tree() - #self.parent.modify_statusbar() + self.uistate.modify_statusbar() def get_selected_objects(self): (mode,paths) = self.person_selection.get_selected_rows() @@ -652,7 +763,7 @@ class PersonView(PageView.PageView): def build_backhistmenu(self,event): """Builds and displays the menu with the back portion of the history""" - hobj = self.state.phistory + hobj = self.uistate.phistory if hobj.index > 0: backhistmenu = gtk.Menu() backhistmenu.set_title(_('Back Menu')) @@ -667,7 +778,7 @@ class PersonView(PageView.PageView): hotkey = "_%s" % chr(ord('a')+num-11) elif num >= 21: 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]" % (hotkey, NameDisplay.displayer.display(person), @@ -713,71 +824,50 @@ class PersonView(PageView.PageView): self.build_fwdhistmenu(event) def fwd_clicked(self,obj,step=1): - print "fwd clicked" - hobj = self.state.phistory + hobj = self.uistate.phistory hobj.lock = True - print hobj.history - if hobj.index+1 < len(hobj.history): + if not hobj.at_end(): try: - hobj.index += step - handle = str(hobj.history[hobj.index]) - self.state.active = self.state.db.get_person_from_handle(handle) - self.state.modify_statusbar() - self.state.change_active_handle(handle) - hobj.mhistory.append(self.history[hobj.index]) + handle = hobj.forward() + self.dbstate.active = self.dbstate.db.get_person_from_handle(handle) + self.uistate.modify_statusbar() + self.dbstate.change_active_handle(handle) + hobj.mhistory.append(hobj.history[hobj.index]) #self.redraw_histmenu() - self.set_buttons(True) - if hobj.index == len(hobj.history)-1: - 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) + self.fwd_action.set_sensitive(not hobj.at_end()) + self.back_action.set_sensitive(True) except: - self.clear_history() + hobj.clear() + self.fwd_action.set_sensitive(False) + self.back_action.set_sensitive(False) else: - self.fwdbtn.set_sensitive(False) - self.forward.set_sensitive(False) - self.backbtn.set_sensitive(True) - self.back.set_sensitive(True) - self.goto_active_person() + self.fwd_action.set_sensitive(False) + self.back_action.set_sensitive(True) hobj.lock = False def back_clicked(self,obj,step=1): - hobj = self.state.phistory + hobj = self.uistate.phistory hobj.lock = True - if hobj.index > 0: + if not hobj.at_front(): try: - hobj.index -= step - handle = str(hobj.history[hobj.hindex]) - self.active = self.db.get_person_from_handle(handle) - self.modify_statusbar() - self.change_active_handle(handle) + handle = hobj.back() + self.active = self.dbstate.db.get_person_from_handle(handle) + self.uistate.modify_statusbar() + self.dbstate.change_active_handle(handle) hobj.mhistory.append(hobj.history[hobj.index]) - self.redraw_histmenu() - self.set_buttons(1) - if hobj.index == 0: - 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) +# self.redraw_histmenu() + self.back_action.set_sensitive(not hobj.at_front()) + self.fwd_action.set_sensitive(True) except: - hobj.clear_history() + hobj.clear() + self.fwd_action.set_sensitive(False) + self.back_action.set_sensitive(False) else: - self.backbtn.set_sensitive(False) - self.back.set_sensitive(False) - self.fwdbtn.set_sensitive(True) - self.forward.set_sensitive(True) - self.goto_active_person() + self.back_action.set_sensitive(False) + self.fwd_action.set_sensitive(True) hobj.lock = False def home(self,obj): - defperson = self.state.db.get_default_person() + defperson = self.dbstate.db.get_default_person() if defperson: - self.state.change_active_person(defperson) - self.goto_active_person() + self.dbstate.change_active_person(defperson) diff --git a/src/ViewManager.py b/src/ViewManager.py index 6279115a5..c6e87995d 100644 --- a/src/ViewManager.py +++ b/src/ViewManager.py @@ -57,6 +57,9 @@ import GrampsCfg import Errors import DisplayTrace import Utils +import QuestionDialog +import PageView +import Navigation #------------------------------------------------------------------------- # @@ -99,6 +102,7 @@ uidefault = ''' + @@ -132,8 +136,14 @@ uidefault = ''' 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.views = [] self.window = gtk.Window() @@ -160,14 +170,17 @@ 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.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() def init_interface(self): @@ -187,7 +200,7 @@ class ViewManager: obj.set_style(style) def build_ui_manager(self): - self.merge_id = 0 + self.merge_ids = [] self.uimanager = gtk.UIManager() accelgroup = self.uimanager.get_accel_group() @@ -259,10 +272,12 @@ class ViewManager: def create_pages(self): self.pages = [] + self.prev_nav = PageView.NAVIGATION_NONE + index = 0 self.set_color(self.ebox) for page_def in self.views: - page = page_def(self.state) + page = page_def(self.state,self.uistate) # create icon/label for notebook hbox = gtk.HBox() @@ -291,8 +306,8 @@ class ViewManager: self.bbox.pack_start(button,False) def change_page(self,obj,page,num): - if self.merge_id: - self.uimanager.remove_ui(self.merge_id) + for mergeid in self.merge_ids: + self.uimanager.remove_ui(mergeid) if self.active_page: groups = self.active_page.get_actions() for grp in groups: @@ -300,16 +315,28 @@ class ViewManager: if len(self.pages) > 0: 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() 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()) + 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): choose = gtk.FileChooserDialog(_('GRAMPS: Open database'), - self.state.window, + self.uistate.window, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, @@ -396,7 +423,7 @@ class ViewManager: def on_new_activate(self,obj): choose = gtk.FileChooserDialog(_('GRAMPS: Create GRAMPS database'), - self.state.window, + self.uistate.window, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, @@ -501,9 +528,9 @@ class ViewManager: return 0 elif not os.access(filename,os.W_OK): mode = "r" - WarningDialog(_('Read only database'), - _('You do not have write access to the selected ' - 'file.')) + QuestionDialog.WarningDialog(_('Read only database'), + _('You do not have write access ' + 'to the selected file.')) try: if self.load_database(filename,callback,mode=mode) == 1: @@ -511,19 +538,19 @@ class ViewManager: filename = filename[:-1] name = os.path.basename(filename) 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: - self.state.window.set_title("%s - GRAMPS" % name) + self.uistate.window.set_title("%s - GRAMPS" % name) else: GrampsKeys.save_last_file("") - ErrorDialog(_('Cannot open database'), + QuestionDialog.ErrorDialog(_('Cannot open database'), _('The database file specified could not be opened.')) return 0 except ( IOError, OSError, Errors.FileVersionError), msg: - ErrorDialog(_('Cannot open database'),str(msg)) + QuestionDialog.ErrorDialog(_('Cannot open database'),str(msg)) return 0 except (db.DBAccessError,db.DBError), msg: - ErrorDialog(_('Cannot open database'), + QuestionDialog.ErrorDialog(_('Cannot open database'), _('%s could not be opened.' % filename) + '\n' + msg[1]) return 0 except Exception: @@ -588,9 +615,8 @@ class ViewManager: ScratchPad.ScratchPadWindow(self.state, self) def on_import(self,obj): - print "import" choose = gtk.FileChooserDialog(_('GRAMPS: Import database'), - self.state.window, + self.uistate.window, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, diff --git a/src/gramps_main.py b/src/gramps_main.py index 7ad880efb..dbdca8c15 100755 --- a/src/gramps_main.py +++ b/src/gramps_main.py @@ -32,6 +32,7 @@ import const import Errors import PluginMgr import TipOfDay +import DbState from GrampsMime import mime_type_is_defined from QuestionDialog import ErrorDialog @@ -39,7 +40,7 @@ from QuestionDialog import ErrorDialog import gnome -iconpaths = [".","/usr/share/gramps","~/devel/srcx"] +iconpaths = [".","/usr/share/gramps"] def register_stock_icons (): import os @@ -183,7 +184,10 @@ class Gramps: # self.date_format_key_update) register_stock_icons() - a = ViewManager.ViewManager() + + state = DbState.DbState() + + a = ViewManager.ViewManager(state) a.register_view(PersonView.PersonView) a.register_view(PedView.PedView) a.init_interface()