diff --git a/ChangeLog b/ChangeLog index d4548d3f0..795f673bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2006-04-07 Don Allingham + * src/Editors/_EditFamily.py: remove empty families + 2006-04-07 Brian Matherly * src/docgen/PdfDoc.py: fix columns, error check images * src/docgen/RTFDoc.py: error check images diff --git a/src/DataViews/_FamilyView.py b/src/DataViews/_FamilyView.py index d15da0901..d56cee4f0 100644 --- a/src/DataViews/_FamilyView.py +++ b/src/DataViews/_FamilyView.py @@ -34,9 +34,9 @@ import Errors from PluginUtils import ReportUtils _GenderCode = { - RelLib.Person.MALE : u'\u2642', - RelLib.Person.FEMALE : u'\u2640', - RelLib.Person.UNKNOWN : u'\u2650', + RelLib.Person.MALE : u'\u2642', + RelLib.Person.FEMALE : u'\u2640', + RelLib.Person.UNKNOWN : u'\u2650', } _NAME_START = 0 @@ -72,19 +72,20 @@ class AttachList: self.max_x = 0 self.max_y = 0 - def attach(self,widget,x0,x1,y0,y1,xoptions=gtk.EXPAND|gtk.FILL, + def attach(self, widget, x0, x1, y0, y1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.EXPAND|gtk.FILL): assert(x1>x0) - self.list.append((widget,x0,x1,y0,y1,xoptions,yoptions)) - self.max_x = max(self.max_x,x1) - self.max_y = max(self.max_y,y1) + self.list.append((widget, x0, x1, y0, y1, xoptions, yoptions)) + self.max_x = max(self.max_x, x1) + self.max_y = max(self.max_y, y1) class FamilyView(PageView.PersonNavView): - def __init__(self,dbstate,uistate): - PageView.PersonNavView.__init__(self,'Relationship View',dbstate,uistate) - dbstate.connect('database-changed',self.change_db) - dbstate.connect('active-changed',self.change_person) + def __init__(self, dbstate, uistate): + + PageView.PersonNavView.__init__(self, 'Relationship View', dbstate, uistate) + dbstate.connect('database-changed', self.change_db) + dbstate.connect('active-changed', self.change_person) self.show_siblings = Config.get_family_siblings() if self.show_siblings == None: self.show_siblings = True @@ -95,15 +96,15 @@ class FamilyView(PageView.PersonNavView): self.redrawing = False self.child = None - def connect_to_db(self,db): + def connect_to_db(self, db): db.connect('person-update', self.person_update) - db.connect('person-rebuild',self.person_rebuild) + db.connect('person-rebuild', self.person_rebuild) db.connect('family-update', self.family_update) db.connect('family-add', self.family_add) db.connect('family-delete', self.family_delete) - db.connect('family-rebuild',self.family_rebuild) + db.connect('family-rebuild', self.family_rebuild) - def person_update(self,handle_list): + def person_update(self, handle_list): if self.dbstate.active: while not self.change_person(self.dbstate.active.handle): pass @@ -113,17 +114,17 @@ class FamilyView(PageView.PersonNavView): while not self.change_person(self.dbstate.active.handle): pass - def family_update(self,handle_list): + def family_update(self, handle_list): if self.dbstate.active: while not self.change_person(self.dbstate.active.handle): pass - def family_add(self,handle_list): + def family_add(self, handle_list): if self.dbstate.active: while not self.change_person(self.dbstate.active.handle): pass - def family_delete(self,handle_list): + def family_delete(self, handle_list): if self.dbstate.active: while not self.change_person(self.dbstate.active.handle): pass @@ -143,7 +144,7 @@ class FamilyView(PageView.PersonNavView): def build_widget(self): self.scroll = gtk.ScrolledWindow() - self.scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) + self.scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scroll.show() self.vbox = gtk.VBox() self.vbox.show() @@ -190,36 +191,36 @@ class FamilyView(PageView.PersonNavView): def define_actions(self): PageView.PersonNavView.define_actions(self) - self.add_toggle_action('Details', None, _('Show details'), - None, None, self.details_toggle, + self.add_toggle_action('Details', None, _('Show details'), + None, None, self.details_toggle, self.show_details) - self.add_toggle_action('Siblings', None, _('Show siblings'), - None, None, self.siblings_toggle, + self.add_toggle_action('Siblings', None, _('Show siblings'), + None, None, self.siblings_toggle, self.show_siblings) - def siblings_toggle(self,obj): + def siblings_toggle(self, obj): self.show_siblings = obj.get_active() self.change_person(self.dbstate.active.handle) Config.save_family_siblings(self.show_siblings) - def details_toggle(self,obj): + def details_toggle(self, obj): self.show_details = obj.get_active() self.change_person(self.dbstate.active.handle) Config.save_family_details(self.show_details) - def change_db(self,db): + def change_db(self, db): self.connect_to_db(db) if self.child: self.vbox.remove(self.child) self.child = None - self.dbstate.db.connect('family-update',self.redraw) - self.dbstate.db.connect('family-add',self.redraw) - self.dbstate.db.connect('family-delete',self.redraw) - self.dbstate.db.connect('person-update',self.redraw) - self.dbstate.db.connect('person-add',self.redraw) - self.dbstate.db.connect('person-delete',self.redraw) + self.dbstate.db.connect('family-update', self.redraw) + self.dbstate.db.connect('family-add', self.redraw) + self.dbstate.db.connect('family-delete', self.redraw) + self.dbstate.db.connect('person-update', self.redraw) + self.dbstate.db.connect('person-add', self.redraw) + self.dbstate.db.connect('person-delete', self.redraw) - def get_name(self,handle,use_gender=False): + def get_name(self, handle, use_gender=False): if handle: p = self.dbstate.db.get_person_from_handle(handle) name = NameDisplay.displayer.display(p) @@ -227,15 +228,15 @@ class FamilyView(PageView.PersonNavView): gender = _GenderCode[p.gender] else: gender = "" - return (name,gender) + return (name, gender) else: - return (_(u"Unknown"),"") + return (_(u"Unknown"), "") - def redraw(self,*obj): + def redraw(self, *obj): if self.dbstate.active: self.change_person(self.dbstate.active.handle) - def change_person(self,obj): + def change_person(self, obj): if self.redrawing: return False self.redrawing = True @@ -251,11 +252,11 @@ class FamilyView(PageView.PersonNavView): self.row = 5 family_handle_list = person.get_parent_family_handle_list() if family_handle_list: - for (family_handle,mrel,frel) in family_handle_list: + for (family_handle, mrel, frel) in family_handle_list: if family_handle: self.write_parents(family_handle) else: - self.write_label("%s:" % _('Parents'),None,True) + self.write_label("%s:" % _('Parents'), None, True) self.row += 1 family_handle_list = person.get_family_handle_list() @@ -264,14 +265,14 @@ class FamilyView(PageView.PersonNavView): if family_handle: self.write_family(family_handle) else: - self.write_label("%s:" % _('Family'),None,False) + self.write_label("%s:" % _('Family'), None, False) self.row += 1 self.row = 1 self.write_title(person) # Here it is necessary to beat GTK into submission. For some - # bizzare reason, if you have an empty column that is spanned, + # bizzare reason, if you have an empty column that is spanned, # you lose the appropriate FILL handling. So, we need to see if # column 3 is unused (usually if there is no siblings or children. # If so, we need to subtract one index of each x coord > 3. @@ -286,7 +287,7 @@ class FamilyView(PageView.PersonNavView): else: cols = self.attach.max_x-1 - self.child = gtk.Table(self.attach.max_y,cols) + self.child = gtk.Table(self.attach.max_y, cols) self.child.set_border_width(12) self.child.set_col_spacings(12) self.child.set_row_spacings(9) @@ -299,31 +300,31 @@ class FamilyView(PageView.PersonNavView): x0 -= 1 if x1 > 4: x1 -= 1 - self.child.attach(d[0],x0,x1,d[3],d[4],d[5],d[6]) + self.child.attach(d[0], x0, x1, d[3], d[4], d[5], d[6]) self.child.show_all() if old_child: self.vbox.remove(old_child) - self.vbox.pack_start(self.child,False) + self.vbox.pack_start(self.child, False) self.redrawing = False return True - def write_title(self,person): + def write_title(self, person): # name and edit button name = NameDisplay.displayer.display(person) fmt = '%s %s' - text = fmt % (cgi.escape(name),_GenderCode[person.gender]) + text = fmt % (cgi.escape(name), _GenderCode[person.gender]) label = GrampsWidgets.MarkupLabel(text) - button = GrampsWidgets.IconButton(self.edit_button_press,person.handle) + button = GrampsWidgets.IconButton(self.edit_button_press, person.handle) - hbox = GrampsWidgets.LinkBox(label,button) + hbox = GrampsWidgets.LinkBox(label, button) # GRAMPS ID self.row = 1 - self.write_person_data("%s:" % _('ID'),person.gramps_id) + self.write_person_data("%s:" % _('ID'), person.gramps_id) # birth/death events @@ -332,20 +333,20 @@ class FamilyView(PageView.PersonNavView): birth = self.dbstate.db.get_event_from_handle(birth_ref.ref) else: birth = None - self.write_person_event("%s:" % _('Birth'),birth) + self.write_person_event("%s:" % _('Birth'), birth) death_ref = person.get_death_ref() if death_ref: death = self.dbstate.db.get_event_from_handle(death_ref.ref) else: death = None - self.write_person_event("%s:" % _('Death'),death) + self.write_person_event("%s:" % _('Death'), death) # separator end = self.attach.max_x sep = gtk.HSeparator() sep.show() - self.attach.attach(hbox,_NAME_START,end,0,1,gtk.FILL|gtk.EXPAND) + self.attach.attach(hbox, _NAME_START, end, 0, 1, gtk.FILL|gtk.EXPAND) # image image_list = person.get_media_list() @@ -356,10 +357,10 @@ class FamilyView(PageView.PersonNavView): image = gtk.Image() image.set_from_pixbuf(pixbuf) image.show() - self.attach.attach(image,end,end+1,0,4, + self.attach.attach(image, end, end+1, 0, 4, xoptions=gtk.SHRINK|gtk.FILL) - self.attach.attach(sep,0,self.attach.max_x,4,5) + self.attach.attach(sep, 0, self.attach.max_x, 4, 5) def write_person_event(self, ename, event): if event: @@ -372,8 +373,8 @@ class FamilyView(PageView.PersonNavView): date_str = DateHandler.displayer.display(dobj) value = { - 'date' : DateHandler.displayer.display(dobj), - 'place' : pname, + 'date' : DateHandler.displayer.display(dobj), + 'place' : pname, } else: pname = None @@ -381,37 +382,37 @@ class FamilyView(PageView.PersonNavView): if dobj: if pname: - self.write_person_data(ename, + self.write_person_data(ename, _('%(date)s in %(place)s') % value) else: - self.write_person_data(ename,'%(date)s' % value) + self.write_person_data(ename, '%(date)s' % value) elif pname: - self.write_person_data(ename,pname) + self.write_person_data(ename, pname) else: - self.write_person_data(ename,'') + self.write_person_data(ename, '') - def write_person_data(self,title,data): - self.attach.attach(GrampsWidgets.BasicLabel(title),_ALABEL_START, - _ALABEL_STOP,self.row,self.row+1, + def write_person_data(self, title, data): + self.attach.attach(GrampsWidgets.BasicLabel(title), _ALABEL_START, + _ALABEL_STOP, self.row, self.row+1, xoptions=gtk.FILL|gtk.SHRINK) - self.attach.attach(GrampsWidgets.BasicLabel(data), - _ADATA_START,_ADATA_STOP, - self.row,self.row+1) + self.attach.attach(GrampsWidgets.BasicLabel(data), + _ADATA_START, _ADATA_STOP, + self.row, self.row+1) self.row += 1 - def write_label(self,title,family,is_parent): + def write_label(self, title, family, is_parent): msg = "%s" % cgi.escape(title) - self.attach.attach(GrampsWidgets.MarkupLabel(msg), - _LABEL_START,_LABEL_STOP, - self.row,self.row+1,gtk.SHRINK|gtk.FILL) + self.attach.attach(GrampsWidgets.MarkupLabel(msg), + _LABEL_START, _LABEL_STOP, + self.row, self.row+1, gtk.SHRINK|gtk.FILL) if family: value = family.gramps_id else: value = "" - self.attach.attach(GrampsWidgets.BasicLabel(value), - _DATA_START,_DATA_STOP, - self.row,self.row+1,gtk.SHRINK|gtk.FILL) + self.attach.attach(GrampsWidgets.BasicLabel(value), + _DATA_START, _DATA_STOP, + self.row, self.row+1, gtk.SHRINK|gtk.FILL) hbox = gtk.HBox() hbox.set_spacing(12) @@ -422,42 +423,42 @@ class FamilyView(PageView.PersonNavView): call_fcn = self.add_family del_fcn = self.delete_family - add = GrampsWidgets.IconButton(call_fcn,None,gtk.STOCK_ADD) - hbox.pack_start(add,False) + add = GrampsWidgets.IconButton(call_fcn, None, gtk.STOCK_ADD) + hbox.pack_start(add, False) if is_parent: - add = GrampsWidgets.IconButton(self.select_family,None,gtk.STOCK_INDEX) - hbox.pack_start(add,False) + add = GrampsWidgets.IconButton(self.select_family, None, gtk.STOCK_INDEX) + hbox.pack_start(add, False) if family: - edit = GrampsWidgets.IconButton(self.edit_family,family.handle, + edit = GrampsWidgets.IconButton(self.edit_family, family.handle, gtk.STOCK_EDIT) - hbox.pack_start(edit,False) - delete = GrampsWidgets.IconButton(del_fcn,family.handle, + hbox.pack_start(edit, False) + delete = GrampsWidgets.IconButton(del_fcn, family.handle, gtk.STOCK_REMOVE) - hbox.pack_start(delete,False) - self.attach.attach(hbox,_BTN_START,_BTN_STOP,self.row,self.row+1) + hbox.pack_start(delete, False) + self.attach.attach(hbox, _BTN_START, _BTN_STOP, self.row, self.row+1) self.row += 1 ###################################################################### - def write_parents(self,family_handle): + def write_parents(self, family_handle): family = self.dbstate.db.get_family_from_handle(family_handle) if not family: return - self.write_label("%s:" % _('Parents'),family,True), - self.write_person(_('Father'),family.get_father_handle()) + self.write_label("%s:" % _('Parents'), family, True), + self.write_person(_('Father'), family.get_father_handle()) if self.show_details: value = self.info_string(family.get_father_handle()) if value: - self.attach.attach(GrampsWidgets.BasicLabel(value),_PDTLS_START, - _PDTLS_STOP,self.row, self.row+1) + self.attach.attach(GrampsWidgets.BasicLabel(value), _PDTLS_START, + _PDTLS_STOP, self.row, self.row+1) self.row += 1 - self.write_person(_('Mother'),family.get_mother_handle()) + self.write_person(_('Mother'), family.get_mother_handle()) if self.show_details: value = self.info_string(family.get_mother_handle()) if value: - self.attach.attach(GrampsWidgets.BasicLabel(value),_PDTLS_START, + self.attach.attach(GrampsWidgets.BasicLabel(value), _PDTLS_START, _PDTLS_STOP, self.row, self.row+1) self.row += 1 @@ -469,50 +470,50 @@ class FamilyView(PageView.PersonNavView): label = _("Siblings") if child_list: for child in child_list: - self.write_child(label,child) + self.write_child(label, child) label = u"" self.row += 1 - def write_person(self,title,handle): + def write_person(self, title, handle): if title: format = '%s: ' else: format = "%s" label = GrampsWidgets.MarkupLabel(format % cgi.escape(title)) - self.attach.attach(label,_PLABEL_START,_PLABEL_STOP,self.row, + self.attach.attach(label, _PLABEL_START, _PLABEL_STOP, self.row, self.row+1, xoptions=gtk.FILL|gtk.SHRINK) if handle: - link_label = GrampsWidgets.LinkLabel(self.get_name(handle,True), - self.button_press,handle) - button = GrampsWidgets.IconButton(self.edit_button_press,handle) - self.attach.attach(GrampsWidgets.LinkBox(link_label,button), - _PDATA_START,_PDATA_STOP,self.row,self.row+1) + link_label = GrampsWidgets.LinkLabel(self.get_name(handle, True), + self.button_press, handle) + button = GrampsWidgets.IconButton(self.edit_button_press, handle) + self.attach.attach(GrampsWidgets.LinkBox(link_label, button), + _PDATA_START, _PDATA_STOP, self.row, self.row+1) else: link_label = gtk.Label(_('Unknown')) - link_label.set_alignment(0,0.5) + link_label.set_alignment(0, 0.5) link_label.show() - self.attach.attach(link_label, - _PDATA_START,_PDATA_STOP,self.row,self.row+1) + self.attach.attach(link_label, + _PDATA_START, _PDATA_STOP, self.row, self.row+1) self.row += 1 - def write_child(self,title,handle): + def write_child(self, title, handle): if title: format = '%s: ' else: format = "%s" label = GrampsWidgets.MarkupLabel(format % cgi.escape(title)) - self.attach.attach(label,_CLABEL_START,_CLABEL_STOP,self.row, - self.row+1,xoptions=gtk.FILL|gtk.SHRINK) + self.attach.attach(label, _CLABEL_START, _CLABEL_STOP, self.row, + self.row+1, xoptions=gtk.FILL|gtk.SHRINK) - link_label = GrampsWidgets.LinkLabel(self.get_name(handle,True), - self.button_press,handle) - button = GrampsWidgets.IconButton(self.edit_button_press,handle) - self.attach.attach(GrampsWidgets.LinkBox(link_label,button), - _CDATA_START, _CDATA_STOP, self.row, self.row+1, + link_label = GrampsWidgets.LinkLabel(self.get_name(handle, True), + self.button_press, handle) + button = GrampsWidgets.IconButton(self.edit_button_press, handle) + self.attach.attach(GrampsWidgets.LinkBox(link_label, button), + _CDATA_START, _CDATA_STOP, self.row, self.row+1, xoptions=gtk.EXPAND|gtk.FILL) self.row += 1 @@ -520,17 +521,17 @@ class FamilyView(PageView.PersonNavView): if self.show_details: value = self.info_string(handle) if value: - self.attach.attach(GrampsWidgets.BasicLabel(value), - _CDTLS_START, _CDTLS_STOP, self.row, + self.attach.attach(GrampsWidgets.BasicLabel(value), + _CDTLS_START, _CDTLS_STOP, self.row, self.row+1) self.row += 1 - def write_data(self,title,start_col=_SDATA_START,stop_col=_SDATA_STOP): - self.attach.attach(GrampsWidgets.BasicLabel(title),start_col,stop_col, + def write_data(self, title, start_col=_SDATA_START, stop_col=_SDATA_STOP): + self.attach.attach(GrampsWidgets.BasicLabel(title), start_col, stop_col, self.row, self.row+1, xoptions=gtk.EXPAND|gtk.FILL) self.row += 1 - def info_string(self,handle): + def info_string(self, handle): child = self.dbstate.db.get_person_from_handle(handle) if not child: return None @@ -538,22 +539,22 @@ class FamilyView(PageView.PersonNavView): death_ref = child.get_death_ref() value = None if birth_ref or death_ref: - info = ReportUtils.get_birth_death_strings(self.dbstate.db,child) + info = ReportUtils.get_birth_death_strings(self.dbstate.db, child) bdate = info[0] ddate = info[4] if bdate and ddate: - value = _("b. %s, d. %s") % (bdate,ddate) + value = _("b. %s, d. %s") % (bdate, ddate) elif bdate: value = _("b. %s") % (bdate) elif ddate: value = _("d. %s") % (ddate) return value - def button_press(self,obj,event,handle): + def button_press(self, obj, event, handle): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: self.dbstate.change_active_handle(handle) - def write_relationship(self,family): + def write_relationship(self, family): rtype = family.get_relationship() if type(rtype) == tuple: if rtype[0] == RelLib.Family.CUSTOM: @@ -564,22 +565,22 @@ class FamilyView(PageView.PersonNavView): rel_text = Utils.family_relations[rtype] self.write_data(_('Relationship type: %s') % rel_text) - def place_name(self,handle): + def place_name(self, handle): p = self.dbstate.db.get_place_from_handle(handle) return p.get_title() - def write_marriage(self,family): + def write_marriage(self, family): value = False for event_ref in family.get_event_ref_list(): handle = event_ref.ref event = self.dbstate.db.get_event_from_handle(handle) etype = event.get_type() if etype[0] == RelLib.Event.MARRIAGE: - self.write_event_ref(_('Marriage'),event) + self.write_event_ref(_('Marriage'), event) value = True return value - def write_event_ref(self, ename, event, start_col=_SDATA_START, + def write_event_ref(self, ename, event, start_col=_SDATA_START, stop_col=_SDATA_STOP): if event: dobj = event.get_date_object() @@ -591,9 +592,9 @@ class FamilyView(PageView.PersonNavView): date_str = DateHandler.displayer.display(dobj) value = { - 'date' : DateHandler.displayer.display(dobj), - 'place' : pname, - 'event_type' : ename, + 'date' : DateHandler.displayer.display(dobj), + 'place' : pname, + 'event_type' : ename, } else: pname = None @@ -603,18 +604,18 @@ class FamilyView(PageView.PersonNavView): if dobj: if pname: self.write_data(_('%(event_type)s: %(date)s in %(place)s') % - value,start_col,stop_col) + value, start_col, stop_col) else: - self.write_data(_('%(event_type)s: %(date)s') % value, + self.write_data(_('%(event_type)s: %(date)s') % value, start_col, stop_col) elif pname: - self.write_data(_('%(event_type)s: %(place)s') % value, - start_col,stop_col) + self.write_data(_('%(event_type)s: %(place)s') % value, + start_col, stop_col) else: - self.write_data(_('%(event_type)s:') % value, + self.write_data(_('%(event_type)s:') % value, start_col, stop_col) - def write_family(self,family_handle): + def write_family(self, family_handle): family = self.dbstate.db.get_family_from_handle(family_handle) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() @@ -623,14 +624,14 @@ class FamilyView(PageView.PersonNavView): else: handle = father_handle - self.write_label("%s:" % _('Family'),family,False) + self.write_label("%s:" % _('Family'), family, False) if handle: - self.write_person(_('Spouse'),handle) + self.write_person(_('Spouse'), handle) value = self.info_string(handle) if value: - self.attach.attach(GrampsWidgets.BasicLabel(value), - _PDTLS_START, _PDTLS_STOP, + self.attach.attach(GrampsWidgets.BasicLabel(value), + _PDTLS_START, _PDTLS_STOP, self.row, self.row+1) self.row += 1 if not self.write_marriage(family): @@ -640,7 +641,7 @@ class FamilyView(PageView.PersonNavView): label = _("Children") if child_list: for child in child_list: - self.write_child(label,child) + self.write_child(label, child) label = u"" self.row += 1 @@ -654,7 +655,7 @@ class FamilyView(PageView.PersonNavView): except Errors.WindowActiveError: pass - def edit_person(self,obj,handle): + def edit_person(self, obj, handle): from Editors import EditPerson person = self.dbstate.db.get_person_from_handle(handle) try: @@ -662,16 +663,16 @@ class FamilyView(PageView.PersonNavView): except Errors.WindowActiveError: pass - def edit_family(self,obj,event,handle): + def edit_family(self, obj, event, handle): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: from Editors import EditFamily family = self.dbstate.db.get_family_from_handle(handle) try: - EditFamily(self.dbstate,self.uistate,[],family) + EditFamily(self.dbstate, self.uistate, [], family) except Errors.WindowActiveError: pass - def add_family(self,obj,event,handle): + def add_family(self, obj, event, handle): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: from Editors import EditFamily family = RelLib.Family() @@ -683,7 +684,7 @@ class FamilyView(PageView.PersonNavView): family.set_mother_handle(person.handle) try: - EditFamily(self.dbstate,self.uistate,[],family) + EditFamily(self.dbstate, self.uistate, [], family) except Errors.WindowActiveError: pass @@ -700,16 +701,16 @@ class FamilyView(PageView.PersonNavView): family.add_child_handle(person.handle) person.add_parent_family_handle( - family.handle, - (RelLib.Person.CHILD_BIRTH,''), - (RelLib.Person.CHILD_BIRTH,'')) + family.handle, + (RelLib.Person.CHILD_BIRTH, ''), + (RelLib.Person.CHILD_BIRTH, '')) trans = self.dbstate.db.transaction_begin() - self.dbstate.db.commit_person(person,trans) - self.dbstate.db.commit_family(family,trans) - self.dbstate.db.transaction_commit(trans,_("Add Family")) + self.dbstate.db.commit_person(person, trans) + self.dbstate.db.commit_family(family, trans) + self.dbstate.db.transaction_commit(trans, _("Add Family")) - def add_parent_family(self,obj,event,handle): + def add_parent_family(self, obj, event, handle): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: from Editors import EditFamily family = RelLib.Family() @@ -718,24 +719,24 @@ class FamilyView(PageView.PersonNavView): family.add_child_handle(person.handle) try: - EditFamily(self.dbstate,self.uistate,[],family) + EditFamily(self.dbstate, self.uistate, [], family) except Errors.WindowActiveError: pass - def delete_family(self,obj,event,handle): + def delete_family(self, obj, event, handle): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: import GrampsDb - GrampsDb.remove_parent_from_family(self.dbstate.db, - self.dbstate.active.handle, + GrampsDb.remove_parent_from_family(self.dbstate.db, + self.dbstate.active.handle, handle) - def delete_parent_family(self,obj,event,handle): + def delete_parent_family(self, obj, event, handle): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1: import GrampsDb - GrampsDb.remove_child_from_family(self.dbstate.db, - self.dbstate.active.handle, + GrampsDb.remove_child_from_family(self.dbstate.db, + self.dbstate.active.handle, handle) - def change_to(self,obj,handle): + def change_to(self, obj, handle): self.dbstate.change_active_handle(handle) diff --git a/src/Editors/_EditFamily.py b/src/Editors/_EditFamily.py index f0a7c65a9..1f5c27209 100644 --- a/src/Editors/_EditFamily.py +++ b/src/Editors/_EditFamily.py @@ -335,7 +335,8 @@ class FastFemaleFilter: #------------------------------------------------------------------------- class EditFamily(EditPrimary): - def __init__(self,dbstate,uistate,track,family): + def __init__(self,dbstate, uistate, track, family): + EditPrimary.__init__(self, dbstate, uistate, track, family, dbstate.db.get_family_from_handle) @@ -765,7 +766,13 @@ class EditFamily(EditPrimary): person.family_list.append(self.obj.handle) self.db.commit_person(person,trans) + def object_is_empty(self): + return self.obj.get_father_handle() == None and \ + self.obj.get_mother_handle() == None and \ + len(self.obj.get_child_handle_list()) == 0 + def save(self,*obj): + if not self.added: original = self.db.get_family_from_handle(self.obj.handle) else: @@ -806,6 +813,10 @@ class EditFamily(EditPrimary): _("No data exists for this family. Please " "enter data or cancel the edit.")) return + elif original and self.object_is_empty(): + trans = self.db.transaction_begin() + self.db.remove_family(self.obj.handle,trans) + self.db.transaction_commit(trans,_("Remove Family")) elif cmp(original.serialize(),self.obj.serialize()): trans = self.db.transaction_begin() @@ -838,5 +849,6 @@ class EditFamily(EditPrimary): else: self.db.commit_family(self.obj,trans) self.db.transaction_commit(trans,_("Edit Family")) + self.close_window() diff --git a/src/PeopleModel.py b/src/PeopleModel.py index 7122543c5..9cbfbe2f9 100644 --- a/src/PeopleModel.py +++ b/src/PeopleModel.py @@ -5,21 +5,28 @@ # # 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 +# 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, +# 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 +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id$ +""" +TreeModel for the GRAMPS Person tree. +""" + +__author__ = "Donald N. Allingham" +__revision__ = "$Revision:$" + #------------------------------------------------------------------------- # # Standard python modules @@ -77,32 +84,38 @@ _codeset = GrampsLocale.codeset # #------------------------------------------------------------------------- -_ID_COL = 1 -_GENDER_COL= 2 -_NAME_COL = 3 -_DEATH_COL = 6 -_BIRTH_COL = 7 -_EVENT_COL = 8 -_FAMILY_COL= 9 -_CHANGE_COL= 19 -_MARKER_COL= 20 +_ID_COL = 1 +_GENDER_COL = 2 +_NAME_COL = 3 +_DEATH_COL = 6 +_BIRTH_COL = 7 +_EVENT_COL = 8 +_FAMILY_COL = 9 +_CHANGE_COL = 19 +_MARKER_COL = 20 #------------------------------------------------------------------------- # # python 2.3 has a bug in the unicode sorting using locale.strcoll. Seems # to have a buffer overrun. We can convince it to do the right thing by -# forcing the string to be nul terminated,sorting,then stripping off the +# forcing the string to be nul terminated, sorting, then stripping off the # nul. # #------------------------------------------------------------------------- if sys.version_info[0:2] == (2, 3): def locale_sort(mylist): - mylist = map(lambda x: x + "\x00",mylist) + """ + Sort version to get around a python2.3 bug with unicode strings + """ + mylist = [ value + "\x00" for value in mylist ] mylist.sort(locale.strcoll) - return map(lambda x: x[:-1],mylist) + return [ value[:-1] for value in mylist ] else: def locale_sort(mylist): + """ + Normal sort routine + """ mylist.sort(locale.strcoll) return mylist @@ -112,8 +125,15 @@ else: # #------------------------------------------------------------------------- class PeopleModel(gtk.GenericTreeModel): + """ + Basic GenericTreeModel interface to handle the Tree interface for + the PersonView + """ def __init__(self, db, data_filter=None, invert_result=False, skip=[]): + """ + Initialize the model building the initial data + """ gtk.GenericTreeModel.__init__(self) self.db = db @@ -128,10 +148,16 @@ class PeopleModel(gtk.GenericTreeModel): self.rebuild_data(data_filter, skip) def rebuild_data(self, data_filter=None, skip=[]): + """ + Convience function that calculates the new data and assigns it. + """ self.calculate_data(data_filter, skip) self.assign_data() def calculate_data(self, dfilter=None, skip=[]): + """ + Calculates the new path to node values for the model. + """ if dfilter: self.dfilter = dfilter self.temp_iter2path = {} @@ -194,7 +220,7 @@ class PeopleModel(gtk.GenericTreeModel): def on_get_n_columns(self): return len(COLUMN_DEFS) - def on_get_path(self,node): + def on_get_path(self, node): '''returns the tree path (a tuple of indices at the various levels) for a particular node.''' try: @@ -209,7 +235,7 @@ class PeopleModel(gtk.GenericTreeModel): def on_get_column_type(self, index): return COLUMN_DEFS[index][COLUMN_DEF_TYPE] - def on_get_iter(self,path): + def on_get_iter(self, path): try: if len(path)==1: # Top Level return self.top_path2iter[path[0]] @@ -223,23 +249,23 @@ class PeopleModel(gtk.GenericTreeModel): # test for header or data row-type if self.sname_sub.has_key(node): # Header rows dont get the background color set - if col==self.marker_color_column: + if col == self.marker_color_column: return None # test for 'header' column being empty (most are) if not COLUMN_DEFS[col][COLUMN_DEF_HEADER]: return u'' - # return values for 'header' row,calling a function + # return values for 'header' row, calling a function # according to column_defs table val = COLUMN_DEFS[col][COLUMN_DEF_HEADER](self, node) return val else: - # return values for 'data' row,calling a function + # return values for 'data' row, calling a function # according to column_defs table try: if node != self.prev_handle: self.prev_data = self.db.get_raw_person_data(str(node)) self.prev_handle = node - return COLUMN_DEFS[col][COLUMN_DEF_LIST](self, + return COLUMN_DEFS[col][COLUMN_DEF_LIST](self, self.prev_data, node) except: if col == _MARKER_COL: @@ -247,7 +273,7 @@ class PeopleModel(gtk.GenericTreeModel): else: return u'error' - def on_iter_next(self,node): + def on_iter_next(self, node): '''returns the next node at this level of the tree''' try: path = self.top_path2iter.index(node) @@ -265,7 +291,7 @@ class PeopleModel(gtk.GenericTreeModel): else: return self.path2iter.get((node, 0)) - def on_iter_has_child(self,node): + def on_iter_has_child(self, node): '''returns true if this node has children''' if node == None: return len(self.sname_sub) @@ -292,7 +318,7 @@ class PeopleModel(gtk.GenericTreeModel): except IndexError: return None - def on_iter_parent(self,node): + def on_iter_parent(self, node): '''returns the parent of this node''' path = self.iter2path.get(node) if path: @@ -309,7 +335,7 @@ class PeopleModel(gtk.GenericTreeModel): handle = data[0] for family_handle in data[_FAMILY_COL]: family = self.db.get_family_from_handle(family_handle) - for spouse_id in [family.get_father_handle(), + for spouse_id in [family.get_father_handle(), family.get_mother_handle()]: if not spouse_id: continue @@ -317,7 +343,7 @@ class PeopleModel(gtk.GenericTreeModel): continue spouse = self.db.get_person_from_handle(spouse_id) if len(spouses_names) > 0: - spouses_names += "," + spouses_names += ", " spouses_names += NameDisplay.displayer.display(spouse) return spouses_names @@ -330,15 +356,16 @@ class PeopleModel(gtk.GenericTreeModel): return data[_ID_COL] def column_change(self, data, node): - return unicode(time.strftime('%x %X', time.localtime(data[_CHANGE_COL])), - _codeset) + return unicode( + time.strftime('%x %X', time.localtime(data[_CHANGE_COL])), + _codeset) def column_gender(self, data, node): return _GENDER[data[_GENDER_COL]] def column_birth_day(self, data, node): if data[_BIRTH_COL]: - b=EventRef() + b = EventRef() b.unserialize(data[_BIRTH_COL]) birth = self.db.get_event_from_handle(b.ref) date_str = DateHandler.get_date(birth) @@ -351,7 +378,7 @@ class PeopleModel(gtk.GenericTreeModel): event = self.db.get_event_from_handle(er.ref) etype = event.get_type()[0] date_str = DateHandler.get_date(event) - if (etype in [Event.BAPTISM,Event.CHRISTEN] + if (etype in [Event.BAPTISM, Event.CHRISTEN] and date_str != ""): return "" + cgi.escape(date_str) + "" @@ -372,7 +399,7 @@ class PeopleModel(gtk.GenericTreeModel): event = self.db.get_event_from_handle(er.ref) etype = event.get_type()[0] date_str = DateHandler.get_date(event) - if (etype in [Event.BURIAL,Event.CREMATION] + if (etype in [Event.BURIAL, Event.CREMATION] and date_str != ""): return "" + cgi.escape(date_str) + "" @@ -404,7 +431,7 @@ class PeopleModel(gtk.GenericTreeModel): er.unserialize(event_ref) event = self.db.get_event_from_handle(er.ref) etype = event.get_type()[0] - if etype in [Event.BAPTISM,Event.CHRISTEN]: + if etype in [Event.BAPTISM, Event.CHRISTEN]: place_handle = event.get_place_handle() if place_handle: place = self.db.get_place_from_handle(place_handle) @@ -422,7 +449,8 @@ class PeopleModel(gtk.GenericTreeModel): if event: place_handle = event.get_place_handle() if place_handle: - place_title = self.db.get_place_from_handle(place_handle).get_title() + place = self.db.get_place_from_handle(place_handle) + place_title = place.get_title() if place_title != "": return cgi.escape(place_title) @@ -431,10 +459,11 @@ class PeopleModel(gtk.GenericTreeModel): er.unserialize(event_ref) event = self.db.get_event_from_handle(er.ref) etype = event.get_type()[0] - if etype in [Event.BURIAL,Event.CREMATION]: + if etype in [Event.BURIAL, Event.CREMATION]: place_handle = event.get_place_handle() if place_handle: - place_title = self.db.get_place_from_handle(place_handle).get_title() + place = self.db.get_place_from_handle(place_handle) + place_title = place.get_title() if place_title != "": return "" + cgi.escape(place_title) + "" @@ -466,7 +495,10 @@ class PeopleModel(gtk.GenericTreeModel): def column_tooltip(self, data, node): if const.use_tips: - return ToolTips.TipFromFunction(self.db,lambda: self.db.get_person_from_handle(data[0])) + return ToolTips.TipFromFunction( + self.db, + lambda: self.db.get_person_from_handle(data[0]) + ) else: return u'' @@ -480,32 +512,32 @@ class PeopleModel(gtk.GenericTreeModel): def column_header_view(self, node): return True -_GENDER = [ _(u'female'),_(u'male'),_(u'unknown') ] +_GENDER = [ _(u'female'), _(u'male'), _(u'unknown') ] # table of column definitions -# (unless this is declared after the PeopleModel class,an error is thrown) +# (unless this is declared after the PeopleModel class, an error is thrown) + COLUMN_DEFS = [ - # data column (method) header column (method) column data type - (PeopleModel.column_name, PeopleModel.column_header, str), - (PeopleModel.column_id, None, str), - (PeopleModel.column_gender, None, str), - (PeopleModel.column_birth_day, None, str), - (PeopleModel.column_birth_place, None, str), - (PeopleModel.column_death_day, None, str), - (PeopleModel.column_death_place, None, str), - (PeopleModel.column_spouse, None, str), - (PeopleModel.column_change, None, str), - (PeopleModel.column_cause_of_death, None, str), - (PeopleModel.column_marker_text, None, str), - (PeopleModel.column_marker_color, None, str), + (PeopleModel.column_name, PeopleModel.column_header, str), + (PeopleModel.column_id, None, str), + (PeopleModel.column_gender, None, str), + (PeopleModel.column_birth_day, None, str), + (PeopleModel.column_birth_place, None, str), + (PeopleModel.column_death_day, None, str), + (PeopleModel.column_death_place, None, str), + (PeopleModel.column_spouse, None, str), + (PeopleModel.column_change, None, str), + (PeopleModel.column_cause_of_death, None, str), + (PeopleModel.column_marker_text, None, str), + (PeopleModel.column_marker_color, None, str), # the order of the above columns must match PeopleView.column_names - # these columns are hidden,and must always be last in the list - (PeopleModel.column_tooltip, None, object), - (PeopleModel.column_int_id, None, str), + # these columns are hidden, and must always be last in the list + (PeopleModel.column_tooltip, None, object), + (PeopleModel.column_int_id, None, str), ] -# dynamic calculation of column indices,for use by various Views +# dynamic calculation of column indices, for use by various Views COLUMN_INT_ID = 13 # indices into main column definition table diff --git a/src/RelLib/_Date.py b/src/RelLib/_Date.py index 783987664..f1c0727c6 100644 --- a/src/RelLib/_Date.py +++ b/src/RelLib/_Date.py @@ -8,7 +8,7 @@ # 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, +# 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. @@ -23,7 +23,7 @@ "Support for dates" __author__ = "Donald N. Allingham" -__version__ = "$Revision$" +__revision__ = "$Revision$" from gettext import gettext as _ from _CalSdn import * @@ -35,7 +35,7 @@ from _CalSdn import * #------------------------------------------------------------------------- class DateError(Exception): """Error used to report Date errors""" - def __init__(self,value=""): + def __init__(self, value=""): Exception.__init__(self) self.value = value @@ -49,7 +49,7 @@ class DateError(Exception): #------------------------------------------------------------------------- class Date: """ - The core date handling class for GRAMPs. Supports partial dates, + The core date handling class for GRAMPs. Supports partial dates, compound dates and alternate calendars. """ @@ -61,9 +61,9 @@ class Date: MOD_SPAN = 5 MOD_TEXTONLY = 6 - QUAL_NONE = 0 - QUAL_ESTIMATED = 1 - QUAL_CALCULATED= 2 + QUAL_NONE = 0 + QUAL_ESTIMATED = 1 + QUAL_CALCULATED = 2 CAL_GREGORIAN = 0 CAL_JULIAN = 1 @@ -72,7 +72,7 @@ class Date: CAL_PERSIAN = 4 CAL_ISLAMIC = 5 - EMPTY = (0,0,0,False) + EMPTY = (0, 0, 0, False) _POS_DAY = 0 _POS_MON = 1 @@ -84,39 +84,39 @@ class Date: _POS_RSL = 7 _calendar_convert = [ - gregorian_sdn, - julian_sdn, - hebrew_sdn, - french_sdn, - persian_sdn, - islamic_sdn, + gregorian_sdn, + julian_sdn, + hebrew_sdn, + french_sdn, + persian_sdn, + islamic_sdn, ] _calendar_change = [ - gregorian_ymd, - julian_ymd, - hebrew_ymd, - french_ymd, - persian_ymd, - islamic_ymd, + gregorian_ymd, + julian_ymd, + hebrew_ymd, + french_ymd, + persian_ymd, + islamic_ymd, ] - calendar_names = ["Gregorian", - "Julian", - "Hebrew", - "French Republican", - "Persian", + calendar_names = ["Gregorian", + "Julian", + "Hebrew", + "French Republican", + "Persian", "Islamic"] - ui_calendar_names = [_("Gregorian"), - _("Julian"), - _("Hebrew"), - _("French Republican"), - _("Persian"), + ui_calendar_names = [_("Gregorian"), + _("Julian"), + _("Hebrew"), + _("French Republican"), + _("Persian"), _("Islamic")] - def __init__(self,source=None): + def __init__(self, source=None): """ Creates a new Date instance. """ @@ -136,15 +136,21 @@ class Date: self.sortval = 0 def serialize(self): - return (self.calendar,self.modifier,self.quality, - self.dateval,self.text,self.sortval) + """ + Convert to a series of tuples for data storage + """ + return (self.calendar, self.modifier, self.quality, + self.dateval, self.text, self.sortval) - def unserialize(self,data): - (self.calendar,self.modifier,self.quality, - self.dateval,self.text,self.sortval) = data + def unserialize(self, data): + """ + Load from the format created by serialize + """ + (self.calendar, self.modifier, self.quality, + self.dateval, self.text, self.sortval) = data return self - def copy(self,source): + def copy(self, source): """ Copy all the attributes of the given Date instance to the present instance, without creating a new object. @@ -156,17 +162,17 @@ class Date: self.text = source.text self.sortval = source.sortval - def __cmp__(self,other): + def __cmp__(self, other): """ Comparison function. Allows the usage of equality tests. This allows you do run statements like 'date1 <= date2' """ - if isinstance(other,Date): - return cmp(self.sortval,other.sortval) + if isinstance(other, Date): + return cmp(self.sortval, other.sortval) else: return -1 - def is_equal(self,other): + def is_equal(self, other): """ Return 1 if the given Date instance is the same as the present instance IN ALL REGARDS. Needed, because the __cmp__ only looks @@ -216,14 +222,14 @@ class Date: val = self.text elif self.modifier == Date.MOD_RANGE or self.modifier == Date.MOD_SPAN: val = "%04d-%02d-%02d - %04d-%02d-%02d" % ( - self.dateval[Date._POS_YR],self.dateval[Date._POS_MON], - self.dateval[Date._POS_DAY],self.dateval[Date._POS_RYR], - self.dateval[Date._POS_RMON],self.dateval[Date._POS_RDAY]) + self.dateval[Date._POS_YR], self.dateval[Date._POS_MON], + self.dateval[Date._POS_DAY], self.dateval[Date._POS_RYR], + self.dateval[Date._POS_RMON], self.dateval[Date._POS_RDAY]) else: val = "%04d-%02d-%02d" % ( - self.dateval[Date._POS_YR],self.dateval[Date._POS_MON], + self.dateval[Date._POS_YR], self.dateval[Date._POS_MON], self.dateval[Date._POS_DAY]) - return "%s%s%s%s" % (qual,pref,val,cal) + return "%s%s%s%s" % (qual, pref, val, cal) def get_sort_value(self): """ @@ -251,12 +257,12 @@ class Date: """ return self.modifier - def set_modifier(self,val): + def set_modifier(self, val): """ Sets the modifier for the date. """ - if val not in (Date.MOD_NONE,Date.MOD_BEFORE,Date.MOD_AFTER, - Date.MOD_ABOUT,Date.MOD_RANGE,Date.MOD_SPAN, + if val not in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, + Date.MOD_ABOUT, Date.MOD_RANGE, Date.MOD_SPAN, Date.MOD_TEXTONLY): raise DateError("Invalid modifier") self.modifier = val @@ -272,11 +278,11 @@ class Date: """ return self.quality - def set_quality(self,val): + def set_quality(self, val): """ Sets the quality selected for the date. """ - if val not in (Date.QUAL_NONE,Date.QUAL_ESTIMATED, + if val not in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): raise DateError("Invalid quality") self.quality = val @@ -295,12 +301,12 @@ class Date: """ return self.calendar - def set_calendar(self,val): + def set_calendar(self, val): """ Sets the calendar selected for the date. """ - if val not in (Date.CAL_GREGORIAN,Date.CAL_JULIAN,Date.CAL_HEBREW, - Date.CAL_FRENCH,Date.CAL_PERSIAN,Date.CAL_ISLAMIC): + if val not in (Date.CAL_GREGORIAN, Date.CAL_JULIAN, Date.CAL_HEBREW, + Date.CAL_FRENCH, Date.CAL_PERSIAN, Date.CAL_ISLAMIC): raise DateError("Invalid calendar") self.calendar = val @@ -309,7 +315,7 @@ class Date: Returns a tuple representing the start date. If the date is a compound date (range or a span), it is the first part of the compound date. If the date is a text string, a tuple of - (0,0,0,False) is returned. Otherwise, a date of (DD,MM,YY,slash) + (0, 0, 0, False) is returned. Otherwise, a date of (DD, MM, YY, slash) is returned. If slash is True, then the date is in the form of 1530/1. """ if self.modifier == Date.MOD_TEXTONLY: @@ -322,7 +328,7 @@ class Date: """ Returns a tuple representing the second half of a compound date. If the date is not a compound date, (including text strings) a tuple - of (0,0,0,False) is returned. Otherwise, a date of (DD,MM,YY,slash) + of (0, 0, 0, False) is returned. Otherwise, a date of (DD, MM, YY, slash) is returned. If slash is True, then the date is in the form of 1530/1. """ if self.modifier == Date.MOD_RANGE or self.modifier == Date.MOD_SPAN: @@ -331,21 +337,30 @@ class Date: val = Date.EMPTY return val - def _get_low_item(self,index): + def _get_low_item(self, index): + """ + Returns the item specified + """ if self.modifier == Date.MOD_TEXTONLY: val = 0 else: val = self.dateval[index] return val - def _get_low_item_valid(self,index): + def _get_low_item_valid(self, index): + """ + Determines if the item specified is valid + """ if self.modifier == Date.MOD_TEXTONLY: val = False else: val = self.dateval[index] != 0 return val - def _get_high_item(self,index): + def _get_high_item(self, index): + """ + Returns the item specified + """ if self.modifier == Date.MOD_SPAN or self.modifier == Date.MOD_RANGE: val = self.dateval[index] else: @@ -360,13 +375,17 @@ class Date: """ return self._get_low_item(Date._POS_YR) - def set_year(self,year): + def set_year(self, year): """ + Sets the year value """ - self.dateval = self.dateval[0:2] + (year,) + self.dateval[3:] - self.calc_sort_value() + self.dateval = self.dateval[0:2] + (year, ) + self.dateval[3:] + self._calc_sort_value() def get_year_valid(self): + """ + Returns true if the year is valid + """ return self._get_low_item_valid(Date._POS_YR) def get_month(self): @@ -378,6 +397,9 @@ class Date: return self._get_low_item(Date._POS_MON) def get_month_valid(self): + """ + Returns true if the month is valid + """ return self._get_low_item_valid(Date._POS_MON) def get_day(self): @@ -389,15 +411,15 @@ class Date: return self._get_low_item(Date._POS_DAY) def get_day_valid(self): + """ + Returns true if the day is valid + """ return self._get_low_item_valid(Date._POS_DAY) def get_valid(self): """ Returns true if any part of the date is valid""" return self.modifier != Date.MOD_TEXTONLY - def get_incomplete(self): - pass - def get_stop_year(self): """ Returns the day of the year associated with the second @@ -441,7 +463,7 @@ class Date: """ return self.text - def set(self,quality,modifier,calendar,value,text=None): + def set(self, quality, modifier, calendar, value, text=None): """ Sets the date to the specified value. Parameters are:: @@ -452,76 +474,82 @@ class Date: calendar - The calendar associated with the date (see get_calendar for more information). value - A tuple representing the date information. For a - non-compound date, the format is (DD,MM,YY,slash) + non-compound date, the format is (DD, MM, YY, slash) and for a compound date the tuple stores data as - (DD,MM,YY,slash1,DD,MM,YY,slash2) + (DD, MM, YY, slash1, DD, MM, YY, slash2) text - A text string holding either the verbatim user input or a comment relating to the date. The sort value is recalculated. """ - if modifier in (Date.MOD_NONE,Date.MOD_BEFORE, - Date.MOD_AFTER,Date.MOD_ABOUT) and len(value) < 4: - raise DateError("Invalid value. Should be: (DD,MM,YY,slash)") - if modifier in (Date.MOD_RANGE,Date.MOD_SPAN) and len(value) < 8: - raise DateError( - "Invalid value. Should be: (DD,MM,YY,slash1,DD,MM,YY,slash2)") - if modifier not in (Date.MOD_NONE,Date.MOD_BEFORE,Date.MOD_AFTER, - Date.MOD_ABOUT,Date.MOD_RANGE,Date.MOD_SPAN, + if modifier in (Date.MOD_NONE, Date.MOD_BEFORE, + Date.MOD_AFTER, Date.MOD_ABOUT) and len(value) < 4: + raise DateError("Invalid value. Should be: (DD, MM, YY, slash)") + if modifier in (Date.MOD_RANGE, Date.MOD_SPAN) and len(value) < 8: + raise DateError("Invalid value. Should be: (DD, MM, " + "YY, slash1, DD, MM, YY, slash2)") + if modifier not in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, + Date.MOD_ABOUT, Date.MOD_RANGE, Date.MOD_SPAN, Date.MOD_TEXTONLY): raise DateError("Invalid modifier") - if quality not in (Date.QUAL_NONE,Date.QUAL_ESTIMATED, + if quality not in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): raise DateError("Invalid quality") - if calendar not in (Date.CAL_GREGORIAN,Date.CAL_JULIAN,Date.CAL_HEBREW, - Date.CAL_FRENCH,Date.CAL_PERSIAN,Date.CAL_ISLAMIC): + if calendar not in (Date.CAL_GREGORIAN, Date.CAL_JULIAN, + Date.CAL_HEBREW, Date.CAL_FRENCH, + Date.CAL_PERSIAN, Date.CAL_ISLAMIC): raise DateError("Invalid calendar") self.quality = quality self.modifier = modifier self.calendar = calendar self.dateval = value - year = max(value[Date._POS_YR],1) - month = max(value[Date._POS_MON],1) - day = max(value[Date._POS_DAY],1) + year = max(value[Date._POS_YR], 1) + month = max(value[Date._POS_MON], 1) + day = max(value[Date._POS_DAY], 1) if year == 0 and month == 0 and day == 0: self.sortval = 0 else: - self.sortval = Date._calendar_convert[calendar](year,month,day) + func = Date._calendar_convert[calendar] + self.sortval = func(year, month, day) if text: self.text = text - def calc_sort_value(self): - year = max(self.dateval[Date._POS_YR],1) - month = max(self.dateval[Date._POS_MON],1) - day = max(self.dateval[Date._POS_DAY],1) + def _calc_sort_value(self): + """ + Calculates the numerical sort value associated with the date + """ + year = max(self.dateval[Date._POS_YR], 1) + month = max(self.dateval[Date._POS_MON], 1) + day = max(self.dateval[Date._POS_DAY], 1) if year == 0 and month == 0 and day == 0: self.sortval = 0 else: - self.sortval = Date._calendar_convert[self.calendar](year,month,day) + func = Date._calendar_convert[self.calendar] + self.sortval = func(year, month, day) - def convert_calendar(self,calendar): + def convert_calendar(self, calendar): """ Converts the date from the current calendar to the specified calendar. """ if calendar == self.calendar: return - (y,m,d) = Date._calendar_change[calendar](self.sortval) + (year, month, day) = Date._calendar_change[calendar](self.sortval) if self.is_compound(): - ry = max(self.dateval[Date._POS_RYR],1) - rm = max(self.dateval[Date._POS_RMON],1) - rd = max(self.dateval[Date._POS_RDAY],1) - sdn = Date._calendar_convert[self.calendar](ry,rm,rd) - (ny,nm,nd) = Date._calendar_change[calendar](sdn) - self.dateval = (d,m,y,self.dateval[Date._POS_SL], - nd,nm,ny,self.dateval[Date._POS_RSL]) + ryear = max(self.dateval[Date._POS_RYR], 1) + rmonth = max(self.dateval[Date._POS_RMON], 1) + rday = max(self.dateval[Date._POS_RDAY], 1) + sdn = Date._calendar_convert[self.calendar](ryear, rmonth, rday) + (nyear, nmonth, nday) = Date._calendar_change[calendar](sdn) + self.dateval = (day, month, year, self.dateval[Date._POS_SL], + nday, nmonth, nyear, self.dateval[Date._POS_RSL]) else: - self.dateval = (d,m,y,self.dateval[Date._POS_SL]) + self.dateval = (day, month, year, self.dateval[Date._POS_SL]) self.calendar = calendar - def set_as_text(self,text): + def set_as_text(self, text): """ Sets the day to a text string, and assigns the sort value to zero. @@ -530,7 +558,7 @@ class Date: self.text = text self.sortval = 0 - def set_text_value(self,text): + def set_text_value(self, text): """ Sets the text string to a given text. """ diff --git a/src/ViewManager.py b/src/ViewManager.py index 5223c3e1e..405bb00a8 100644 --- a/src/ViewManager.py +++ b/src/ViewManager.py @@ -8,7 +8,7 @@ # 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, +# 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. @@ -20,14 +20,22 @@ # $Id$ +""" +Manages the main window and the pluggable views +""" + +__author__ = "Donald N. Allingham" +__revision__ = "$Revision:$" + #------------------------------------------------------------------------- # # Standard python modules # #------------------------------------------------------------------------- +import os + from gettext import gettext as _ from bsddb import db -import os from cStringIO import StringIO #------------------------------------------------------------------------- @@ -77,9 +85,9 @@ import GrampsWidgets # #------------------------------------------------------------------------- _KNOWN_FORMATS = { - const.app_gramps : _('GRAMPS (grdb)'), - const.app_gramps_xml : _('GRAMPS XML'), - const.app_gedcom : _('GEDCOM'), + const.app_gramps : _('GRAMPS (grdb)'), + const.app_gramps_xml : _('GRAMPS XML'), + const.app_gedcom : _('GEDCOM'), } uidefault = ''' @@ -158,29 +166,33 @@ uidefault = ''' class ViewManager: - def __init__(self,state): - - self.navigation_type = { - PageView.NAVIGATION_NONE: (None, None), - PageView.NAVIGATION_PERSON: (None,None), - } - + def __init__(self, state): + """ + Initialize the ViewManager + """ self.state = state self.active_page = None self.views = [] self.pages = [] - self.window = gtk.Window() - self.window.set_icon_from_file(const.icon) - self.window.connect('destroy', self.quit) self.file_loaded = False - + self._build_main_window() + self._connect_signals() + + def _build_main_window(self): + """ + Builds the GTK interface + """ try: width = Config.get_width() height = Config.get_height() - self.window.set_default_size(width,height) except: - self.window.set_default_size(775,500) - + width = 775 + height = 500 + + self.window = gtk.Window() + self.window.set_icon_from_file(const.icon) + self.window.set_default_size(width, height) + self.statusbar = gtk.Statusbar() self.RelClass = relationship_class @@ -191,7 +203,7 @@ class ViewManager: self.ebox = gtk.EventBox() self.bbox = gtk.VBox() self.ebox.add(self.bbox) - hbox.pack_start(self.ebox,False) + hbox.pack_start(self.ebox, False) hbox.show_all() self.show_sidebar = Config.get_view() @@ -204,45 +216,47 @@ class ViewManager: self.notebook = gtk.Notebook() self.notebook.set_show_tabs(False) self.notebook.show() - self.build_ui_manager() + self._init_lists() + self._build_ui_manager() - hbox.pack_start(self.notebook,True) + hbox.pack_start(self.notebook, True) self.menubar = self.uimanager.get_widget('/MenuBar') self.toolbar = self.uimanager.get_widget('/ToolBar') vbox.pack_start(self.menubar, False) vbox.pack_start(self.toolbar, False) vbox.add(hbox) self.progress = gtk.ProgressBar() - self.progress.set_size_request(100,-1) + self.progress.set_size_request(100, -1) self.progress.hide() self.statusbar.show() self.warnbtn = GrampsWidgets.WarnButton() hbox2 = gtk.HBox() hbox2.set_spacing(4) hbox2.set_border_width(2) - hbox2.pack_start(self.progress,False) - hbox2.pack_start(self.warnbtn,False) - hbox2.pack_end(self.statusbar,True) + hbox2.pack_start(self.progress, False) + hbox2.pack_start(self.warnbtn, False) + hbox2.pack_end(self.statusbar, True) hbox2.show() - vbox.pack_end(hbox2,False) + vbox.pack_end(hbox2, False) vbox.show() - self.notebook.connect('switch-page',self.change_page) - self.uistate = DisplayState.DisplayState(self.window, self.statusbar, - self.progress, self.warnbtn, - self.uimanager, self.state) + self.uistate = DisplayState.DisplayState( + self.window, self.statusbar, self.progress, self.warnbtn, + self.uimanager, self.state) toolbar = self.uimanager.get_widget('/ToolBar') openbtn = gtk.MenuToolButton(gtk.STOCK_OPEN) openbtn.show() - openbtn.connect('clicked',self.open_activate) + openbtn.connect('clicked', self.open_activate) openbtn.set_sensitive(False) self.uistate.set_open_widget(openbtn) - toolbar.insert(openbtn,1) + toolbar.insert(openbtn, 1) self.person_nav = Navigation.PersonNavigation(self.uistate) - self.navigation_type[PageView.NAVIGATION_PERSON] = (self.person_nav,None) - self.recent_manager = DisplayState.RecentDocsMenu(self.uistate,self.state, + self._navigation_type[PageView.NAVIGATION_PERSON] = (self.person_nav, + None) + self.recent_manager = DisplayState.RecentDocsMenu(self.uistate, + self.state, self.read_file) self.recent_manager.build() @@ -260,9 +274,97 @@ class ViewManager: else: self.toolbar.hide() + def _connect_signals(self): + """ + connects the signals needed + """ + self.window.connect('destroy', self.quit) + self.notebook.connect('switch-page', self.change_page) + + def _init_lists(self): + self._file_action_list = [ + ('FileMenu', None, '_File'), + ('New', gtk.STOCK_NEW, '_New', "n", None, + self.new_activate), + ('Open', gtk.STOCK_OPEN, '_Open', "o", None, + self.open_activate), + ('OpenRecent', None, 'Open _Recent'), + ('Quit', gtk.STOCK_QUIT, '_Quit', "q", None, self.quit), + ('ViewMenu', None, '_View'), + ('Preferences', gtk.STOCK_PREFERENCES, '_Preferences', None, None, + self.preferences_activate), + ('HelpMenu', None, '_Help'), + ('HomePage', None, _('GRAMPS _home page'), None, None, + self.home_page_activate), + ('MailingLists', None, _('GRAMPS _mailing lists'), None, None, + self.mailing_lists_activate), + ('ReportBug', None, _('_Report a bug'), None, None, + self.report_bug_activate), + ('About', gtk.STOCK_ABOUT, '_About', None, None, self.about), + ('PluginStatus', None, '_Plugin status', None, None, + self.plugin_status), + ('FAQ', None, '_FAQ', None, None, self.faq_activate), + ('UserManual', gtk.STOCK_HELP, '_User Manual', 'F1', None, + self.manual_activate), + ('TipOfDay', None, 'Tip of the day', None, None, + self.tip_of_day_activate), + ] + + self._action_action_list = [ + ('SaveAs', gtk.STOCK_SAVE_AS, '_Save As'), + ('Export', gtk.STOCK_SAVE_AS, '_Export', "e", None, + self.export_data), + ('Abandon', gtk.STOCK_REVERT_TO_SAVED, '_Abandon changes and quit'), + ('CmpMerge', None, '_Compare and merge'), + ('FastMerge', None, '_Fast merge'), + ('ScratchPad', gtk.STOCK_PASTE, '_ScratchPad', None, None, + self.scratchpad), + ('Import', gtk.STOCK_CONVERT, '_Import', "i", None, + self.import_data), + ('Reports', gtk.STOCK_DND_MULTIPLE, '_Reports', None, None, + self.reports_clicked), + ('Tools', gtk.STOCK_EXECUTE, '_Tools', None, None, + self.tools_clicked), + ('EditMenu', None, '_Edit'), + ('ColumnEdit', gtk.STOCK_PROPERTIES, '_Column Editor'), + ('GoMenu', None, '_Go'), + ('BookMenu', None, '_Bookmarks'), + ('AddBook', gtk.STOCK_INDEX, '_Add bookmark', 'd', None, + self.add_bookmark), + ('EditBook', None, '_Edit bookmarks', 'b', None, + self.edit_bookmarks), + ('GoToBook', gtk.STOCK_JUMP_TO, '_Go to bookmark'), + ('ReportsMenu', None, '_Reports'), + ('ToolsMenu', None, '_Tools'), + ('WindowsMenu', None, '_Windows'), + ] + + self._file_toggle_action_list = [ + ('Sidebar', None, '_Sidebar', None, None, self.sidebar_toggle, + self.show_sidebar ), + ('Toolbar', None, '_Toolbar', None, None, self.toolbar_toggle, + self.show_toolbar ), + ] + + self._undo_action_list = [ + ('Undo', gtk.STOCK_UNDO, '_Undo', 'z', None, self.undo), + ] + + self._redo_action_list = [ + ('Redo', gtk.STOCK_REDO, '_Redo', 'z', None, + self.redo), + ] + + self._navigation_type = { + PageView.NAVIGATION_NONE: (None, None), + PageView.NAVIGATION_PERSON: (None, None), + } + def init_interface(self): + self._init_lists() + self.create_pages() - self.change_page(None,None) + self.change_page(None, None) if not self.file_loaded: self.actiongroup.set_visible(False) self.fileactions.set_sensitive(False) @@ -275,23 +377,23 @@ class ViewManager: def do_load_plugins(self): self.uistate.status_text(_('Loading document formats...')) error = load_plugins(const.docgenDir) - error |= load_plugins(os.path.join(const.home_dir,"docgen")) + error |= load_plugins(os.path.join(const.home_dir, "docgen")) self.uistate.status_text(_('Loading plugins...')) error |= load_plugins(const.pluginsDir) - error |= load_plugins(os.path.join(const.home_dir,"plugins")) + error |= load_plugins(os.path.join(const.home_dir, "plugins")) if Config.get_pop_plugin_status() and error: Plugins.PluginStatus(self.state, self.uistate, []) self.uistate.push_message(_('Ready')) - def quit(self,obj=None): + def quit(self, obj=None): self.state.db.close() - (width,height) = self.window.get_size() + (width, height) = self.window.get_size() Config.save_width(width) Config.save_height(height) Config.sync() gtk.main_quit() - def build_ui_manager(self): + def _build_ui_manager(self): self.merge_ids = [] self.uimanager = gtk.UIManager() @@ -303,120 +405,70 @@ class ViewManager: self.undoactions = gtk.ActionGroup('Undo') self.redoactions = gtk.ActionGroup('Redo') - self.fileactions.add_actions([ - ('FileMenu', None, '_File'), - ('New', gtk.STOCK_NEW, '_New', "n", None, self.new_activate), - ('Open', gtk.STOCK_OPEN, '_Open', "o", None, self.open_activate), - ('OpenRecent', None, 'Open _Recent'), - ('Quit', gtk.STOCK_QUIT, '_Quit', "q", None, self.quit), - ('ViewMenu', None, '_View'), - ('Preferences', gtk.STOCK_PREFERENCES, '_Preferences', None, None, self.preferences_activate), - ('HelpMenu', None, '_Help'), - ('HomePage', None, _('GRAMPS _home page'), None, None, self.home_page_activate), - ('MailingLists', None, _('GRAMPS _mailing lists'), None, None, self.mailing_lists_activate), - ('ReportBug', None, _('_Report a bug'), None, None, self.report_bug_activate), - ('About', gtk.STOCK_ABOUT, '_About', None, None, self.about), - ('PluginStatus', None, '_Plugin status', None, None, self.plugin_status), - ('FAQ', None, '_FAQ', None, None, self.faq_activate), - ('UserManual', gtk.STOCK_HELP, '_User Manual', 'F1', None, self.manual_activate), - ('TipOfDay', None, 'Tip of the day', None, None, self.tip_of_day_activate), - ]) + self.fileactions.add_actions(self._file_action_list) + self.actiongroup.add_actions(self._action_action_list) + self.fileactions.add_toggle_actions(self._file_toggle_action_list) - self.actiongroup.add_actions([ - # Name Stock Icon Label - ('SaveAs', gtk.STOCK_SAVE_AS, '_Save As'), - ('Export', gtk.STOCK_SAVE_AS, '_Export', "e", None, self.export_data), - ('Abandon', gtk.STOCK_REVERT_TO_SAVED, '_Abandon changes and quit'), - ('CmpMerge', None, '_Compare and merge'), - ('FastMerge', None, '_Fast merge'), - ('ScratchPad', gtk.STOCK_PASTE, '_ScratchPad', None, None, self.scratchpad), - ('Import', gtk.STOCK_CONVERT, '_Import', "i", None, self.import_data), - ('Reports', gtk.STOCK_DND_MULTIPLE, '_Reports', None, None, self.reports_clicked), - ('Tools', gtk.STOCK_EXECUTE, '_Tools', None, None, self.tools_clicked), - ('EditMenu', None, '_Edit'), - ('ColumnEdit', gtk.STOCK_PROPERTIES, '_Column Editor'), - ('GoMenu', None, '_Go'), - ('BookMenu', None, '_Bookmarks'), - ('AddBook', gtk.STOCK_INDEX, '_Add bookmark', 'd', None, self.add_bookmark), - ('EditBook', None, '_Edit bookmarks', 'b', None, self.edit_bookmarks), - ('GoToBook', gtk.STOCK_JUMP_TO, '_Go to bookmark'), - ('ReportsMenu', None, '_Reports'), - ('ToolsMenu', None, '_Tools'), - ('WindowsMenu', None, '_Windows'), - ]) - - self.fileactions.add_toggle_actions([ - ('Sidebar', None, '_Sidebar', None, None, self.sidebar_toggle, - self.show_sidebar - ), - ('Toolbar', None, '_Toolbar', None, None, self.toolbar_toggle, - self.show_toolbar - ), - ]) - - self.undoactions.add_actions([ - ('Undo',gtk.STOCK_UNDO,'_Undo','z',None,self.undo)]) + self.undoactions.add_actions(self._undo_action_list) self.undoactions.set_sensitive(False) - self.redoactions.add_actions([ - ('Redo',gtk.STOCK_REDO,'_Redo','z',None,self.redo) - ]) + self.redoactions.add_actions(self._redo_action_list) self.redoactions.set_sensitive(False) merge_id = self.uimanager.add_ui_from_string(uidefault) - self.uimanager.insert_action_group(self.fileactions,1) - self.uimanager.insert_action_group(self.actiongroup,1) - self.uimanager.insert_action_group(self.undoactions,1) - self.uimanager.insert_action_group(self.redoactions,1) + self.uimanager.insert_action_group(self.fileactions, 1) + self.uimanager.insert_action_group(self.actiongroup, 1) + self.uimanager.insert_action_group(self.undoactions, 1) + self.uimanager.insert_action_group(self.redoactions, 1) - def home_page_activate(self,obj): + def home_page_activate(self, obj): import GrampsDisplay GrampsDisplay.url(const.url_homepage) - def mailing_lists_activate(self,obj): + def mailing_lists_activate(self, obj): import GrampsDisplay GrampsDisplay.url( const.url_mailinglist) - def preferences_activate(self,obj): + def preferences_activate(self, obj): GrampsCfg.display_preferences_box(self.state.db) - def report_bug_activate(self,obj): + def report_bug_activate(self, obj): import GrampsDisplay GrampsDisplay.url( const.url_bugtracker) - def manual_activate(self,obj): + def manual_activate(self, obj): """Display the GRAMPS manual""" try: import GrampsDisplay GrampsDisplay.help('index') except gobject.GError, msg: - QuestionDialog.ErrorDialog(_("Could not open help"),str(msg)) + QuestionDialog.ErrorDialog(_("Could not open help"), str(msg)) - def faq_activate(self,obj): + def faq_activate(self, obj): """Display FAQ""" try: import GrampsDisplay GrampsDisplay.help('faq') except gobject.GError, msg: - QuestionDialog.ErrorDialog(_("Could not open help"),str(msg)) + QuestionDialog.ErrorDialog(_("Could not open help"), str(msg)) - def tip_of_day_activate(self,obj): + def tip_of_day_activate(self, obj): """Display Tip of the day""" TipOfDay.TipOfDay(self.uistate) - def plugin_status(self,obj): + def plugin_status(self, obj): """Display Tip of the day""" - Plugins.PluginStatus(self.state,self.uistate,[]) + Plugins.PluginStatus(self.state, self.uistate, []) - def about(self,obj): + def about(self, obj): about = gtk.AboutDialog() about.set_name(const.program_name) about.set_version(const.version) about.set_copyright(const.copyright_msg) try: - f = open(const.license_file,"r") - about.set_license(f.read().replace('\x0c','')) + f = open(const.license_file, "r") + about.set_license(f.read().replace('\x0c', '')) f.close() except: pass @@ -430,7 +482,7 @@ class ViewManager: about.show() about.run() - def sidebar_toggle(self,obj): + def sidebar_toggle(self, obj): if obj.get_active(): self.ebox.show() self.notebook.set_show_tabs(False) @@ -441,7 +493,7 @@ class ViewManager: Config.save_view(False) Config.sync() - def toolbar_toggle(self,obj): + def toolbar_toggle(self, obj): if obj.get_active(): self.toolbar.show() Config.save_toolbar(True) @@ -459,13 +511,13 @@ class ViewManager: index = 0 for page_def in self.views: - page = page_def(self.state,self.uistate) + page = page_def(self.state, self.uistate) # create icon/label for notebook hbox = gtk.HBox() image = gtk.Image() - image.set_from_stock(page.get_stock(),gtk.ICON_SIZE_MENU) - hbox.pack_start(image,False) + image.set_from_stock(page.get_stock(), gtk.ICON_SIZE_MENU) + hbox.pack_start(image, False) hbox.add(gtk.Label(page.get_title())) hbox.show_all() @@ -473,24 +525,24 @@ class ViewManager: page.define_actions() page_display = page.get_display() page_display.show_all() - self.notebook.append_page(page_display,hbox) + self.notebook.append_page(page_display, hbox) self.pages.append(page) # create the button add it to the sidebar - button = gtk.Button(stock=page.get_stock(),label=page.get_title()) + button = gtk.Button(stock=page.get_stock(), label=page.get_title()) button.set_border_width(4) button.set_relief(gtk.RELIEF_NONE) - button.set_alignment(0,0.5) - button.connect('clicked', - lambda x,y : self.notebook.set_current_page(y), index) + button.set_alignment(0, 0.5) + button.connect('clicked', + lambda x, y : self.notebook.set_current_page(y), index) button.show() index += 1 - self.bbox.pack_start(button,False) + self.bbox.pack_start(button, False) self.active_page = self.pages[0] self.active_page.set_active() - def change_page(self,obj,page,num=-1): + def change_page(self, obj, page, num=-1): if num == -1: num = self.notebook.get_current_page() @@ -510,18 +562,18 @@ class ViewManager: self.active_page = self.pages[num] self.active_page.set_active() - old_nav = self.navigation_type[self.prev_nav] + 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()] + 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.uimanager.insert_action_group(grp, 1) ui = self.active_page.ui_definition() self.merge_ids = [self.uimanager.add_ui_from_string(ui)] @@ -534,15 +586,14 @@ class ViewManager: self.pages[num].change_page() - def open_activate(self,obj): + def open_activate(self, obj): - choose = gtk.FileChooserDialog(_('GRAMPS: Open database'), - self.uistate.window, - gtk.FILE_CHOOSER_ACTION_OPEN, - (gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK)) + choose = gtk.FileChooserDialog( + _('GRAMPS: Open database'), + self.uistate.window, + gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) # Always add automatic (macth all files) filter add_all_files_filter(choose) @@ -550,7 +601,7 @@ class ViewManager: add_xml_filter(choose) add_gedcom_filter(choose) - format_list = [const.app_gramps,const.app_gramps_xml,const.app_gedcom] + format_list = [const.app_gramps, const.app_gramps_xml, const.app_gedcom] # Add more data type selections if opening existing db for data in import_list: @@ -564,7 +615,7 @@ class ViewManager: format_list.append(mime_type) _KNOWN_FORMATS[mime_type] = format_name - (box,type_selector) = format_maker(format_list) + (box, type_selector) = format_maker(format_list) choose.set_extra_widget(box) # Suggested folder: try last open file, last import, last export, @@ -586,13 +637,13 @@ class ViewManager: filetype = type_selector.get_value() if filetype == 'auto': filetype = Mime.get_type(filename) - (the_path,the_file) = os.path.split(filename) + (the_path, the_file) = os.path.split(filename) choose.destroy() - if filetype in [const.app_gramps,const.app_gramps_xml, + if filetype in [const.app_gramps, const.app_gramps_xml, const.app_gedcom]: try: - return self.open_native(filename,filetype) + return self.open_native(filename, filetype) except db.DBInvalidArgError, msg: QuestionDialog.ErrorDialog( _("Could not open file: %s") % filename, msg[1]) @@ -601,40 +652,22 @@ class ViewManager: log.error("Failed to open native.", exc_info=True) return False - # The above native formats did not work, so we need to - # look up the importer for this format - # and create an empty native database to import data in -# for (importData,mime_filter,mime_type,native_format,format_name) in import_list: -# if filetype == mime_type or the_file == mime_type: -# QuestionDialog.OkDialog( -# _("Opening non-native format"), -# _("New GRAMPS database has to be set up " -# "when opening non-native formats. The " -# "following dialog will let you select " -# "the new database."), -# self.state.window) -# prompter = NewNativeDbPrompter(self.parent,self.parent_window) -# if prompter.chooser(): -# importData(self.state.db,filename) -# #self.parent.import_tool_callback() -# return True -# else: -# return False QuestionDialog.ErrorDialog( - _("Could not open file: %s") % filename, - _('File type "%s" is unknown to GRAMPS.\n\nValid types are: GRAMPS database, GRAMPS XML, GRAMPS package, and GEDCOM.') % filetype) + _("Could not open file: %s") % filename, + _('File type "%s" is unknown to GRAMPS.\n\n' + 'Valid types are: GRAMPS database, GRAMPS XML, ' + 'GRAMPS package, and GEDCOM.') % filetype) choose.destroy() return False - def new_activate(self,obj): + def new_activate(self, obj): - choose = gtk.FileChooserDialog(_('GRAMPS: Create GRAMPS database'), - self.uistate.window, - gtk.FILE_CHOOSER_ACTION_SAVE, - (gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK)) + choose = gtk.FileChooserDialog( + _('GRAMPS: Create GRAMPS database'), + self.uistate.window, + gtk.FILE_CHOOSER_ACTION_SAVE, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) # Always add automatic (macth all files) filter add_all_files_filter(choose) @@ -650,7 +683,7 @@ class ViewManager: if len(default_dir)<=1: default_dir = '~/' - new_filename = Utils.get_new_filename('grdb',default_dir) + new_filename = Utils.get_new_filename('grdb', default_dir) choose.set_current_folder(default_dir) choose.set_current_name(os.path.split(new_filename)[1]) @@ -668,13 +701,14 @@ class ViewManager: self.state.db.close() except: pass - self.state.change_database(GrampsDb.gramps_db_factory(const.app_gramps)()) + factory = GrampsDb.gramps_db_factory + self.state.change_database(factory(const.app_gramps)()) self.uistate.clear_history() self.read_file(filename) self.state.signal_change() - self.change_page(None,None) + self.change_page(None, None) # Add the file to the recent items - RecentFiles.recent_files(filename,const.app_gramps) + RecentFiles.recent_files(filename, const.app_gramps) self.recent_manager.build() return True else: @@ -683,61 +717,62 @@ class ViewManager: choose.destroy() return False - def open_native(self,filename,filetype): + def open_native(self, filename, filetype): """ Open native database and return the status. """ - (the_path,the_file) = os.path.split(filename) + (the_path, the_file) = os.path.split(filename) Config.save_last_import_dir(the_path) + factory = GrampsDb.gramps_db_factory success = False if filetype == const.app_gramps: - self.state.change_database(GrampsDb.gramps_db_factory(db_type = const.app_gramps)()) - success = self.read_file(filename) #,update_msg) + self.state.change_database(factory(db_type = const.app_gramps)()) + success = self.read_file(filename) #, update_msg) self.state.signal_change() - self.change_page(None,None) + self.change_page(None, None) elif filetype == const.app_gramps_xml: - self.state.change_database(GrampsDb.gramps_db_factory(db_type = const.app_gramps_xml)()) + self.state.change_database(factory(db_type = const.app_gramps_xml)()) success = self.read_file(filename) self.state.signal_change() - self.change_page(None,None) + self.change_page(None, None) elif filetype == const.app_gedcom: - self.state.change_database(GrampsDb.gramps_db_factory(db_type = const.app_gedcom)()) + self.state.change_database(factory(db_type = const.app_gedcom)()) success = self.read_file(filename) self.state.signal_change() - self.change_page(None,None) + self.change_page(None, None) if success: # Add the file to the recent items - RecentFiles.recent_files(filename,filetype) + RecentFiles.recent_files(filename, filetype) self.recent_manager.build() self.actiongroup.set_visible(True) self.uistate.clear_history() return success - def read_file(self,filename,callback=None): + def read_file(self, filename, callback=None): mode = "w" filename = os.path.normpath(os.path.abspath(filename)) if os.path.isdir(filename): QuestionDialog.ErrorDialog( - _('Cannot open database'), + _('Cannot open database'), _('The selected file is a directory, not ' 'a file.\nA GRAMPS database must be a file.')) return False elif os.path.exists(filename): - if not os.access(filename,os.R_OK): + if not os.access(filename, os.R_OK): QuestionDialog.ErrorDialog( - _('Cannot open database'), + _('Cannot open database'), _('You do not have read access to the selected ' 'file.')) return False - elif not os.access(filename,os.W_OK): + elif not os.access(filename, os.W_OK): mode = "r" QuestionDialog.WarningDialog( - _('Read only database'), + _('Read only database'), _('You do not have write access ' 'to the selected file.')) @@ -751,15 +786,15 @@ class ViewManager: # attempt to update the screen while we are loading the # new data - self.state.emit('database-changed',(GrampsDb.GrampsDbBase(),)) + self.state.emit('database-changed', (GrampsDb.GrampsDbBase(), )) try: - if self.load_database(filename,callback,mode=mode): + if self.load_database(filename, callback, mode=mode): if filename[-1] == '/': filename = filename[:-1] name = os.path.basename(filename) if self.state.db.readonly: - msg = "%s (%s) - GRAMPS" % (name,_('Read Only')) + msg = "%s (%s) - GRAMPS" % (name, _('Read Only')) self.uistate.window.set_title(msg) else: msg = "%s - GRAMPS" % name @@ -767,15 +802,15 @@ class ViewManager: else: Config.save_last_file("") QuestionDialog.ErrorDialog( - _('Cannot open database'), + _('Cannot open database'), _('The database file specified could not be opened.')) return False except ( IOError, OSError, Errors.FileVersionError), msg: - QuestionDialog.ErrorDialog(_('Cannot open database'),str(msg)) + QuestionDialog.ErrorDialog(_('Cannot open database'), str(msg)) return False - except (db.DBAccessError,db.DBError), msg: + except (db.DBAccessError, db.DBError), msg: QuestionDialog.ErrorDialog( - _('Cannot open database'), + _('Cannot open database'), _('%s could not be opened.' % filename) + '\n' + msg[1]) return False except Exception: @@ -790,15 +825,15 @@ class ViewManager: self.actiongroup.set_visible(True) return True - def load_database(self,name,callback=None,mode="w"): + def load_database(self, name, callback=None, mode="w"): self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) self.progress.show() - if not self.state.db.load(name,self.uistate.pulse_progressbar,mode): + if not self.state.db.load(name, self.uistate.pulse_progressbar, mode): return False self.progress.hide() - return self.post_load(name,callback) + return self.post_load(name, callback) - def post_load(self,name,callback=None): + def post_load(self, name, callback=None): if not self.state.db.version_supported(): raise Errors.FileVersionError( "The database version is not supported by this " @@ -821,85 +856,85 @@ class ViewManager: self.relationship = self.RelClass(self.state.db) self.state.change_active_person(self.state.db.find_initial_person()) - self.change_page(None,None) + self.change_page(None, None) self.state.db.undo_callback = self.change_undo_label self.state.db.redo_callback = self.change_redo_label self.actiongroup.set_visible(True) self.window.window.set_cursor(None) return True - def change_undo_label(self,label): + def change_undo_label(self, label): self.uimanager.remove_action_group(self.undoactions) self.undoactions = gtk.ActionGroup('Undo') if label: self.undoactions.add_actions([ - ('Undo',gtk.STOCK_UNDO,label,'z',None,self.undo)]) + ('Undo', gtk.STOCK_UNDO, label, 'z', None, self.undo)]) else: self.undoactions.add_actions([ - ('Undo',gtk.STOCK_UNDO,'_Undo', - 'z',None,self.undo)]) + ('Undo', gtk.STOCK_UNDO, '_Undo', + 'z', None, self.undo)]) self.undoactions.set_sensitive(False) - self.uimanager.insert_action_group(self.undoactions,1) + self.uimanager.insert_action_group(self.undoactions, 1) - def change_redo_label(self,label): + def change_redo_label(self, label): self.uimanager.remove_action_group(self.redoactions) self.redoactions = gtk.ActionGroup('Redo') if label: self.redoactions.add_actions([ - ('Redo',gtk.STOCK_REDO,label,'z', - None,self.redo)]) + ('Redo', gtk.STOCK_REDO, label, 'z', + None, self.redo)]) else: self.redoactions.add_actions([ - ('Redo',gtk.STOCK_UNDO,'_Redo', - 'z',None,self.redo)]) + ('Redo', gtk.STOCK_UNDO, '_Redo', + 'z', None, self.redo)]) self.redoactions.set_sensitive(False) - self.uimanager.insert_action_group(self.redoactions,1) + self.uimanager.insert_action_group(self.redoactions, 1) def setup_bookmarks(self): - self.bookmarks = Bookmarks.Bookmarks(self.state,self.uimanager, + self.bookmarks = Bookmarks.Bookmarks(self.state, self.uimanager, self.state.db.get_bookmarks()) - def add_bookmark(self,obj): + def add_bookmark(self, obj): if self.state.active: self.bookmarks.add(self.state.active.get_handle()) name = NameDisplay.displayer.display(self.state.active) self.uistate.push_message(_("%s has been bookmarked") % name) else: QuestionDialog.WarningDialog( - _("Could Not Set a Bookmark"), + _("Could Not Set a Bookmark"), _("A bookmark could not be set because " "no one was selected.")) - def edit_bookmarks(self,obj): + def edit_bookmarks(self, obj): self.bookmarks.edit() - def reports_clicked(self,obj): - Plugins.ReportPlugins(self.state,self.uistate,[]) + def reports_clicked(self, obj): + Plugins.ReportPlugins(self.state, self.uistate, []) - def tools_clicked(self,obj): - Plugins.ToolPlugins(self.state,self.uistate,[]) + def tools_clicked(self, obj): + Plugins.ToolPlugins(self.state, self.uistate, []) - def scratchpad(self,obj): + def scratchpad(self, obj): import ScratchPad ScratchPad.ScratchPadWindow(self.state, self) - def undo(self,obj): + def undo(self, obj): self.state.db.undo() - def redo(self,obj): + def redo(self, obj): self.state.db.redo() - def export_data(self,obj): + def export_data(self, obj): import Exporter - Exporter.Exporter(self.state,self.uistate) + Exporter.Exporter(self.state, self.uistate) - def import_data(self,obj): - choose = gtk.FileChooserDialog(_('GRAMPS: Import database'), - self.uistate.window, - gtk.FILE_CHOOSER_ACTION_OPEN, - (gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, + def import_data(self, obj): + choose = gtk.FileChooserDialog(_('GRAMPS: Import database'), + self.uistate.window, + gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) choose.set_local_only(False) # Always add automatic (macth all files) filter @@ -908,7 +943,7 @@ class ViewManager: add_xml_filter(choose) add_gedcom_filter(choose) - format_list = [const.app_gramps,const.app_gramps_xml,const.app_gedcom] + format_list = [const.app_gramps, const.app_gramps_xml, const.app_gedcom] # Add more data type selections if opening existing db for data in import_list: @@ -922,7 +957,7 @@ class ViewManager: format_list.append(mime_type) _KNOWN_FORMATS[mime_type] = format_name - (box,type_selector) = format_maker(format_list) + (box, type_selector) = format_maker(format_list) choose.set_extra_widget(box) # Suggested folder: try last open file, import, then last export, @@ -944,33 +979,33 @@ class ViewManager: if filetype == 'auto': try: filetype = Mime.get_type(filename) - except RuntimeError,msg: + except RuntimeError, msg: QuestionDialog.ErrorDialog( - _("Could not open file: %s") % filename, + _("Could not open file: %s") % filename, str(msg)) return False # First we try our best formats - if filetype in (const.app_gramps, - const.app_gramps_xml, + if filetype in (const.app_gramps, + const.app_gramps_xml, const.app_gedcom): - self._do_import(choose, - GrampsDb.gramps_db_reader_factory(filetype), + self._do_import(choose, + GrampsDb.gramps_db_reader_factory(filetype), filename) return True # Then we try all the known plugins - (the_path,the_file) = os.path.split(filename) + (the_path, the_file) = os.path.split(filename) Config.save_last_import_dir(the_path) - for (importData,mime_filter,mime_type, - native_format,format_name) in import_list: + for (importData, mime_filter, mime_type, + native_format, format_name) in import_list: if filetype == mime_type or the_file == mime_type: - self._do_import(choose,importData,filename) + self._do_import(choose, importData, filename) return True # Finally, we give up and declare this an unknown format QuestionDialog.ErrorDialog( - _("Could not open file: %s") % filename, + _("Could not open file: %s") % filename, _('File type "%s" is unknown to GRAMPS.\n\n' 'Valid types are: GRAMPS database, GRAMPS XML, ' 'GRAMPS package, and GEDCOM.') % filetype) @@ -978,36 +1013,36 @@ class ViewManager: choose.destroy() return False - def _do_import(self,dialog,importer,filename): + def _do_import(self, dialog, importer, filename): dialog.destroy() self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) self.progress.show() - importer(self.state.db,filename,self.uistate.pulse_progressbar) + importer(self.state.db, filename, self.uistate.pulse_progressbar) self.uistate.clear_history() self.progress.hide() self.window.window.set_cursor(None) def build_tools_menu(self): self.toolactions = gtk.ActionGroup('ToolWindow') - (ui,actions) = self.build_plugin_menu('ToolsMenu', - tool_list, - Tool.tool_categories, + (ui, actions) = self.build_plugin_menu('ToolsMenu', + tool_list, + Tool.tool_categories, make_tool_callback) self.toolactions.add_actions(actions) self.uistate.uimanager.add_ui_from_string(ui) - self.uimanager.insert_action_group(self.toolactions,1) + self.uimanager.insert_action_group(self.toolactions, 1) def build_report_menu(self): self.reportactions = gtk.ActionGroup('ReportWindow') - (ui,actions) = self.build_plugin_menu('ReportsMenu', - report_list, - Report.standalone_categories, + (ui, actions) = self.build_plugin_menu('ReportsMenu', + report_list, + Report.standalone_categories, make_report_callback) self.reportactions.add_actions(actions) self.uistate.uimanager.add_ui_from_string(ui) - self.uimanager.insert_action_group(self.reportactions,1) + self.uimanager.insert_action_group(self.reportactions, 1) - def build_plugin_menu(self,text,item_list,categories,func): + def build_plugin_menu(self, text, item_list, categories, func): actions = [] f = StringIO() f.write('' % text) @@ -1023,25 +1058,25 @@ class ViewManager: category = categories[item[3]] if hash_data.has_key(category): hash_data[category].append( - (item[0],item[1],item[2],item[4],item[3])) + (item[0], item[1], item[2], item[4], item[3])) else: hash_data[category] = [ - (item[0],item[1],item[2],item[4],item[3])] + (item[0], item[1], item[2], item[4], item[3])] # Sort categories, skipping the unsupported catlist = [item for item in hash_data.keys() if item != Plugins.UNSUPPORTED] catlist.sort() for key in catlist: - new_key = key.replace(' ','-') + new_key = key.replace(' ', '-') f.write('' % new_key) - actions.append((new_key,None,key)) + actions.append((new_key, None, key)) lst = hash_data[key] lst.sort(by_menu_name) for name in lst: - new_key = name[2].replace(' ','-') + new_key = name[2].replace(' ', '-') f.write('' % new_key) - actions.append((new_key,None,name[2],None,None, - func(name,self.state))) + actions.append((new_key, None, name[2], None, None, + func(name, self.state))) f.write('') # If there are any unsupported items we add separator @@ -1049,21 +1084,21 @@ class ViewManager: if hash_data.has_key(Plugins.UNSUPPORTED): f.write('') f.write('' % Plugins.UNSUPPORTED) - actions.append((Plugins.UNSUPPORTED,None,Plugins.UNSUPPORTED)) + actions.append((Plugins.UNSUPPORTED, None, Plugins.UNSUPPORTED)) lst = hash_data[key] lst.sort(by_menu_name) for name in lst: - new_key = name[2].replace(' ','-') + new_key = name[2].replace(' ', '-') f.write('' % new_key) - actions.append((new_key,None,name[2],None,None, - func(name,self.state))) + actions.append((new_key, None, name[2], None, None, + func(name, self.state))) f.write('') f.write('') - return (f.getvalue(),actions) + return (f.getvalue(), actions) -def by_menu_name(a,b): - return cmp(a[2],b[2]) +def by_menu_name(a, b): + return cmp(a[2], b[2]) def add_all_files_filter(chooser): """ @@ -1112,14 +1147,14 @@ def add_gedcom_filter(chooser): mime_filter.add_mime_type(const.app_gedcom) chooser.add_filter(mime_filter) -def make_report_callback(lst,dbstate): - return lambda x: Report.report(dbstate.db,dbstate.get_active_person(), - lst[0],lst[1],lst[2],lst[3],lst[4]) +def make_report_callback(lst, dbstate): + return lambda x: Report.report(dbstate.db, dbstate.get_active_person(), + lst[0], lst[1], lst[2], lst[3], lst[4]) -def make_tool_callback(lst,dbstate): - return lambda x: Tool.gui_tool(dbstate.db,dbstate.get_active_person(), - lst[0],lst[1],lst[2],lst[3],lst[4], - dbstate.db.request_rebuild,None) +def make_tool_callback(lst, dbstate): + return lambda x: Tool.gui_tool(dbstate.db, dbstate.get_active_person(), + lst[0], lst[1], lst[2], lst[3], lst[4], + dbstate.db.request_rebuild, None) #------------------------------------------------------------------------- # @@ -1129,17 +1164,17 @@ def make_tool_callback(lst,dbstate): class GrampsFormatWidget(gtk.ComboBox): def __init__(self): - gtk.ComboBox.__init__(self,model=None) + gtk.ComboBox.__init__(self, model=None) - def set(self,format_list): + def set(self, format_list): self.store = gtk.ListStore(str) self.set_model(self.store) cell = gtk.CellRendererText() - self.pack_start(cell,True) - self.add_attribute(cell,'text',0) + self.pack_start(cell, True) + self.add_attribute(cell, 'text', 0) self.format_list = format_list - for format,label in format_list: + for format, label in format_list: self.store.append(row=[label]) self.set_active(False) @@ -1157,10 +1192,10 @@ def format_maker(formats): The auto selection is always added as the first one. The returned box contains both the label and the selector. """ - format_list = [ ('auto',_('Automatically detected')) ] + format_list = [ ('auto', _('Automatically detected')) ] for format in formats: if _KNOWN_FORMATS.has_key(format): - format_list.append( (format,_KNOWN_FORMATS[format]) ) + format_list.append( (format, _KNOWN_FORMATS[format]) ) type_selector = GrampsFormatWidget() type_selector.set(format_list) @@ -1169,7 +1204,7 @@ def format_maker(formats): label = gtk.Label(_('Select file _type:')) label.set_use_underline(True) label.set_mnemonic_widget(type_selector) - box.pack_start(label,expand=False,fill=False,padding=6) + box.pack_start(label, expand=False, fill=False, padding=6) box.add(type_selector) box.show_all() - return (box,type_selector) + return (box, type_selector)