def __init__(self, dbstate, user, options_class, name, callback=None): uistate = user.uistate self.label = _("Gender Statistics tool") tool.Tool.__init__(self, dbstate, options_class, name) stats_list = [] for name, value in dbstate.db.genderStats.stats.items(): stats_list.append( (name,) + value + (_GENDER[dbstate.db.genderStats.guess_gender(name)],) ) if uistate: ManagedWindow.__init__(self, uistate, [], self.__class__) titles = [(_('Name'), 0, 100), (_('Male'), 1, 70, INTEGER), (_('Female'), 2, 70, INTEGER), (_('Unknown'), 3, 90, INTEGER), (_('Guess'), 4, 70)] treeview = Gtk.TreeView() model = ListModel(treeview, titles) for entry in sorted(stats_list): model.add(entry, entry[0]) s = Gtk.ScrolledWindow() s.add(treeview) dialog = Gtk.Dialog() dialog.add_button(_('_Close'), Gtk.ResponseType.CLOSE) dialog.connect('response', self._response) dialog.vbox.pack_start(s, expand=True, fill=True, padding=0) self.set_window(dialog, None, self.label) self.setup_configs('interface.dumpgenderstats', 420, 300) self.show() else: if len(_('Name')) < 16: print('%s%s%s' % (_('Name'), " " * (16 - len(_('Name'))), _('Male')), '\t%s'*3 % (_('Female'), _('Unknown'), _('Guess'))) else: print(_('Name'), '\t%s'*4 % (_('Male'), _('Female'), _('Unknown'), _('Guess'))) print() for entry in sorted(stats_list): if len(entry[0]) < 16: print('%s%s%s' % (entry[0], " " * (16 - len(entry[0])), entry[1]), '\t%s'*3 % (entry[2:])) else: print(entry[0], '\t%s'*4 % (entry[1:]))
class Backlinks(Gramplet): """ Displays the back references for an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = Gtk.TreeView() titles = [(_('Type'), 1, 100), (_('Name'), 2, 100), ('', 3, 1), #hidden column for the handle ('', 4, 1)] #hidden column for non-localized object type self.model = ListModel(top, titles, event_func=self.cb_double_click) return top def display_backlinks(self, active_handle): """ Display the back references for an object. """ for classname, handle in \ self.dbstate.db.find_backlink_handles(active_handle): name = navigation_label(self.dbstate.db, classname, handle)[0] self.model.add((_(classname), name, handle, classname)) self.set_has_data(self.model.count > 0) def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle is None: return False for handle in self.dbstate.db.find_backlink_handles(active_handle): return True return False def cb_double_click(self, treeview): """ Handle double click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() if not iter_: return (objclass, handle) = (model.get_value(iter_, 3), model.get_value(iter_, 2)) edit_object(self.dbstate, self.uistate, objclass, handle)
class Attributes(Gramplet): """ Displays the attributes of an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to view a quick report showing ' 'all people with the selected attribute.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [(_('Key'), 1, 100), (_('Value'), 2, 100)] self.model = ListModel(top, titles, event_func=self.display_report) return top def display_attributes(self, obj): """ Display the attributes of an object. """ for attr in obj.get_attribute_list(): self.model.add((str(attr.get_type()), attr.get_value())) self.set_has_data(self.model.count > 0) def display_report(self, treeview): """ Display the quick report for matching attribute key. """ model, iter_ = treeview.get_selection().get_selected() if iter_: key = model.get_value(iter_, 0) run_quick_report_by_name(self.dbstate, self.uistate, 'attribute_match', key) def get_has_data(self, obj): """ Return True if the gramplet has data, else return False. """ if obj is None: return False if obj.get_attribute_list(): return True return False
def __init__(self, dbstate, user, options_class, name, callback=None): uistate = user.uistate self.label = _("Associations state tool") tool.Tool.__init__(self, dbstate, options_class, name) if uistate: ManagedWindow.__init__(self,uistate,[], self.__class__) stats_list = [] plist = dbstate.db.get_person_handles(sort_handles=True) for handle in plist: person = dbstate.db.get_person_from_handle(handle) name1 = name_displayer.display(person) refs = person.get_person_ref_list() if refs: for ref in person.serialize()[-1]: (a, b, c, two, value) = ref person2 = dbstate.db.get_person_from_handle(two) name2 = name_displayer.display(person2) stats_list.append((name1, value, name2)) if uistate: titles = [ (_('Name'), 0, 200), (_('Type of link'), 1, 200), (_('Of'), 2, 200), ] treeview = Gtk.TreeView() model = ListModel(treeview, titles) for entry in stats_list: model.add(entry, entry[0]) window = Gtk.Window() window.set_default_size(800, 600) s = Gtk.ScrolledWindow() s.add(treeview) window.add(s) window.show_all() self.set_window(window, None, self.label) self.show() else: print('\t%s'*3 % ('Name','Type of link','Of')) print() for entry in stats_list: print('\t%s'*3 % entry)
def __init__(self, uistate, data, parent): super().__init__(uistate, [], self) self.window = Gtk.Dialog("Gramp") self.set_window(self.window, None, _("Database Information")) self.window.set_modal(True) self.ok = self.window.add_button(_("_OK"), Gtk.ResponseType.OK) self.ok.connect("clicked", self.on_ok_clicked) self.window.set_position(Gtk.WindowPosition.CENTER) self.window.set_default_size(600, 400) s = Gtk.ScrolledWindow() titles = [(_("Setting"), 0, 150), (_("Value"), 1, 400)] treeview = Gtk.TreeView() model = ListModel(treeview, titles) for key, value in sorted(data.items()): model.add((key, str(value)), key) s.add(treeview) self.window.vbox.pack_start(s, True, True, 0) self.show()
def __init__(self, dbstate, user, options_class, name, callback=None): uistate = user.uistate self.label = _("Gender Statistics tool") tool.Tool.__init__(self, dbstate, options_class, name) if uistate: ManagedWindow.__init__(self,uistate,[], self.__class__) stats_list = [] for name, value in dbstate.db.genderStats.stats.items(): stats_list.append( (name,) + value + (_GENDER[dbstate.db.genderStats.guess_gender(name)],) ) if uistate: titles = [ (_('Name'),0,100), (_('Male'),1,70,INTEGER), (_('Female'),2,70,INTEGER), (_('Unknown'),3,70,INTEGER), (_('Guess'),4,70) ] treeview = Gtk.TreeView() model = ListModel(treeview, titles) for entry in stats_list: model.add(entry, entry[0]) window = Gtk.Window() window.set_default_size(400, 300) s = Gtk.ScrolledWindow() s.add(treeview) window.add(s) window.show_all() self.set_window(window, None, self.label) self.show() else: print('\t%s'*5 % ('Name','Male','Female','Unknown','Guess')) print() for entry in stats_list: print('\t%s'*5 % entry)
def __init__(self, uistate, data, track): super().__init__(uistate, track, self, modal=True) self.window = Gtk.Dialog() self.set_window(self.window, None, _("Database Information")) self.setup_configs('interface.information', 600, 400) self.ok = self.window.add_button(_('_OK'), Gtk.ResponseType.OK) self.ok.connect('clicked', self.on_ok_clicked) s = Gtk.ScrolledWindow() titles = [ (_('Setting'), 0, 150), (_('Value'), 1, 400) ] treeview = Gtk.TreeView() model = ListModel(treeview, titles) for key, value in sorted(data.items()): model.add((key, str(value),), key) s.add(treeview) self.window.vbox.pack_start(s, True, True, 0) self.show()
class Attributes(Gramplet): """ Displays the attributes of an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the object containing the ' 'selected attribute.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [(_('Date'), 1, 100), ('', 1, 100), (_('Key'), 2, 100), (_('Value'), 3, 100), ('', NOSORT, 50,) ] self.model = ListModel(top, titles, event_func=self._display_editor) return top def add_attributes(self, obj, date_object=None): """ Add the attributes of an object to the model. """ event_date = event_sort = handle = '' if date_object is not None: event_date = gramps.gen.datehandler.displayer.display(date_object) event_sort = '%012d' % date_object.get_sort_value() try: handle = obj.get_handle() except AttributeError: handle = obj.ref for attr in obj.get_attribute_list(): self.model.add((event_date, event_sort, str(attr.get_type()), attr.get_value(), handle )) def display_attributes(self, obj): """ Display the attributes of an object. """ self.add_attributes(obj) for event_ref in obj.get_event_ref_list(): event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = event.get_date_object() self.add_attributes(event, event_date) self.add_attributes(event_ref, event_date) self.set_has_data(self.model.count > 0) def _display_editor(self, treeview): """ Display the appropriate editor window for the attribute. """ pass def get_has_data(self, obj): """ Return True if the gramplet has data, else return False. """ if obj is None: return False if obj.get_attribute_list(): return True for event_ref in obj.get_event_ref_list(): if event_ref.get_attribute_list(): return True return False def _get_event_ref(self, event): """ Return the event reference belonging to the active person or family for the given event. """ for event_ref in self.object_for_update.get_event_ref_list(): if event_ref.ref == event.get_handle(): return event_ref return None def _object_edited(self, ref, event): pass
class GeoEvents(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the events for a person or family. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'event-update': self.changed}) self.callman.connect_all(keys=['event']) def changed(self, handle): """ Called when a registered event is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Right-click on a row to edit the selected event' ' or the related place.') self.set_tooltip(tip) top = Gtk.TreeView() top.set_hover_selection(True) titles = [ ( '', NOSORT, 50, ), (_('Type'), 1, 100), (_('Description'), 2, 250), (_('Date'), 3, 160), ('', NOSORT, 50), (_('Place'), 4, 300), (_('Id'), 5, 80), (_('Latitude'), 6, 130), (_('Longitude'), 7, 130), ] self.model = ListModel(top, titles, right_click=self.menu_edit) return top def add_event_ref(self, event_ref, spouse=None, name=""): """ Add an event to the model. """ self.callman.register_handles({'event': [event_ref.ref]}) event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() place_name = place_displayer.display_event(self.dbstate.db, event) place_handle = event.get_place_handle() place_id = latitude = longitude = "" if place_handle: plc = self.dbstate.db.get_place_from_handle(place_handle) if plc: place_id = plc.get_gramps_id() latitude = plc.get_latitude() longitude = plc.get_longitude() latitude, longitude = conv_lat_lon(latitude, longitude, "D.D8") description = event.get_description() if description == "": description = name self.model.add((event.get_handle(), str(event.get_type()), description, event_date, event_sort, place_name, place_id, latitude, longitude)) def menu_edit(self, treeview, event): """ Show a menu to select either Edit the selected event or the Place related to this event. """ self.menu = Gtk.Menu() menu = self.menu menu.set_title(_('Edit')) title = _('Edit the event') add_item = Gtk.MenuItem(label=title) add_item.connect("activate", self.edit_event, treeview) add_item.show() menu.append(add_item) title = _('Edit the place') add_item = Gtk.MenuItem(label=title) add_item.connect("activate", self.edit_place, treeview) add_item.show() menu.append(add_item) menu.show() menu.popup(None, None, None, None, event.button, event.time) def edit_place(self, menuitem, treeview): """ Edit the place related to the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) place_handle = event.get_place_handle() place_id = latitude = longitude = "" if place_handle: plc = self.dbstate.db.get_place_from_handle(place_handle) EditPlace(self.dbstate, self.uistate, [], plc) except WindowActiveError: pass def edit_event(self, menuitem, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except WindowActiveError: pass
class ShowMatches(ManagedWindow): def __init__(self, dbstate, uistate, track, the_list, the_map, callback): ManagedWindow.__init__(self, uistate, track, self.__class__) self.dellist = {} self.list = the_list self.map = the_map self.length = len(self.list) self.update = callback self.db = dbstate.db self.dbstate = dbstate self.uistate = uistate top = Glade(toplevel="mergelist") window = top.toplevel self.set_window(window, top.get_object('title'), _('Potential Merges')) self.mlist = top.get_object("mlist") top.connect_signals({ "destroy_passed_object": self.close, "on_do_merge_clicked": self.on_do_merge_clicked, "on_help_show_clicked": self.on_help_clicked, "on_delete_show_event": self.close, "on_merge_ok_clicked": self.__dummy, "on_help_clicked": self.__dummy, "on_delete_merge_event": self.__dummy, "on_delete_event": self.__dummy, }) mtitles = [(_('Rating'), 3, 75), (_('First Person'), 1, 200), (_('Second Person'), 2, 200), ('', -1, 0)] self.list = ListModel(self.mlist, mtitles, event_func=self.on_do_merge_clicked) self.redraw() self.show() def build_menu_names(self, obj): return (_("Merge candidates"), None) def on_help_clicked(self, obj): """Display the relevant portion of GRAMPS manual""" display_help(WIKI_HELP_PAGE, WIKI_HELP_SEC) def redraw(self): list = [] for p1key, p1data in self.map.items(): if p1key in self.dellist: continue (p2key, c) = p1data if p1key == p2key: continue list.append((c, p1key, p2key)) self.list.clear() for (c, p1key, p2key) in list: c1 = "%5.2f" % c c2 = "%5.2f" % (100 - c) p1 = self.db.get_person_from_handle(p1key) p2 = self.db.get_person_from_handle(p2key) if not p1 or not p2: continue pn1 = name_displayer.display(p1) pn2 = name_displayer.display(p2) self.list.add([c1, pn1, pn2, c2], (p1key, p2key)) def on_do_merge_clicked(self, obj): store, iter = self.list.selection.get_selected() if not iter: return (self.p1, self.p2) = self.list.get_object(iter) MergePerson(self.dbstate, self.uistate, self.p1, self.p2, self.on_update, True) def on_update(self): if self.db.has_person_handle(self.p1): phoenix = self.p1 titanic = self.p2 else: phoenix = self.p2 titanic = self.p1 self.dellist[titanic] = phoenix for key, data in self.dellist.items(): if data == titanic: self.dellist[key] = phoenix self.update() self.redraw() def update_and_destroy(self, obj): self.update(1) self.close() def __dummy(self, obj): """dummy callback, needed because a shared glade file is used for both toplevel windows and all signals must be handled. """ pass
class Ancestor(Gramplet): def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ self.view = Gtk.TreeView() self.view.set_tooltip_column(3) titles = [(_('Name'), 0, 230), (_('Birth'), 2, 100), ('', NOSORT, 1), ('', NOSORT, 1), # tooltip ('', NOSORT, 100)] # handle self.model = ListModel(self.view, titles, list_mode="tree", event_func=self.cb_double_click) return self.view def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle: person = self.dbstate.db.get_person_from_handle(active_handle) if person: family_handle = person.get_main_parents_family_handle() family = self.dbstate.db.get_family_from_handle(family_handle) if family and (family.get_father_handle() or family.get_mother_handle()): return True return False def cb_double_click(self, treeview): """ Handle double click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() if not iter_: return try: handle = model.get_value(iter_, 4) person = self.dbstate.db.get_person_from_handle(handle) EditPerson(self.dbstate, self.uistate, [], person) except WindowActiveError: pass def db_changed(self): self.update() def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') if active_handle: self.set_has_data(self.get_has_data(active_handle)) else: self.set_has_data(False) def main(self): active_handle = self.get_active('Person') self.model.clear() if active_handle: self.add_to_tree(1, None, active_handle) self.view.expand_all() self.set_has_data(self.get_has_data(active_handle)) else: self.set_has_data(False) def add_to_tree(self, depth, parent_id, person_handle): if depth > config.get('behavior.generation-depth'): return person = self.dbstate.db.get_person_from_handle(person_handle) name = name_displayer.display(person) birth = get_birth_or_fallback(self.dbstate.db, person) death = get_death_or_fallback(self.dbstate.db, person) birth_text = birth_date = birth_sort = '' if birth: birth_date = get_date(birth) birth_sort = '%012d' % birth.get_date_object().get_sort_value() birth_text = _('%(abbr)s %(date)s') % \ {'abbr': birth.type.get_abbreviation(), 'date': birth_date} death_date = death_sort = death_text = '' if death: death_date = get_date(death) death_sort = '%012d' % death.get_date_object().get_sort_value() death_text = _('%(abbr)s %(date)s') % \ {'abbr': death.type.get_abbreviation(), 'date': death_date} tooltip = name + '\n' + birth_text + '\n' + death_text label = _('%(depth)s. %(name)s') % {'depth': depth, 'name': name} item_id = self.model.add([label, birth_date, birth_sort, tooltip, person_handle], node=parent_id) family_handle = person.get_main_parents_family_handle() family = self.dbstate.db.get_family_from_handle(family_handle) if family: if family.get_father_handle(): self.add_to_tree(depth + 1, item_id, family.get_father_handle()) if family.get_mother_handle(): self.add_to_tree(depth + 1, item_id, family.get_mother_handle()) return item_id
class ShowMatches(ManagedWindow): def __init__(self, dbstate, uistate, track, the_list, the_map, callback): ManagedWindow.__init__(self,uistate,track,self.__class__) self.dellist = {} self.list = the_list self.map = the_map self.length = len(self.list) self.update = callback self.db = dbstate.db self.dbstate = dbstate self.uistate = uistate top = Glade(toplevel="mergelist") window = top.toplevel self.set_window(window, top.get_object('title'), _('Potential Merges')) self.mlist = top.get_object("mlist") top.connect_signals({ "destroy_passed_object" : self.close, "on_do_merge_clicked" : self.on_do_merge_clicked, "on_help_show_clicked" : self.on_help_clicked, "on_delete_show_event" : self.close, "on_merge_ok_clicked" : self.__dummy, "on_help_clicked" : self.__dummy, "on_delete_merge_event" : self.__dummy, "on_delete_event" : self.__dummy, }) mtitles = [ (_('Rating'),3,75), (_('First Person'),1,200), (_('Second Person'),2,200), ('',-1,0) ] self.list = ListModel(self.mlist,mtitles, event_func=self.on_do_merge_clicked) self.redraw() self.show() def build_menu_names(self, obj): return (_("Merge candidates"),None) def on_help_clicked(self, obj): """Display the relevant portion of GRAMPS manual""" display_help(WIKI_HELP_PAGE , WIKI_HELP_SEC) def redraw(self): list = [] for p1key, p1data in self.map.items(): if p1key in self.dellist: continue (p2key,c) = p1data if p1key == p2key: continue list.append((c,p1key,p2key)) self.list.clear() for (c,p1key,p2key) in list: c1 = "%5.2f" % c c2 = "%5.2f" % (100-c) p1 = self.db.get_person_from_handle(p1key) p2 = self.db.get_person_from_handle(p2key) if not p1 or not p2: continue pn1 = name_displayer.display(p1) pn2 = name_displayer.display(p2) self.list.add([c1, pn1, pn2,c2],(p1key,p2key)) def on_do_merge_clicked(self, obj): store,iter = self.list.selection.get_selected() if not iter: return (self.p1,self.p2) = self.list.get_object(iter) MergePerson(self.dbstate, self.uistate, self.p1, self.p2, self.on_update, True) def on_update(self): if self.db.has_person_handle(self.p1): phoenix = self.p1 titanic = self.p2 else: phoenix = self.p2 titanic = self.p1 self.dellist[titanic] = phoenix for key, data in self.dellist.items(): if data == titanic: self.dellist[key] = phoenix self.update() self.redraw() def update_and_destroy(self, obj): self.update(1) self.close() def __dummy(self, obj): """dummy callback, needed because a shared glade file is used for both toplevel windows and all signals must be handled. """ pass
class FamilyChildren(Children): """ Displays the children of a family. """ def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected child.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Child'), 1, 250), (_('Birth Date'), 3, 100), ('', 3, 100), (_('Death Date'), 5, 100), ('', 5, 100)] self.model = ListModel(top, titles, event_func=self.edit_person) return top def db_changed(self): self.connect(self.dbstate.db, 'family-update', self.update) self.connect_signal('Family', self.update) # familiy active-changed self.connect(self.dbstate.db, 'person-update', self.update) def main(self): active_handle = self.get_active('Family') self.model.clear() if active_handle: family = self.dbstate.db.get_family_from_handle(active_handle) self.display_family(family) else: self.set_has_data(False) def update_has_data(self): active_handle = self.get_active('Family') if active_handle: active = self.dbstate.db.get_family_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) else: self.set_has_data(False) def get_has_data(self, active_family): """ Return True if the gramplet has data, else return False. """ if active_family is None: return False if active_family.get_child_ref_list(): return True return False def display_family(self, family): """ Display the children of given family. """ for child_ref in family.get_child_ref_list(): child = self.dbstate.db.get_person_from_handle(child_ref.ref) self.add_child(child) self.set_has_data(self.model.count > 0) def add_child(self, child): """ Add a child to the model. """ name = name_displayer.display(child) birth = get_birth_or_fallback(self.dbstate.db, child) birth_date, birth_sort, birth_place = self.get_date_place(birth) death = get_death_or_fallback(self.dbstate.db, child) death_date, death_sort, death_place = self.get_date_place(death) self.model.add((child.get_handle(), name, birth_date, birth_sort, death_date, death_sort))
class Ancestor(Gramplet): def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ self.view = Gtk.TreeView() self.view.set_tooltip_column(3) titles = [ (_('Name'), 0, 230), (_('Birth'), 2, 100), ('', NOSORT, 1), ('', NOSORT, 1), # tooltip ('', NOSORT, 100) ] # handle self.model = ListModel(self.view, titles, list_mode="tree", event_func=self.cb_double_click) return self.view def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle: person = self.dbstate.db.get_person_from_handle(active_handle) if person: family_handle = person.get_main_parents_family_handle() family = self.dbstate.db.get_family_from_handle(family_handle) if family and (family.get_father_handle() or family.get_mother_handle()): return True return False def cb_double_click(self, treeview): """ Handle double click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() if not iter_: return try: handle = model.get_value(iter_, 4) person = self.dbstate.db.get_person_from_handle(handle) EditPerson(self.dbstate, self.uistate, [], person) except WindowActiveError: pass def db_changed(self): self.update() def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') if active_handle: self.set_has_data(self.get_has_data(active_handle)) else: self.set_has_data(False) def main(self): active_handle = self.get_active('Person') self.model.clear() if active_handle: self.add_to_tree(1, None, active_handle) self.view.expand_all() self.set_has_data(self.get_has_data(active_handle)) else: self.set_has_data(False) def add_to_tree(self, depth, parent_id, person_handle): if depth > config.get('behavior.generation-depth'): return person = self.dbstate.db.get_person_from_handle(person_handle) name = name_displayer.display(person) birth = get_birth_or_fallback(self.dbstate.db, person) death = get_death_or_fallback(self.dbstate.db, person) birth_text = birth_date = birth_sort = '' if birth: birth_date = get_date(birth) birth_sort = '%012d' % birth.get_date_object().get_sort_value() birth_text = _('%(abbr)s %(date)s') % \ {'abbr': birth.type.get_abbreviation(), 'date': birth_date} death_date = death_sort = death_text = '' if death: death_date = get_date(death) death_sort = '%012d' % death.get_date_object().get_sort_value() death_text = _('%(abbr)s %(date)s') % \ {'abbr': death.type.get_abbreviation(), 'date': death_date} tooltip = name + '\n' + birth_text + '\n' + death_text label = _('%(depth)s. %(name)s') % {'depth': depth, 'name': name} item_id = self.model.add( [label, birth_date, birth_sort, tooltip, person_handle], node=parent_id) family_handle = person.get_main_parents_family_handle() family = self.dbstate.db.get_family_from_handle(family_handle) if family: if family.get_father_handle(): self.add_to_tree(depth + 1, item_id, family.get_father_handle()) if family.get_mother_handle(): self.add_to_tree(depth + 1, item_id, family.get_mother_handle()) return item_id
class PersonResidence(Gramplet): """ Displays residence events for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Date'), 1, 200), (_('Place'), 2, 200)] self.model = ListModel(top, titles, event_func=self.edit_event) return top def db_changed(self): self.dbstate.db.connect('person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) else: self.set_has_data(False) def get_has_data(self, active_person): """ Return True if the gramplet has data, else return False. """ if active_person: for event_ref in active_person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if int(event.get_type()) == EventType.RESIDENCE: return True return False def main(self): # return false finishes self.model.clear() active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) if active_person: self.display_person(active_person) else: self.set_has_data(False) else: self.set_has_data(False) def display_person(self, active_person): """ Display the residence events of the active person. """ count = 0 for event_ref in active_person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if int(event.get_type()) == EventType.RESIDENCE: self.add_residence(event) count += 1 self.set_has_data(count > 0) def add_residence(self, event): """ Add a residence event to the model. """ date = get_date(event) place = '' handle = event.get_place_handle() if handle: place = place_displayer.display_event(self.dbstate.db, event) self.model.add((event.get_handle(), date, place)) def edit_event(self, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except WindowActiveError: pass
class Attributes(Gramplet): """ Displays the attributes of an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the object containing the ' 'selected attribute.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [(_('Date'), 1, 100), ('', 1, 100), (_('Key'), 2, 100), (_('Value'), 3, 100), ( '', NOSORT, 50, )] self.model = ListModel(top, titles, event_func=self._display_editor) return top def add_attributes(self, obj, date_object=None): """ Add the attributes of an object to the model. """ event_date = event_sort = handle = '' if date_object is not None: event_date = gramps.gen.datehandler.displayer.display(date_object) event_sort = '%012d' % date_object.get_sort_value() try: handle = obj.get_handle() except AttributeError: handle = obj.ref for attr in obj.get_attribute_list(): self.model.add((event_date, event_sort, str(attr.get_type()), attr.get_value(), handle)) def display_attributes(self, obj): """ Display the attributes of an object. """ self.add_attributes(obj) for event_ref in obj.get_event_ref_list(): event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = event.get_date_object() self.add_attributes(event, event_date) self.add_attributes(event_ref, event_date) self.set_has_data(self.model.count > 0) def _display_editor(self, treeview): """ Display the appropriate editor window for the attribute. """ pass def get_has_data(self, obj): """ Return True if the gramplet has data, else return False. """ if obj is None: return False if obj.get_attribute_list(): return True for event_ref in obj.get_event_ref_list(): if event_ref.get_attribute_list(): return True return False def _get_event_ref(self, event): """ Return the event reference belonging to the active person or family for the given event. """ for event_ref in self.object_for_update.get_event_ref_list(): if event_ref.ref == event.get_handle(): return event_ref return None def _object_edited(self, ref, event): pass
class PersonChildren(Children): """ Displays the children of a person. """ def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected child.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Child'), 1, 250), (_('Birth Date'), 3, 100), ('', 3, 100), (_('Death Date'), 5, 100), ('', 5, 100), (_('Spouse'), 6, 250)] self.model = ListModel(top, titles, event_func=self.edit_person) return top def db_changed(self): self.dbstate.db.connect('person-update', self.update) def active_changed(self, handle): self.update() def main(self): active_handle = self.get_active('Person') self.model.clear() if active_handle: self.display_person(active_handle) else: self.set_has_data(False) def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) else: self.set_has_data(False) def get_has_data(self, active_person): """ Return True if the gramplet has data, else return False. """ if active_person is None: return False for family_handle in active_person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(family_handle) if family and family.get_child_ref_list(): return True return False def display_person(self, active_handle): """ Display the children of the active person. """ active_person = self.dbstate.db.get_person_from_handle(active_handle) for family_handle in active_person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(family_handle) self.display_family(family, active_person) self.set_has_data(self.model.count > 0) def display_family(self, family, active_person): """ Display the children of given family. """ spouse_handle = find_spouse(active_person, family) if spouse_handle: spouse = self.dbstate.db.get_person_from_handle(spouse_handle) else: spouse = None for child_ref in family.get_child_ref_list(): child = self.dbstate.db.get_person_from_handle(child_ref.ref) self.add_child(child, spouse) def add_child(self, child, spouse): """ Add a child to the model. """ name = name_displayer.display(child) if spouse: spouse = name_displayer.display(spouse) spouse = spouse or '' birth = get_birth_or_fallback(self.dbstate.db, child) birth_date, birth_sort, birth_place = self.get_date_place(birth) death = get_death_or_fallback(self.dbstate.db, child) death_date, death_sort, death_place = self.get_date_place(death) self.model.add((child.get_handle(), name, birth_date, birth_sort, death_date, death_sort, spouse))
class Citations(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the citations for an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'citation-update': self.changed, 'person-update': self.changed, 'family-update': self.changed, 'event-update': self.changed, 'media-update': self.changed, 'place-update': self.changed}) self.callman.connect_all(keys=['citation', 'family', 'person', 'event', 'media', 'place']) def changed(self, handle): """ Called when a registered citation is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected source/citation.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Source/Citation'), 1, 350), (_('Author'), 2, 200), (_('Publisher'), 3, 150)] self.model = ListModel(top, titles, list_mode="tree", event_func=self.invoke_editor) return top def add_citations(self, obj): for citation_handle in obj.get_citation_list(): self.add_citation_ref(citation_handle) def add_name_citations(self, obj): names = [obj.get_primary_name()] + obj.get_alternate_names() for name in names: self.add_citations(name) def add_attribute_citations(self, obj): for attr in obj.get_attribute_list(): self.add_citations(attr) def add_mediaref_citations(self, obj): for media_ref in obj.get_media_list(): self.add_citations(media_ref) self.add_attribute_citations(media_ref) media = self.dbstate.db.get_media_from_handle(media_ref.ref) self.add_media_citations(media) def add_media_citations(self, media): self.callman.register_handles({'media': [media.handle]}) self.add_citations(media) self.add_attribute_citations(media) def add_eventref_citations(self, obj): for event_ref in obj.get_event_ref_list(): self.add_attribute_citations(event_ref) event = self.dbstate.db.get_event_from_handle(event_ref.ref) self.add_event_citations(event) def add_event_citations(self, event): self.callman.register_handles({'event': [event.handle]}) self.add_citations(event) self.add_attribute_citations(event) self.add_mediaref_citations(event) place_handle = event.get_place_handle() if place_handle: place = self.dbstate.db.get_place_from_handle(place_handle) if place: self.add_place_citations(place) def add_place_citations(self, place): self.callman.register_handles({'place': [place.handle]}) self.add_citations(place) self.add_mediaref_citations(place) def add_address_citations(self, obj): for address in obj.get_address_list(): self.add_citations(address) def add_lds_citations(self, obj): for lds in obj.get_lds_ord_list(): self.add_citations(lds) place_handle = lds.get_place_handle() if place_handle: place = self.dbstate.db.get_place_from_handle(place_handle) if place: self.add_place_citations(place) def add_association_citations(self, obj): for assoc in obj.get_person_ref_list(): self.add_citations(assoc) def add_citation_ref(self, citation_handle): """ Add a citation to the model. """ self.callman.register_handles({'citation': [citation_handle]}) citation = self.dbstate.db.get_citation_from_handle(citation_handle) page = citation.get_page() if not page: page = _('<No Citation>') source_handle = citation.get_reference_handle() source = self.dbstate.db.get_source_from_handle(source_handle) title = source.get_title() author = source.get_author() publisher = source.get_publication_info() if source_handle not in self.source_nodes: node = self.model.add([source_handle, title, author, publisher]) self.source_nodes[source_handle] = node self.model.add([citation_handle, page, '', ''], node=self.source_nodes[source_handle]) def check_citations(self, obj): return True if obj.get_citation_list() else False def check_name_citations(self, obj): names = [obj.get_primary_name()] + obj.get_alternate_names() for name in names: if self.check_citations(name): return True return False def check_attribute_citations(self, obj): for attr in obj.get_attribute_list(): if self.check_citations(attr): return True return False def check_mediaref_citations(self, obj): for media_ref in obj.get_media_list(): if self.check_citations(media_ref): return True if self.check_attribute_citations(media_ref): return True media = self.dbstate.db.get_media_from_handle(media_ref.ref) if self.check_media_citations(media): return True return False def check_media_citations(self, media): if self.check_citations(media): return True if self.check_attribute_citations(media): return True return False def check_eventref_citations(self, obj): if obj: for event_ref in obj.get_event_ref_list(): if self.check_attribute_citations(event_ref): return True event = self.dbstate.db.get_event_from_handle(event_ref.ref) if self.check_event_citations(event): return True return False def check_event_citations(self, event): if self.check_citations(event): return True if self.check_attribute_citations(event): return True if self.check_mediaref_citations(event): return True place_handle = event.get_place_handle() if place_handle: place = self.dbstate.db.get_place_from_handle(place_handle) if place and self.check_place_citations(place): return True return False def check_place_citations(self, place): if self.check_citations(place): return True if self.check_mediaref_citations(place): return True return False def check_address_citations(self, obj): for address in obj.get_address_list(): if self.check_citations(address): return True return False def check_lds_citations(self, obj): for lds in obj.get_lds_ord_list(): if self.check_citations(lds): return True place_handle = lds.get_place_handle() if place_handle: place = self.dbstate.db.get_place_from_handle(place_handle) if place and self.check_place_citations(place): return True return False def check_association_citations(self, obj): for assoc in obj.get_person_ref_list(): if self.check_citations(assoc): return True return False def invoke_editor(self, treeview): """ Edit the selected source or citation. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) # bug 9094. # str(model.get_path(iter_)) return something like NNN:MMM # So if we have only NNN, it's a node # removing the str() solves the problem. if len(model.get_path(iter_)) == 1: self.edit_source(handle) else: self.edit_citation(handle) def edit_source(self, handle): """ Edit the selected source. """ try: source = self.dbstate.db.get_source_from_handle(handle) EditSource(self.dbstate, self.uistate, [], source) except WindowActiveError: pass def edit_citation(self, handle): """ Edit the selected citation. """ try: citation = self.dbstate.db.get_citation_from_handle(handle) source_handle = citation.get_reference_handle() source = self.dbstate.db.get_source_from_handle(source_handle) EditCitation(self.dbstate, self.uistate, [], citation, source) except WindowActiveError: pass
class Events(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the events for a person or family. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'event-update': self.changed}) self.callman.connect_all(keys=['event']) def changed(self, handle): """ Called when a registered event is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [( '', NOSORT, 50, ), (_('Type'), 1, 100), (_('Description'), 2, 150), (_('Date'), 3, 100), ('', NOSORT, 50), (_('Age'), 4, 100), ('', NOSORT, 50), (_('Place'), 5, 400), (_('Main Participants'), 6, 200), (_('Role'), 7, 100)] self.model = ListModel(top, titles, event_func=self.edit_event) return top def add_event_ref(self, event_ref, spouse=None): """ Add an event to the model. """ self.callman.register_handles({'event': [event_ref.ref]}) event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() person_age = self.column_age(event) person_age_sort = self.column_sort_age(event) place = place_displayer.display_event(self.dbstate.db, event) participants = get_participant_from_event(self.dbstate.db, event_ref.ref) self.model.add((event.get_handle(), str(event.get_type()), event.get_description(), event_date, event_sort, person_age, person_age_sort, place, participants, str(event_ref.get_role()))) def column_age(self, event): """ Returns a string representation of age in years. Change precision=2 for "year, month", or precision=3 for "year, month, days" """ date = event.get_date_object() start_date = self.cached_start_date if date and start_date: return (date - start_date).format(precision=age_precision) else: return "" def column_sort_age(self, event): """ Returns a string version of number of days of age. """ date = event.get_date_object() start_date = self.cached_start_date if date and start_date: return "%09d" % int(date - start_date) else: return "" def edit_event(self, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except WindowActiveError: pass
class Participants(Gramplet, DbGUIElement): """ Displays the participants of an event. """ def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'person-update': self.changed, 'event-update': self.changed}) self.callman.connect_all(keys=['person', 'event']) #self.dbstate.db.connect('person-update', self.update) self.connect_signal('Event', self.update) def changed(self, handle): """ Called when a registered person is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected participant.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Name'), 1, 250), (_('Role'), 2, 80), (_('Birth Date'), 3, 100), ('', 3, 100), (_('Spouses'), 4, 200)] self.model = ListModel(top, titles, event_func=self.edit_person) return top def display_participants(self, active_handle): """ Display the participants of an event. """ for classname, handle in \ self.dbstate.db.find_backlink_handles(active_handle): if classname == 'Person': self.display_person(handle, active_handle) elif classname == 'Family': self.display_family(handle, active_handle) self.set_has_data(self.model.count > 0) def display_person(self, handle, event_handle): """ Display a participant in the event. """ person = self.dbstate.db.get_person_from_handle(handle) role = self.get_role(person, event_handle) self.add_person(person, role) def display_family(self, handle, event_handle): """ Display a participant in the event. """ family = self.dbstate.db.get_family_from_handle(handle) role = self.get_role(family, event_handle) mother_handle = family.get_mother_handle() mother = self.dbstate.db.get_person_from_handle(mother_handle) self.add_person(mother, role) father_handle = family.get_father_handle() father = self.dbstate.db.get_person_from_handle(father_handle) self.add_person(father, role) def add_person(self, person, role): """ Add a person to the model. """ self.callman.register_handles({'person': [person.get_handle()]}) name = displayer.display(person) spouses = self.get_spouses(person) birth = get_birth_or_fallback(self.dbstate.db, person) self.callman.register_handles({'event': [birth.get_handle()]}) birth_date, birth_sort, birth_place = self.get_date_place(birth) self.model.add((person.get_handle(), name, role, birth_date, birth_sort, spouses)) def get_role(self, obj, event_handle): """ Get the role of a person or family in an event. """ for event_ref in obj.get_event_ref_list(): if event_ref.ref == event_handle: return str(event_ref.get_role()) return None def get_spouses(self, person): """ Get the spouses of a given person. """ spouses = [] for handle in person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(handle) father_handle = family.get_father_handle() if father_handle and father_handle != person.get_handle(): self.callman.register_handles({'person': [father_handle]}) father = self.dbstate.db.get_person_from_handle(father_handle) spouses.append(displayer.display(father)) mother_handle = family.get_mother_handle() if mother_handle and mother_handle != person.get_handle(): self.callman.register_handles({'person': [mother_handle]}) mother = self.dbstate.db.get_person_from_handle(mother_handle) spouses.append(displayer.display(mother)) return ' | '.join(spouses) def get_date_place(self, event): """ Return the date and place of the given event. """ event_date = '' event_place = '' event_sort = '%012d' % 0 if event: event_date = get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() handle = event.get_place_handle() if handle: place = self.dbstate.db.get_place_from_handle(handle) event_place = place.get_title() return (event_date, event_sort, event_place) def edit_person(self, treeview): """ Edit the selected child. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: person = self.dbstate.db.get_person_from_handle(handle) EditPerson(self.dbstate, self.uistate, [], person) except WindowActiveError: pass def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle is None: return False for handle in self.dbstate.db.find_backlink_handles(active_handle): return True return False def update_has_data(self): active_handle = self.get_active('Event') self.set_has_data(self.get_has_data(active_handle)) def main(self): active_handle = self.get_active('Event') self.model.clear() self.callman.unregister_all() if active_handle: self.display_participants(active_handle) else: self.set_has_data(False)
class GeoEvents(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the events for a person or family. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'event-update': self.changed}) self.callman.connect_all(keys=['event']) def changed(self, handle): """ Called when a registered event is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Right-click on a row to edit the selected event' ' or the related place.') self.set_tooltip(tip) top = Gtk.TreeView() top.set_hover_selection(True) titles = [('', NOSORT, 50,), (_('Type'), 1, 100), (_('Description'), 2, 250), (_('Date'), 3, 160), ('', NOSORT, 50), (_('Place'), 4, 300), (_('Id'), 5, 80), (_('Latitude'), 6, 130), (_('Longitude'), 7, 130), ] self.model = ListModel(top, titles, right_click=self.menu_edit) return top def add_event_ref(self, event_ref, spouse=None, name=""): """ Add an event to the model. """ self.callman.register_handles({'event': [event_ref.ref]}) event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() place_name = place_displayer.display_event(self.dbstate.db, event) place_handle = event.get_place_handle() place_id = latitude = longitude = "" if place_handle: plc = self.dbstate.db.get_place_from_handle(place_handle) if plc: place_id = plc.get_gramps_id() latitude = plc.get_latitude() longitude = plc.get_longitude() latitude, longitude = conv_lat_lon(latitude, longitude, "D.D8") description = event.get_description() if description == "": description = name self.model.add((event.get_handle(), str(event.get_type()), description, event_date, event_sort, place_name, place_id, latitude, longitude )) def menu_edit(self, treeview, event): """ Show a menu to select either Edit the selected event or the Place related to this event. """ self.menu = Gtk.Menu() menu = self.menu menu.set_title(_('Edit')) title = _('Edit the event') add_item = Gtk.MenuItem(label=title) add_item.connect("activate", self.edit_event, treeview) add_item.show() menu.append(add_item) title = _('Edit the place') add_item = Gtk.MenuItem(label=title) add_item.connect("activate", self.edit_place, treeview) add_item.show() menu.append(add_item) menu.show() menu.popup(None, None, None, None, event.button, event.time) def edit_place(self, menuitem, treeview): """ Edit the place related to the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) place_handle = event.get_place_handle() place_id = latitude = longitude = "" if place_handle: plc = self.dbstate.db.get_place_from_handle(place_handle) EditPlace(self.dbstate, self.uistate, [], plc) except WindowActiveError: pass def edit_event(self, menuitem, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except WindowActiveError: pass
class MetadataView(Gtk.TreeView): def __init__(self): Gtk.TreeView.__init__(self) self.sections = {} titles = [(_('Key'), 1, 235), (_('Value'), 2, 325)] self.model = ListModel(self, titles, list_mode="tree") def display_exif_tags(self, full_path): """ Display the exif tags. """ self.sections = {} self.model.clear() if not os.path.exists(full_path): return False retval = False with open(full_path, 'rb') as fd: try: buf = fd.read() metadata = GExiv2.Metadata() metadata.open_buf(buf) get_human = metadata.get_tag_interpreted_string for section, key, key2, func in TAGS: if not key in metadata.get_exif_tags(): continue if func is not None: if key2 is None: human_value = func(metadata[key]) else: if key2 in metadata.get_exif_tags(): human_value = func(metadata[key], metadata[key2]) else: human_value = func(metadata[key], None) else: human_value = get_human(key) if key2 in metadata.get_exif_tags(): human_value += ' ' + get_human(key2) label = metadata.get_tag_label(key) node = self.__add_section(section) if human_value is None: human_value = '' self.model.add((label, human_value), node=node) self.model.tree.expand_all() retval = self.model.count > 0 except: pass return retval def __add_section(self, section): """ Add the section heading node to the model. """ if section not in self.sections: node = self.model.add([section, '']) self.sections[section] = node else: node = self.sections[section] return node def get_has_data(self, full_path): """ Return True if the gramplet has data, else return False. """ if not os.path.exists(full_path): return False with open(full_path, 'rb') as fd: retval = False try: buf = fd.read() metadata = GExiv2.Metadata() metadata.open_buf(buf) for tag in TAGS: if tag in metadata.get_exif_tags(): retval = True break except: pass return retval
class Locations(Gramplet, DbGUIElement): """ Gramplet showing the locations of a place over time. """ def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'place-update': self.changed}) self.callman.connect_all(keys=['place']) def db_changed(self): self.connect_signal('Place', self.update) def changed(self, handle): """ Called when a registered place is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected place.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', 0, 50), (_('Name'), 1, 300), (_('Type'), 2, 150), (_('Date'), 4, 150), ('', NOSORT, 50)] self.model = ListModel(top, titles, list_mode="tree", event_func=self.edit_place) return top def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Place') if active_handle: active = self.dbstate.db.get_place_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) else: self.set_has_data(False) def get_has_data(self, place): """ Return True if the gramplet has data, else return False. """ pass def main(self): self.model.clear() self.callman.unregister_all() active_handle = self.get_active('Place') if active_handle: active = self.dbstate.db.get_place_from_handle(active_handle) if active: self.display_place(active, None, [active_handle]) else: self.set_has_data(False) else: self.set_has_data(False) def display_place(self, place, node, visited): """ Display the location hierarchy for the active place. """ pass def add_place(self, placeref, place, node, visited): """ Add a place to the model. """ place_date = get_date(placeref) place_sort = '%012d' % placeref.get_date_object().get_sort_value() place_name = place.get_name().get_value() place_type = str(place.get_type()) new_node = self.model.add([place.handle, place_name, place_type, place_date, place_sort], node=node) self.display_place(place, new_node, visited + [place.handle]) def edit_place(self, treeview): """ Edit the selected place. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) place = self.dbstate.db.get_place_from_handle(handle) try: EditPlace(self.dbstate, self.uistate, [], place) except WindowActiveError: pass
class Citations(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the citations for an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'citation-update': self.changed}) self.callman.connect_all(keys=['citation']) def changed(self, handle): """ Called when a registered citation is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected source/citation.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Source/Citation'), 1, 350), (_('Author'), 2, 200), (_('Publisher'), 3, 150)] self.model = ListModel(top, titles, list_mode="tree", event_func=self.invoke_editor) return top def add_citations(self, obj): for citation_handle in obj.get_citation_list(): self.add_citation_ref(citation_handle) def add_name_citations(self, obj): names = [obj.get_primary_name()] + obj.get_alternate_names() for name in names: self.add_citations(name) def add_attribute_citations(self, obj): for attr in obj.get_attribute_list(): self.add_citations(attr) def add_mediaref_citations(self, obj): for media_ref in obj.get_media_list(): self.add_citations(media_ref) self.add_attribute_citations(media_ref) media = self.dbstate.db.get_media_from_handle(media_ref.ref) self.add_media_citations(media) def add_media_citations(self, media): self.add_citations(media) self.add_attribute_citations(media) def add_eventref_citations(self, obj): for event_ref in obj.get_event_ref_list(): self.add_attribute_citations(event_ref) event = self.dbstate.db.get_event_from_handle(event_ref.ref) self.add_event_citations(event) def add_event_citations(self, event): self.add_citations(event) self.add_attribute_citations(event) self.add_mediaref_citations(event) place_handle = event.get_place_handle() if place_handle: place = self.dbstate.db.get_place_from_handle(place_handle) if place: self.add_place_citations(place) def add_place_citations(self, place): self.add_citations(place) self.add_mediaref_citations(place) def add_address_citations(self, obj): for address in obj.get_address_list(): self.add_citations(address) def add_lds_citations(self, obj): for lds in obj.get_lds_ord_list(): self.add_citations(lds) place_handle = lds.get_place_handle() place = self.dbstate.db.get_place_from_handle(place_handle) if place: self.add_place_citations(place) def add_association_citations(self, obj): for assoc in obj.get_person_ref_list(): self.add_citations(assoc) def add_citation_ref(self, citation_handle): """ Add a citation to the model. """ self.callman.register_handles({'citation': [citation_handle]}) citation = self.dbstate.db.get_citation_from_handle(citation_handle) page = citation.get_page() if not page: page = _('<No Citation>') source_handle = citation.get_reference_handle() source = self.dbstate.db.get_source_from_handle(source_handle) title = source.get_title() author = source.get_author() publisher = source.get_publication_info() if source_handle not in self.source_nodes: node = self.model.add([source_handle, title, author, publisher]) self.source_nodes[source_handle] = node self.model.add([citation_handle, page, '', ''], node=self.source_nodes[source_handle]) def check_citations(self, obj): return True if obj.get_citation_list() else False def check_name_citations(self, obj): names = [obj.get_primary_name()] + obj.get_alternate_names() for name in names: if self.check_citations(name): return True return False def check_attribute_citations(self, obj): for attr in obj.get_attribute_list(): if self.check_citations(attr): return True return False def check_mediaref_citations(self, obj): for media_ref in obj.get_media_list(): if self.check_citations(media_ref): return True if self.check_attribute_citations(media_ref): return True media = self.dbstate.db.get_media_from_handle(media_ref.ref) if self.check_media_citations(media): return True return False def check_media_citations(self, media): if self.check_citations(media): return True if self.check_attribute_citations(media): return True return False def check_eventref_citations(self, obj): if obj: for event_ref in obj.get_event_ref_list(): if self.check_attribute_citations(event_ref): return True event = self.dbstate.db.get_event_from_handle(event_ref.ref) if self.check_event_citations(event): return True return False def check_event_citations(self, event): if self.check_citations(event): return True if self.check_attribute_citations(event): return True if self.check_mediaref_citations(event): return True place_handle = event.get_place_handle() if place_handle: place = self.dbstate.db.get_place_from_handle(place_handle) if place and self.check_place_citations(place): return True return False def check_place_citations(self, place): if self.check_citations(place): return True if self.check_mediaref_citations(place): return True return False def check_address_citations(self, obj): for address in obj.get_address_list(): if self.check_citations(address): return True return False def check_lds_citations(self, obj): for lds in obj.get_lds_ord_list(): if self.check_citations(lds): return True place_handle = lds.get_place_handle() place = self.dbstate.db.get_place_from_handle(place_handle) if place and self.check_place_citations(place): return True return False def check_association_citations(self, obj): for assoc in obj.get_person_ref_list(): if self.check_citations(assoc): return True return False def invoke_editor(self, treeview): """ Edit the selected source or citation. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) # bug 9094. # str(model.get_path(iter_)) return something like NNN:MMM # So if we have only NNN, it's a node # removing the str() solves the problem. if len(model.get_path(iter_)) == 1: self.edit_source(handle) else: self.edit_citation(handle) def edit_source(self, handle): """ Edit the selected source. """ try: source = self.dbstate.db.get_source_from_handle(handle) EditSource(self.dbstate, self.uistate, [], source) except WindowActiveError: pass def edit_citation(self, handle): """ Edit the selected citation. """ try: citation = self.dbstate.db.get_citation_from_handle(handle) source_handle = citation.get_reference_handle() source = self.dbstate.db.get_source_from_handle(source_handle) EditCitation(self.dbstate, self.uistate, [], citation, source) except WindowActiveError: pass
class Participants(Gramplet, DbGUIElement): """ Displays the participants of an event. """ def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({ 'person-update': self.changed, 'event-update': self.changed }) self.callman.connect_all(keys=['person', 'event']) #self.dbstate.db.connect('person-update', self.update) self.connect_signal('Event', self.update) def changed(self, handle): """ Called when a registered person is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected participant.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [( '', NOSORT, 50, ), (_('Name'), 1, 250), (_('Role'), 2, 80), (_('Birth Date'), 3, 100), ('', 3, 100), (_('Spouses'), 4, 200)] self.model = ListModel(top, titles, event_func=self.edit_person) return top def display_participants(self, active_handle): """ Display the participants of an event. """ for classname, handle in \ self.dbstate.db.find_backlink_handles(active_handle): if classname == 'Person': self.display_person(handle, active_handle) elif classname == 'Family': self.display_family(handle, active_handle) self.set_has_data(self.model.count > 0) def display_person(self, handle, event_handle): """ Display a participant in the event. """ person = self.dbstate.db.get_person_from_handle(handle) role = self.get_role(person, event_handle) self.add_person(person, role) def display_family(self, handle, event_handle): """ Display a participant in the event. """ family = self.dbstate.db.get_family_from_handle(handle) role = self.get_role(family, event_handle) mother_handle = family.get_mother_handle() if mother_handle: mother = self.dbstate.db.get_person_from_handle(mother_handle) self.add_person(mother, role) father_handle = family.get_father_handle() if father_handle: father = self.dbstate.db.get_person_from_handle(father_handle) self.add_person(father, role) def add_person(self, person, role): """ Add a person to the model. """ self.callman.register_handles({'person': [person.get_handle()]}) name = displayer.display(person) spouses = self.get_spouses(person) birth = get_birth_or_fallback(self.dbstate.db, person) if birth: self.callman.register_handles({'event': [birth.get_handle()]}) birth_date, birth_sort, birth_place = self.get_date_place(birth) self.model.add( (person.get_handle(), name, role, birth_date, birth_sort, spouses)) def get_role(self, obj, event_handle): """ Get the role of a person or family in an event. """ for event_ref in obj.get_event_ref_list(): if event_ref.ref == event_handle: return str(event_ref.get_role()) return None def get_spouses(self, person): """ Get the spouses of a given person. """ spouses = [] for handle in person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(handle) father_handle = family.get_father_handle() if father_handle and father_handle != person.get_handle(): self.callman.register_handles({'person': [father_handle]}) father = self.dbstate.db.get_person_from_handle(father_handle) spouses.append(displayer.display(father)) mother_handle = family.get_mother_handle() if mother_handle and mother_handle != person.get_handle(): self.callman.register_handles({'person': [mother_handle]}) mother = self.dbstate.db.get_person_from_handle(mother_handle) spouses.append(displayer.display(mother)) return ' | '.join(spouses) def get_date_place(self, event): """ Return the date and place of the given event. """ event_date = '' event_place = '' event_sort = '%012d' % 0 if event: event_date = get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() event_place = place_displayer.display_event(self.dbstate.db, event) return (event_date, event_sort, event_place) def edit_person(self, treeview): """ Edit the selected child. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: person = self.dbstate.db.get_person_from_handle(handle) EditPerson(self.dbstate, self.uistate, [], person) except WindowActiveError: pass def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle is None: return False for handle in self.dbstate.db.find_backlink_handles(active_handle): return True return False def update_has_data(self): active_handle = self.get_active('Event') self.set_has_data(self.get_has_data(active_handle)) def main(self): active_handle = self.get_active('Event') self.model.clear() self.callman.unregister_all() if active_handle: self.display_participants(active_handle) else: self.set_has_data(False)
class MediaBrowser(Gramplet): """ Displays an object tree and a media preview for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = Gtk.HBox() self.photo = Photo() self.photo.show() view = Gtk.TreeView() titles = [(_("Object"), 1, 250)] self.model = ListModel(view, titles, list_mode="tree", select_func=self.row_selected) top.pack_start(view, True, True, 0) top.pack_start(self.photo, True, False, 5) top.show_all() return top def db_changed(self): self.dbstate.db.connect("person-update", self.update) self.update() def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active("Person") active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) def main(self): active_handle = self.get_active("Person") active = self.dbstate.db.get_person_from_handle(active_handle) self.model.clear() self.photo.set_image(None) if active: self.display_data(active) else: self.set_has_data(False) def display_data(self, person): """ Display the object tree for the active person. """ self.add_media(person) self.add_events(person) self.add_sources(person) self.set_has_data(self.model.count > 0) def add_events(self, obj, parent_node=None): """ Add event nodes to the model. """ for event_ref in obj.get_event_ref_list(): handle = event_ref.ref name, event = navigation_label(self.dbstate.db, "Event", handle) node = self.model.add([name], node=parent_node) self.add_sources(event, node) self.add_media(event, node) def add_sources(self, obj, parent_node=None): """ Add source nodes to the model. """ for citation_handle in obj.get_citation_list(): citation = self.dbstate.db.get_citation_from_handle(citation_handle) handle = citation.get_reference_handle() name, src = navigation_label(self.dbstate.db, "Source", handle) node = self.model.add([name], node=parent_node) self.add_media(src, node) def add_media(self, obj, parent_node=None): """ Add media object nodes to the model. """ for media_ref in obj.get_media_list(): handle = media_ref.ref name, media = navigation_label(self.dbstate.db, "Media", handle) full_path = media_path_full(self.dbstate.db, media.get_path()) rect = media_ref.get_rectangle() self.model.add([name], info=media_ref, node=parent_node) def row_selected(self, selection): """ Change the image when a row is selected. """ selected = self.model.get_selected_objects() if selected: if selected[0]: self.load_image(selected[0]) else: self.photo.set_image(None) else: self.photo.set_image(None) def load_image(self, media_ref): """ Display an image from the given media reference. """ media = self.dbstate.db.get_object_from_handle(media_ref.ref) full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() rectangle = media_ref.get_rectangle() self.photo.set_image(full_path, mime_type, rectangle) def get_has_data(self, person): """ Return True if the gramplet has data, else return False. """ if person is None: return False elif person.get_event_ref_list(): return True elif person.get_citation_list(): return True elif person.get_media_list(): return True return False
class PersonResidence(Gramplet): """ Displays residence events for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Date'), 1, 200), (_('Place'), 2, 200)] self.model = ListModel(top, titles, event_func=self.edit_event) return top def db_changed(self): self.connect(self.dbstate.db, 'person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) else: self.set_has_data(False) def get_has_data(self, active_person): """ Return True if the gramplet has data, else return False. """ if active_person: for event_ref in active_person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if int(event.get_type()) == EventType.RESIDENCE: return True return False def main(self): # return false finishes self.model.clear() active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) if active_person: self.display_person(active_person) else: self.set_has_data(False) else: self.set_has_data(False) def display_person(self, active_person): """ Display the residence events of the active person. """ count = 0 for event_ref in active_person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if int(event.get_type()) == EventType.RESIDENCE: self.add_residence(event) count += 1 self.set_has_data(count > 0) def add_residence(self, event): """ Add a residence event to the model. """ date = get_date(event) place = '' handle = event.get_place_handle() if handle: place = place_displayer.display_event(self.dbstate.db, event) self.model.add((event.get_handle(), date, place)) def edit_event(self, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except WindowActiveError: pass
class Descendant(Gramplet): """ Gramplet to display descendants of the active person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ self.view = Gtk.TreeView() self.view.set_tooltip_column(3) titles = [(_('Name'), 0, 230), (_('Birth'), 2, 100), ('', NOSORT, 1), ('', NOSORT, 1), # tooltip ('', NOSORT, 100)] # handle self.model = ListModel(self.view, titles, list_mode="tree", event_func=self.cb_double_click, right_click=self.cb_right_click) return self.view def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle: person = self.dbstate.db.get_person_from_handle(active_handle) if person: for family_handle in person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(family_handle) if family: for child_ref in family.get_child_ref_list(): return True return False def cb_double_click(self, treeview): """ Handle double click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() if not iter_: return try: handle = model.get_value(iter_, 4) person = self.dbstate.db.get_person_from_handle(handle) EditPerson(self.dbstate, self.uistate, [], person) except WindowActiveError: pass def cb_right_click(self, treeview, event): """ Handle right click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() sensitivity = 1 if iter_ else 0 menu = Gtk.Menu() menu.set_title(_('Descendent Menu')) entries = [ (_("Edit"), lambda obj: self.cb_double_click(treeview), sensitivity), (None, None, 0), (_("Copy all"), lambda obj: self.on_copy_all(treeview), 1), ] for stock_id, callback, sensitivity in entries: item = Gtk.ImageMenuItem(stock_id) if callback: item.connect("activate", callback) item.set_sensitive(sensitivity) item.show() menu.append(item) self.menu = menu self.menu.popup(None, None, None, None, event.button, event.time) def on_copy_all(self, treeview): """ Copy tree to clipboard. """ model = treeview.get_model() text = model_to_text(model, [0, 1], level=1) text_to_clipboard(text) def db_changed(self): self.update() def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') if active_handle: self.set_has_data(self.get_has_data(active_handle)) else: self.set_has_data(False) def main(self): active_handle = self.get_active('Person') self.model.clear() if active_handle: self.add_to_tree(None, active_handle) self.view.expand_all() self.set_has_data(self.get_has_data(active_handle)) else: self.set_has_data(False) def add_to_tree(self, parent_id, person_handle): """ Add a person to the tree. """ person = self.dbstate.db.get_person_from_handle(person_handle) name = name_displayer.display(person) birth = get_birth_or_fallback(self.dbstate.db, person) death = get_death_or_fallback(self.dbstate.db, person) birth_text = birth_date = birth_sort = '' if birth: birth_date = get_date(birth) birth_sort = '%012d' % birth.get_date_object().get_sort_value() birth_text = _('%(abbr)s %(date)s') % \ {'abbr': birth.type.get_abbreviation(), 'date': birth_date} death_date = death_sort = death_text = '' if death: death_date = get_date(death) death_sort = '%012d' % death.get_date_object().get_sort_value() death_text = _('%(abbr)s %(date)s') % \ {'abbr': death.type.get_abbreviation(), 'date': death_date} tooltip = name + '\n' + birth_text + '\n' + death_text item_id = self.model.add([name, birth_date, birth_sort, tooltip, person_handle], node=parent_id) for family_handle in person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(family_handle) for child_ref in family.get_child_ref_list(): self.add_to_tree(item_id, child_ref.ref) return item_id
def __init__(self, dbstate, user, options_class, name, callback=None): uistate = user.uistate self.label = _("Relation and distances with root") self.dbstate = dbstate FilterClass = GenericFilterFactory('Person') self.path = '.' filter = FilterClass() tool.Tool.__init__(self, dbstate, options_class, name) if uistate: window = Gtk.Window() window.set_default_size(880, 600) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) window.add(box) # dirty work-around for Gtk.HeaderBar() and FolderChooser chooser = Gtk.FileChooserDialog(_("Folder Chooser"), parent=uistate.window, action=Gtk.FileChooserAction.SELECT_FOLDER, buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL, _('_Select'), Gtk.ResponseType.OK)) chooser.set_tooltip_text(_("Please, select a folder")) status = chooser.run() if status == Gtk.ResponseType.OK: # work-around 'IsADirectoryError' with self() # TypeError: invalid file: gi.FunctionInfo() self.path = chooser.get_current_folder() chooser.destroy() ManagedWindow.__init__(self, uistate, [], self.__class__) self.titles = [ (_('Rel_id'), 0, 40, INTEGER), # would be INTEGER (_('Relation'), 1, 300, str), (_('Name'), 2, 200, str), (_('up'), 3, 35, INTEGER), (_('down'), 4, 35, INTEGER), (_('Common MRA'), 5, 40, INTEGER), (_('Rank'), 6, 40, INTEGER), (_('Period'), 7, 40, str), ] treeview = Gtk.TreeView() model = ListModel(treeview, self.titles) s = Gtk.ScrolledWindow() s.add(treeview) box.pack_start(s, True, True, 0) button = Gtk.Button(label=_("Save")) button.connect("clicked", self.button_clicked) box.pack_end(button, False, True, 0) self.stats_list = [] # behavior can be different according to CPU and generation depth max_level = config.get('behavior.generation-depth') # compact and interlinked tree # single core 2.80 Ghz needs +/- 0.1 second per person if max_level >= 15: var = max_level * 0.01 elif 10 <= max_level < 15: var = max_level * 0.02 else: var = max_level * 0.025 plist = self.dbstate.db.iter_person_handles() length = self.dbstate.db.get_number_of_people() default_person = self.dbstate.db.get_default_person() if uistate: self.progress = ProgressMeter(self.label, can_cancel=True, parent=window) else: self.progress = ProgressMeter(self.label) if default_person: # rather designed for run via GUI... root_id = default_person.get_gramps_id() ancestors = rules.person.IsAncestorOf([str(root_id), True]) descendants = rules.person.IsDescendantOf([str(root_id), True]) related = rules.person.IsRelatedWith([str(root_id)]) # filtering people can be useful on some large data set # counter on filtering pass was not efficient # Not the proper solution, but a lazy one providing expected message filter.add_rule(related) self.progress.set_pass(_('Please wait, filtering...')) filtered_list = filter.apply(self.dbstate.db, plist) relationship = get_relationship_calculator() else: # TODO: provide selection widget for CLI and GUI WarningDialog(_("No default_person")) return count = 0 filtered_people = len(filtered_list) self.progress.set_pass(_('Generating relation map...'), filtered_people) if self.progress.get_cancelled(): self.progress.close() return step_one = time.clock() # init for counters for handle in filtered_list: nb = len(self.stats_list) count += 1 self.progress.step() step_two = time.clock() start = 99 if count > start: # provide a basic interface for counters need = (step_two - step_one) / count wait = need * filtered_people remain = int(wait) - int(step_two - step_one) # sorry, lazy header = _("%d/%d \n %d/%d seconds \n %d/%d \n%f|\t%f" % (count, filtered_people, remain, int(wait), nb, length, float(need), float(var)) ) self.progress.set_header(header) if self.progress.get_cancelled(): self.progress.close() return person = dbstate.db.get_person_from_handle(handle) timeout_one = time.clock() # for delta and timeout estimations dist = relationship.get_relationship_distance_new( dbstate.db, default_person, person, only_birth=True) timeout_two = time.clock() rank = dist[0][0] if rank == -1 or rank > max_level: # not related and ignored people continue limit = timeout_two - timeout_one expect = (limit - var) / max_level if limit > var: n = name_displayer.display(person) _LOG.debug("Sorry! '{0}' needs {1} second, \ variation = '{2}'".format(n, limit, expect ) ) continue else: _LOG.debug("variation = '{}'".format(limit)) # delta, see above max_level 'wall' section rel = relationship.get_one_relationship( dbstate.db, default_person, person) rel_a = dist[0][2] Ga = len(rel_a) rel_b = dist[0][4] Gb = len(rel_b) mra = 1 # m: mother; f: father if Ga > 0: for letter in rel_a: if letter == 'm': mra = mra * 2 + 1 if letter == 'f': mra = mra * 2 # design: mra gender will be often female (m: mother) if rel_a[-1] == "f" and Gb != 0: # male gender, look at spouse mra = mra + 1 name = name_displayer.display(person) # pseudo privacy; sample for DNA stuff and mapping import hashlib no_name = hashlib.sha384(name.encode() + handle.encode()).hexdigest() _LOG.info(no_name) # own internal password via handle kekule = number.get_number(Ga, Gb, rel_a, rel_b) # workaround - possible unique ID and common numbers uuid = str(uuid4()) _LOG.info("Random UUID: {}".format(uuid)) if kekule == "u": # TODO: cousin(e)s need a key kekule = 0 if kekule == "nb": # non-birth kekule = -1 try: test = int(kekule) except: # 1: related to mother; 0.x : no more girls lineage kekule = 1 period = get_timeperiod(self.dbstate.db, handle) # sometimes 'iterator' (generator) is more faster #handle_list = map(handle, filtered_list) iterator = (handle for handle in filtered_list) # experimentations; not used yet new_list=[int(kekule), int(Ga), int(Gb), int(mra), int(rank)] if max_level > 7: line = (iterator, array('l', new_list)) else: line = (iterator, array('b', new_list)) self.stats_list.append((int(kekule), rel, name, int(Ga), int(Gb), int(mra), int(rank), str(period))) self.progress.close() from itertools import groupby for key, items in groupby(self.stats_list, lambda x: x[0]): for subitem in items: _LOG.info(subitem) _LOG.debug("total: {}".format(nb)) for entry in self.stats_list: if uistate: model.add(entry, entry[0]) else: print(entry) if uistate: window.show() self.set_window(window, None, self.label) self.show()
class MediaBrowser(Gramplet): """ Displays an object tree and a media preview for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = Gtk.HBox() self.photo = Photo() self.photo.show() view = Gtk.TreeView() titles = [(_('Object'), 1, 250)] self.model = ListModel(view, titles, list_mode="tree", select_func=self.row_selected) top.pack_start(view, True, True, 0) top.pack_start(self.photo, True, False, 5) top.show_all() return top def db_changed(self): self.connect(self.dbstate.db, 'person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) def main(self): self.model.clear() self.photo.set_image(None) active_handle = self.get_active('Person') if self.dbstate.db.has_person_handle(active_handle): self.display_data( self.dbstate.db.get_person_from_handle(active_handle)) else: self.set_has_data(False) def display_data(self, person): """ Display the object tree for the active person. """ self.add_media(person) self.add_events(person) self.add_sources(person) self.set_has_data(self.model.count > 0) def add_events(self, obj, parent_node=None): """ Add event nodes to the model. """ for event_ref in obj.get_event_ref_list(): handle = event_ref.ref name, event = navigation_label(self.dbstate.db, 'Event', handle) node = self.model.add([name], node=parent_node) self.add_sources(event, node) self.add_media(event, node) def add_sources(self, obj, parent_node=None): """ Add source nodes to the model. """ for citation_handle in obj.get_citation_list(): citation = self.dbstate.db.get_citation_from_handle( citation_handle) handle = citation.get_reference_handle() name, src = navigation_label(self.dbstate.db, 'Source', handle) node = self.model.add([name], node=parent_node) self.add_media(src, node) def add_media(self, obj, parent_node=None): """ Add media object nodes to the model. """ for media_ref in obj.get_media_list(): handle = media_ref.ref name, media = navigation_label(self.dbstate.db, 'Media', handle) full_path = media_path_full(self.dbstate.db, media.get_path()) rect = media_ref.get_rectangle() self.model.add([name], info=media_ref, node=parent_node) def row_selected(self, selection): """ Change the image when a row is selected. """ selected = self.model.get_selected_objects() if selected: if selected[0]: self.load_image(selected[0]) else: self.photo.set_image(None) else: self.photo.set_image(None) def load_image(self, media_ref): """ Display an image from the given media reference. """ media = self.dbstate.db.get_media_from_handle(media_ref.ref) full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() rectangle = media_ref.get_rectangle() self.photo.set_image(full_path, mime_type, rectangle) def get_has_data(self, person): """ Return True if the gramplet has data, else return False. """ if person is None: return False elif person.get_event_ref_list(): return True elif person.get_citation_list(): return True elif person.get_media_list(): return True return False
class Events(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the events for a person or family. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'event-update': self.changed}) self.callman.connect_all(keys=['event']) def changed(self, handle): """ Called when a registered event is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', NOSORT, 50,), (_('Type'), 1, 100), (_('Description'), 2, 150), (_('Date'), 3, 100), ('', NOSORT, 50), (_('Age'), 4, 100), ('', NOSORT, 50), (_('Place'), 5, 400), (_('Main Participants'), 6, 200), (_('Role'), 7, 100)] self.model = ListModel(top, titles, event_func=self.edit_event) return top def add_event_ref(self, event_ref, spouse=None): """ Add an event to the model. """ self.callman.register_handles({'event': [event_ref.ref]}) event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() person_age = self.column_age(event) person_age_sort = self.column_sort_age(event) place = place_displayer.display_event(self.dbstate.db, event) participants = get_participant_from_event(self.dbstate.db, event_ref.ref) self.model.add((event.get_handle(), str(event.get_type()), event.get_description(), event_date, event_sort, person_age, person_age_sort, place, participants, str(event_ref.get_role()))) def column_age(self, event): """ Returns a string representation of age in years. Change precision=2 for "year, month", or precision=3 for "year, month, days" """ date = event.get_date_object() start_date = self.get_start_date() if date and start_date: return (date - start_date).format(precision=age_precision) else: return "" def column_sort_age(self, event): """ Returns a string version of number of days of age. """ date = event.get_date_object() start_date = self.get_start_date() if date and start_date: return "%09d" % int(date - start_date) else: return "" def edit_event(self, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except WindowActiveError: pass
class Locations(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Gramplet showing the locations of a place over time. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'place-update': self.changed}) self.callman.connect_all(keys=['place']) def db_changed(self): self.connect_signal('Place', self.update) def changed(self, handle): """ Called when a registered place is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected place.') self.set_tooltip(tip) top = Gtk.TreeView() titles = [('', 0, 50), (_('Name'), 1, 300), (_('Type'), 2, 150), (_('Date'), 4, 150), ('', NOSORT, 50)] self.model = ListModel(top, titles, list_mode="tree", event_func=self.edit_place) return top def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Place') if active_handle: active = self.dbstate.db.get_place_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) else: self.set_has_data(False) def main(self): self.model.clear() self.callman.unregister_all() active_handle = self.get_active('Place') if active_handle: active = self.dbstate.db.get_place_from_handle(active_handle) if active: self.display_place(active, None, [active_handle]) else: self.set_has_data(False) else: self.set_has_data(False) def display_place(self, place, node, visited): """ Display the location hierarchy for the active place. """ self.callman.register_obj(place) for placeref in place.get_placeref_list(): if placeref.ref in visited: continue place_date = get_date(placeref) place_sort = '%012d' % placeref.get_date_object().get_sort_value() parent_place = self.dbstate.db.get_place_from_handle(placeref.ref) parent_name = parent_place.get_name().get_value() parent_type = str(parent_place.get_type()) parent_node = self.model.add([ placeref.ref, parent_name, parent_type, place_date, place_sort ], node=node) self.display_place(parent_place, parent_node, visited + [placeref.ref]) self.set_has_data(self.model.count > 0) self.model.tree.expand_all() def get_has_data(self, place): """ Return True if the gramplet has data, else return False. """ if place is None: return False if len(place.get_placeref_list()) > 0: return True else: return False def edit_place(self, treeview): """ Edit the selected place. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) place = self.dbstate.db.get_place_from_handle(handle) try: EditPlace(self.dbstate, self.uistate, [], place) except WindowActiveError: pass