Beispiel #1
0
    def __build_window(self):
        """Build the window from Glade.
        """
        from gramps.gui.glade import Glade
        glade_xml = Glade()
        self._window = glade_xml.toplevel
        self._window.set_transient_for(self._parent)

        # remember active widgets for future use
        self._swin = glade_xml.get_object('swin')
        self._drawing_area = glade_xml.get_object('drawingarea')
        self._first_button = glade_xml.get_object('first')
        self._prev_button = glade_xml.get_object('prev')
        self._next_button = glade_xml.get_object('next')
        self._last_button = glade_xml.get_object('last')
        self._pages_entry = glade_xml.get_object('entry')
        self._pages_label = glade_xml.get_object('label')
        self._zoom_fit_width_button = glade_xml.get_object('zoom_fit_width')
        self._zoom_fit_width_button.set_stock_id('gramps-zoom-fit-width')
        self._zoom_best_fit_button = glade_xml.get_object('zoom_best_fit')
        self._zoom_best_fit_button.set_stock_id('gramps-zoom-best-fit')
        self._zoom_in_button = glade_xml.get_object('zoom_in')
        self._zoom_in_button.set_stock_id('gramps-zoom-in')
        self._zoom_out_button = glade_xml.get_object('zoom_out')
        self._zoom_out_button.set_stock_id('gramps-zoom-out')

        # connect the signals
        glade_xml.connect_signals(self)
        self._drawing_area.connect("draw", self.on_drawingarea_draw_event)
Beispiel #2
0
    def __build_window(self):
        """Build the window from Glade.
        """
        from gramps.gui.glade import Glade
        glade_xml = Glade()
        self._window = glade_xml.toplevel
        self._window.set_transient_for(self._parent)

        # remember active widgets for future use
        self._swin = glade_xml.get_object('swin')
        self._drawing_area = glade_xml.get_object('drawingarea')
        self._first_button = glade_xml.get_object('first')
        self._prev_button = glade_xml.get_object('prev')
        self._next_button = glade_xml.get_object('next')
        self._last_button = glade_xml.get_object('last')
        self._pages_entry = glade_xml.get_object('entry')
        self._pages_label = glade_xml.get_object('label')
        self._zoom_fit_width_button = glade_xml.get_object('zoom_fit_width')
        self._zoom_fit_width_button.set_stock_id('gramps-zoom-fit-width')
        self._zoom_best_fit_button = glade_xml.get_object('zoom_best_fit')
        self._zoom_best_fit_button.set_stock_id('gramps-zoom-best-fit')
        self._zoom_in_button = glade_xml.get_object('zoom_in')
        self._zoom_in_button.set_stock_id('gramps-zoom-in')
        self._zoom_out_button = glade_xml.get_object('zoom_out')
        self._zoom_out_button.set_stock_id('gramps-zoom-out')

        # connect the signals
        glade_xml.connect_signals(self)
        self._drawing_area.connect("draw", self.on_drawingarea_draw_event)
Beispiel #3
0
    def create_gui(self):
        self.filternames = []
        category = self.uistate.viewmanager.active_page.get_category()
        if category == "People": category = "Person"
        if category.endswith("ies"): category = category[0:-3] + "y"
        if category.endswith("s"): category = category[0:-1]
        self.current_category = category

        glade = Glade(toplevel='dialog1')
        self.dialog = glade.toplevel
        combo_categories = glade.get_child_object("combo_categories")
        self.combo_filters = glade.get_child_object("combo_filters")
        self.add_button = glade.get_child_object("add_button")
        self.edit_button = glade.get_child_object("edit_button")
        self.delete_button = glade.get_child_object("delete_button")

        self.execute_button = glade.get_child_object("execute_button")
        self.update_button = glade.get_child_object("update_button")
        self.close_button = glade.get_child_object("close_button")
        self.box = glade.get_child_object("box")

        if 0: glade.connect_signals(
            {
                'on_filter_changed': self.on_filter_changed,
                'add_new_filter': self.add_new_filter,
                'edit_filter': self.edit_filter,
                'delete_filter': self.delete_filter,
                'execute_clicked': self.execute_clicked,
                'update_clicked': self.update_clicked,
                'close_clicked': self.close_clicked,
                'on_category_changed': self.on_category_changed,
            }
        )
        if 1:
            self.combo_filters.connect("changed", self.on_filter_changed)

            self.add_button.connect("clicked", self.add_new_filter)
            self.edit_button.connect("clicked", self.edit_filter)
            self.delete_button.connect("clicked", self.delete_filter)

            self.execute_button.connect("clicked", self.execute_clicked)
            self.update_button.connect("clicked", self.update_clicked)
            self.close_button.connect("clicked", self.close_clicked)

        for cat in self.categories_translated:
            combo_categories.append_text(cat)
        combo_categories.connect("changed", self.on_category_changed)

        if self.current_category not in self.categories:
            self.current_category = "Person"
        i = self.categories.index(self.current_category)
        combo_categories.set_active(i)

        self.dialog.connect("delete-event", lambda x, y: self.close_clicked(self.dialog))
        self.dialog.show_all()
        return self.dialog
Beispiel #4
0
    def display(self):
        # get the main window from glade
        topDialog = Glade()

        # set gramps style title for the window
        window = topDialog.toplevel
        self.set_window(window,
                        topDialog.get_object("title"),
                        _("Database Owner Editor"))
        self.setup_configs('interface.ownereditor', 500, 400)

        # move help button to the left side
        action_area = topDialog.get_object("action_area")
        help_button = topDialog.get_object("help_button")
        action_area.set_child_secondary(help_button, True)

        # connect signals
        topDialog.connect_signals({
            "on_ok_button_clicked": self.on_ok_button_clicked,
            "on_cancel_button_clicked": self.close,
            "on_help_button_clicked": self.on_help_button_clicked,
            "on_eventbox_button_press_event": self.on_button_press_event,
            "on_menu_activate": self.on_menu_activate})

        # fetch the popup menu
        self.menu = topDialog.get_object("popup_menu")
        self.track_ref_for_deletion("menu")

        #topDialog.connect_signals({"on_menu_activate": self.on_menu_activate})

        # get current db owner and attach it to the entries of the window
        self.owner = self.db.get_researcher()

        self.entries = []
        entry = [
            ("name", self.owner.set_name, self.owner.get_name),
            ("address", self.owner.set_address, self.owner.get_address),
            ("locality", self.owner.set_locality, self.owner.get_locality),
            ("city", self.owner.set_city, self.owner.get_city),
            ("state", self.owner.set_state, self.owner.get_state),
            ("country", self.owner.set_country, self.owner.get_country),
            ("zip", self.owner.set_postal_code, self.owner.get_postal_code),
            ("phone", self.owner.set_phone, self.owner.get_phone),
            ("email", self.owner.set_email, self.owner.get_email),
        ]

        for (name,set_fn,get_fn) in entry:
            self.entries.append(MonitoredEntry(topDialog.get_object(name),
                                               set_fn,
                                               get_fn,
                                               self.db.readonly))
        # ok, let's see what we've done
        self.show()
Beispiel #5
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        tool.Tool.__init__(self, dbstate, options_class, name)
        ManagedWindow.__init__(self, uistate, [],
                                             self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.map = {}
        self.list = []
        self.index = 0
        self.merger = None
        self.mergee = None
        self.removed = {}
        self.update = callback
        self.use_soundex = 1

        top = Glade(toplevel="finddupes", also_load=["liststore1"])

        # retrieve options
        threshold = self.options.handler.options_dict['threshold']
        use_soundex = self.options.handler.options_dict['soundex']

        my_menu = Gtk.ListStore(str, object)
        for val in sorted(_val2label):
            my_menu.append([_val2label[val], val])

        self.soundex_obj = top.get_object("soundex")
        self.soundex_obj.set_active(use_soundex)
        self.soundex_obj.show()

        self.menu = top.get_object("menu")
        self.menu.set_model(my_menu)
        self.menu.set_active(0)

        window = top.toplevel
        self.set_window(window, top.get_object('title'),
                        _('Find Possible Duplicate People'))
        self.setup_configs('interface.duplicatepeopletool', 350, 220)

        top.connect_signals({
            "on_do_merge_clicked"   : self.__dummy,
            "on_help_show_clicked"  : self.__dummy,
            "on_delete_show_event"  : self.__dummy,
            "on_merge_ok_clicked"   : self.on_merge_ok_clicked,
            "destroy_passed_object" : self.close,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_merge_event" : self.close,
            "on_delete_event"       : self.close,
            })

        self.show()
Beispiel #6
0
    def display(self):
        # get the main window from glade
        topDialog = Glade()

        # set gramps style title for the window
        window = topDialog.toplevel
        self.set_window(window, topDialog.get_object("title"),
                        _("Database Owner Editor"))
        self.setup_configs('interface.ownereditor', 500, 400)

        # move help button to the left side
        action_area = topDialog.get_object("action_area")
        help_button = topDialog.get_object("help_button")
        action_area.set_child_secondary(help_button, True)

        # connect signals
        topDialog.connect_signals({
            "on_ok_button_clicked": self.on_ok_button_clicked,
            "on_cancel_button_clicked": self.close,
            "on_help_button_clicked": self.on_help_button_clicked,
            "on_eventbox_button_press_event": self.on_button_press_event,
            "on_menu_activate": self.on_menu_activate
        })

        # fetch the popup menu
        self.menu = topDialog.get_object("popup_menu")
        self.track_ref_for_deletion("menu")

        #topDialog.connect_signals({"on_menu_activate": self.on_menu_activate})

        # get current db owner and attach it to the entries of the window
        self.owner = self.db.get_researcher()

        self.entries = []
        entry = [
            ("name", self.owner.set_name, self.owner.get_name),
            ("address", self.owner.set_address, self.owner.get_address),
            ("locality", self.owner.set_locality, self.owner.get_locality),
            ("city", self.owner.set_city, self.owner.get_city),
            ("state", self.owner.set_state, self.owner.get_state),
            ("country", self.owner.set_country, self.owner.get_country),
            ("zip", self.owner.set_postal_code, self.owner.get_postal_code),
            ("phone", self.owner.set_phone, self.owner.get_phone),
            ("email", self.owner.set_email, self.owner.get_email),
        ]

        for (name, set_fn, get_fn) in entry:
            self.entries.append(
                MonitoredEntry(topDialog.get_object(name), set_fn, get_fn,
                               self.db.readonly))
        # ok, let's see what we've done
        self.show()
Beispiel #7
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        tool.Tool.__init__(self, dbstate, options_class, name)
        ManagedWindow.__init__(self, uistate, [],
                                             self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.map = {}
        self.list = []
        self.index = 0
        self.merger = None
        self.mergee = None
        self.removed = {}
        self.update = callback
        self.use_soundex = 1

        top = Glade()

        # retrieve options
        threshold = self.options.handler.options_dict['threshold']
        use_soundex = self.options.handler.options_dict['soundex']

        my_menu = Gtk.ListStore(str, object)
        for val in sorted(_val2label):
            my_menu.append([_val2label[val], val])

        self.soundex_obj = top.get_object("soundex")
        self.soundex_obj.set_active(use_soundex)
        self.soundex_obj.show()

        self.menu = top.get_object("menu")
        self.menu.set_model(my_menu)
        self.menu.set_active(0)

        window = top.toplevel
        self.set_window(window, top.get_object('title'),
                        _('Find Possible Duplicate People'))
        self.setup_configs('interface.duplicatepeopletool', 350, 220)

        top.connect_signals({
            "on_do_merge_clicked"   : self.__dummy,
            "on_help_show_clicked"  : self.__dummy,
            "on_delete_show_event"  : self.__dummy,
            "on_merge_ok_clicked"   : self.on_merge_ok_clicked,
            "destroy_passed_object" : self.close,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_merge_event" : self.close,
            "on_delete_event"       : self.close,
            })

        self.show()
    def display(self):

        top_dialog = Glade()

        top_dialog.connect_signals({
            "destroy_passed_object" : self.close,
            "on_ok_clicked" : self.on_ok_clicked,
            "on_help_clicked" : self.on_help_clicked,
            "on_delete_event"   : self.close,
            })

        window = top_dialog.toplevel
        self.set_window(window, top_dialog.get_object('title'), self.label)
        self.setup_configs('interface.changenames', 500, 450)

        self.clear_button = top_dialog.get_object('checkbutton1')
        self.copy_button = top_dialog.get_object('checkbutton2')
        self.tag_button = top_dialog.get_object('checkbutton3')

        self.treeview = top_dialog.get_object("list")

        self.r = Gtk.CellRendererToggle()
        self.r.set_property('activatable', True)
        self.r.set_property('radio', True)
        self.r.connect('toggled', self.toggled)

        c = Gtk.TreeViewColumn(_('Select'), self.r, active=1)
        self.treeview.append_column(c)

        c = Gtk.TreeViewColumn(_('Database'),
                               Gtk.CellRendererText(),text=2)
        self.treeview.append_column(c)

        c = Gtk.TreeViewColumn(_('Display'),
                               Gtk.CellRendererText(),text=3)
        self.treeview.append_column(c)

        self.selection = self.treeview.get_selection()

        self.model = Gtk.ListStore(str, bool, str, str)

        self.treeview.set_model(self.model)

        self.progress.set_pass(_('Building display'), len(self.name_list))
        for handle, title, descr in self.name_list:
            self.model.append([handle, title == descr, title, descr])
            self.progress.step()
        self.progress.close()

        self.show()
    def display(self):

        top_dialog = Glade()

        top_dialog.connect_signals({
            "destroy_passed_object" : self.close,
            "on_ok_clicked" : self.on_ok_clicked,
            "on_help_clicked" : self.on_help_clicked,
            "on_delete_event"   : self.close,
            })

        window = top_dialog.toplevel
        self.set_window(window, top_dialog.get_object('title'), self.label)
        self.setup_configs('interface.changenames', 500, 450)

        self.clear_button = top_dialog.get_object('checkbutton1')
        self.copy_button = top_dialog.get_object('checkbutton2')
        self.tag_button = top_dialog.get_object('checkbutton3')

        self.treeview = top_dialog.get_object("list")

        self.r = Gtk.CellRendererToggle()
        self.r.set_property('activatable', True)
        self.r.set_property('radio', True)
        self.r.connect('toggled', self.toggled)

        c = Gtk.TreeViewColumn(_('Select'), self.r, active=1)
        self.treeview.append_column(c)

        c = Gtk.TreeViewColumn(_('Database'),
                               Gtk.CellRendererText(),text=2)
        self.treeview.append_column(c)

        c = Gtk.TreeViewColumn(_('Display'),
                               Gtk.CellRendererText(),text=3)
        self.treeview.append_column(c)

        self.selection = self.treeview.get_selection()

        self.model = Gtk.ListStore(str, bool, str, str)

        self.treeview.set_model(self.model)

        self.progress.set_pass(_('Building display'), len(self.name_list))
        for handle, title, descr in self.name_list:
            self.model.append([handle, title == descr, title, descr])
            self.progress.step()
        self.progress.close()

        self.show()
Beispiel #10
0
    def __init__(self, dbstate, uistate, track, the_list, the_map, callback):
        ManagedWindow.__init__(self,uistate,track,self.__class__)

        self.dellist = set()
        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.setup_configs('interface.duplicatepeopletoolmatches', 500, 350)

        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,
            })
        self.db.connect("person-delete", self.person_delete)

        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()
Beispiel #11
0
    def run(self):

        top = Glade(toplevel="mergecitations", also_load=["liststore1"])

        # retrieve options
        fields = self.options.handler.options_dict['fields']
        dont_merge_notes = self.options.handler.options_dict[
            'dont_merge_notes']

        my_menu = Gtk.ListStore(str, object)
        for val in sorted(_val2label):
            my_menu.append([_val2label[val], val])

        self.notes_obj = top.get_object("notes")
        self.notes_obj.set_active(dont_merge_notes)
        self.notes_obj.show()

        self.menu = top.get_object("menu")
        self.menu.set_model(my_menu)
        self.menu.set_active(fields)

        window = top.toplevel
        window.set_transient_for(self.user.uistate.window)
        window.show()
        #        self.set_window(window, top.get_object('title'),
        #                        _('Merge citations'))
        self.set_window(
            window, top.get_object('title2'),
            _("Notes, media objects and data-items of matching "
              "citations will be combined."))
        self.setup_configs('interface.mergecitations', 700, 230)

        top.connect_signals({
            "on_merge_ok_clicked": self.on_merge_ok_clicked,
            "destroy_passed_object": self.cancel,
            "on_help_clicked": self.on_help_clicked,
            "on_delete_merge_event": self.close,
            "on_delete_event": self.close,
        })

        self.show()
Beispiel #12
0
    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.setup_configs('interface.duplicatepeopletoolmatches', 500, 350)

        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()
Beispiel #13
0
    def run(self):

        top = Glade(toplevel="mergecitations")

        # retrieve options
        fields = self.options.handler.options_dict['fields']
        dont_merge_notes = self.options.handler.options_dict['dont_merge_notes']

        my_menu = Gtk.ListStore(str, object)
        for val in sorted(_val2label):
            my_menu.append([_val2label[val], val])

        self.notes_obj = top.get_object("notes")
        self.notes_obj.set_active(dont_merge_notes)
        self.notes_obj.show()

        self.menu = top.get_object("menu")
        self.menu.set_model(my_menu)
        self.menu.set_active(fields)

        window = top.toplevel
        window.set_transient_for(self.user.uistate.window)
        window.show()
#        self.set_window(window, top.get_object('title'),
#                        _('Merge citations'))
        self.set_window(window, top.get_object('title2'),
                        _("Notes, media objects and data-items of matching "
                          "citations will be combined."))
        self.setup_configs('interface.mergecitations', 700, 230)

        top.connect_signals({
            "on_merge_ok_clicked"   : self.on_merge_ok_clicked,
            "destroy_passed_object" : self.cancel,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_merge_event" : self.close,
            "on_delete_event"       : self.close,
            })

        self.show()
Beispiel #14
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        dummy_opt = options_class
        dummy_nme = name
        dummy_cb = callback

        self.title = _('Clean input data')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.db = dbstate.db
        self.tooltip = ""
        self.f_lat = False
        self.f_lon = False

        top_dialog = Glade()

        top_dialog.connect_signals({
            "destroy_passed_object": self.close,
            "on_help_clicked": self.on_help_clicked,
            "on_delete_event": self.close,
        })

        window = top_dialog.toplevel
        title = top_dialog.get_object("title")
        self.set_window(window, title, self.title)
        tip = _('Search leading and/or trailing spaces for persons'
                ' and places. Search comma or bad sign in coordinates'
                ' fields.\n'
                'Double click on a row to edit its content.')
        title.set_tooltip_text(tip)

        # start the progress indicator
        self.progress = ProgressMeter(self.title,
                                      _('Starting'),
                                      parent=uistate.window)
        steps = self.db.get_number_of_people() + self.db.get_number_of_places()
        self.progress.set_pass(
            _('Looking for possible fields with leading or'
              ' trailing spaces'), steps)

        self.model_1 = Gtk.ListStore(
            GObject.TYPE_STRING,  # 0==handle
            GObject.TYPE_STRING,  # 1==firstname
            GObject.TYPE_STRING,  # 2==surname
            GObject.TYPE_STRING,  # 3==alternate name
            GObject.TYPE_STRING,  # 4==group_as
        )
        self.model_1.set_sort_column_id(
            Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 1)

        self.label_1 = top_dialog.get_object("label_1")
        self.label_1.set_text(_('Person'))
        self.treeview_1 = top_dialog.get_object("treeview_1")
        self.treeview_1.set_model(self.model_1)
        col1 = Gtk.TreeViewColumn(_('handle'), Gtk.CellRendererText(), text=0)
        renderer1 = Gtk.CellRendererText()
        renderer1.set_property('underline-set', True)
        renderer1.set_property('underline', 2)  # 2=double underline
        col2 = Gtk.TreeViewColumn(_('firstname'), renderer1, text=1)
        renderer2 = Gtk.CellRendererText()
        renderer2.set_property('underline-set', True)
        renderer2.set_property('underline', 2)  # 2=double underline
        col3 = Gtk.TreeViewColumn(_('surname'), renderer2, text=2)
        renderer3 = Gtk.CellRendererText()
        renderer3.set_property('underline-set', True)
        renderer3.set_property('underline', 2)  # 2=double underline
        col4 = Gtk.TreeViewColumn(_('alternate name'), renderer3, text=3)
        renderer4 = Gtk.CellRendererText()
        renderer4.set_property('underline-set', True)
        renderer4.set_property('underline', 2)  # 2=double underline
        col5 = Gtk.TreeViewColumn(_('group as'), renderer4, text=4)
        col1.set_resizable(True)
        col1.set_visible(False)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col5.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.treeview_1.append_column(col1)
        self.treeview_1.append_column(col2)
        self.treeview_1.append_column(col3)
        self.treeview_1.append_column(col4)
        self.treeview_1.append_column(col5)
        self.treeselection = self.treeview_1.get_selection()
        self.treeview_1.connect('row-activated', self.rowactivated_cb1)

        self.model_2 = Gtk.ListStore(
            GObject.TYPE_STRING,  # 0==handle
            GObject.TYPE_STRING,  # 1==name
            GObject.TYPE_STRING,  # 2==latitude
            GObject.TYPE_STRING,  # 3==longitude
            GObject.TYPE_STRING)  # 4==tooltip
        self.model_2.set_sort_column_id(
            Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 1)

        self.label_2 = top_dialog.get_object("label_2")
        self.label_2.set_text(_('Place'))
        self.treeview_2 = top_dialog.get_object("treeview_2")
        self.treeview_2.set_model(self.model_2)
        col1 = Gtk.TreeViewColumn(_('handle'), Gtk.CellRendererText(), text=0)
        renderer5 = Gtk.CellRendererText()
        renderer5.set_property('underline-set', True)
        renderer5.set_property('underline', 2)  # 2=double underline
        col2 = Gtk.TreeViewColumn(_('name'), renderer5, text=1)
        renderer6 = Gtk.CellRendererText()
        renderer6.set_property('underline-set', True)
        renderer6.set_property('underline', 2)  # 2=double underline
        col3 = Gtk.TreeViewColumn(_('latitude'), renderer6, text=2)
        renderer7 = Gtk.CellRendererText()
        renderer7.set_property('underline-set', True)
        renderer7.set_property('underline', 2)  # 2=double underline
        col4 = Gtk.TreeViewColumn(_('longitude'), renderer7, text=3)
        col5 = Gtk.TreeViewColumn(_('tooltip'), Gtk.CellRendererText(), text=4)
        col1.set_resizable(True)
        col1.set_visible(False)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col5.set_visible(False)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.treeview_2.append_column(col1)
        self.treeview_2.append_column(col2)
        self.treeview_2.append_column(col3)
        self.treeview_2.append_column(col4)
        self.treeview_2.append_column(col5)
        self.treeview_2.set_tooltip_column(4)
        self.treeselection = self.treeview_2.get_selection()
        self.treeview_2.connect('row-activated', self.rowactivated_cb2)

        self.places()
        self.people()

        # close the progress bar
        self.progress.close()

        self.show()
Beispiel #15
0
class PatchNames(tool.BatchTool, ManagedWindow):
    titleid = 1
    nickid = 2
    pref1id = 3
    compid = 4

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Name and title extraction tool')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.set_window(Gtk.Window(), Gtk.Label(), '')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        winprefix = Gtk.Dialog(
            _("Default prefix and connector settings"), self.uistate.window,
            Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
            (_('_OK'), Gtk.ResponseType.ACCEPT))

        winprefix.vbox.set_spacing(5)
        hboxpref = Gtk.Box()
        label = Gtk.Label(label=_('Prefixes to search for:'))
        hboxpref.pack_start(label, False, False, 5)
        self.prefixbox = Gtk.Entry()
        self.prefixbox.set_text(', '.join(PREFIX_LIST))
        hboxpref.pack_start(self.prefixbox, True, True, 0)
        winprefix.vbox.pack_start(hboxpref, True, True, 0)
        hboxcon = Gtk.Box()
        label = Gtk.Label(label=_('Connectors splitting surnames:'))
        hboxcon.pack_start(label, False, False, 5)
        self.conbox = Gtk.Entry()
        self.conbox.set_text(', '.join(CONNECTOR_LIST))
        hboxcon.pack_start(self.conbox, True, True, 0)
        winprefix.vbox.pack_start(hboxcon, True, True, 0)
        hboxconns = Gtk.Box()
        label = Gtk.Label(label=_('Connectors not splitting surnames:'))
        hboxconns.pack_start(label, False, False, 5)
        self.connsbox = Gtk.Entry()
        self.connsbox.set_text(', '.join(CONNECTOR_LIST_NONSPLIT))
        hboxconns.pack_start(self.connsbox, True, True, 0)
        winprefix.vbox.pack_start(hboxconns, True, True, 0)
        winprefix.show_all()
        winprefix.resize(700, 100)

        response = winprefix.run()
        self.prefix_list = self.prefixbox.get_text().split(',')
        self.prefix_list = list(map(strip, self.prefix_list))
        self.prefixbox = None
        self.connector_list = self.conbox.get_text().split(',')
        self.connector_list = list(map(strip, self.connector_list))
        self.conbox = None
        self.connector_list_nonsplit = self.connsbox.get_text().split(',')
        self.connector_list_nonsplit = list(
            map(strip, self.connector_list_nonsplit))
        self.connsbox = None

        # Find a prefix in the first_name
        self._fn_prefix_re = re.compile(
            "(\S+)\s+(%s)\s*$" % '|'.join(self.prefix_list), re.IGNORECASE)

        # Find a prefix in the surname
        self._sn_prefix_re = re.compile(
            "^\s*(%s)\s+(.+)" % '|'.join(self.prefix_list), re.IGNORECASE)
        # Find a connector in the surname
        self._sn_con_re = re.compile(
            "^\s*(.+)\s+(%s)\s+(.+)" % '|'.join(self.connector_list),
            re.IGNORECASE)
        winprefix.destroy()

        self.cb = callback
        self.handle_to_action = {}

        self.progress = ProgressMeter(  # parent-OK
            _('Extracting Information from Names'),
            '',
            parent=self.uistate.window)
        self.progress.set_pass(_('Analyzing names'),
                               self.db.get_number_of_people())

        for person in self.db.iter_people():
            key = person.handle
            name = person.get_primary_name()
            first = name.get_first_name()
            sname = name.get_surname()

            old_prefix = []
            old_surn = []
            old_con = []
            old_prim = []
            old_orig = []
            for surn in name.get_surname_list():
                old_prefix.append(surn.get_prefix())
                old_surn.append(surn.get_surname())
                old_con.append(surn.get_connector())
                old_prim.append(surn.get_primary())
                old_orig.append(surn.get_origintype())

            if name.get_title():
                old_title = [name.get_title()]
            else:
                old_title = []
            new_title = []

            match = _title_re.match(first)
            while match:
                groups = match.groups()
                first = groups[1]
                new_title.append(groups[0])
                match = _title_re.match(first)
            matchnick = _nick_re.match(first)

            if new_title:
                titleval = (" ".join(old_title + new_title), first)
                if key in self.handle_to_action:
                    self.handle_to_action[key][self.titleid] = titleval
                else:
                    self.handle_to_action[key] = {self.titleid: titleval}
            elif matchnick:
                # we check for nick, which changes given name like title
                groups = matchnick.groups()
                nickval = (groups[0], groups[1])
                if key in self.handle_to_action:
                    self.handle_to_action[key][self.nickid] = nickval
                else:
                    self.handle_to_action[key] = {self.nickid: nickval}
            else:
                # Try to find the name prefix in the given name, also this
                # changes given name
                match = self._fn_prefix_re.match(first)
                if match:
                    groups = match.groups()
                    if old_prefix[0]:
                        # Put the found prefix before the old prefix
                        new_prefix = " ".join([groups[1], old_prefix[0]])
                    else:
                        new_prefix = groups[1]
                    pref1val = (groups[0], new_prefix, groups[1])
                    if key in self.handle_to_action:
                        self.handle_to_action[key][self.pref1id] = pref1val
                    else:
                        self.handle_to_action[key] = {self.pref1id: pref1val}

            #check for Gedcom import of compound surnames
            if len(old_surn) == 1 and old_con[0] == '':
                prefixes = old_prefix[0].split(',')
                surnames = old_surn[0].split(',')
                if len(prefixes) > 1 and len(prefixes) == len(surnames):
                    #assume a list of prefix and a list of surnames
                    prefixes = list(map(strip, prefixes))
                    surnames = list(map(strip, surnames))
                    primaries = [False] * len(prefixes)
                    primaries[0] = True
                    origs = []
                    for ind in range(len(prefixes)):
                        origs.append(NameOriginType())
                    origs[0] = old_orig[0]
                    compoundval = (surnames, prefixes, [''] * len(prefixes),
                                   primaries, origs)
                    if key in self.handle_to_action:
                        self.handle_to_action[key][self.compid] = compoundval
                    else:
                        self.handle_to_action[key] = {self.compid: compoundval}
                    #we cannot check compound surnames, so continue the loop
                    continue

            # Next, try to split surname in compounds: prefix surname connector
            found = False
            new_prefix_list = []
            new_surname_list = []
            new_connector_list = []
            new_prim_list = []
            new_orig_list = []
            ind = 0
            cont = True
            for pref, surn, con, prim, orig in zip(old_prefix, old_surn,
                                                   old_con, old_prim,
                                                   old_orig):
                surnval = surn.split()
                if surnval == []:
                    new_prefix_list.append(pref)
                    new_surname_list.append('')
                    new_connector_list.append(con)
                    new_prim_list.append(prim)
                    new_orig_list.append(orig)
                    cont = False
                    continue
                val = surnval.pop(0)
                while cont:
                    new_prefix_list.append(pref)
                    new_surname_list.append('')
                    new_connector_list.append(con)
                    new_prim_list.append(prim)
                    new_orig_list.append(orig)

                    while cont and (val.lower() in self.prefix_list):
                        found = True
                        if new_prefix_list[-1]:
                            new_prefix_list[-1] += ' ' + val
                        else:
                            new_prefix_list[-1] = val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #after prefix we have a surname
                    if cont:
                        new_surname_list[-1] = val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #if value after surname indicates continue, then continue
                    while cont and (val.lower()
                                    in self.connector_list_nonsplit):
                        #add this val to the current surname
                        new_surname_list[-1] += ' ' + val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    # if previous is non-splitting connector, then add new val to
                    # current surname
                    if cont and (new_surname_list[-1].split()[-1].lower()
                                 in self.connector_list_nonsplit):
                        new_surname_list[-1] += ' ' + val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #if next is a connector, add it to the surname
                    if cont and val.lower() in self.connector_list:
                        found = True
                        if new_connector_list[-1]:
                            new_connector_list[-1] = ' ' + val
                        else:
                            new_connector_list[-1] = val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #initialize for a next surname in case there are still
                    #val
                    if cont:
                        found = True  # we split surname
                        pref = ''
                        con = ''
                        prim = False
                        orig = NameOriginType()
                ind += 1
            if found:
                compoundval = (new_surname_list, new_prefix_list,
                               new_connector_list, new_prim_list,
                               new_orig_list)
                if key in self.handle_to_action:
                    self.handle_to_action[key][self.compid] = compoundval
                else:
                    self.handle_to_action[key] = {self.compid: compoundval}

            self.progress.step()

        if self.handle_to_action:
            self.display()
        else:
            self.progress.close()
            self.close()
            OkDialog(
                _('No modifications made'),  # parent-OK
                _("No titles, nicknames or prefixes were found"),
                parent=self.uistate.window)

    def build_menu_names(self, obj):
        return (self.label, None)

    def toggled(self, cell, path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]
        self.model.row_changed(path, row.iter)

    def display(self):

        self.top = Glade()
        window = self.top.toplevel
        self.top.connect_signals({
            "destroy_passed_object": self.close,
            "on_ok_clicked": self.on_ok_clicked,
            "on_help_clicked": self.on_help_clicked,
            "on_delete_event": self.close,
        })

        self.list = self.top.get_object("list")
        self.set_window(window, self.top.get_object('title'), self.label)

        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING)

        r = Gtk.CellRendererToggle()
        r.connect('toggled', self.toggled)
        c = Gtk.TreeViewColumn(_('Select'), r, active=0)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('ID'), Gtk.CellRendererText(), text=1)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Type'), Gtk.CellRendererText(), text=2)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Value'), Gtk.CellRendererText(), text=3)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Current Name'),
                               Gtk.CellRendererText(),
                               text=4)
        self.list.append_column(c)

        self.list.set_model(self.model)

        self.nick_hash = {}
        self.title_hash = {}
        self.prefix1_hash = {}
        self.compound_hash = {}

        self.progress.set_pass(_('Building display'),
                               len(list(self.handle_to_action.keys())))

        for key, data in self.handle_to_action.items():
            p = self.db.get_person_from_handle(key)
            gid = p.get_gramps_id()
            if self.nickid in data:
                given, nick = data[self.nickid]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Nickname'))
                self.model.set_value(handle, 3, nick)
                self.model.set_value(handle, 4,
                                     p.get_primary_name().get_name())
                self.nick_hash[key] = handle

            if self.titleid in data:
                title, given = data[self.titleid]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Person|Title'))
                self.model.set_value(handle, 3, title)
                self.model.set_value(handle, 4,
                                     p.get_primary_name().get_name())
                self.title_hash[key] = handle

            if self.pref1id in data:
                given, prefixtotal, new_prefix = data[self.pref1id]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Prefix in given name'))
                self.model.set_value(handle, 3, prefixtotal)
                self.model.set_value(handle, 4,
                                     p.get_primary_name().get_name())
                self.prefix1_hash[key] = handle

            if self.compid in data:
                surn_list, pref_list, con_list, prims, origs = data[
                    self.compid]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Compound surname'))
                newval = ''
                for sur, pre, con in zip(surn_list, pref_list, con_list):
                    if newval:
                        newval += '-['
                    else:
                        newval = '['
                    newval += pre + ',' + sur
                    if con:
                        newval += ',' + con + ']'
                    else:
                        newval += ']'
                self.model.set_value(handle, 3, newval)
                self.model.set_value(handle, 4,
                                     p.get_primary_name().get_name())
                self.compound_hash[key] = handle

            self.progress.step()

        self.progress.close()
        self.show()

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def on_ok_clicked(self, obj):
        with DbTxn(_("Extract information from names"), self.db,
                   batch=True) as trans:
            self.db.disable_signals()

            for key, data in self.handle_to_action.items():
                p = self.db.get_person_from_handle(key)
                if self.nickid in data:
                    modelhandle = self.nick_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        given, nick = data[self.nickid]
                        name = p.get_primary_name()
                        name.set_first_name(given.strip())
                        name.set_nick_name(nick.strip())

                if self.titleid in data:
                    modelhandle = self.title_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        title, given = data[self.titleid]
                        name = p.get_primary_name()
                        name.set_first_name(given.strip())
                        name.set_title(title.strip())

                if self.pref1id in data:
                    modelhandle = self.prefix1_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        given, prefixtotal, prefix = data[self.pref1id]
                        name = p.get_primary_name()
                        name.set_first_name(given.strip())
                        oldpref = name.get_surname_list()[0].get_prefix(
                        ).strip()
                        if oldpref == '' or oldpref == prefix.strip():
                            name.get_surname_list()[0].set_prefix(prefix)
                        else:
                            name.get_surname_list()[0].set_prefix(
                                '%s %s' % (prefix, oldpref))

                if self.compid in data:
                    modelhandle = self.compound_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        surns, prefs, cons, prims, origs = data[self.compid]
                        name = p.get_primary_name()
                        new_surn_list = []
                        for surn, pref, con, prim, orig in zip(
                                surns, prefs, cons, prims, origs):
                            new_surn_list.append(Surname())
                            new_surn_list[-1].set_surname(surn.strip())
                            new_surn_list[-1].set_prefix(pref.strip())
                            new_surn_list[-1].set_connector(con.strip())
                            new_surn_list[-1].set_primary(prim)
                            new_surn_list[-1].set_origintype(orig)
                        name.set_surname_list(new_surn_list)

                self.db.commit_person(p, trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        self.close()
        self.cb()
Beispiel #16
0
class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
    """ Class for Reodering Gramps ID Tool """
    xobjects = (('person', 'people'), ('family', 'families'),
                ('event', 'events'), ('place', 'places'),
                ('source', 'sources'), ('citation', 'citations'),
                ('repository', 'repositories'), ('media', 'media'), ('note',
                                                                     'notes'))

    def build_menu_names_(self, widget=None):
        """ The menu name """
        return (_('Main window'), _("Reorder Gramps IDs"))

    def __init__(self, dbstate, user, options_class, name, callback=None):
        self.uistate = user.uistate
        self.dbstate = dbstate.db

        if self.uistate:
            tool.BatchTool.__init__(self, dbstate, user, options_class, name)
            if self.fail:
                return  # user denied to modify Gramps IDs

        ManagedWindow.__init__(self, self.uistate, [], self.__class__)
        if not self.uistate:
            UpdateCallback.__init__(self, user.callback)

        self.object_status = True
        self.change_status = False
        self.start_zero = True
        self.step_cnt, self.step_list = 0, ['1', '2', '5', '10']
        self.keep_status = True

        self.obj_values = {}  # enable access to all internal values
        self.active_entries, self.format_entries = {}, {}
        self.change_entries = {}
        self.start_entries, self.step_entries = {}, {}
        self.keep_entries = {}

        self.prim_methods, self.obj_methods = {}, {}
        for prim_obj, prim_objs in self.xobjects:
            class_type = prim_obj.title()
            iter_handles = "self.dbstate.iter_%s_handles" % prim_obj
            get_number_obj = "self.dbstate.get_number_of_%s" % prim_objs
            prefix_fmt = "self.dbstate.%s_prefix" % prim_obj
            get_from_id = "self.dbstate.get_%s_from_gramps_id" % prim_obj
            get_from_handle = "self.dbstate.get_%s_from_handle" % prim_obj
            next_from_id = "self.dbstate.find_next_%s_gramps_id" % prim_obj
            commit = "self.dbstate.commit_%s" % prim_obj

            self.prim_methods[prim_obj] = (eval(prefix_fmt),
                                           eval(get_number_obj)(),
                                           eval(next_from_id)())
            self.obj_methods[prim_obj] = (eval(class_type), eval(iter_handles),
                                          eval(commit), eval(get_from_id),
                                          eval(get_from_handle),
                                          eval(next_from_id))

            object_fmt, quant_id, next_id = self.prim_methods[prim_obj]

            obj_value = ReorderEntry(object_fmt, quant_id, next_id)
            self.obj_values[prim_obj] = obj_value

        if self.uistate:
            self._display()
        else:
            self._execute()

    def __on_object_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Active' attribute """
        self.object_status = not self.object_status

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_active' % prim_obj)
            obj.set_active(self.object_status)

    def __on_object_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        self.active_entries[obj_name].set_val(obj_state)

        for obj_entry in ['actual', 'quant', 'format', 'change']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            obj.set_sensitive(obj_state)

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_change' % obj_name)
            if obj.get_active():
                obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
                obj.set_sensitive(obj_state)

    def __on_format_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Format' scheme of identifiers """
        for prim_obj, tmp in self.xobjects:
            obj_format = self.top.get_object('%s_format' % prim_obj)
            if not obj_format.get_sensitive():
                continue

            obj_fmt = self.obj_values[prim_obj].res_fmt()
            self.format_entries[prim_obj].force_value(obj_fmt)
            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].last_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_change_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Change' attribute """
        self.change_status = not self.change_status

        for prim_obj, tmp in self.xobjects:
            obj_change = self.top.get_object('%s_change' % prim_obj)
            if not obj_change.get_sensitive():
                continue

            self.change_entries[prim_obj].set_val(self.change_status)
            obj_change.set_active(self.change_status)

    def __on_change_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            if obj_entry == 'keep':
                if self.obj_values[obj_name].stored_prefix != \
                   self.obj_values[obj_name].object_prefix:
                    self.keep_entries[obj_name].set_val(False)
                else:
                    obj.set_active(obj_state)
                    self.keep_entries[obj_name].set_val(obj_state)
            obj.set_sensitive(obj_state)

    def __on_start_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Start' values of identifiers """
        self.start_zero = not self.start_zero

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_start' % prim_obj)
            if not obj.get_sensitive():
                continue

            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].next_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_step_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Step' width of identifiers """
        self.step_cnt = self.step_cnt + 1 if self.step_cnt < 3 else 0

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_step' % prim_obj)
            if not obj.get_sensitive():
                continue

            step_val = self.step_list[self.step_cnt]
            self.step_entries[prim_obj].force_value(step_val)

    def __on_keep_button_clicked(self, widget=None):
        """ compute the primary object and toggle the 'Active' attribute """
        self.keep_status = not self.keep_status

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_change' % prim_obj)
            if not obj.get_active():
                continue

            obj = self.top.get_object('%s_keep' % prim_obj)
            obj.set_active(self.keep_status)
            self.keep_entries[prim_obj].set_val(self.keep_status)

    def __on_format_entry_keyrelease(self, widget, event, data=None):
        """ activated on all return's of an entry """
        if event.keyval in [Gdk.KEY_Return]:
            obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
            obj_fmt = self.format_entries[obj_name].get_val()
            self.format_entries[obj_name].force_value(obj_fmt)
            self.start_entries[obj_name].update()

            obj_change = self.top.get_object('%s_change' % obj_name)
            obj_change.grab_focus()

        return False

    def __on_format_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        obj_fmt = self.format_entries[obj_name].get_val()

        self.format_entries[obj_name].set_val(obj_fmt)
        self.start_entries[obj_name].update()

        return False

    def __on_start_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        self.start_entries[obj_name].update()

        return False

    def __on_ok_button_clicked(self, widget=None):
        """ execute the reodering and close """
        self._execute()
        self._update()

        self.close()

    def __on_cancel_button_clicked(self, widget=None):
        """ cancel the reodering and close """
        self.close()

    def __on_help_button_clicked(self, widget=None):
        """ display the relevant portion of Gramps manual """
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def _display(self):
        """ organize Glade 'Reorder IDs' window """

        # get the main window from glade
        self.top = Glade(toplevel="reorder-ids")
        window = self.top.toplevel

        # set gramps style title for the window
        self.set_window(window, self.top.get_object("title"), \
                        _("Reorder Gramps IDs"))

        # connect signals
        self.top.connect_signals({
            "on_object_button_clicked":
            self.__on_object_button_clicked,
            "on_object_button_toggled":
            self.__on_object_button_toggled,
            "on_format_button_clicked":
            self.__on_format_button_clicked,
            "on_start_button_clicked":
            self.__on_start_button_clicked,
            "on_step_button_clicked":
            self.__on_step_button_clicked,
            "on_keep_button_clicked":
            self.__on_keep_button_clicked,
            "on_change_button_clicked":
            self.__on_change_button_clicked,
            "on_change_button_toggled":
            self.__on_change_button_toggled,
            "on_format_entry_keyrelease":
            self.__on_format_entry_keyrelease,
            "on_format_entry_focusout":
            self.__on_format_entry_focusout,
            "on_start_entry_focusout":
            self.__on_start_entry_focusout,
            "on_help_button_clicked":
            self.__on_help_button_clicked,
            "on_cancel_button_clicked":
            self.__on_cancel_button_clicked,
            "on_ok_button_clicked":
            self.__on_ok_button_clicked
        })

        # Calculate all entries and update Glade window
        for prim_obj, tmp in self.xobjects:
            # populate Object, Actual & Quantity fields with values
            obj_active = self.top.get_object('%s_active' % prim_obj)
            self.active_entries[prim_obj] = MonitoredCheckbox(
                obj_active, obj_active, self.obj_values[prim_obj].set_active,
                self.obj_values[prim_obj].get_active)
            obj_actual = self.top.get_object('%s_actual' % prim_obj)
            obj_actual.set_text('%s' % self.obj_values[prim_obj].last_id())
            obj_quant = self.top.get_object('%s_quant' % prim_obj)
            obj_quant.set_text('%s' % str(self.obj_values[prim_obj].quant_id))

            # connect/populate Format, Start, Step, Keep & Change fields with GTK/values
            obj_format = self.top.get_object('%s_format' % prim_obj)
            self.format_entries[prim_obj] = MonitoredEntry(
                obj_format, self.obj_values[prim_obj].set_fmt,
                self.obj_values[prim_obj].get_fmt)
            obj_change = self.top.get_object('%s_change' % prim_obj)
            self.change_entries[prim_obj] = MonitoredCheckbox(
                obj_change, obj_change, self.obj_values[prim_obj].set_change,
                self.obj_values[prim_obj].get_change)
            obj_start = self.top.get_object('%s_start' % prim_obj)
            self.start_entries[prim_obj] = MonitoredEntry(
                obj_start, self.obj_values[prim_obj].set_id,
                self.obj_values[prim_obj].get_id)
            obj_step = self.top.get_object('%s_step' % prim_obj)
            self.step_entries[prim_obj] = MonitoredEntry(
                obj_step,
                self.obj_values[prim_obj].set_step,
                self.obj_values[prim_obj].get_step,
                changed=self.obj_values[prim_obj].change_step)
            obj_keep = self.top.get_object('%s_keep' % prim_obj)
            self.keep_entries[prim_obj] = MonitoredCheckbox(
                obj_keep,
                obj_keep,
                self.obj_values[prim_obj].set_keep,
                self.obj_values[prim_obj].get_keep,
                readonly=True)

        # fetch the popup menu
        self.menu = self.top.get_object("popup_menu")

        # ok, let's see what we've done
        self.show()

    def _update(self):
        """ store changed objects formats in DB """

        update = False
        for prim_obj, tmp in self.xobjects:
            obj_value = self.obj_values[prim_obj]
            if obj_value.object_fmt != obj_value.stored_fmt:
                prefix = obj_value.object_prefix.lower()
                constant = 'preferences.%sprefix' % prefix
                config.set(constant, obj_value.object_fmt)
                update = True

        if update:
            config.save()
            self.dbstate.set_prefixes(config.get('preferences.iprefix'),
                                      config.get('preferences.oprefix'),
                                      config.get('preferences.fprefix'),
                                      config.get('preferences.sprefix'),
                                      config.get('preferences.cprefix'),
                                      config.get('preferences.pprefix'),
                                      config.get('preferences.eprefix'),
                                      config.get('preferences.rprefix'),
                                      config.get('preferences.nprefix'))

    def _execute(self):
        """ execute all primary objects and reorder if neccessary """

        # Update progress calculation
        if self.uistate:
            self.progress = ProgressMeter(_('Reorder Gramps IDs'), '')
        else:
            total_objs = 0
            for prim_obj, tmp in self.xobjects:
                if self.obj_values[prim_obj].active_obj:
                    total_objs += self.obj_values[prim_obj].quant_id
            self.set_total(total_objs)

        # Update database
        self.dbstate.disable_signals()
        for prim_obj, prim_objs in self.xobjects:
            with DbTxn(_('Reorder %s IDs ...') % prim_obj, self.dbstate, batch=True) \
            as self.trans:
                if self.obj_values[prim_obj].active_obj:
                    if self.uistate:
                        self.progress.set_pass(_('Reorder %s IDs ...') % \
                                               _(prim_objs.title()), \
                                               self.obj_values[prim_obj].quant_id)
                    # Process reordering
                    self._reorder(prim_obj)

        self.dbstate.enable_signals()
        self.dbstate.request_rebuild()

        # Update progress calculation
        if self.uistate:
            self.progress.close()
        else:
            print('\nDone.')

    # finds integer portion in a GrampsID
    _findint = re.compile('^[^\d]*(\d+)[^\d]*')

    def _reorder(self, prim_obj):
        """ reorders all selected objects with a (new) style, start & step """

        dup_ids = []  # list of duplicate identifiers
        new_ids = {}  # list of new identifiers

        class_type, iter_handles, commit, get_from_id, get_from_handle, next_from_id = \
            self.obj_methods[prim_obj]

        prefix_fmt = self.obj_values[prim_obj].get_fmt()
        prefix = prefix_fmt.split('%', 1)[0]
        new_id = self.obj_values[prim_obj].get_id()
        keep_fmt = self.obj_values[prim_obj].get_keep()
        change = self.obj_values[prim_obj].get_change()

        formatmatch = _parseformat.match(prefix_fmt)
        index_max = int("9" * int(formatmatch.groups()[0]))

        for handle in iter_handles():
            # Update progress
            if self.uistate:
                self.progress.step()
            else:
                self.update()

            # extract basic data out of the database
            obj = get_from_handle(handle)

            act_id = obj.get_gramps_id()
            if change:
                # update the defined ID numbers into objects under consideration
                # of keeping ID if format not matches prefix
                # (implication logical boolean operator below)
                if act_id.startswith(prefix) or not keep_fmt:
                    obj.set_gramps_id(new_id)
                    commit(obj, self.trans)
                    new_id = self.obj_values[prim_obj].succ_id()
            else:
                # attempt to extract integer - if we can't, treat it as a duplicate
                try:
                    match = _findint.match(act_id)
                    if match:
                        # get the integer, build the new handle. Make sure it
                        # hasn't already been chosen. If it has, put this
                        # in the duplicate handle list

                        index = int(match.groups()[0])
                        if formatmatch:
                            if index > index_max:
                                new_id = next_from_id()
                            else:
                                new_id = prefix_fmt % index
                        else:
                            # prefix_fmt does not contain a number after %, eg I%d
                            new_id = prefix_fmt % index

                        if new_id == act_id:
                            if new_id in new_ids:
                                dup_ids.append(obj.get_handle())
                            else:
                                new_ids[new_id] = act_id
                        elif get_from_id(new_id) is not None:
                            dup_ids.append(obj.get_handle())
                        else:
                            obj.set_id(new_id)
                            commit(obj, self.trans)
                            new_ids[new_id] = act_id
                    else:
                        dup_ids.append(handle)
                except:
                    dup_ids.append(handle)

        # go through the duplicates, looking for the first available
        # handle that matches the new scheme.
        if dup_ids:
            if self.uistate:
                self.progress.set_pass(_('Finding and assigning unused IDs.'),
                                       len(dup_ids))
            for handle in dup_ids:
                obj = get_from_handle(handle)
                obj.set_gramps_id(next_from_id())
                commit(obj, self.trans)
Beispiel #17
0
class DisplayChart(ManagedWindow):
    def __init__(self, dbstate, uistate, people_list, track):
        self.dbstate = dbstate
        self.uistate = uistate

        ManagedWindow.__init__(self, uistate, track, self)

        self.db = dbstate.db
        self.my_list = people_list
        self.row_data = []
        self.save_form = None

        self.topDialog = Glade()
        self.topDialog.connect_signals(
            {
                "on_write_table": self.on_write_table,
                "destroy_passed_object": self.close,
                "on_help_clicked": self.on_help_clicked,
                "on_apply_clicked": self.__dummy,
                "on_editor_clicked": self.__dummy,
            }
        )

        window = self.topDialog.toplevel
        self.set_window(window, self.topDialog.get_object("title"), _("Event Comparison Results"))

        self.eventlist = self.topDialog.get_object("treeview")
        self.sort = Sort(self.db)
        self.my_list.sort(key=self.sort.by_last_name_key)

        self.event_titles = self.make_event_titles()

        self.table_titles = [_("Person"), _("ID")]
        for event_name in self.event_titles:
            self.table_titles.append(_("%(event_name)s Date") % {"event_name": event_name})
            self.table_titles.append("sort")  # This won't be shown in a tree
            self.table_titles.append(_("%(event_name)s Place") % {"event_name": event_name})

        self.build_row_data()
        self.draw_display()
        self.show()

    def __dummy(self, obj):
        """dummy callback, needed because widget is in same glade file
        as another widget, so callbacks must be defined to avoid warnings.
        """
        pass

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def build_menu_names(self, obj):
        return (_("Event Comparison Results"), None)

    def draw_display(self):

        model_index = 0
        tree_index = 0
        mylist = []
        renderer = Gtk.CellRendererText()
        for title in self.table_titles:
            mylist.append(str)
            if title == "sort":
                # This will override the previously defined column
                self.eventlist.get_column(tree_index - 1).set_sort_column_id(model_index)
            else:
                column = Gtk.TreeViewColumn(title, renderer, text=model_index)
                column.set_sort_column_id(model_index)
                self.eventlist.append_column(column)
                # This one numbers the tree columns: increment on new column
                tree_index += 1
            # This one numbers the model columns: always increment
            model_index += 1

        model = Gtk.ListStore(*mylist)
        self.eventlist.set_model(model)

        self.progress_bar.set_pass(_("Building display"), len(self.row_data))
        for data in self.row_data:
            model.append(row=list(data))
            self.progress_bar.step()
        self.progress_bar.close()

    def build_row_data(self):
        self.progress_bar = ProgressMeter(_("Comparing Events"), "", parent=self.window)
        self.progress_bar.set_pass(_("Building data"), len(self.my_list))
        for individual_id in self.my_list:
            individual = self.db.get_person_from_handle(individual_id)
            name = individual.get_primary_name().get_name()
            gid = individual.get_gramps_id()

            the_map = defaultdict(list)
            for ievent_ref in individual.get_event_ref_list():
                ievent = self.db.get_event_from_handle(ievent_ref.ref)
                event_name = str(ievent.get_type())
                the_map[event_name].append(ievent_ref.ref)

            first = True
            done = False
            while not done:
                added = False
                tlist = [name, gid] if first else ["", ""]

                for ename in self.event_titles:
                    if ename in the_map and len(the_map[ename]) > 0:
                        event_handle = the_map[ename][0]
                        del the_map[ename][0]
                        date = place = ""

                        if event_handle:
                            event = self.db.get_event_from_handle(event_handle)
                            date = get_date(event)
                            sortdate = "%09d" % (event.get_date_object().get_sort_value())
                            place_handle = event.get_place_handle()
                            if place_handle:
                                place = self.db.get_place_from_handle(place_handle).get_title()
                        tlist += [date, sortdate, place]
                        added = True
                    else:
                        tlist += [""] * 3

                if first:
                    first = False
                    self.row_data.append(tlist)
                elif not added:
                    done = True
                else:
                    self.row_data.append(tlist)
            self.progress_bar.step()

    def make_event_titles(self):
        """
        Create the list of unique event types, along with the person's
        name, birth, and death.
        This should be the column titles of the report.
        """
        the_map = defaultdict(int)
        for individual_id in self.my_list:
            individual = self.db.get_person_from_handle(individual_id)
            for event_ref in individual.get_event_ref_list():
                event = self.db.get_event_from_handle(event_ref.ref)
                name = str(event.get_type())
                if not name:
                    break
                the_map[name] += 1

        unsort_list = sorted([(d, k) for k, d in the_map.items()], key=lambda x: x[0], reverse=True)

        sort_list = [item[1] for item in unsort_list]
        ## Presently there's no Birth and Death. Instead there's Birth Date and
        ## Birth Place, as well as Death Date and Death Place.
        ##         # Move birth and death to the begining of the list
        ##         if _("Death") in the_map:
        ##             sort_list.remove(_("Death"))
        ##             sort_list = [_("Death")] + sort_list

        ##         if _("Birth") in the_map:
        ##             sort_list.remove(_("Birth"))
        ##             sort_list = [_("Birth")] + sort_list

        return sort_list

    def on_write_table(self, obj):
        f = Gtk.FileChooserDialog(
            _("Select filename"),
            parent=self.window,
            action=Gtk.FileChooserAction.SAVE,
            buttons=(_("_Cancel"), Gtk.ResponseType.CANCEL, _("_Save"), Gtk.ResponseType.OK),
        )

        f.set_current_folder(get_curr_dir())
        status = f.run()
        f.hide()

        if status == Gtk.ResponseType.OK:
            name = conv_to_unicode(f.get_filename())
            doc = ODSTab(len(self.row_data))
            doc.creator(self.db.get_researcher().get_name())

            spreadsheet = TableReport(name, doc)

            new_titles = []
            skip_columns = []
            index = 0
            for title in self.table_titles:
                if title == "sort":
                    skip_columns.append(index)
                else:
                    new_titles.append(title)
                index += 1
            spreadsheet.initialize(len(new_titles))

            spreadsheet.write_table_head(new_titles)

            index = 0
            for top in self.row_data:
                spreadsheet.set_row(index % 2)
                index += 1
                spreadsheet.write_table_data(top, skip_columns)

            spreadsheet.finalize()
        f.destroy()
Beispiel #18
0
class EventComparisonResults(ManagedWindow):
    def __init__(self, dbstate, uistate, people_list, track):
        self.dbstate = dbstate
        self.uistate = uistate

        ManagedWindow.__init__(self, uistate, track, self)

        self.db = dbstate.db
        self.my_list = people_list
        self.row_data = []
        self.save_form = None

        self.topDialog = Glade(toplevel="eventcmp")
        self.topDialog.connect_signals({
            "on_write_table": self.on_write_table,
            "destroy_passed_object": self.close,
            "on_help_clicked": self.on_help_clicked,
            "on_apply_clicked": self.__dummy,
            "on_editor_clicked": self.__dummy,
        })

        window = self.topDialog.toplevel
        self.set_window(window, self.topDialog.get_object('title'),
                        _('Event Comparison Results'))
        self.setup_configs('interface.eventcomparisonresults', 750, 400)

        self.eventlist = self.topDialog.get_object('treeview')
        self.sort = Sort(self.db)
        self.my_list.sort(key=self.sort.by_last_name_key)

        self.event_titles = self.make_event_titles()

        self.table_titles = [_("Person"), _("ID")]
        for event_name in self.event_titles:
            self.table_titles.append(
                _("%(event_name)s Date") % {'event_name': event_name})
            self.table_titles.append('sort')  # This won't be shown in a tree
            self.table_titles.append(
                _("%(event_name)s Place") % {'event_name': event_name})

        self.build_row_data()
        self.draw_display()
        self.show()

    def __dummy(self, obj):
        """dummy callback, needed because widget is in same glade file
        as another widget, so callbacks must be defined to avoid warnings.
        """
        pass

    def on_help_clicked(self, obj):
        """Display the relevant portion of Gramps manual"""
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def build_menu_names(self, obj):
        return (_("Event Comparison Results"), None)

    def draw_display(self):

        model_index = 0
        tree_index = 0
        mylist = []
        renderer = Gtk.CellRendererText()
        for title in self.table_titles:
            mylist.append(str)
            if title == 'sort':
                # This will override the previously defined column
                self.eventlist.get_column(tree_index -
                                          1).set_sort_column_id(model_index)
            else:
                column = Gtk.TreeViewColumn(title, renderer, text=model_index)
                column.set_sort_column_id(model_index)
                self.eventlist.append_column(column)
                # This one numbers the tree columns: increment on new column
                tree_index += 1
            # This one numbers the model columns: always increment
            model_index += 1

        model = Gtk.ListStore(*mylist)
        self.eventlist.set_model(model)

        self.progress_bar.set_pass(_('Building display'), len(self.row_data))
        for data in self.row_data:
            model.append(row=list(data))
            self.progress_bar.step()
        self.progress_bar.close()

    def build_row_data(self):
        self.progress_bar = ProgressMeter(_('Comparing Events'),
                                          '',
                                          parent=self.uistate.window)
        self.progress_bar.set_pass(_('Building data'), len(self.my_list))
        for individual_id in self.my_list:
            individual = self.db.get_person_from_handle(individual_id)
            name = individual.get_primary_name().get_name()
            gid = individual.get_gramps_id()

            the_map = defaultdict(list)
            for ievent_ref in individual.get_event_ref_list():
                ievent = self.db.get_event_from_handle(ievent_ref.ref)
                event_name = str(ievent.get_type())
                the_map[event_name].append(ievent_ref.ref)

            first = True
            done = False
            while not done:
                added = False
                tlist = [name, gid] if first else ["", ""]

                for ename in self.event_titles:
                    if ename in the_map and len(the_map[ename]) > 0:
                        event_handle = the_map[ename][0]
                        del the_map[ename][0]
                        date = place = ""

                        if event_handle:
                            event = self.db.get_event_from_handle(event_handle)
                            date = get_date(event)
                            sortdate = "%09d" % (
                                event.get_date_object().get_sort_value())
                            place_handle = event.get_place_handle()
                            if place_handle:
                                place = self.db.get_place_from_handle(
                                    place_handle).get_title()
                        tlist += [date, sortdate, place]
                        added = True
                    else:
                        tlist += [""] * 3

                if first:
                    first = False
                    self.row_data.append(tlist)
                elif not added:
                    done = True
                else:
                    self.row_data.append(tlist)
            self.progress_bar.step()

    def make_event_titles(self):
        """
        Create the list of unique event types, along with the person's
        name, birth, and death.
        This should be the column titles of the report.
        """
        the_map = defaultdict(int)
        for individual_id in self.my_list:
            individual = self.db.get_person_from_handle(individual_id)
            for event_ref in individual.get_event_ref_list():
                event = self.db.get_event_from_handle(event_ref.ref)
                name = str(event.get_type())
                if not name:
                    break
                the_map[name] += 1

        unsort_list = sorted([(d, k) for k, d in the_map.items()],
                             key=lambda x: x[0],
                             reverse=True)

        sort_list = [item[1] for item in unsort_list]
        ## Presently there's no Birth and Death. Instead there's Birth Date and
        ## Birth Place, as well as Death Date and Death Place.
        ##         # Move birth and death to the begining of the list
        ##         if _("Death") in the_map:
        ##             sort_list.remove(_("Death"))
        ##             sort_list = [_("Death")] + sort_list

        ##         if _("Birth") in the_map:
        ##             sort_list.remove(_("Birth"))
        ##             sort_list = [_("Birth")] + sort_list

        return sort_list

    def on_write_table(self, obj):
        f = Gtk.FileChooserDialog(_("Select filename"),
                                  parent=self.window,
                                  action=Gtk.FileChooserAction.SAVE,
                                  buttons=(_('_Cancel'),
                                           Gtk.ResponseType.CANCEL, _('_Save'),
                                           Gtk.ResponseType.OK))

        f.set_current_folder(get_curr_dir())
        status = f.run()
        f.hide()

        if status == Gtk.ResponseType.OK:
            name = f.get_filename()
            doc = ODSTab(len(self.row_data))
            doc.creator(self.db.get_researcher().get_name())

            spreadsheet = TableReport(name, doc)

            new_titles = []
            skip_columns = []
            index = 0
            for title in self.table_titles:
                if title == 'sort':
                    skip_columns.append(index)
                else:
                    new_titles.append(title)
                index += 1
            spreadsheet.initialize(len(new_titles))

            spreadsheet.write_table_head(new_titles)

            index = 0
            for top in self.row_data:
                spreadsheet.set_row(index % 2)
                index += 1
                spreadsheet.write_table_data(top, skip_columns)

            spreadsheet.finalize()
        f.destroy()
Beispiel #19
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.title = _('Find database loop')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        #self.db = CacheProxyDb(dbstate.db)
        self.db = dbstate.db

        top_dialog = Glade()

        top_dialog.connect_signals({
            "destroy_passed_object" : self.close,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_event"       : self.close,
        })

        window = top_dialog.toplevel
        title = top_dialog.get_object("title")
        self.set_window(window, title, self.title)

        # start the progress indicator
        self.progress = ProgressMeter(self.title, _('Starting'),
                                      parent=uistate.window)
        self.progress.set_pass(_('Looking for possible loop for each person'),
                               self.db.get_number_of_people())

        self.model = Gtk.ListStore(
            GObject.TYPE_STRING,    # 0==father id
            GObject.TYPE_STRING,    # 1==father
            GObject.TYPE_STRING,    # 2==son id
            GObject.TYPE_STRING,    # 3==son
            GObject.TYPE_STRING,    # 4==family gid
            GObject.TYPE_STRING)    # 5==loop number
        self.model.set_sort_column_id(
            Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 0)

        self.treeview = top_dialog.get_object("treeview")
        self.treeview.set_model(self.model)
        col0 = Gtk.TreeViewColumn('',
                                  Gtk.CellRendererText(), text=5)
        col1 = Gtk.TreeViewColumn(_('Gramps ID'),
                                  Gtk.CellRendererText(), text=0)
        col2 = Gtk.TreeViewColumn(_('Parent'),
                                  Gtk.CellRendererText(), text=1)
        col3 = Gtk.TreeViewColumn(_('Gramps ID'),
                                  Gtk.CellRendererText(), text=2)
        col4 = Gtk.TreeViewColumn(_('Child'),
                                  Gtk.CellRendererText(), text=3)
        col5 = Gtk.TreeViewColumn(_('Family ID'),
                                  Gtk.CellRendererText(), text=4)
        col1.set_resizable(True)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col5.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.treeview.append_column(col0)
        self.treeview.append_column(col1)
        self.treeview.append_column(col2)
        self.treeview.append_column(col3)
        self.treeview.append_column(col4)
        self.treeview.append_column(col5)
        self.treeselection = self.treeview.get_selection()
        self.treeview.connect('row-activated', self.rowactivated_cb)

        self.curr_fam = None
        people = self.db.get_person_handles()
        self.total = len(people)  # total number of people to process.
        self.count = 0  # current number of people completely processed
        self.loop = 0  # Number of loops found for GUI

        pset = OrderedDict()
        # pset is the handle list of persons from the current start of
        # exploration path to the current limit.  The use of OrderedDict
        # allows us to use it as a LIFO during recursion, as well as makes for
        # quick lookup.  If we find a loop, pset provides a nice way to get
        # the loop path.
        self.done = set()
        # self.done is the handle set of people that have been fully explored
        # and do NOT have loops in the decendent tree.  We use this to avoid
        # repeating work when we encounter one of these during the search.
        for person_handle in people:
            person = self.db.get_person_from_handle(person_handle)
            self.current = person
            self.parent = None
            self.descendants(person_handle, pset)

        # close the progress bar
        self.progress.close()

        self.show()
class ChangeGivenNames(tool.BatchTool, ManagedWindow):

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Capitalization changes')
        self.dbstate = dbstate
        self.uistate = uistate
        self.cb = callback

        ManagedWindow.__init__(self,uistate,[],self.__class__)
        self.set_window(Gtk.Window(),Gtk.Label(),'')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        given_name_dict = self.get_given_name_dict()

        self.progress = ProgressMeter(_('Checking Given Names'),'',
                                      parent=uistate.window)
        self.progress.set_pass(_('Searching given names'),
                               len(given_name_dict.keys()))
        self.name_list = []

        for name in given_name_dict.keys():
            if name != capitalize(name):
                self.name_list.append((name, given_name_dict[name]))

            if uistate:
                self.progress.step()

        if self.name_list:
            self.display()
        else:
            self.progress.close()
            self.close()
            OkDialog(_('No modifications made'),
                     _("No capitalization changes were detected."),
                     parent=uistate.window)

    def get_given_name_dict(self):
        givennames = {}
        self.name_map = {}
        for person in self.db.iter_people():
            allnames = [person.get_primary_name()] + person.get_alternate_names()
            allnames = set(name.get_first_name().strip() for name in allnames)
            for givenname in allnames:
                givennames[givenname] = givennames.get(givenname, 0) + 1
                self.name_map[givenname] = self.name_map.get(givenname, set([]))
                self.name_map[givenname].add(person.handle)
        return givennames

    def display(self):

        if lin():
            import locale, os
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            base = os.path.dirname(__file__)
            locale.bindtextdomain("addon", base + "/locale")

            self.glade = Gtk.Builder()
            self.glade.set_translation_domain("addon")

            path = base + "/changenames.glade"
            self.glade.add_from_file(path)

            #from gi.repository import GObject
            GObject.GObject.__init__(self.glade)

            self.top = self.glade.get_object('changenames')

            self.glade.connect_signals({
                "destroy_passed_object" : self.close,
                "on_ok_clicked" : self.on_ok_clicked,
                "on_help_clicked" : self.on_help_clicked,
                "on_edit_clicked" : self.on_edit_clicked,
                "on_delete_event"   : self.close,
                })

            self.list = self.glade.get_object("list")
            self.set_window(self.top, self.glade.get_object('title'), self.label)

        else:
            self.top = Glade("changenames.glade")

            window = self.top.toplevel
            self.top.connect_signals({
                "destroy_passed_object" : self.close,
                "on_ok_clicked" : self.on_ok_clicked,
                "on_help_clicked" : self.on_help_clicked,
                "on_edit_clicked" : self.on_edit_clicked,
                "on_delete_event"   : self.close,
                })

            self.list = self.top.get_object("list")
            self.set_window(window,self.top.get_object('title'),self.label)

        # selected, original name, changed, count
        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING, GObject.TYPE_INT)
        self.handles = {}

        r = Gtk.CellRendererToggle()
        r.connect('toggled',self.toggled)
        c = Gtk.TreeViewColumn(_('Select'),r,active=0)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Original Name'),
                               Gtk.CellRendererText(),text=1)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Capitalization Change'),
                               Gtk.CellRendererText(),text=2)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Affected Names'),
                               Gtk.CellRendererText(),text=3)
        self.list.append_column(c)

        self.list.set_model(self.model)

        self.iter_list = []
        self.progress.set_pass(_('Building display'),len(self.name_list))
        for name, count in self.name_list:
            handle = self.model.append()
            self.model.set_value(handle,0, False)
            self.model.set_value(handle,1, name)
            namecap = capitalize(name)
            self.model.set_value(handle,2, namecap)
            self.model.set_value(handle,3, count)
            self.iter_list.append(handle)
            self.progress.step()
        self.progress.close()

        self.show()

    def toggled(self,cell,path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]

    def build_menu_names(self, obj):
        return (self.label,None)

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(WIKI_HELP_PAGE , WIKI_HELP_SEC)

    def on_edit_clicked(self, button):
        """Edit the selected person"""
        from gramps.gui.editors import EditPerson
        selection = self.list.get_selection()
        store, paths = selection.get_selected_rows()
        tpath = paths[0] if len(paths) > 0 else None
        node = store.get_iter(tpath) if tpath else None
        if node:
            name = store.get_value(node, 1)
            for handle in self.name_map[name]:
                person = self.dbstate.db.get_person_from_handle(handle)
                EditPerson(self.dbstate, self.uistate, [], person)

    def on_ok_clicked(self, obj):
        with DbTxn(_("Capitalization changes"), self.db, batch=True
                   ) as self.trans:
            self.db.disable_signals()
            changelist = set(self.model.get_value(node,1)
                             for node in self.iter_list
                                if self.model.get_value(node,0))

            for handle in self.db.get_person_handles(False):
                person = self.db.get_person_from_handle(handle)
                change = False
                for name in [person.get_primary_name()] + person.get_alternate_names():
                    if name.first_name in changelist:
                        change = True
                        fname = capitalize(name.first_name)
                        name.set_first_name(fname)
                if change:
                    self.db.commit_person(person, self.trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        self.close()
        self.cb()
Beispiel #21
0
class ChangeGivenNames(tool.BatchTool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Capitalization changes')
        self.dbstate = dbstate
        self.uistate = uistate
        self.cb = callback

        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.set_window(Gtk.Window(), Gtk.Label(), '')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        given_name_dict = self.get_given_name_dict()

        self.progress = ProgressMeter(_('Checking Given Names'),
                                      '',
                                      parent=uistate.window)
        self.progress.set_pass(_('Searching given names'),
                               len(given_name_dict.keys()))
        self.name_list = []

        for name in given_name_dict.keys():
            if name != capitalize(name):
                self.name_list.append((name, given_name_dict[name]))

            if uistate:
                self.progress.step()

        if self.name_list:
            self.display()
        else:
            self.progress.close()
            self.close()
            OkDialog(_('No modifications made'),
                     _("No capitalization changes were detected."),
                     parent=uistate.window)

    def get_given_name_dict(self):
        givennames = {}
        self.name_map = {}
        for person in self.db.iter_people():
            allnames = [person.get_primary_name()
                        ] + person.get_alternate_names()
            allnames = set(name.get_first_name().strip() for name in allnames)
            for givenname in allnames:
                givennames[givenname] = givennames.get(givenname, 0) + 1
                self.name_map[givenname] = self.name_map.get(
                    givenname, set([]))
                self.name_map[givenname].add(person.handle)
        return givennames

    def display(self):

        if lin():
            import locale, os
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            base = os.path.dirname(__file__)
            locale.bindtextdomain("addon", base + "/locale")

            self.glade = Gtk.Builder()
            self.glade.set_translation_domain("addon")

            path = base + "/changenames.glade"
            self.glade.add_from_file(path)

            #from gi.repository import GObject
            GObject.GObject.__init__(self.glade)

            self.top = self.glade.get_object('changenames')

            self.glade.connect_signals({
                "destroy_passed_object": self.close,
                "on_ok_clicked": self.on_ok_clicked,
                "on_help_clicked": self.on_help_clicked,
                "on_edit_clicked": self.on_edit_clicked,
                "on_delete_event": self.close,
            })

            self.list = self.glade.get_object("list")
            self.set_window(self.top, self.glade.get_object('title'),
                            self.label)

        else:
            self.top = Glade("changenames.glade")

            window = self.top.toplevel
            self.top.connect_signals({
                "destroy_passed_object": self.close,
                "on_ok_clicked": self.on_ok_clicked,
                "on_help_clicked": self.on_help_clicked,
                "on_edit_clicked": self.on_edit_clicked,
                "on_delete_event": self.close,
            })

            self.list = self.top.get_object("list")
            self.set_window(window, self.top.get_object('title'), self.label)

        # selected, original name, changed, count
        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING, GObject.TYPE_INT)
        self.handles = {}

        r = Gtk.CellRendererToggle()
        r.connect('toggled', self.toggled)
        c = Gtk.TreeViewColumn(_('Select'), r, active=0)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Original Name'),
                               Gtk.CellRendererText(),
                               text=1)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Capitalization Change'),
                               Gtk.CellRendererText(),
                               text=2)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Affected Names'),
                               Gtk.CellRendererText(),
                               text=3)
        self.list.append_column(c)

        self.list.set_model(self.model)

        self.iter_list = []
        self.progress.set_pass(_('Building display'), len(self.name_list))
        for name, count in self.name_list:
            handle = self.model.append()
            self.model.set_value(handle, 0, False)
            self.model.set_value(handle, 1, name)
            namecap = capitalize(name)
            self.model.set_value(handle, 2, namecap)
            self.model.set_value(handle, 3, count)
            self.iter_list.append(handle)
            self.progress.step()
        self.progress.close()

        self.show()

    def toggled(self, cell, path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]

    def build_menu_names(self, obj):
        return (self.label, None)

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(WIKI_HELP_PAGE, WIKI_HELP_SEC)

    def on_edit_clicked(self, button):
        """Edit the selected person"""
        from gramps.gui.editors import EditPerson
        selection = self.list.get_selection()
        store, paths = selection.get_selected_rows()
        tpath = paths[0] if len(paths) > 0 else None
        node = store.get_iter(tpath) if tpath else None
        if node:
            name = store.get_value(node, 1)
            for handle in self.name_map[name]:
                person = self.dbstate.db.get_person_from_handle(handle)
                EditPerson(self.dbstate, self.uistate, [], person)

    def on_ok_clicked(self, obj):
        with DbTxn(_("Capitalization changes"), self.db,
                   batch=True) as self.trans:
            self.db.disable_signals()
            changelist = set(
                self.model.get_value(node, 1) for node in self.iter_list
                if self.model.get_value(node, 0))

            for handle in self.db.get_person_handles(False):
                person = self.db.get_person_from_handle(handle)
                change = False
                for name in [person.get_primary_name()
                             ] + person.get_alternate_names():
                    if name.first_name in changelist:
                        change = True
                        fname = capitalize(name.first_name)
                        name.set_first_name(fname)
                if change:
                    self.db.commit_person(person, self.trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        self.close()
        self.cb()
Beispiel #22
0
class ExtractCity(tool.BatchTool, ManagedWindow):
    """
    Extracts city, state, and zip code information from an place description
    if the title is empty and the description falls into the category of:

       New York, NY 10000

    Sorry for those not in the US or Canada. I doubt this will work for any
    other locales.
    Works for Sweden if the decriptions is like
        Stockholm (A)
    where the letter A is the abbreviation letter for laen.
    Works for France if the description is like
        Paris, IDF 75000, FRA
    or  Paris, ILE DE FRANCE 75000, FRA
    """

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Extract Place data')

        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.set_window(Gtk.Window(), Gtk.Label(), '')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)

        if not self.fail:
            uistate.set_busy_cursor(True)
            self.run(dbstate.db)
            uistate.set_busy_cursor(False)

    def run(self, db):
        """
        Performs the actual extraction of information
        """

        self.progress = ProgressMeter(_('Checking Place Titles'), '')
        self.progress.set_pass(_('Looking for place fields'),
                               self.db.get_number_of_places())

        self.name_list = []
        self.place_import = PlaceImport(db)

        for place in db.iter_places():
            descr = place_displayer.display(db, place)
            self.progress.step()

            loc = get_main_location(db, place)
            location = ((loc.get(PlaceType.STREET, '')),
                        (loc.get(PlaceType.LOCALITY, '')),
                        (loc.get(PlaceType.PARISH, '')),
                        (loc.get(PlaceType.CITY, '')),
                        (loc.get(PlaceType.COUNTY, '')),
                        (loc.get(PlaceType.STATE, '')),
                        (loc.get(PlaceType.COUNTRY, '')))
            self.place_import.store_location(location, place.handle)

            if len(place.get_placeref_list()) == 0:

                match = CITY_STATE_ZIP.match(descr.strip())
                if match:
                    data = match.groups()
                    city = data[0]
                    state = data[2]
                    postal = data[5]

                    val = " ".join(state.strip().split()).upper()
                    if state:
                        new_state = STATE_MAP.get(val.upper())
                        if new_state:
                            self.name_list.append(
                                (place.handle, (city, new_state[0], postal,
                                          COUNTRY[new_state[1]])))
                    continue

                # Check if there is a left parant. in the string, might be Swedish laen.
                match = CITY_LAEN.match(descr.strip().replace(","," "))
                if match:
                    data = match.groups()
                    city = data[0]
                    state = '(' + data[1] + ')'
                    postal = None
                    val = " ".join(state.strip().split()).upper()
                    if state:
                        new_state = STATE_MAP.get(val.upper())
                        if new_state:
                            self.name_list.append(
                                (place.handle, (city, new_state[0], postal,
                                          COUNTRY[new_state[1]])))
                    continue
                match = CITY_STATE.match(descr.strip())
                if match:
                    data = match.groups()
                    city = data[0]
                    state = data[1]
                    postal = None
                    if state:
                        m0 = STATE_ZIP.match(state)
                        if m0:
                            (state, postal) = m0.groups()

                    val = " ".join(state.strip().split()).upper()
                    if state:
                        new_state = STATE_MAP.get(val.upper())
                        if new_state:
                            self.name_list.append(
                                (place.handle, (city, new_state[0], postal,
                                          COUNTRY[new_state[1]])))
                    continue

                val = " ".join(descr.strip().split()).upper()
                new_state = STATE_MAP.get(val)
                if new_state:
                    self.name_list.append(
                        (place.handle, (None, new_state[0], None,
                                  COUNTRY[new_state[1]])))
        self.progress.close()

        if self.name_list:
            self.display()
        else:
            self.close()
            from gramps.gui.dialog import OkDialog
            OkDialog(_('No modifications made'),
                     _("No place information could be extracted."))

    def display(self):

        self.top = Glade("changenames.glade")
        window = self.top.toplevel
        self.top.connect_signals({
            "destroy_passed_object" : self.close,
            "on_ok_clicked" : self.on_ok_clicked,
            "on_help_clicked" : self.on_help_clicked,
            "on_delete_event"   : self.close,
            })

        self.list = self.top.get_object("list")
        self.set_window(window, self.top.get_object('title'), self.label)
        lbl = self.top.get_object('info')
        lbl.set_line_wrap(True)
        lbl.set_text(
            _('Below is a list of Places with the possible data that can '
              'be extracted from the place title. Select the places you '
              'wish Gramps to convert.'))

        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING)

        r = Gtk.CellRendererToggle()
        r.connect('toggled', self.toggled)
        c = Gtk.TreeViewColumn(_('Select'), r, active=0)
        self.list.append_column(c)

        for (title, col) in COLS:
            render = Gtk.CellRendererText()
            if col > 1:
                render.set_property('editable', True)
                render.connect('edited', self.__change_name, col)

            self.list.append_column(
                Gtk.TreeViewColumn(title, render, text=col))
        self.list.set_model(self.model)

        self.iter_list = []
        self.progress.set_pass(_('Building display'), len(self.name_list))
        for (id, data) in self.name_list:

            place = self.db.get_place_from_handle(id)
            descr = place_displayer.display(self.db, place)

            handle = self.model.append()
            self.model.set_value(handle, 0, True)
            self.model.set_value(handle, 1, descr)
            if data[0]:
                self.model.set_value(handle, 2, data[0])
            if data[1]:
                self.model.set_value(handle, 3, data[1])
            if data[2]:
                self.model.set_value(handle, 4, data[2])
            if data[3]:
                self.model.set_value(handle, 5, data[3])
            self.model.set_value(handle, 6, id)
            self.iter_list.append(handle)
            self.progress.step()
        self.progress.close()

        self.show()

    def __change_name(self, text, path, new_text, col):
        self.model[path][col] = new_text
        return

    def toggled(self, cell, path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]

    def build_menu_names(self, obj):
        return (self.label, None)

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help()

    def on_ok_clicked(self, obj):
        with DbTxn(_("Extract Place data"), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            changelist = [node for node in self.iter_list
                          if self.model.get_value(node, 0)]

            for change in changelist:
                row = self.model[change]
                place = self.db.get_place_from_handle(row[6])
                location = ('', '', '', row[2], '', row[3], row[5])
                self.place_import.store_location(location, place.handle)
                if row[2]:
                    place.set_name(PlaceName(value=row[2]))
                place.set_type(PlaceType.CITY)
                if row[4]:
                    place.set_code(row[4])
                self.db.commit_place(place, self.trans)

            self.place_import.generate_hierarchy(self.trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        self.close()
Beispiel #23
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.title = _('Find database loop')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        #self.db = CacheProxyDb(dbstate.db)
        self.db = dbstate.db

        top_dialog = Glade()

        top_dialog.connect_signals({
            "destroy_passed_object": self.close,
            "on_help_clicked": self.on_help_clicked,
            "on_delete_event": self.close,
        })

        window = top_dialog.toplevel
        title = top_dialog.get_object("title")
        self.set_window(window, title, self.title)

        # start the progress indicator
        self.progress = ProgressMeter(self.title,
                                      _('Starting'),
                                      parent=uistate.window)
        self.progress.set_pass(_('Looking for possible loop for each person'),
                               self.db.get_number_of_people())

        self.model = Gtk.ListStore(
            GObject.TYPE_STRING,  # 0==father id
            GObject.TYPE_STRING,  # 1==father
            GObject.TYPE_STRING,  # 2==son id
            GObject.TYPE_STRING,  # 3==son
            GObject.TYPE_STRING,  # 4==family gid
            GObject.TYPE_STRING)  # 5==loop number
        self.model.set_sort_column_id(
            Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 0)

        self.treeview = top_dialog.get_object("treeview")
        self.treeview.set_model(self.model)
        col0 = Gtk.TreeViewColumn('', Gtk.CellRendererText(), text=5)
        col1 = Gtk.TreeViewColumn(_('Gramps ID'),
                                  Gtk.CellRendererText(),
                                  text=0)
        col2 = Gtk.TreeViewColumn(_('Parent'), Gtk.CellRendererText(), text=1)
        col3 = Gtk.TreeViewColumn(_('Gramps ID'),
                                  Gtk.CellRendererText(),
                                  text=2)
        col4 = Gtk.TreeViewColumn(_('Child'), Gtk.CellRendererText(), text=3)
        col5 = Gtk.TreeViewColumn(_('Family ID'),
                                  Gtk.CellRendererText(),
                                  text=4)
        col1.set_resizable(True)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col5.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.treeview.append_column(col0)
        self.treeview.append_column(col1)
        self.treeview.append_column(col2)
        self.treeview.append_column(col3)
        self.treeview.append_column(col4)
        self.treeview.append_column(col5)
        self.treeselection = self.treeview.get_selection()
        self.treeview.connect('row-activated', self.rowactivated_cb)

        self.curr_fam = None
        people = self.db.get_person_handles()
        self.total = len(people)  # total number of people to process.
        self.count = 0  # current number of people completely processed
        self.loop = 0  # Number of loops found for GUI

        pset = OrderedDict()
        # pset is the handle list of persons from the current start of
        # exploration path to the current limit.  The use of OrderedDict
        # allows us to use it as a LIFO during recursion, as well as makes for
        # quick lookup.  If we find a loop, pset provides a nice way to get
        # the loop path.
        self.done = set()
        # self.done is the handle set of people that have been fully explored
        # and do NOT have loops in the decendent tree.  We use this to avoid
        # repeating work when we encounter one of these during the search.
        for person_handle in people:
            person = self.db.get_person_from_handle(person_handle)
            self.current = person
            self.parent = None
            self.descendants(person_handle, pset)

        # close the progress bar
        self.progress.close()

        self.show()
Beispiel #24
0
class ChangeTypes(tool.BatchTool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.user = user
        self.dbstate = dbstate

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        if uistate:
            self.title = _('Change Event Types')
            ManagedWindow.__init__(self, uistate, [], self.__class__)
            self.init_gui()
        else:
            self.run_tool()

    def init_gui(self):
        # Draw dialog and make it handle everything

        self.glade = Glade()

        self.auto1 = self.glade.get_object("original")
        self.auto2 = self.glade.get_object("new")

        # Need to display localized event names
        etype = EventType()
        custom_events = self.dbstate.db.get_event_types()
        event_names = sorted(etype.get_standard_names() + custom_events,
                             key=glocale.sort_key)

        self.fill_combo(self.auto1, event_names)
        self.fill_combo(self.auto2, event_names)

        etype.set_from_xml_str(self.options.handler.options_dict['fromtype'])
        self.auto1.get_child().set_text(str(etype))

        etype.set_from_xml_str(self.options.handler.options_dict['totype'])
        self.auto2.get_child().set_text(str(etype))

        window = self.glade.toplevel
        self.set_window(window, self.glade.get_object('title'), self.title)
        self.setup_configs('interface.changetypes', 640, 260)

        self.glade.connect_signals({
            "on_close_clicked": self.close,
            "on_apply_clicked": self.on_apply_clicked,
            "on_delete_event": self.close,
        })

        self.show()

    def build_menu_names(self, obj):
        return (self.title, None)

    def run_tool(self, parent_window=None):
        # Run tool and return results
        # These are English names, no conversion needed
        fromtype = self.options.handler.options_dict['fromtype']
        totype = self.options.handler.options_dict['totype']

        modified = 0

        with DbTxn(_('Change types'), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            with self.user.progress(_('Analyzing Events'), '',
                                    self.db.get_number_of_events()) as step:
                for event_handle in self.db.get_event_handles():
                    event = self.db.get_event_from_handle(event_handle)
                    if event.get_type().xml_str() == fromtype:
                        event.type.set_from_xml_str(totype)
                        modified += 1
                        self.db.commit_event(event, self.trans)
                        step()
        self.db.enable_signals()
        self.db.request_rebuild()

        if modified == 0:
            msg = _("No event record was modified.")
        else:
            # Translators: leave all/any {...} untranslated
            msg = ngettext("{number_of} event record was modified.",
                           "{number_of} event records were modified.",
                           modified).format(number_of=modified)

        self.user.info(_('Change types'), msg, parent=parent_window)
        return (bool(modified), msg)

    def on_apply_clicked(self, obj):
        # Need to store English names for later comparison
        the_type = EventType()

        the_type.set(self.auto1.get_child().get_text())
        self.options.handler.options_dict['fromtype'] = the_type.xml_str()

        the_type.set(self.auto2.get_child().get_text())
        self.options.handler.options_dict['totype'] = the_type.xml_str()

        self.run_tool(self.parent_window)

        # Save options
        self.options.handler.save_options()

        self.close()

    def fill_combo(self, combo, data_list):
        """
        Fill a combo box with completion data
        """
        store = Gtk.ListStore(GObject.TYPE_STRING)

        for data in data_list:
            if data:
                store.append(row=[data])

        combo.set_popup_fixed_width(False)
        combo.set_wrap_width(4)
        combo.set_model(store)
        combo.set_entry_text_column(0)
        completion = Gtk.EntryCompletion()
        completion.set_model(store)
        completion.set_minimum_key_length(1)
        completion.set_text_column(0)
        combo.get_child().set_completion(completion)
Beispiel #25
0
class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
    """ Class for Reodering Gramps ID Tool """
    xobjects = (('person', 'people'), ('family', 'families'),
                ('event', 'events'), ('place', 'places'),
                ('source', 'sources'), ('citation', 'citations'),
                ('repository', 'repositories'),
                ('media', 'media'), ('note', 'notes'))

    def build_menu_names_(self, widget=None):
        """ The menu name """
        return (_('Main window'), _("Reorder Gramps IDs"))

    def __init__(self, dbstate, user, options_class, name, callback=None):
        self.uistate = user.uistate
        self.dbstate = dbstate.db

        if self.uistate:
            tool.BatchTool.__init__(self, dbstate, user, options_class, name)
            if self.fail:
                return   # user denied to modify Gramps IDs

        ManagedWindow.__init__(self, self.uistate, [], self.__class__)
        if not self.uistate:
            UpdateCallback.__init__(self, user.callback)

        self.object_status = True
        self.change_status = False
        self.start_zero = True
        self.step_cnt, self.step_list = 0, ['1', '2', '5', '10']
        self.keep_status = True

        self.obj_values = {}   # enable access to all internal values
        self.active_entries, self.format_entries = {}, {}
        self.change_entries = {}
        self.start_entries, self.step_entries = {}, {}
        self.keep_entries = {}

        self.prim_methods, self.obj_methods = {}, {}
        for prim_obj, prim_objs in self.xobjects:
            class_type = prim_obj.title()
            table = "self.dbstate.%s_map" % prim_obj
            get_number_obj = "self.dbstate.get_number_of_%s" % prim_objs
            prefix_fmt = "self.dbstate.%s_prefix" % prim_obj
            get_from_id = "self.dbstate.get_%s_from_gramps_id" % prim_obj
            get_from_handle = "self.dbstate.get_%s_from_handle" % prim_obj
            next_from_id = "self.dbstate.find_next_%s_gramps_id" % prim_obj
            commit = "self.dbstate.commit_%s" % prim_obj

            self.prim_methods[prim_obj] = (eval(prefix_fmt), eval(get_number_obj)(),
                                           eval(next_from_id)())
            self.obj_methods[prim_obj] = (eval(class_type), eval(table), eval(commit),
                                          eval(get_from_id), eval(get_from_handle),
                                          eval(next_from_id))

            object_fmt, quant_id, next_id = self.prim_methods[prim_obj]

            obj_value = ReorderEntry(object_fmt, quant_id, next_id)
            self.obj_values[prim_obj] = obj_value

        if self.uistate:
            self._display()
        else:
            self._execute()

    def __on_object_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Active' attribute """
        self.object_status = not self.object_status

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_active' % prim_obj)
            obj.set_active(self.object_status)

    def __on_object_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        self.active_entries[obj_name].set_val(obj_state)

        for obj_entry in ['actual', 'quant', 'format', 'change']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            obj.set_sensitive(obj_state)

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_change' % obj_name)
            if obj.get_active():
                obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
                obj.set_sensitive(obj_state)

    def __on_format_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Format' scheme of identifiers """
        for prim_obj, tmp in self.xobjects:
            obj_format = self.top.get_object('%s_format' % prim_obj)
            if not obj_format.get_sensitive():
                continue

            obj_fmt = self.obj_values[prim_obj].res_fmt()
            self.format_entries[prim_obj].force_value(obj_fmt)
            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].last_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_change_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Change' attribute """
        self.change_status = not self.change_status

        for prim_obj, tmp in self.xobjects:
            obj_change = self.top.get_object('%s_change' % prim_obj)
            if not obj_change.get_sensitive():
                continue

            self.change_entries[prim_obj].set_val(self.change_status)
            obj_change.set_active(self.change_status)

    def __on_change_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            if obj_entry == 'keep':
                if self.obj_values[obj_name].stored_prefix != \
                   self.obj_values[obj_name].object_prefix:
                    self.keep_entries[obj_name].set_val(False)
                else:
                    obj.set_active(obj_state)
                    self.keep_entries[obj_name].set_val(obj_state)
            obj.set_sensitive(obj_state)

    def __on_start_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Start' values of identifiers """
        self.start_zero = not self.start_zero

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_start' % prim_obj)
            if not obj.get_sensitive():
                continue

            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].next_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_step_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Step' width of identifiers """
        self.step_cnt = self.step_cnt +1 if self.step_cnt < 3 else 0

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_step' % prim_obj)
            if not obj.get_sensitive():
                continue

            step_val = self.step_list[self.step_cnt]
            self.step_entries[prim_obj].force_value(step_val)

    def __on_keep_button_clicked(self, widget=None):
        """ compute the primary object and toggle the 'Active' attribute """
        self.keep_status = not self.keep_status

        for prim_obj, tmp in self.xobjects:
            obj = self.top.get_object('%s_change' % prim_obj)
            if not obj.get_active():
                continue

            obj = self.top.get_object('%s_keep' % prim_obj)
            obj.set_active(self.keep_status)
            self.keep_entries[prim_obj].set_val(self.keep_status)

    def __on_format_entry_keyrelease(self, widget, event, data=None):
        """ activated on all return's of an entry """
        if event.keyval in [Gdk.KEY_Return]:
            obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
            obj_fmt = self.format_entries[obj_name].get_val()
            self.format_entries[obj_name].force_value(obj_fmt)
            self.start_entries[obj_name].update()

            obj_change = self.top.get_object('%s_change' % obj_name)
            obj_change.grab_focus()

        return False

    def __on_format_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        obj_fmt = self.format_entries[obj_name].get_val()

        self.format_entries[obj_name].set_val(obj_fmt)
        self.start_entries[obj_name].update()

        return False

    def __on_start_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        self.start_entries[obj_name].update()

        return False

    def __on_ok_button_clicked(self, widget=None):
        """ execute the reodering and close """
        self._execute()
        self._update()

        self.close()

    def __on_cancel_button_clicked(self, widget=None):
        """ cancel the reodering and close """
        self.close()

    def __on_help_button_clicked(self, widget=None):
        """ display the relevant portion of Gramps manual """
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def _display(self):
        """ organize Glade 'Reorder IDs' window """

        # get the main window from glade
        self.top = Glade(toplevel="reorder-ids")
        window = self.top.toplevel

        # set gramps style title for the window
        self.set_window(window, self.top.get_object("title"), \
                        _("Reorder Gramps IDs"))

        # connect signals
        self.top.connect_signals({
            "on_object_button_clicked" : self.__on_object_button_clicked,
            "on_object_button_toggled" : self.__on_object_button_toggled,
            "on_format_button_clicked" : self.__on_format_button_clicked,
            "on_start_button_clicked" : self.__on_start_button_clicked,
            "on_step_button_clicked" : self.__on_step_button_clicked,
            "on_keep_button_clicked" : self.__on_keep_button_clicked,
            "on_change_button_clicked" : self.__on_change_button_clicked,
            "on_change_button_toggled" : self.__on_change_button_toggled,
            "on_format_entry_keyrelease" : self.__on_format_entry_keyrelease,
            "on_format_entry_focusout" : self.__on_format_entry_focusout,
            "on_start_entry_focusout" : self.__on_start_entry_focusout,
            "on_help_button_clicked" : self.__on_help_button_clicked,
            "on_cancel_button_clicked" : self.__on_cancel_button_clicked,
            "on_ok_button_clicked" : self.__on_ok_button_clicked
        })

        # Calculate all entries and update Glade window
        for prim_obj, tmp in self.xobjects:
            # populate Object, Actual & Quantity fields with values
            obj_active = self.top.get_object('%s_active' % prim_obj)
            self.active_entries[prim_obj] = MonitoredCheckbox(obj_active, obj_active,
                                        self.obj_values[prim_obj].set_active,
                                        self.obj_values[prim_obj].get_active)
            obj_actual = self.top.get_object('%s_actual' % prim_obj)
            obj_actual.set_text('%s' % self.obj_values[prim_obj].last_id())
            obj_quant = self.top.get_object('%s_quant' % prim_obj)
            obj_quant.set_text('%s' % str(self.obj_values[prim_obj].quant_id))

            # connect/populate Format, Start, Step, Keep & Change fields with GTK/values
            obj_format = self.top.get_object('%s_format' % prim_obj)
            self.format_entries[prim_obj] = MonitoredEntry(obj_format,
                                    self.obj_values[prim_obj].set_fmt,
                                    self.obj_values[prim_obj].get_fmt)
            obj_change = self.top.get_object('%s_change' % prim_obj)
            self.change_entries[prim_obj] = MonitoredCheckbox(obj_change, obj_change,
                                    self.obj_values[prim_obj].set_change,
                                    self.obj_values[prim_obj].get_change)
            obj_start = self.top.get_object('%s_start' % prim_obj)
            self.start_entries[prim_obj] = MonitoredEntry(obj_start,
                                    self.obj_values[prim_obj].set_id,
                                    self.obj_values[prim_obj].get_id)
            obj_step = self.top.get_object('%s_step' % prim_obj)
            self.step_entries[prim_obj] = MonitoredEntry(obj_step,
                                    self.obj_values[prim_obj].set_step,
                                    self.obj_values[prim_obj].get_step,
                                    changed=self.obj_values[prim_obj].change_step)
            obj_keep = self.top.get_object('%s_keep' % prim_obj)
            self.keep_entries[prim_obj] = MonitoredCheckbox(obj_keep, obj_keep,
                                    self.obj_values[prim_obj].set_keep,
                                    self.obj_values[prim_obj].get_keep,
                                    readonly=True)

        # fetch the popup menu
        self.menu = self.top.get_object("popup_menu")

        # ok, let's see what we've done
        self.show()

    def _update(self):
        """ store changed objects formats in DB """

        update = False
        for prim_obj, tmp in self.xobjects:
            obj_value = self.obj_values[prim_obj]
            if obj_value.object_fmt != obj_value.stored_fmt:
                prefix = obj_value.object_prefix.lower()
                constant = 'preferences.%sprefix' % prefix
                config.set(constant, obj_value.object_fmt)
                update = True

        if update:
            config.save()
            self.dbstate.set_prefixes(
                config.get('preferences.iprefix'),
                config.get('preferences.oprefix'),
                config.get('preferences.fprefix'),
                config.get('preferences.sprefix'),
                config.get('preferences.cprefix'),
                config.get('preferences.pprefix'),
                config.get('preferences.eprefix'),
                config.get('preferences.rprefix'),
                config.get('preferences.nprefix'))

    def _execute(self):
        """ execute all primary objects and reorder if neccessary """

        # Update progress calculation
        if self.uistate:
            self.progress = ProgressMeter(_('Reorder Gramps IDs'), '')
        else:
            total_objs = 0
            for prim_obj, tmp in self.xobjects:
                if self.obj_values[prim_obj].active_obj:
                    total_objs += self.obj_values[prim_obj].quant_id
            self.set_total(total_objs)

        # Update database
        self.dbstate.disable_signals()
        for prim_obj, prim_objs in self.xobjects:
            with DbTxn(_('Reorder %s IDs ...') % prim_obj, self.dbstate, batch=True) \
            as self.trans:
                if self.obj_values[prim_obj].active_obj:
                    if self.uistate:
                        self.progress.set_pass(_('Reorder %s IDs ...') % \
                                               _(prim_objs.title()), \
                                               self.obj_values[prim_obj].quant_id)
                    # Process reordering
                    self._reorder(prim_obj)

        self.dbstate.enable_signals()
        self.dbstate.request_rebuild()

        # Update progress calculation
        if self.uistate:
            self.progress.close()
        else:
            print('\nDone.')

    # finds integer portion in a GrampsID
    _findint = re.compile('^[^\d]*(\d+)[^\d]*')
    def _reorder(self, prim_obj):
        """ reorders all selected objects with a (new) style, start & step """

        dup_ids = []   # list of duplicate identifiers
        new_ids = {}   # list of new identifiers

        class_type, table, commit, get_from_id, get_from_handle, next_from_id = \
            self.obj_methods[prim_obj]

        prefix_fmt = self.obj_values[prim_obj].get_fmt()
        prefix = prefix_fmt.split('%', 1)[0]
        new_id = self.obj_values[prim_obj].get_id()
        keep_fmt = self.obj_values[prim_obj].get_keep()
        change = self.obj_values[prim_obj].get_change()

        formatmatch = _parseformat.match(prefix_fmt)
        index_max = int("9" * int(formatmatch.groups()[0]))

        for handle in list(table.keys()):
            # Update progress
            if self.uistate:
                self.progress.step()
            else:
                self.update()

            # extract basic data out of the database
            table_data = table[handle]
            obj = class_type()
            obj.unserialize(table_data)

            act_id = obj.get_gramps_id()
            if change:
                # update the defined ID numbers into objects under consideration
                # of keeping ID if format not matches prefix
                # (implication logical boolean operator below)
                if act_id.startswith(prefix) or not keep_fmt:
                    obj.set_gramps_id(new_id)
                    commit(obj, self.trans)
                    new_id = self.obj_values[prim_obj].succ_id()
            else:
                # attempt to extract integer - if we can't, treat it as a duplicate
                try:
                    match = _findint.match(act_id)
                    if match:
                        # get the integer, build the new handle. Make sure it
                        # hasn't already been chosen. If it has, put this
                        # in the duplicate handle list

                        index = int(match.groups()[0])
                        if formatmatch:
                            if index > index_max:
                                new_id = next_from_id()
                            else:
                                new_id = prefix_fmt % index
                        else:
                            # prefix_fmt does not contain a number after %, eg I%d
                            new_id = prefix_fmt % index

                        if new_id == act_id:
                            if new_id in new_ids:
                                dup_ids.append(obj.get_handle())
                            else:
                                new_ids[new_id] = act_id
                        elif get_from_id(new_id) is not None:
                            dup_ids.append(obj.get_handle())
                        else:
                            obj.set_id(new_id)
                            commit(obj, self.trans)
                            new_ids[new_id] = act_id
                    else:
                        dup_ids.append(handle)
                except:
                    dup_ids.append(handle)

        # go through the duplicates, looking for the first available
        # handle that matches the new scheme.
        if dup_ids:
            if self.uistate:
                self.progress.set_pass(_('Finding and assigning unused IDs.'), len(dup_ids))
            for handle in dup_ids:
                obj = get_from_handle(handle)
                obj.set_gramps_id(next_from_id())
                commit(obj, self.trans)
Beispiel #26
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        tool.ActivePersonTool.__init__(self, dbstate, uistate, options_class,
                                       name)

        if self.fail:   # bug #2709 -- fail if we have no active person
            return

        person_handle = uistate.get_active('Person')
        person = dbstate.db.get_person_from_handle(person_handle)
        self.name = person.get_primary_name().get_regular_name()
        self.title = _('Not related to "%s"') % self.name
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.db = dbstate.db

        topDialog = Glade()

        topDialog.connect_signals({
            "destroy_passed_object" : self.close,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_event"       : self.close,
        })

        window = topDialog.toplevel
        title = topDialog.get_object("title")
        self.set_window(window, title, self.title)

        self.tagcombo = topDialog.get_object("tagcombo")
        tagmodel = Gtk.ListStore(str)
        self.tagcombo.set_model(tagmodel)
        self.tagcombo.set_entry_text_column(0)
        tagmodel.append((_('ToDo'),))
        tagmodel.append((_('NotRelated'),))
        self.tagcombo.set_sensitive(False)

        self.tagapply = topDialog.get_object("tagapply")
        self.tagapply.set_sensitive(False)
        self.tagapply.connect('clicked', self.applyTagClicked)

        # start the progress indicator
        self.progress = ProgressMeter(self.title,_('Starting'),
                                      parent=self.window)

        # setup the columns
        self.model = Gtk.TreeStore(
            GObject.TYPE_STRING,    # 0==name
            GObject.TYPE_STRING,    # 1==person gid
            GObject.TYPE_STRING,    # 2==parents
            GObject.TYPE_STRING,    # 3==tags
            GObject.TYPE_STRING)    # 4==family gid (not shown to user)

        # note -- don't assign the model to the tree until it has been populated,
        # otherwise the screen updates are terribly slow while names are appended
        self.treeView = topDialog.get_object("treeview")
        col1 = Gtk.TreeViewColumn(_('Name'),    Gtk.CellRendererText(), text=0)
        col2 = Gtk.TreeViewColumn(_('ID'),      Gtk.CellRendererText(), text=1)
        col3 = Gtk.TreeViewColumn(_('Parents'), Gtk.CellRendererText(), text=2)
        col4 = Gtk.TreeViewColumn(_('Tags'),    Gtk.CellRendererText(), text=3)
        col1.set_resizable(True)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col1.set_sort_column_id(0)
#        col2.set_sort_column_id(1)
#        col3.set_sort_column_id(2)
        col4.set_sort_column_id(3)
        self.treeView.append_column(col1)
        self.treeView.append_column(col2)
        self.treeView.append_column(col3)
        self.treeView.append_column(col4)
        self.treeSelection = self.treeView.get_selection()
        self.treeSelection.set_mode(Gtk.SelectionMode.MULTIPLE)
        self.treeSelection.set_select_function(self.selectIsAllowed, None)
        self.treeSelection.connect('changed', self.rowSelectionChanged)
        self.treeView.connect('row-activated', self.rowActivated)

        # initialize a few variables we're going to need
        self.numberOfPeopleInDatabase    = self.db.get_number_of_people()
        self.numberOfRelatedPeople       = 0
        self.numberOfUnrelatedPeople     = 0

        # create the sets used to track related and unrelated people
        self.handlesOfPeopleToBeProcessed       = set()
        self.handlesOfPeopleAlreadyProcessed    = set()
        self.handlesOfPeopleNotRelated          = set()

        # build a set of all people related to the selected person
        self.handlesOfPeopleToBeProcessed.add(person.get_handle())
        self.findRelatedPeople()

        # now that we have our list of related people, find everyone
        # in the database who isn't on our list
        self.findUnrelatedPeople()

        # populate the treeview model with the names of unrelated people
        if self.numberOfUnrelatedPeople == 0:
            # feature request 2356: avoid genitive form
            title.set_text(_('Everyone in the database is related to %s') % self.name)
        else:
            self.populateModel()
            self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
            self.treeView.set_model(self.model)
#            self.treeView.set_row_separator_func(self.iterIsSeparator, None)
            self.treeView.expand_all()

        # done searching through the database, so close the progress bar
        self.progress.close()

        self.show()
Beispiel #27
0
class ChangeTypes(tool.BatchTool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.user = user

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        if uistate:
            self.title = _('Change Event Types')
            ManagedWindow.__init__(self, uistate, [], self.__class__)
            self.init_gui()
        else:
            self.run_tool()

    def init_gui(self):
        # Draw dialog and make it handle everything

        self.glade = Glade()

        self.auto1 = self.glade.get_object("original")
        self.auto2 = self.glade.get_object("new")

        # Need to display localized event names
        etype = EventType()
        event_names = sorted(etype.get_standard_names(), key=glocale.sort_key)

        fill_combo(self.auto1, event_names)
        fill_combo(self.auto2, event_names)

        etype.set_from_xml_str(self.options.handler.options_dict['fromtype'])
        self.auto1.get_child().set_text(str(etype))

        etype.set_from_xml_str(self.options.handler.options_dict['totype'])
        self.auto2.get_child().set_text(str(etype))

        window = self.glade.toplevel
        self.set_window(window, self.glade.get_object('title'), self.title)

        self.glade.connect_signals({
            "on_close_clicked": self.close,
            "on_apply_clicked": self.on_apply_clicked,
            "on_delete_event": self.close,
        })

        self.show()

    def build_menu_names(self, obj):
        return (self.title, None)

    def run_tool(self, parent_window=None):
        # Run tool and return results
        # These are English names, no conversion needed
        fromtype = self.options.handler.options_dict['fromtype']
        totype = self.options.handler.options_dict['totype']

        modified = 0

        with DbTxn(_('Change types'), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            with self.user.progress(_('Analyzing Events'), '',
                                    self.db.get_number_of_events()) as step:
                for event_handle in self.db.get_event_handles():
                    event = self.db.get_event_from_handle(event_handle)
                    if event.get_type().xml_str() == fromtype:
                        event.type.set_from_xml_str(totype)
                        modified += 1
                        self.db.commit_event(event, self.trans)
                        step()
        self.db.enable_signals()
        self.db.request_rebuild()

        if modified == 0:
            msg = _("No event record was modified.")
        else:
            # translators: leave all/any {...} untranslated
            msg = ngettext("{number_of} event record was modified.",
                           "{number_of} event records were modified.",
                           modified).format(number_of=modified)

        self.user.info(_('Change types'), msg, parent_window)
        return (bool(modified), msg)

    def on_apply_clicked(self, obj):
        # Need to store English names for later comparison
        the_type = EventType()

        the_type.set(self.auto1.get_child().get_text())
        self.options.handler.options_dict['fromtype'] = the_type.xml_str()

        the_type.set(self.auto2.get_child().get_text())
        self.options.handler.options_dict['totype'] = the_type.xml_str()

        self.run_tool(self.window)

        # Save options
        self.options.handler.save_options()

        self.close()
Beispiel #28
0
class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
    """ Class for Reodering Gramps ID Tool """
    xobjects = (('person', 'people'), ('family', 'families'),
                ('event', 'events'), ('place', 'places'),
                ('source', 'sources'), ('citation', 'citations'),
                ('repository', 'repositories'), ('media', 'media'), ('note',
                                                                     'notes'))

    def build_menu_names_(self, widget=None):
        """ The menu name """
        return (_('Main window'), _("Reorder Gramps IDs"))

    def __init__(self, dbstate, user, options_class, name, callback=None):
        self.uistate = user.uistate
        self.db = dbstate.db

        if self.uistate:
            tool.BatchTool.__init__(self, dbstate, user, options_class, name)
            if self.fail:
                return  # user denied to modify Gramps IDs

        ManagedWindow.__init__(self, self.uistate, [], self.__class__)
        if not self.uistate:
            UpdateCallback.__init__(self, user.callback)

        self.object_status = True
        self.change_status = False
        self.start_zero = True
        self.step_cnt, self.step_list = 0, ['1', '2', '5', '10']
        self.keep_status = True

        self.obj_values = {}  # enable access to all internal values
        self.active_entries, self.format_entries = {}, {}
        self.change_entries = {}
        self.start_entries, self.step_entries = {}, {}
        self.keep_entries = {}

        self.prim_methods, self.obj_methods = {}, {}
        for prim_obj, prim_objs in self.xobjects:
            get_handles = "get_%s_handles" % prim_obj
            get_number_obj = "get_number_of_%s" % prim_objs
            prefix_fmt = "%s_prefix" % prim_obj
            get_from_id = "get_%s_from_gramps_id" % prim_obj
            get_from_handle = "get_%s_from_handle" % prim_obj
            next_from_id = "find_next_%s_gramps_id" % prim_obj
            commit = "commit_%s" % prim_obj

            self.prim_methods[prim_obj] = (getattr(self.db, prefix_fmt),
                                           getattr(self.db, get_number_obj)(),
                                           getattr(self.db, next_from_id)())
            self.obj_methods[prim_obj] = (getattr(self.db, get_handles),
                                          getattr(self.db, commit),
                                          getattr(self.db, get_from_id),
                                          getattr(self.db, get_from_handle),
                                          getattr(self.db, next_from_id))

            object_fmt, quant_id, next_id = self.prim_methods[prim_obj]

            obj_value = ReorderEntry(object_fmt, quant_id, next_id, prim_obj)
            self.obj_values[prim_obj] = obj_value

        if self.uistate:
            self._display()
        else:
            self._execute()

    def __on_object_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Active' attribute """
        self.object_status = not self.object_status

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_active' % prim_obj)
            obj.set_active(self.object_status)

    def __on_object_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        self.active_entries[obj_name].set_val(obj_state)

        for obj_entry in ['actual', 'quant', 'format', 'change']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            obj.set_sensitive(obj_state)

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_change' % obj_name)
            if obj.get_active():
                obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
                obj.set_sensitive(obj_state)

    def __on_format_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Format' scheme of identifiers """
        for prim_obj, dummy in self.xobjects:
            obj_format = self.top.get_object('%s_format' % prim_obj)
            if not obj_format.get_sensitive():
                continue

            obj_fmt = self.obj_values[prim_obj].res_fmt()
            self.format_entries[prim_obj].force_value(obj_fmt)
            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].last_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_change_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Change' attribute """
        self.change_status = not self.change_status

        for prim_obj, dummy in self.xobjects:
            obj_change = self.top.get_object('%s_change' % prim_obj)
            if not obj_change.get_sensitive():
                continue

            self.change_entries[prim_obj].set_val(self.change_status)
            obj_change.set_active(self.change_status)

    def __on_change_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            if obj_entry == 'keep':
                if (self.obj_values[obj_name].stored_prefix !=
                        self.obj_values[obj_name].object_prefix
                        and self.obj_values[obj_name].stored_suffix !=
                        self.obj_values[obj_name].object_suffix):
                    self.keep_entries[obj_name].set_val(False)
                else:
                    obj.set_active(obj_state)
                    self.keep_entries[obj_name].set_val(obj_state)
            obj.set_sensitive(obj_state)

    def __on_start_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Start' values of identifiers """
        self.start_zero = not self.start_zero

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_start' % prim_obj)
            if not obj.get_sensitive():
                continue

            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].next_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_step_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Step' width of identifiers """
        self.step_cnt = self.step_cnt + 1 if self.step_cnt < 3 else 0

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_step' % prim_obj)
            if not obj.get_sensitive():
                continue

            step_val = self.step_list[self.step_cnt]
            self.step_entries[prim_obj].force_value(step_val)

    def __on_keep_button_clicked(self, widget=None):
        """ compute the primary object and toggle the 'Active' attribute """
        self.keep_status = not self.keep_status

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_change' % prim_obj)
            if not obj.get_active():
                continue

            obj = self.top.get_object('%s_keep' % prim_obj)
            obj.set_active(self.keep_status)
            self.keep_entries[prim_obj].set_val(self.keep_status)

    def __on_format_entry_keyrelease(self, widget, event, data=None):
        """ activated on all return's of an entry """
        if event.keyval in [Gdk.KEY_Return]:
            obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
            obj_fmt = self.format_entries[obj_name].get_val()
            self.format_entries[obj_name].force_value(obj_fmt)
            self.start_entries[obj_name].update()

            obj_change = self.top.get_object('%s_change' % obj_name)
            obj_change.grab_focus()

        return False

    def __on_format_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        obj_fmt = self.format_entries[obj_name].get_val()

        self.format_entries[obj_name].set_text(obj_fmt)
        self.start_entries[obj_name].update()

        return False

    def __on_start_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        self.start_entries[obj_name].update()

        return False

    def __on_ok_button_clicked(self, widget=None):
        """ execute the reodering and close """
        self._execute()
        self._update()

        self.close()

    def __on_cancel_button_clicked(self, widget=None):
        """ cancel the reodering and close """
        self.close()

    def __on_help_button_clicked(self, widget=None):
        """ display the relevant portion of Gramps manual """
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def _display(self):
        """ organize Glade 'Reorder IDs' window """

        # get the main window from glade
        self.top = Glade(toplevel="reorder-ids")
        window = self.top.toplevel

        # set gramps style title for the window
        self.set_window(window, self.top.get_object("title"),
                        _("Reorder Gramps IDs"))

        # connect signals
        self.top.connect_signals({
            "on_object_button_clicked":
            self.__on_object_button_clicked,
            "on_object_button_toggled":
            self.__on_object_button_toggled,
            "on_format_button_clicked":
            self.__on_format_button_clicked,
            "on_start_button_clicked":
            self.__on_start_button_clicked,
            "on_step_button_clicked":
            self.__on_step_button_clicked,
            "on_keep_button_clicked":
            self.__on_keep_button_clicked,
            "on_change_button_clicked":
            self.__on_change_button_clicked,
            "on_change_button_toggled":
            self.__on_change_button_toggled,
            "on_format_entry_keyrelease":
            self.__on_format_entry_keyrelease,
            "on_format_entry_focusout":
            self.__on_format_entry_focusout,
            "on_start_entry_focusout":
            self.__on_start_entry_focusout,
            "on_help_button_clicked":
            self.__on_help_button_clicked,
            "on_cancel_button_clicked":
            self.__on_cancel_button_clicked,
            "on_ok_button_clicked":
            self.__on_ok_button_clicked
        })

        # Calculate all entries and update Glade window
        for prim_obj, dummy in self.xobjects:
            # populate Object, Actual & Quantity fields with values
            obj_active = self.top.get_object('%s_active' % prim_obj)
            self.active_entries[prim_obj] = MonitoredCheckbox(
                obj_active, obj_active, self.obj_values[prim_obj].set_active,
                self.obj_values[prim_obj].get_active)
            obj_actual = self.top.get_object('%s_actual' % prim_obj)
            obj_actual.set_text('%s' % self.obj_values[prim_obj].last_id())
            obj_quant = self.top.get_object('%s_quant' % prim_obj)
            obj_quant.set_text('%s' % str(self.obj_values[prim_obj].quant_id))

            # connect/populate Format, Start, Step, Keep & Change fields
            #  with GTK/values
            obj_format = self.top.get_object('%s_format' % prim_obj)
            self.format_entries[prim_obj] = MonitoredEntry(
                obj_format, self.obj_values[prim_obj].set_fmt,
                self.obj_values[prim_obj].get_fmt)
            obj_change = self.top.get_object('%s_change' % prim_obj)
            self.change_entries[prim_obj] = MonitoredCheckbox(
                obj_change, obj_change, self.obj_values[prim_obj].set_change,
                self.obj_values[prim_obj].get_change)
            obj_start = self.top.get_object('%s_start' % prim_obj)
            self.start_entries[prim_obj] = MonitoredEntry(
                obj_start, self.obj_values[prim_obj].set_id,
                self.obj_values[prim_obj].get_id)
            obj_step = self.top.get_object('%s_step' % prim_obj)
            self.step_entries[prim_obj] = MonitoredEntry(
                obj_step,
                self.obj_values[prim_obj].set_step,
                self.obj_values[prim_obj].get_step,
                changed=self.obj_values[prim_obj].change_step)
            obj_keep = self.top.get_object('%s_keep' % prim_obj)
            self.keep_entries[prim_obj] = MonitoredCheckbox(
                obj_keep,
                obj_keep,
                self.obj_values[prim_obj].set_keep,
                self.obj_values[prim_obj].get_keep,
                readonly=True)

        # fetch the popup menu
        self.menu = self.top.get_object("popup_menu")

        # ok, let's see what we've done
        self.window.resize(700, 410)
        self.show()

    def _update(self):
        """ store changed objects formats in DB """

        update = False
        for prim_obj, dummy in self.xobjects:
            obj_value = self.obj_values[prim_obj]
            if obj_value.object_fmt != obj_value.stored_fmt:
                constant = 'preferences.%sprefix' % PREFIXES[prim_obj]
                config.set(constant, obj_value.object_fmt)
                update = True

        if update:
            config.save()
            self.db.set_prefixes(config.get('preferences.iprefix'),
                                 config.get('preferences.oprefix'),
                                 config.get('preferences.fprefix'),
                                 config.get('preferences.sprefix'),
                                 config.get('preferences.cprefix'),
                                 config.get('preferences.pprefix'),
                                 config.get('preferences.eprefix'),
                                 config.get('preferences.rprefix'),
                                 config.get('preferences.nprefix'))

    def _execute(self):
        """ execute all primary objects and reorder if neccessary """

        # Update progress calculation
        if self.uistate:
            self.progress = ProgressMeter(_('Reorder Gramps IDs'), '')
        else:
            total_objs = 0
            for prim_obj, dummy in self.xobjects:
                if self.obj_values[prim_obj].active_obj:
                    total_objs += self.obj_values[prim_obj].quant_id
            self.set_total(total_objs)

        # Update database
        self.db.disable_signals()
        for prim_obj, prim_objs in self.xobjects:
            with DbTxn(_('Reorder %s IDs ...') % prim_obj, self.db,
                       batch=True) as self.trans:
                if self.obj_values[prim_obj].active_obj:
                    if self.uistate:
                        self.progress.set_pass(
                            _('Reorder %s IDs ...') % _(prim_objs.title()),
                            self.obj_values[prim_obj].quant_id)
                    # reset the db next_id index to zero so we restart new IDs
                    # at lowest possible position
                    setattr(self.db, DB_INDXES[prim_obj] + 'map_index', 0)
                    # Process reordering
                    self._reorder(prim_obj)

        self.db.enable_signals()
        self.db.request_rebuild()

        # Update progress calculation
        if self.uistate:
            self.progress.close()
        else:
            print('\nDone.')

    # finds integer portion in a GrampsID
    _findint = re.compile(r'^[^\d]*(\d+)[^\d]*$')
    # finds prefix, number, suffix of a Gramps ID ignoring a leading or
    # trailing space.  The number must be at least three digits.
    _prob_id = re.compile(r'^ *([^\d]*)(\d{3,9})([^\d]*) *$')

    def _reorder(self, prim_obj):
        """ reorders all selected objects with a (new) style, start & step """

        dup_ids = []  # list of duplicate identifiers
        new_ids = {}  # list of new identifiers

        get_handles, commit, get_from_id, get_from_handle, next_from_id = \
            self.obj_methods[prim_obj]

        prefix_fmt = self.obj_values[prim_obj].get_fmt()
        prefix = self.obj_values[prim_obj].object_prefix
        suffix = self.obj_values[prim_obj].object_suffix
        old_pref = self.obj_values[prim_obj].stored_prefix
        old_suff = self.obj_values[prim_obj].stored_suffix
        new_id = self.obj_values[prim_obj].get_id()
        keep_fmt = self.obj_values[prim_obj].get_keep()
        change = self.obj_values[prim_obj].get_change()
        index_max = int("9" * self.obj_values[prim_obj].width_fmt)
        do_same = False
        # Process in handle order, which is in order handles were created.
        # This makes renumberd IDs more consistant.
        handles = get_handles()
        handles.sort()

        for handle in handles:
            # Update progress
            if self.uistate:
                self.progress.step()
            else:
                self.update()

            # extract basic data out of the database
            obj = get_from_handle(handle)

            act_id = obj.get_gramps_id()
            # here we see if the ID looks like a new or previous or default
            # Gramps ID.
            # If not we ask user if he really wants to replace it.
            # This should allow user to protect a GetGov ID or similar
            match = self._prob_id.match(act_id)
            if not (match and
                    (prefix == match.groups()[0] and suffix
                     == match.groups()[2] or old_pref == match.groups()[0] and
                     old_suff == match.groups()[2] or len(match.groups()[0])
                     == 1 and len(match.groups()[2]) == 0)) and not do_same:
                xml = Glade(toplevel='dialog')

                top = xml.toplevel
                # self.top.set_icon(ICON)
                top.set_title("%s - Gramps" % _("Reorder Gramps IDs"))
                apply_to_rest = xml.get_object('apply_to_rest')

                label1 = xml.get_object('toplabel')
                label1.set_text('<span weight="bold" size="larger">%s</span>' %
                                _("Reorder Gramps IDs"))
                label1.set_use_markup(True)

                label2 = xml.get_object('mainlabel')
                label2.set_text(_("Do you want to replace %s?" % act_id))
                top.set_transient_for(self.progress._ProgressMeter__dialog)
                self.progress._ProgressMeter__dialog.set_modal(False)
                top.show()
                response = top.run()
                do_same = apply_to_rest.get_active()
                top.destroy()
                self.progress._ProgressMeter__dialog.set_modal(True)
                if response != Gtk.ResponseType.YES:
                    continue

            elif not match and do_same and response != Gtk.ResponseType.YES:
                continue

            if change:
                # update the defined ID numbers into objects under
                # consideration of keeping ID if format not matches prefix
                # (implication logical boolean operator below)
                if act_id.startswith(prefix) and act_id.endswith(suffix) or \
                        not keep_fmt:
                    obj.set_gramps_id(new_id)
                    commit(obj, self.trans)
                    new_id = self.obj_values[prim_obj].succ_id()
            else:
                # attempt to extract integer - if we can't, treat it as a
                # duplicate
                try:
                    match = self._findint.match(act_id)
                    if match:
                        # get the integer, build the new handle. Make sure it
                        # hasn't already been chosen. If it has, put this
                        # in the duplicate handle list

                        index = int(match.groups()[0])
                        if index > index_max:
                            new_id = next_from_id()
                        else:
                            new_id = prefix_fmt % index

                        if new_id == act_id:
                            if new_id in new_ids:
                                dup_ids.append(obj.get_handle())
                            else:
                                new_ids[new_id] = act_id
                        elif get_from_id(new_id) is not None:
                            dup_ids.append(obj.get_handle())
                        else:
                            obj.set_gramps_id(new_id)
                            commit(obj, self.trans)
                            new_ids[new_id] = act_id
                    else:
                        dup_ids.append(handle)
                except:
                    dup_ids.append(handle)

        # go through the duplicates, looking for the first available
        # handle that matches the new scheme.
        if dup_ids:
            if self.uistate:
                self.progress.set_pass(_('Finding and assigning unused IDs.'),
                                       len(dup_ids))
            for handle in dup_ids:
                obj = get_from_handle(handle)
                obj.set_gramps_id(next_from_id())
                commit(obj, self.trans)
Beispiel #29
0
class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
    MARK_COL       = 0
    OBJ_ID_COL     = 1
    OBJ_NAME_COL   = 2
    OBJ_TYPE_COL   = 3
    OBJ_HANDLE_COL = 4

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.title = _('Unused Objects')

        tool.Tool.__init__(self, dbstate, options_class, name)

        if self.db.readonly:
            return

        ManagedWindow.__init__(self, uistate,[], self.__class__)
        UpdateCallback.__init__(self, self.uistate.pulse_progressbar)

        self.dbstate = dbstate
        self.uistate = uistate

        self.tables = {
            'events'  : {'get_func': self.db.get_event_from_handle,
                         'remove'  : self.db.remove_event,
                         'get_text': self.get_event_text,
                         'editor'  : 'EditEvent',
                         'icon'    : 'gramps-event',
                         'name_ix' : 4},
            'sources' : {'get_func': self.db.get_source_from_handle,
                         'remove'  : self.db.remove_source,
                         'get_text': None,
                         'editor'  : 'EditSource',
                         'icon'    : 'gramps-source',
                         'name_ix' : 2},
            'places'  : {'get_func': self.db.get_place_from_handle,
                         'remove'  : self.db.remove_place,
                         'get_text': None,
                         'editor'  : 'EditPlace',
                         'icon'    : 'gramps-place',
                         'name_ix' : 2},
            'media'   : {'get_func': self.db.get_object_from_handle,
                         'remove'  : self.db.remove_object,
                         'get_text': None,
                         'editor'  : 'EditMedia',
                         'icon'    : 'gramps-media',
                         'name_ix' : 4},
            'repos'   : {'get_func': self.db.get_repository_from_handle,
                         'remove'  : self.db.remove_repository,
                         'get_text': None,
                         'editor'  : 'EditRepository',
                         'icon'    : 'gramps-repository',
                         'name_ix' : 3},
            'notes'   : {'get_func': self.db.get_note_from_handle,
                         'remove'  : self.db.remove_note,
                         'get_text': self.get_note_text,
                         'editor'  : 'EditNote',
                         'icon'    : 'gramps-notes',
                         'name_ix' : 2},
            }

        self.init_gui()

    def init_gui(self):
        self.top = Glade()
        window = self.top.toplevel
        self.set_window(window, self.top.get_object('title'), self.title)

        self.events_box = self.top.get_object('events_box')
        self.sources_box = self.top.get_object('sources_box')
        self.places_box = self.top.get_object('places_box')
        self.media_box = self.top.get_object('media_box')
        self.repos_box = self.top.get_object('repos_box')
        self.notes_box = self.top.get_object('notes_box')
        self.find_button = self.top.get_object('find_button')
        self.remove_button = self.top.get_object('remove_button')

        self.events_box.set_active(self.options.handler.options_dict['events'])
        self.sources_box.set_active(
            self.options.handler.options_dict['sources'])
        self.places_box.set_active(
            self.options.handler.options_dict['places'])
        self.media_box.set_active(self.options.handler.options_dict['media'])
        self.repos_box.set_active(self.options.handler.options_dict['repos'])
        self.notes_box.set_active(self.options.handler.options_dict['notes'])

        self.warn_tree = self.top.get_object('warn_tree')
        self.warn_tree.connect('button_press_event', self.double_click)

        self.selection = self.warn_tree.get_selection()

        self.mark_button = self.top.get_object('mark_button')
        self.mark_button.connect('clicked', self.mark_clicked)

        self.unmark_button = self.top.get_object('unmark_button')
        self.unmark_button.connect('clicked', self.unmark_clicked)

        self.invert_button = self.top.get_object('invert_button')
        self.invert_button.connect('clicked', self.invert_clicked)

        self.real_model = Gtk.ListStore(GObject.TYPE_BOOLEAN,
                                        GObject.TYPE_STRING,
                                        GObject.TYPE_STRING,
                                        GObject.TYPE_STRING,
                                        GObject.TYPE_STRING)
        self.sort_model = self.real_model.sort_new_with_model()
        self.warn_tree.set_model(self.sort_model)

        self.renderer = Gtk.CellRendererText()
        self.img_renderer = Gtk.CellRendererPixbuf()
        self.bool_renderer = Gtk.CellRendererToggle()
        self.bool_renderer.connect('toggled', self.selection_toggled)

        # Add mark column
        mark_column = Gtk.TreeViewColumn(_('Mark'), self.bool_renderer,
                                           active=RemoveUnused.MARK_COL)
        mark_column.set_sort_column_id(RemoveUnused.MARK_COL)
        self.warn_tree.append_column(mark_column)

        # Add image column
        img_column = Gtk.TreeViewColumn(None, self.img_renderer )
        img_column.set_cell_data_func(self.img_renderer, self.get_image)
        self.warn_tree.append_column(img_column)

        # Add column with object gramps_id
        id_column = Gtk.TreeViewColumn(_('ID'), self.renderer,
                                       text=RemoveUnused.OBJ_ID_COL)
        id_column.set_sort_column_id(RemoveUnused.OBJ_ID_COL)
        self.warn_tree.append_column(id_column)

        # Add column with object name
        name_column = Gtk.TreeViewColumn(_('Name'), self.renderer,
                                         text=RemoveUnused.OBJ_NAME_COL)
        name_column.set_sort_column_id(RemoveUnused.OBJ_NAME_COL)
        self.warn_tree.append_column(name_column)

        self.top.connect_signals({
            "destroy_passed_object"   : self.close,
            "on_remove_button_clicked": self.do_remove,
            "on_find_button_clicked"  : self.find,
            "on_delete_event"         : self.close,
            })

        self.dc_label = self.top.get_object('dc_label')

        self.sensitive_list = [self.warn_tree, self.mark_button,
                               self.unmark_button, self.invert_button,
                               self.dc_label, self.remove_button]

        for item in self.sensitive_list:
            item.set_sensitive(False)

        self.show()

    def build_menu_names(self, obj):
        return (self.title, None)

    def find(self, obj):
        self.options.handler.options_dict.update(
            events  = self.events_box.get_active(),
            sources = self.sources_box.get_active(),
            places  = self.places_box.get_active(),
            media   = self.media_box.get_active(),
            repos   = self.repos_box.get_active(),
            notes   = self.notes_box.get_active(),
            )

        for item in self.sensitive_list:
            item.set_sensitive(True)

        self.uistate.set_busy_cursor(True)
        self.uistate.progress.show()
        self.window.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

        self.real_model.clear()
        self.collect_unused()

        self.uistate.progress.hide()
        self.uistate.set_busy_cursor(False)
        self.window.get_window().set_cursor(None)
        self.reset()

        # Save options
        self.options.handler.save_options()

    def collect_unused(self):
        # Run through all requested tables and check all objects
        # for being referenced some place. If not, add_results on them.

        db = self.db
        tables = (
            ('events', db.get_event_cursor, db.get_number_of_events),
            ('sources', db.get_source_cursor, db.get_number_of_sources),
            ('places', db.get_place_cursor, db.get_number_of_places),
            ('media', db.get_media_cursor, db.get_number_of_media_objects),
            ('repos', db.get_repository_cursor, db.get_number_of_repositories),
            ('notes', db.get_note_cursor, db.get_number_of_notes),
            )

        for (the_type, cursor_func, total_func) in tables:
            if not self.options.handler.options_dict[the_type]:
                # This table was not requested. Skip it.
                continue

            with cursor_func() as cursor:
                self.set_total(total_func())
                fbh = db.find_backlink_handles
                for handle, data in cursor:
                    if not any(h for h in fbh(handle)):
                        self.add_results((the_type, handle.decode('utf-8'),
                                          data))
                    self.update()
            self.reset()

    def do_remove(self, obj):
        with DbTxn(_("Remove unused objects"), self.db, batch=False) as trans:
            self.db.disable_signals()

            for row_num in range(len(self.real_model)-1, -1, -1):
                path = (row_num,)
                row = self.real_model[path]
                if not row[RemoveUnused.MARK_COL]:
                    continue

                the_type = row[RemoveUnused.OBJ_TYPE_COL]
                handle = row[RemoveUnused.OBJ_HANDLE_COL]
                remove_func = self.tables[the_type]['remove']
                remove_func(handle, trans)

                self.real_model.remove(row.iter)

        self.db.enable_signals()
        self.db.request_rebuild()

    def selection_toggled(self, cell, path_string):
        sort_path = tuple(map(int, path_string.split(':')))
        real_path = self.sort_model.convert_path_to_child_path(Gtk.TreePath(sort_path))
        row = self.real_model[real_path]
        row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]
        self.real_model.row_changed(real_path, row.iter)

    def mark_clicked(self, mark_button):
        for row_num in range(len(self.real_model)):
            path = (row_num,)
            row = self.real_model[path]
            row[RemoveUnused.MARK_COL] = True

    def unmark_clicked(self, unmark_button):
        for row_num in range(len(self.real_model)):
            path = (row_num,)
            row = self.real_model[path]
            row[RemoveUnused.MARK_COL] = False

    def invert_clicked(self, invert_button):
        for row_num in range(len(self.real_model)):
            path = (row_num,)
            row = self.real_model[path]
            row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]

    def double_click(self, obj, event):
        if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
            (model, node) = self.selection.get_selected()
            if not node:
                return
            sort_path = self.sort_model.get_path(node)
            real_path = self.sort_model.convert_path_to_child_path(sort_path)
            row = self.real_model[real_path]
            the_type = row[RemoveUnused.OBJ_TYPE_COL]
            handle = row[RemoveUnused.OBJ_HANDLE_COL]
            self.call_editor(the_type, handle)

    def call_editor(self, the_type, handle):
        try:
            obj = self.tables[the_type]['get_func'](handle)
            editor_str = 'from gramps.gui.editors import %s as editor' % (
                            self.tables[the_type]['editor']
                            )
            exec(editor_str, globals())
            editor(self.dbstate, self.uistate, [], obj)
        except WindowActiveError:
            pass

    def get_image(self, column, cell, model, iter, user_data=None):
        the_type = model.get_value(iter, RemoveUnused.OBJ_TYPE_COL)
        the_icon = self.tables[the_type]['icon']
        cell.set_property('icon-name', the_icon)

    def add_results(self, results):
        (the_type, handle, data) = results
        gramps_id = data[1]

        # if we have a function that will return to us some type
        # of text summary, then we should use it; otherwise we'll
        # use the generic field index provided in the tables above
        if self.tables[the_type]['get_text']:
            text = self.tables[the_type]['get_text'](the_type, handle, data)
        else:
            # grab the text field index we know about, and hope
            # it represents something useful to the user
            name_ix = self.tables[the_type]['name_ix']
            text = data[name_ix]

        # insert a new row into the table
        self.real_model.append(row=[False, gramps_id, text, the_type, handle])

    def get_event_text(self, the_type, handle, data):
        """
        Come up with a short line of text that we can use as
        a summary to represent this event.
        """

        # get the event:
        event = self.tables[the_type]['get_func'](handle)

        # first check to see if the event has a descriptive name
        text = event.get_description()  # (this is rarely set for events)

        # if we don't have a description...
        if text == '':
            # ... then we merge together several fields

            # get the event type (marriage, birth, death, etc.)
            text = str(event.get_type())

            # see if there is a date
            date = _dd.display(event.get_date_object())
            if date != '':
                text += '; %s' % date

            # see if there is a place
            if event.get_place_handle():
                text += '; %s' % _pd.display_event(self.db, event)

        return text

    def get_note_text(self, the_type, handle, data):
        """
        We need just the first few words of a note as a summary.
        """
        # get the note object
        note = self.tables[the_type]['get_func'](handle)

        # get the note text; this ignores (discards) formatting
        text = note.get()

        # convert whitespace to a single space
        text = " ".join(text.split())

        # if the note is too long, truncate it
        if len(text) > 80:
            text = text[:80] + "..."

        return text
Beispiel #30
0
class EventComparison(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.dbstate = dbstate
        self.uistate = uistate

        tool.Tool.__init__(self, dbstate, options_class, name)
        ManagedWindow.__init__(self, uistate, [], self)
        self.qual = 0

        self.filterDialog = Glade(toplevel="filters", also_load=["liststore1"])
        self.filterDialog.connect_signals({
            "on_apply_clicked": self.on_apply_clicked,
            "on_editor_clicked": self.filter_editor_clicked,
            "on_help_clicked": self.on_help_clicked,
            "destroy_passed_object": self.close,
            "on_write_table": self.__dummy,
        })

        window = self.filterDialog.toplevel
        self.filters = self.filterDialog.get_object("filter_list")
        self.label = _('Event comparison filter selection')
        self.set_window(window, self.filterDialog.get_object('title'),
                        self.label)
        self.setup_configs('interface.eventcomparison', 640, 220)

        self.on_filters_changed('Person')
        uistate.connect('filters-changed', self.on_filters_changed)

        self.show()

    def __dummy(self, obj):
        """dummy callback, needed because widget is in same glade file
        as another widget, so callbacks must be defined to avoid warnings.
        """
        pass

    def on_filters_changed(self, name_space):
        if name_space == 'Person':
            all_filter = GenericFilter()
            all_filter.set_name(_("Entire Database"))
            all_filter.add_rule(rules.person.Everyone([]))
            self.filter_model = build_filter_model('Person', [all_filter])
            self.filters.set_model(self.filter_model)
            self.filters.set_active(0)

    def on_help_clicked(self, obj):
        """Display the relevant portion of Gramps manual"""
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def build_menu_names(self, obj):
        return (_("Filter selection"), _("Event Comparison tool"))

    def filter_editor_clicked(self, obj):
        try:
            FilterEditor('Person', CUSTOM_FILTERS, self.dbstate, self.uistate)
        except WindowActiveError:
            pass

    def on_apply_clicked(self, obj):
        cfilter = self.filter_model[self.filters.get_active()][1]

        progress_bar = ProgressMeter(_('Comparing events'),
                                     '',
                                     parent=self.window)
        progress_bar.set_pass(_('Selecting people'), 1)

        plist = cfilter.apply(self.db, self.db.iter_person_handles())

        progress_bar.step()
        progress_bar.close()
        self.options.handler.options_dict['filter'] = self.filters.get_active()
        # Save options
        self.options.handler.save_options()

        if len(plist) == 0:
            WarningDialog(_("No matches were found"), parent=self.window)
        else:
            EventComparisonResults(self.dbstate, self.uistate, plist,
                                   self.track)
Beispiel #31
0
class ChangeTypes(tool.BatchTool, ManagedWindow):

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.user = user

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        if uistate:
            self.title = _('Change Event Types')
            ManagedWindow.__init__(self,uistate,[],
                                                 self.__class__)
            self.init_gui()
        else:
            self.run_tool()

    def init_gui(self):
        # Draw dialog and make it handle everything

        self.glade = Glade()

        self.auto1 = self.glade.get_object("original")
        self.auto2 = self.glade.get_object("new")

        # Need to display localized event names
        etype = EventType()
        event_names = sorted(etype.get_standard_names(), key=glocale.sort_key)

        fill_combo(self.auto1,event_names)
        fill_combo(self.auto2,event_names)

        etype.set_from_xml_str(self.options.handler.options_dict['fromtype'])
        self.auto1.get_child().set_text(str(etype))

        etype.set_from_xml_str(self.options.handler.options_dict['totype'])
        self.auto2.get_child().set_text(str(etype))

        window = self.glade.toplevel
        self.set_window(window,self.glade.get_object('title'),self.title)

        self.glade.connect_signals({
            "on_close_clicked"  : self.close,
            "on_apply_clicked"  : self.on_apply_clicked,
            "on_delete_event"   : self.close,
            })

        self.show()

    def build_menu_names(self, obj):
        return (self.title,None)

    def run_tool(self, parent_window = None):
        # Run tool and return results
        # These are English names, no conversion needed
        fromtype = self.options.handler.options_dict['fromtype']
        totype = self.options.handler.options_dict['totype']

        modified = 0

        with DbTxn(_('Change types'), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            with self.user.progress(
                    _('Analyzing Events'), '',
                    self.db.get_number_of_events()) as step:
                for event_handle in self.db.get_event_handles():
                    event = self.db.get_event_from_handle(event_handle)
                    if event.get_type().xml_str() == fromtype:
                        event.type.set_from_xml_str(totype)
                        modified += 1
                        self.db.commit_event(event,self.trans)
                        step()
        self.db.enable_signals()
        self.db.request_rebuild()

        if modified == 0:
            msg = _("No event record was modified.")
        else:
            # translators: leave all/any {...} untranslated
            msg = ngettext("{number_of} event record was modified.",
                           "{number_of} event records were modified.", modified
                          ).format(number_of=modified)

        self.user.info(_('Change types'), msg, parent_window)
        return (bool(modified),msg)

    def on_apply_clicked(self, obj):
        # Need to store English names for later comparison
        the_type = EventType()

        the_type.set(self.auto1.get_child().get_text())
        self.options.handler.options_dict['fromtype'] = the_type.xml_str()

        the_type.set(self.auto2.get_child().get_text())
        self.options.handler.options_dict['totype'] = the_type.xml_str()

        self.run_tool(self.window)

        # Save options
        self.options.handler.save_options()

        self.close()
Beispiel #32
0
class EventComparison(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.dbstate = dbstate
        self.uistate = uistate

        tool.Tool.__init__(self, dbstate, options_class, name)
        ManagedWindow.__init__(self, uistate, [], self)
        self.qual = 0

        self.filterDialog = Glade(toplevel="filters")
        self.filterDialog.connect_signals(
            {
                "on_apply_clicked": self.on_apply_clicked,
                "on_editor_clicked": self.filter_editor_clicked,
                "on_help_clicked": self.on_help_clicked,
                "destroy_passed_object": self.close,
                "on_write_table": self.__dummy,
            }
        )

        window = self.filterDialog.toplevel
        self.filters = self.filterDialog.get_object("filter_list")
        self.label = _("Event comparison filter selection")
        self.set_window(window, self.filterDialog.get_object("title"), self.label)

        self.on_filters_changed("Person")
        uistate.connect("filters-changed", self.on_filters_changed)

        self.show()

    def __dummy(self, obj):
        """dummy callback, needed because widget is in same glade file
        as another widget, so callbacks must be defined to avoid warnings.
        """
        pass

    def on_filters_changed(self, name_space):
        if name_space == "Person":
            all_filter = GenericFilter()
            all_filter.set_name(_("Entire Database"))
            all_filter.add_rule(rules.person.Everyone([]))
            self.filter_model = build_filter_model("Person", [all_filter])
            self.filters.set_model(self.filter_model)
            self.filters.set_active(0)

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def build_menu_names(self, obj):
        return (_("Filter selection"), _("Event Comparison tool"))

    def filter_editor_clicked(self, obj):
        try:
            FilterEditor("Person", CUSTOM_FILTERS, self.dbstate, self.uistate)
        except WindowActiveError:
            pass

    def on_apply_clicked(self, obj):
        cfilter = self.filter_model[self.filters.get_active()][1]

        progress_bar = ProgressMeter(_("Comparing events"), "", parent=self.window)
        progress_bar.set_pass(_("Selecting people"), 1)

        plist = cfilter.apply(self.db, self.db.iter_person_handles())

        progress_bar.step()
        progress_bar.close()
        self.options.handler.options_dict["filter"] = self.filters.get_active()
        # Save options
        self.options.handler.save_options()

        if len(plist) == 0:
            WarningDialog(_("No matches were found"), parent=self.window)
        else:
            DisplayChart(self.dbstate, self.uistate, plist, self.track)
Beispiel #33
0
class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
    """ Class for Reodering Gramps ID Tool """
    xobjects = (('person', 'people'), ('family', 'families'),
                ('event', 'events'), ('place', 'places'),
                ('source', 'sources'), ('citation', 'citations'),
                ('repository', 'repositories'),
                ('media', 'media'), ('note', 'notes'))

    def build_menu_names_(self, widget=None):
        """ The menu name """
        return (_('Main window'), _("Reorder Gramps IDs"))

    def __init__(self, dbstate, user, options_class, name, callback=None):
        self.uistate = user.uistate
        self.db = dbstate.db

        if self.uistate:
            tool.BatchTool.__init__(self, dbstate, user, options_class, name)
            if self.fail:
                return   # user denied to modify Gramps IDs

        ManagedWindow.__init__(self, self.uistate, [], self.__class__)
        if not self.uistate:
            UpdateCallback.__init__(self, user.callback)

        self.object_status = True
        self.change_status = False
        self.start_zero = True
        self.step_cnt, self.step_list = 0, ['1', '2', '5', '10']
        self.keep_status = True

        self.obj_values = {}   # enable access to all internal values
        self.active_entries, self.format_entries = {}, {}
        self.change_entries = {}
        self.start_entries, self.step_entries = {}, {}
        self.keep_entries = {}

        self.prim_methods, self.obj_methods = {}, {}
        for prim_obj, prim_objs in self.xobjects:
            iter_handles = "iter_%s_handles" % prim_obj
            get_number_obj = "get_number_of_%s" % prim_objs
            prefix_fmt = "%s_prefix" % prim_obj
            get_from_id = "get_%s_from_gramps_id" % prim_obj
            get_from_handle = "get_%s_from_handle" % prim_obj
            next_from_id = "find_next_%s_gramps_id" % prim_obj
            commit = "commit_%s" % prim_obj

            self.prim_methods[prim_obj] = (getattr(self.db, prefix_fmt),
                                           getattr(self.db, get_number_obj)(),
                                           getattr(self.db, next_from_id)())
            self.obj_methods[prim_obj] = (getattr(self.db, iter_handles),
                                          getattr(self.db, commit),
                                          getattr(self.db, get_from_id),
                                          getattr(self.db, get_from_handle),
                                          getattr(self.db, next_from_id))

            object_fmt, quant_id, next_id = self.prim_methods[prim_obj]

            obj_value = ReorderEntry(object_fmt, quant_id, next_id, prim_obj)
            self.obj_values[prim_obj] = obj_value

        if self.uistate:
            self._display()
        else:
            self._execute()

    def __on_object_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Active' attribute """
        self.object_status = not self.object_status

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_active' % prim_obj)
            obj.set_active(self.object_status)

    def __on_object_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        self.active_entries[obj_name].set_val(obj_state)

        for obj_entry in ['actual', 'quant', 'format', 'change']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            obj.set_sensitive(obj_state)

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_change' % obj_name)
            if obj.get_active():
                obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
                obj.set_sensitive(obj_state)

    def __on_format_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Format' scheme of identifiers """
        for prim_obj, dummy in self.xobjects:
            obj_format = self.top.get_object('%s_format' % prim_obj)
            if not obj_format.get_sensitive():
                continue

            obj_fmt = self.obj_values[prim_obj].res_fmt()
            self.format_entries[prim_obj].force_value(obj_fmt)
            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].last_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_change_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Change' attribute """
        self.change_status = not self.change_status

        for prim_obj, dummy in self.xobjects:
            obj_change = self.top.get_object('%s_change' % prim_obj)
            if not obj_change.get_sensitive():
                continue

            self.change_entries[prim_obj].set_val(self.change_status)
            obj_change.set_active(self.change_status)

    def __on_change_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]

        for obj_entry in ['start', 'step', 'keep']:
            obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
            if obj_entry == 'keep':
                if (self.obj_values[obj_name].stored_prefix !=
                        self.obj_values[obj_name].object_prefix and
                        self.obj_values[obj_name].stored_suffix !=
                        self.obj_values[obj_name].object_suffix):
                    self.keep_entries[obj_name].set_val(False)
                else:
                    obj.set_active(obj_state)
                    self.keep_entries[obj_name].set_val(obj_state)
            obj.set_sensitive(obj_state)

    def __on_start_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Start' values of identifiers """
        self.start_zero = not self.start_zero

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_start' % prim_obj)
            if not obj.get_sensitive():
                continue

            if self.start_zero:
                obj_id = self.obj_values[prim_obj].zero_id()
            else:
                obj_id = self.obj_values[prim_obj].next_id()
            self.start_entries[prim_obj].force_value(obj_id)

    def __on_step_button_clicked(self, widget=None):
        """ compute all sensitive primary objects and sets the
            'Step' width of identifiers """
        self.step_cnt = self.step_cnt + 1 if self.step_cnt < 3 else 0

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_step' % prim_obj)
            if not obj.get_sensitive():
                continue

            step_val = self.step_list[self.step_cnt]
            self.step_entries[prim_obj].force_value(step_val)

    def __on_keep_button_clicked(self, widget=None):
        """ compute the primary object and toggle the 'Active' attribute """
        self.keep_status = not self.keep_status

        for prim_obj, dummy in self.xobjects:
            obj = self.top.get_object('%s_change' % prim_obj)
            if not obj.get_active():
                continue

            obj = self.top.get_object('%s_keep' % prim_obj)
            obj.set_active(self.keep_status)
            self.keep_entries[prim_obj].set_val(self.keep_status)

    def __on_format_entry_keyrelease(self, widget, event, data=None):
        """ activated on all return's of an entry """
        if event.keyval in [Gdk.KEY_Return]:
            obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
            obj_fmt = self.format_entries[obj_name].get_val()
            self.format_entries[obj_name].force_value(obj_fmt)
            self.start_entries[obj_name].update()

            obj_change = self.top.get_object('%s_change' % obj_name)
            obj_change.grab_focus()

        return False

    def __on_format_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        obj_fmt = self.format_entries[obj_name].get_val()

        self.format_entries[obj_name].set_text(obj_fmt)
        self.start_entries[obj_name].update()

        return False

    def __on_start_entry_focusout(self, widget, event, data=None):
        """ activated on all focus out of an entry """
        obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
        self.start_entries[obj_name].update()

        return False

    def __on_ok_button_clicked(self, widget=None):
        """ execute the reodering and close """
        self._execute()
        self._update()

        self.close()

    def __on_cancel_button_clicked(self, widget=None):
        """ cancel the reodering and close """
        self.close()

    def __on_help_button_clicked(self, widget=None):
        """ display the relevant portion of Gramps manual """
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def _display(self):
        """ organize Glade 'Reorder IDs' window """

        # get the main window from glade
        self.top = Glade(toplevel="reorder-ids")
        window = self.top.toplevel

        # set gramps style title for the window
        self.set_window(window, self.top.get_object("title"),
                        _("Reorder Gramps IDs"))

        # connect signals
        self.top.connect_signals({
            "on_object_button_clicked" : self.__on_object_button_clicked,
            "on_object_button_toggled" : self.__on_object_button_toggled,
            "on_format_button_clicked" : self.__on_format_button_clicked,
            "on_start_button_clicked" : self.__on_start_button_clicked,
            "on_step_button_clicked" : self.__on_step_button_clicked,
            "on_keep_button_clicked" : self.__on_keep_button_clicked,
            "on_change_button_clicked" : self.__on_change_button_clicked,
            "on_change_button_toggled" : self.__on_change_button_toggled,
            "on_format_entry_keyrelease" : self.__on_format_entry_keyrelease,
            "on_format_entry_focusout" : self.__on_format_entry_focusout,
            "on_start_entry_focusout" : self.__on_start_entry_focusout,
            "on_help_button_clicked" : self.__on_help_button_clicked,
            "on_cancel_button_clicked" : self.__on_cancel_button_clicked,
            "on_ok_button_clicked" : self.__on_ok_button_clicked
        })

        # Calculate all entries and update Glade window
        for prim_obj, dummy in self.xobjects:
            # populate Object, Actual & Quantity fields with values
            obj_active = self.top.get_object('%s_active' % prim_obj)
            self.active_entries[prim_obj] = MonitoredCheckbox(
                obj_active, obj_active, self.obj_values[prim_obj].set_active,
                self.obj_values[prim_obj].get_active)
            obj_actual = self.top.get_object('%s_actual' % prim_obj)
            obj_actual.set_text('%s' % self.obj_values[prim_obj].last_id())
            obj_quant = self.top.get_object('%s_quant' % prim_obj)
            obj_quant.set_text('%s' % str(self.obj_values[prim_obj].quant_id))

            # connect/populate Format, Start, Step, Keep & Change fields
            #  with GTK/values
            obj_format = self.top.get_object('%s_format' % prim_obj)
            self.format_entries[prim_obj] = MonitoredEntry(
                obj_format, self.obj_values[prim_obj].set_fmt,
                self.obj_values[prim_obj].get_fmt)
            obj_change = self.top.get_object('%s_change' % prim_obj)
            self.change_entries[prim_obj] = MonitoredCheckbox(
                obj_change, obj_change, self.obj_values[prim_obj].set_change,
                self.obj_values[prim_obj].get_change)
            obj_start = self.top.get_object('%s_start' % prim_obj)
            self.start_entries[prim_obj] = MonitoredEntry(
                obj_start, self.obj_values[prim_obj].set_id,
                self.obj_values[prim_obj].get_id)
            obj_step = self.top.get_object('%s_step' % prim_obj)
            self.step_entries[prim_obj] = MonitoredEntry(
                obj_step, self.obj_values[prim_obj].set_step,
                self.obj_values[prim_obj].get_step,
                changed=self.obj_values[prim_obj].change_step)
            obj_keep = self.top.get_object('%s_keep' % prim_obj)
            self.keep_entries[prim_obj] = MonitoredCheckbox(
                obj_keep, obj_keep, self.obj_values[prim_obj].set_keep,
                self.obj_values[prim_obj].get_keep, readonly=True)

        # fetch the popup menu
        self.menu = self.top.get_object("popup_menu")

        # ok, let's see what we've done
        self.window.resize(700, 410)
        self.show()

    def _update(self):
        """ store changed objects formats in DB """

        update = False
        for prim_obj, dummy in self.xobjects:
            obj_value = self.obj_values[prim_obj]
            if obj_value.object_fmt != obj_value.stored_fmt:
                constant = 'preferences.%sprefix' % PREFIXES[prim_obj]
                config.set(constant, obj_value.object_fmt)
                update = True

        if update:
            config.save()
            self.db.set_prefixes(
                config.get('preferences.iprefix'),
                config.get('preferences.oprefix'),
                config.get('preferences.fprefix'),
                config.get('preferences.sprefix'),
                config.get('preferences.cprefix'),
                config.get('preferences.pprefix'),
                config.get('preferences.eprefix'),
                config.get('preferences.rprefix'),
                config.get('preferences.nprefix'))

    def _execute(self):
        """ execute all primary objects and reorder if neccessary """

        # Update progress calculation
        if self.uistate:
            self.progress = ProgressMeter(_('Reorder Gramps IDs'), '')
        else:
            total_objs = 0
            for prim_obj, dummy in self.xobjects:
                if self.obj_values[prim_obj].active_obj:
                    total_objs += self.obj_values[prim_obj].quant_id
            self.set_total(total_objs)

        # Update database
        self.db.disable_signals()
        for prim_obj, prim_objs in self.xobjects:
            with DbTxn(_('Reorder %s IDs ...') % prim_obj,
                       self.db, batch=True) as self.trans:
                if self.obj_values[prim_obj].active_obj:
                    if self.uistate:
                        self.progress.set_pass(
                            _('Reorder %s IDs ...') % _(prim_objs.title()),
                            self.obj_values[prim_obj].quant_id)
                    # Process reordering
                    self._reorder(prim_obj)

        self.db.enable_signals()
        self.db.request_rebuild()

        # Update progress calculation
        if self.uistate:
            self.progress.close()
        else:
            print('\nDone.')

    # finds integer portion in a GrampsID
    _findint = re.compile('^[^\d]*(\d+)[^\d]*$')
    # finds prefix, number, suffix of a Gramps ID ignoring a leading or
    # trailing space.  The number must be at least three digits.
    _prob_id = re.compile('^ *([^\d]*)(\d{3,9})([^\d]*) *$')

    def _reorder(self, prim_obj):
        """ reorders all selected objects with a (new) style, start & step """

        dup_ids = []   # list of duplicate identifiers
        new_ids = {}   # list of new identifiers

        iter_handles, commit, get_from_id, get_from_handle, next_from_id = \
            self.obj_methods[prim_obj]

        prefix_fmt = self.obj_values[prim_obj].get_fmt()
        prefix = self.obj_values[prim_obj].object_prefix
        suffix = self.obj_values[prim_obj].object_suffix
        old_pref = self.obj_values[prim_obj].stored_prefix
        old_suff = self.obj_values[prim_obj].stored_suffix
        new_id = self.obj_values[prim_obj].get_id()
        keep_fmt = self.obj_values[prim_obj].get_keep()
        change = self.obj_values[prim_obj].get_change()
        index_max = int("9" * self.obj_values[prim_obj].width_fmt)
        do_same = False

        for handle in iter_handles():
            # Update progress
            if self.uistate:
                self.progress.step()
            else:
                self.update()

            # extract basic data out of the database
            obj = get_from_handle(handle)

            act_id = obj.get_gramps_id()
            # here we see if the ID looks like a new or previous or default
            # Gramps ID.
            # If not we ask user if he really wants to replace it.
            # This should allow user to protect a GetGov ID or similar
            match = self._prob_id.match(act_id)
            if not (match and
                    (prefix == match.groups()[0] and
                     suffix == match.groups()[2] or
                     old_pref == match.groups()[0] and
                     old_suff == match.groups()[2] or
                     len(match.groups()[0]) == 1 and
                     len(match.groups()[2]) == 0)) and not do_same:
                xml = Glade(toplevel='dialog')

                top = xml.toplevel
                # self.top.set_icon(ICON)
                top.set_title("%s - Gramps" % _("Reorder Gramps IDs"))
                apply_to_rest = xml.get_object('apply_to_rest')

                label1 = xml.get_object('toplabel')
                label1.set_text('<span weight="bold" size="larger">%s</span>' %
                                _("Reorder Gramps IDs"))
                label1.set_use_markup(True)

                label2 = xml.get_object('mainlabel')
                label2.set_text(_("Do you want to replace %s?" % act_id))
                top.set_transient_for(self.progress._ProgressMeter__dialog)
                self.progress._ProgressMeter__dialog.set_modal(False)
                top.show()
                response = top.run()
                do_same = apply_to_rest.get_active()
                top.destroy()
                self.progress._ProgressMeter__dialog.set_modal(True)
                if response != Gtk.ResponseType.YES:
                    continue

            elif not match and do_same and response != Gtk.ResponseType.YES:
                continue

            if change:
                # update the defined ID numbers into objects under
                # consideration of keeping ID if format not matches prefix
                # (implication logical boolean operator below)
                if act_id.startswith(prefix) and act_id.endswith(suffix) or \
                        not keep_fmt:
                    obj.set_gramps_id(new_id)
                    commit(obj, self.trans)
                    new_id = self.obj_values[prim_obj].succ_id()
            else:
                # attempt to extract integer - if we can't, treat it as a
                # duplicate
                try:
                    match = self._findint.match(act_id)
                    if match:
                        # get the integer, build the new handle. Make sure it
                        # hasn't already been chosen. If it has, put this
                        # in the duplicate handle list

                        index = int(match.groups()[0])
                        if index > index_max:
                            new_id = next_from_id()
                        else:
                            new_id = prefix_fmt % index

                        if new_id == act_id:
                            if new_id in new_ids:
                                dup_ids.append(obj.get_handle())
                            else:
                                new_ids[new_id] = act_id
                        elif get_from_id(new_id) is not None:
                            dup_ids.append(obj.get_handle())
                        else:
                            obj.set_gramps_id(new_id)
                            commit(obj, self.trans)
                            new_ids[new_id] = act_id
                    else:
                        dup_ids.append(handle)
                except:
                    dup_ids.append(handle)

        # go through the duplicates, looking for the first available
        # handle that matches the new scheme.
        if dup_ids:
            if self.uistate:
                self.progress.set_pass(_('Finding and assigning unused IDs.'),
                                       len(dup_ids))
            for handle in dup_ids:
                obj = get_from_handle(handle)
                obj.set_gramps_id(next_from_id())
                commit(obj, self.trans)
Beispiel #34
0
class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
    MARK_COL = 0
    OBJ_ID_COL = 1
    OBJ_NAME_COL = 2
    OBJ_TYPE_COL = 3
    OBJ_HANDLE_COL = 4

    BUSY_CURSOR = Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
                                             Gdk.CursorType.WATCH)

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.title = _('Unused Objects')

        tool.Tool.__init__(self, dbstate, options_class, name)

        if self.db.readonly:
            return

        ManagedWindow.__init__(self, uistate, [], self.__class__)
        UpdateCallback.__init__(self, self.uistate.pulse_progressbar)

        self.dbstate = dbstate
        self.uistate = uistate

        self.tables = {
            'events': {
                'get_func': self.db.get_event_from_handle,
                'remove': self.db.remove_event,
                'get_text': self.get_event_text,
                'editor': 'EditEvent',
                'icon': 'gramps-event',
                'name_ix': 4
            },
            'sources': {
                'get_func': self.db.get_source_from_handle,
                'remove': self.db.remove_source,
                'get_text': None,
                'editor': 'EditSource',
                'icon': 'gramps-source',
                'name_ix': 2
            },
            'citations': {
                'get_func': self.db.get_citation_from_handle,
                'remove': self.db.remove_citation,
                'get_text': None,
                'editor': 'EditCitation',
                'icon': 'gramps-citation',
                'name_ix': 3
            },
            'places': {
                'get_func': self.db.get_place_from_handle,
                'remove': self.db.remove_place,
                'get_text': None,
                'editor': 'EditPlace',
                'icon': 'gramps-place',
                'name_ix': 2
            },
            'media': {
                'get_func': self.db.get_media_from_handle,
                'remove': self.db.remove_media,
                'get_text': None,
                'editor': 'EditMedia',
                'icon': 'gramps-media',
                'name_ix': 4
            },
            'repos': {
                'get_func': self.db.get_repository_from_handle,
                'remove': self.db.remove_repository,
                'get_text': None,
                'editor': 'EditRepository',
                'icon': 'gramps-repository',
                'name_ix': 3
            },
            'notes': {
                'get_func': self.db.get_note_from_handle,
                'remove': self.db.remove_note,
                'get_text': self.get_note_text,
                'editor': 'EditNote',
                'icon': 'gramps-notes',
                'name_ix': 2
            },
        }

        self.init_gui()

    def init_gui(self):
        self.top = Glade()
        window = self.top.toplevel
        self.set_window(window, self.top.get_object('title'), self.title)

        self.events_box = self.top.get_object('events_box')
        self.sources_box = self.top.get_object('sources_box')
        self.citations_box = self.top.get_object('citations_box')
        self.places_box = self.top.get_object('places_box')
        self.media_box = self.top.get_object('media_box')
        self.repos_box = self.top.get_object('repos_box')
        self.notes_box = self.top.get_object('notes_box')
        self.find_button = self.top.get_object('find_button')
        self.remove_button = self.top.get_object('remove_button')

        self.events_box.set_active(self.options.handler.options_dict['events'])
        self.sources_box.set_active(
            self.options.handler.options_dict['sources'])
        self.citations_box.set_active(
            self.options.handler.options_dict['citations'])
        self.places_box.set_active(self.options.handler.options_dict['places'])
        self.media_box.set_active(self.options.handler.options_dict['media'])
        self.repos_box.set_active(self.options.handler.options_dict['repos'])
        self.notes_box.set_active(self.options.handler.options_dict['notes'])

        self.warn_tree = self.top.get_object('warn_tree')
        self.warn_tree.connect('button_press_event', self.double_click)

        self.selection = self.warn_tree.get_selection()

        self.mark_button = self.top.get_object('mark_button')
        self.mark_button.connect('clicked', self.mark_clicked)

        self.unmark_button = self.top.get_object('unmark_button')
        self.unmark_button.connect('clicked', self.unmark_clicked)

        self.invert_button = self.top.get_object('invert_button')
        self.invert_button.connect('clicked', self.invert_clicked)

        self.real_model = Gtk.ListStore(GObject.TYPE_BOOLEAN,
                                        GObject.TYPE_STRING,
                                        GObject.TYPE_STRING,
                                        GObject.TYPE_STRING,
                                        GObject.TYPE_STRING)
        self.sort_model = self.real_model.sort_new_with_model()
        self.warn_tree.set_model(self.sort_model)

        self.renderer = Gtk.CellRendererText()
        self.img_renderer = Gtk.CellRendererPixbuf()
        self.bool_renderer = Gtk.CellRendererToggle()
        self.bool_renderer.connect('toggled', self.selection_toggled)

        # Add mark column
        mark_column = Gtk.TreeViewColumn(_('Mark'),
                                         self.bool_renderer,
                                         active=RemoveUnused.MARK_COL)
        mark_column.set_sort_column_id(RemoveUnused.MARK_COL)
        self.warn_tree.append_column(mark_column)

        # Add image column
        img_column = Gtk.TreeViewColumn(None, self.img_renderer)
        img_column.set_cell_data_func(self.img_renderer, self.get_image)
        self.warn_tree.append_column(img_column)

        # Add column with object gramps_id
        id_column = Gtk.TreeViewColumn(_('ID'),
                                       self.renderer,
                                       text=RemoveUnused.OBJ_ID_COL)
        id_column.set_sort_column_id(RemoveUnused.OBJ_ID_COL)
        self.warn_tree.append_column(id_column)

        # Add column with object name
        name_column = Gtk.TreeViewColumn(_('Name'),
                                         self.renderer,
                                         text=RemoveUnused.OBJ_NAME_COL)
        name_column.set_sort_column_id(RemoveUnused.OBJ_NAME_COL)
        self.warn_tree.append_column(name_column)

        self.top.connect_signals({
            "destroy_passed_object": self.close,
            "on_remove_button_clicked": self.do_remove,
            "on_find_button_clicked": self.find,
            "on_delete_event": self.close,
        })

        self.dc_label = self.top.get_object('dc_label')

        self.sensitive_list = [
            self.warn_tree, self.mark_button, self.unmark_button,
            self.invert_button, self.dc_label, self.remove_button
        ]

        for item in self.sensitive_list:
            item.set_sensitive(False)

        self.show()

    def build_menu_names(self, obj):
        return (self.title, None)

    def find(self, obj):
        self.options.handler.options_dict.update(
            events=self.events_box.get_active(),
            sources=self.sources_box.get_active(),
            citations=self.citations_box.get_active(),
            places=self.places_box.get_active(),
            media=self.media_box.get_active(),
            repos=self.repos_box.get_active(),
            notes=self.notes_box.get_active(),
        )

        for item in self.sensitive_list:
            item.set_sensitive(True)

        self.uistate.set_busy_cursor(True)
        self.uistate.progress.show()
        self.window.get_window().set_cursor(self.BUSY_CURSOR)

        self.real_model.clear()
        self.collect_unused()

        self.uistate.progress.hide()
        self.uistate.set_busy_cursor(False)
        self.window.get_window().set_cursor(None)
        self.reset()

        # Save options
        self.options.handler.save_options()

    def collect_unused(self):
        # Run through all requested tables and check all objects
        # for being referenced some place. If not, add_results on them.

        db = self.db
        tables = (
            ('events', db.get_event_cursor, db.get_number_of_events),
            ('sources', db.get_source_cursor, db.get_number_of_sources),
            ('citations', db.get_citation_cursor, db.get_number_of_citations),
            ('places', db.get_place_cursor, db.get_number_of_places),
            ('media', db.get_media_cursor, db.get_number_of_media),
            ('repos', db.get_repository_cursor, db.get_number_of_repositories),
            ('notes', db.get_note_cursor, db.get_number_of_notes),
        )

        # bug 7619 : don't select notes from to do list.
        # notes associated to the todo list doesn't have references.
        # get the todo list (from get_note_list method of the todo gramplet )
        all_notes = self.dbstate.db.get_note_handles()
        FilterClass = GenericFilterFactory('Note')
        filter1 = FilterClass()
        filter1.add_rule(rules.note.HasType(["To Do"]))
        todo_list = filter1.apply(self.dbstate.db, all_notes)
        filter2 = FilterClass()
        filter2.add_rule(rules.note.HasType(["Link"]))
        link_list = filter2.apply(self.dbstate.db, all_notes)

        for (the_type, cursor_func, total_func) in tables:
            if not self.options.handler.options_dict[the_type]:
                # This table was not requested. Skip it.
                continue

            with cursor_func() as cursor:
                self.set_total(total_func())
                fbh = db.find_backlink_handles
                for handle, data in cursor:
                    if not any(h for h in fbh(handle)):
                        if handle not in todo_list and handle not in link_list:
                            self.add_results(
                                (the_type, handle.decode('utf-8'), data))
                    self.update()
            self.reset()

    def do_remove(self, obj):
        with DbTxn(_("Remove unused objects"), self.db, batch=False) as trans:
            self.db.disable_signals()

            for row_num in range(len(self.real_model) - 1, -1, -1):
                path = (row_num, )
                row = self.real_model[path]
                if not row[RemoveUnused.MARK_COL]:
                    continue

                the_type = row[RemoveUnused.OBJ_TYPE_COL]
                handle = row[RemoveUnused.OBJ_HANDLE_COL]
                remove_func = self.tables[the_type]['remove']
                remove_func(handle, trans)

                self.real_model.remove(row.iter)

        self.db.enable_signals()
        self.db.request_rebuild()

    def selection_toggled(self, cell, path_string):
        sort_path = tuple(map(int, path_string.split(':')))
        real_path = self.sort_model.convert_path_to_child_path(
            Gtk.TreePath(sort_path))
        row = self.real_model[real_path]
        row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]
        self.real_model.row_changed(real_path, row.iter)

    def mark_clicked(self, mark_button):
        for row_num in range(len(self.real_model)):
            path = (row_num, )
            row = self.real_model[path]
            row[RemoveUnused.MARK_COL] = True

    def unmark_clicked(self, unmark_button):
        for row_num in range(len(self.real_model)):
            path = (row_num, )
            row = self.real_model[path]
            row[RemoveUnused.MARK_COL] = False

    def invert_clicked(self, invert_button):
        for row_num in range(len(self.real_model)):
            path = (row_num, )
            row = self.real_model[path]
            row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]

    def double_click(self, obj, event):
        if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
            (model, node) = self.selection.get_selected()
            if not node:
                return
            sort_path = self.sort_model.get_path(node)
            real_path = self.sort_model.convert_path_to_child_path(sort_path)
            row = self.real_model[real_path]
            the_type = row[RemoveUnused.OBJ_TYPE_COL]
            handle = row[RemoveUnused.OBJ_HANDLE_COL]
            self.call_editor(the_type, handle)

    def call_editor(self, the_type, handle):
        try:
            obj = self.tables[the_type]['get_func'](handle)
            editor_str = 'from gramps.gui.editors import %s as editor' % (
                self.tables[the_type]['editor'])
            exec(editor_str, globals())
            editor(self.dbstate, self.uistate, [], obj)
        except WindowActiveError:
            pass

    def get_image(self, column, cell, model, iter, user_data=None):
        the_type = model.get_value(iter, RemoveUnused.OBJ_TYPE_COL)
        the_icon = self.tables[the_type]['icon']
        cell.set_property('icon-name', the_icon)

    def add_results(self, results):
        (the_type, handle, data) = results
        gramps_id = data[1]

        # if we have a function that will return to us some type
        # of text summary, then we should use it; otherwise we'll
        # use the generic field index provided in the tables above
        if self.tables[the_type]['get_text']:
            text = self.tables[the_type]['get_text'](the_type, handle, data)
        else:
            # grab the text field index we know about, and hope
            # it represents something useful to the user
            name_ix = self.tables[the_type]['name_ix']
            text = data[name_ix]

        # insert a new row into the table
        self.real_model.append(row=[False, gramps_id, text, the_type, handle])

    def get_event_text(self, the_type, handle, data):
        """
        Come up with a short line of text that we can use as
        a summary to represent this event.
        """

        # get the event:
        event = self.tables[the_type]['get_func'](handle)

        # first check to see if the event has a descriptive name
        text = event.get_description()  # (this is rarely set for events)

        # if we don't have a description...
        if text == '':
            # ... then we merge together several fields

            # get the event type (marriage, birth, death, etc.)
            text = str(event.get_type())

            # see if there is a date
            date = _dd.display(event.get_date_object())
            if date != '':
                text += '; %s' % date

            # see if there is a place
            if event.get_place_handle():
                text += '; %s' % _pd.display_event(self.db, event)

        return text

    def get_note_text(self, the_type, handle, data):
        """
        We need just the first few words of a note as a summary.
        """
        # get the note object
        note = self.tables[the_type]['get_func'](handle)

        # get the note text; this ignores (discards) formatting
        text = note.get()

        # convert whitespace to a single space
        text = " ".join(text.split())

        # if the note is too long, truncate it
        if len(text) > 80:
            text = text[:80] + "..."

        return text
Beispiel #35
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.title = _('Find database loop')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.db = dbstate.db

        top_dialog = Glade()

        top_dialog.connect_signals({
            "destroy_passed_object" : self.close,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_event"       : self.close,
        })

        window = top_dialog.toplevel
        title = top_dialog.get_object("title")
        self.set_window(window, title, self.title)

        # start the progress indicator
        self.progress = ProgressMeter(self.title, _('Starting'), # parent-OK
                                      parent=self.window)
        self.progress.set_pass(_('Looking for possible loop for each person'),
                               self.db.get_number_of_people())

        self.model = Gtk.ListStore(
            GObject.TYPE_STRING,    # 0==father id
            GObject.TYPE_STRING,    # 1==father
            GObject.TYPE_STRING,    # 2==son id
            GObject.TYPE_STRING,    # 3==son
            GObject.TYPE_STRING)    # 4==family gid

        self.treeview = top_dialog.get_object("treeview")
        self.treeview.set_model(self.model)
        col1 = Gtk.TreeViewColumn(_('Gramps ID'),
                                  Gtk.CellRendererText(), text=0)
        col2 = Gtk.TreeViewColumn(_('Ancestor'),
                                  Gtk.CellRendererText(), text=1)
        col3 = Gtk.TreeViewColumn(_('Gramps ID'),
                                  Gtk.CellRendererText(), text=2)
        col4 = Gtk.TreeViewColumn(_('Descendant'),
                                  Gtk.CellRendererText(), text=3)
        col5 = Gtk.TreeViewColumn(_('Family ID'),
                                  Gtk.CellRendererText(), text=4)
        col1.set_resizable(True)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col5.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col1.set_sort_column_id(0)
        col2.set_sort_column_id(1)
        col3.set_sort_column_id(2)
        col4.set_sort_column_id(3)
        col5.set_sort_column_id(4)
        self.treeview.append_column(col1)
        self.treeview.append_column(col2)
        self.treeview.append_column(col3)
        self.treeview.append_column(col4)
        self.treeview.append_column(col5)
        self.treeselection = self.treeview.get_selection()
        self.treeview.connect('row-activated', self.rowactivated_cb)

        self.curr_fam = None
        people = self.db.get_person_handles()
        count = 0
        for person_handle in people:
            person = self.db.get_person_from_handle(person_handle)
            count += 1
            self.current = person
            self.parent = None
            self.descendants(person_handle, set())
            self.progress.set_header("%d/%d" % (count, len(people)))
            self.progress.step()

        # close the progress bar
        self.progress.close()

        self.show()
Beispiel #36
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        tool.ActivePersonTool.__init__(self, dbstate, uistate, options_class,
                                       name)

        if self.fail:  # bug #2709 -- fail if we have no active person
            return

        person_handle = uistate.get_active('Person')
        person = dbstate.db.get_person_from_handle(person_handle)
        self.name = person.get_primary_name().get_regular_name()
        self.title = _('Not related to "%s"') % self.name
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.db = dbstate.db

        topDialog = Glade()

        topDialog.connect_signals({
            "destroy_passed_object": self.close,
            "on_help_clicked": self.on_help_clicked,
            "on_delete_event": self.close,
        })

        window = topDialog.toplevel
        title = topDialog.get_object("title")
        self.set_window(window, title, self.title)

        self.tagcombo = topDialog.get_object("tagcombo")
        tagmodel = Gtk.ListStore(str)
        self.tagcombo.set_model(tagmodel)
        self.tagcombo.set_entry_text_column(0)
        tagmodel.append((_('ToDo'), ))
        tagmodel.append((_('NotRelated'), ))
        self.tagcombo.set_sensitive(False)

        self.tagapply = topDialog.get_object("tagapply")
        self.tagapply.set_sensitive(False)
        self.tagapply.connect('clicked', self.applyTagClicked)

        # start the progress indicator
        self.progress = ProgressMeter(self.title,
                                      _('Starting'),
                                      parent=self.window)

        # setup the columns
        self.model = Gtk.TreeStore(
            GObject.TYPE_STRING,  # 0==name
            GObject.TYPE_STRING,  # 1==person gid
            GObject.TYPE_STRING,  # 2==parents
            GObject.TYPE_STRING,  # 3==tags
            GObject.TYPE_STRING)  # 4==family gid (not shown to user)

        # note -- don't assign the model to the tree until it has been populated,
        # otherwise the screen updates are terribly slow while names are appended
        self.treeView = topDialog.get_object("treeview")
        col1 = Gtk.TreeViewColumn(_('Name'), Gtk.CellRendererText(), text=0)
        col2 = Gtk.TreeViewColumn(_('ID'), Gtk.CellRendererText(), text=1)
        col3 = Gtk.TreeViewColumn(_('Parents'), Gtk.CellRendererText(), text=2)
        col4 = Gtk.TreeViewColumn(_('Tags'), Gtk.CellRendererText(), text=3)
        col1.set_resizable(True)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col1.set_sort_column_id(0)
        #        col2.set_sort_column_id(1)
        #        col3.set_sort_column_id(2)
        col4.set_sort_column_id(3)
        self.treeView.append_column(col1)
        self.treeView.append_column(col2)
        self.treeView.append_column(col3)
        self.treeView.append_column(col4)
        self.treeSelection = self.treeView.get_selection()
        self.treeSelection.set_mode(Gtk.SelectionMode.MULTIPLE)
        self.treeSelection.set_select_function(self.selectIsAllowed, None)
        self.treeSelection.connect('changed', self.rowSelectionChanged)
        self.treeView.connect('row-activated', self.rowActivated)

        # initialize a few variables we're going to need
        self.numberOfPeopleInDatabase = self.db.get_number_of_people()
        self.numberOfRelatedPeople = 0
        self.numberOfUnrelatedPeople = 0

        # create the sets used to track related and unrelated people
        self.handlesOfPeopleToBeProcessed = set()
        self.handlesOfPeopleAlreadyProcessed = set()
        self.handlesOfPeopleNotRelated = set()

        # build a set of all people related to the selected person
        self.handlesOfPeopleToBeProcessed.add(person.get_handle())
        self.findRelatedPeople()

        # now that we have our list of related people, find everyone
        # in the database who isn't on our list
        self.findUnrelatedPeople()

        # populate the treeview model with the names of unrelated people
        if self.numberOfUnrelatedPeople == 0:
            # feature request 2356: avoid genitive form
            title.set_text(
                _('Everyone in the database is related to %s') % self.name)
        else:
            self.populateModel()
            self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
            self.treeView.set_model(self.model)
            #            self.treeView.set_row_separator_func(self.iterIsSeparator, None)
            self.treeView.expand_all()

        # done searching through the database, so close the progress bar
        self.progress.close()

        self.show()
Beispiel #37
0
class ProgenOptions(ManagedWindow):
    """ Class for Pro-Gen files import optons"""
    def __init__(self, database, filename, user):
        """ Useful options for Pro-Gen import """
        self.dbase = database
        self.fname = filename
        self.user = user
        self.uistate = user.uistate
        self.option = {}

        # default: Pro-Gen import failed
        self.fail = True

        # initial values
        text = "Pro-Gen Import"
        fname = os.path.basename(filename).split('\\')[-1]
        date = time.strftime('%Y-%m-%d', time.localtime())

        # add import source title/confidence
        #            citation page/confidence/privacy/attribute
        self.import_methods = {}
        dflt = config.get('preferences.default-source')
        if config.get('preferences.tag-on-import'):
            dflt_text = config.get('preferences.tag-on-import-format')
        else:
            dflt_text = '%s %s' % (text, date)
        self.imp_values = ImportSourceCitation \
            (dflt, dflt_text, text, fname, date)

        # add default text / filename / current date
        self.default_methods = {}
        self.default_values = ImportTagTextDefault(text, fname)

        # add tagobjects text / filename / date
        self.tagobj_status = True
        self.tagobj_values, self.tagobj_methods = {}, {}
        self.tagtext_methods = {}
        self.tagfname_status, self.tagfname_methods = True, {}
        self.tagdate_status, self.tagdate_methods = True, {}
        for obj in libprogen.TAGOBJECTS:
            self.tagobj_values[obj] = ImportTagText(self.default_values)

        # add primary object values
        self.primobj_values, self.primobj_methods = {}, {}
        for obj in libprogen.PRIMOBJECTS:
            self.primobj_values[obj] = ImportValue(True)

        # add options values
        self.option_values, self.option_methods = {}, {}
        for obj in libprogen.OPTOBJECTS:
            if obj in ['person-ident', 'family-ident', \
                       'surname-female', 'death-cause']:
                self.option_values[obj] = ImportValue(True)
            else:
                self.option_values[obj] = ImportValue(False)

        # prepare option dictionary
        self._collect()

        # display window if GUI active
        if self.uistate:
            ManagedWindow.__init__(self,
                                   self.uistate, [],
                                   self.__class__,
                                   modal=True)
            self._display()

    def __on_source_button_toggled(self, widget):
        """ compute the source button and toggle the 'Sensitive' attribute """
        obj_source_state = widget.get_active()
        for obj in ['priv', 'title', 'attr']:
            imp_obj = self.glade.get_object('imp_source_%s' % obj)
            imp_obj.set_sensitive(obj_source_state)

        # Check if Source enabled and syncronizing Citation
        self.glade.get_object('imp_citation_btn').set_active(obj_source_state)
        self.glade.get_object('imp_citation_btn').set_sensitive(
            obj_source_state)

    def __on_citation_button_toggled(self, widget):
        """ compute the citation button and toggle the 'Sensitive' attribute """
        # Check if Source enabled and syncronizing Citation
        obj_source_state = self.glade.get_object('imp_source_btn').get_active()

        obj_citation_state = widget.get_active() and obj_source_state
        for obj in ['priv', 'conf', 'page', 'attr']:
            imp_obj = self.glade.get_object('imp_citation_%s' % obj)
            imp_obj.set_sensitive(obj_citation_state)

    def __on_import_entry_keyrelease(self, widget, event, data=None):
        """ activated on all return's of an entry"""
        if event.keyval in [Gdk.KEY_Return]:
            obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[1]
            if obj_name == 'citation_page':
                obj_next = self.glade.get_object('imp_citation_attr')
                obj_next.grab_focus()

    def __on_object_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'Active' attribute """
        self.tagobj_status = not self.tagobj_status

        for obj in libprogen.TAGOBJECTS:
            tag_obj = self.glade.get_object('tag_%s_obj' % obj)
            tag_obj.set_active(self.tagobj_status)

    def __on_object_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        obj_state = widget.get_active()
        obj_name = Gtk.Buildable.get_name(widget)
        obj_name = obj_name.split('_', 1)[1].split('_', 1)[0]

        for obj in ['text', 'fname', 'date']:
            tag_obj = self.glade.get_object('tag_%s_%s' % (obj_name, obj))
            tag_obj.set_sensitive(obj_state)

    def __on_text_button_clicked(self, widget=None):
        """ compute all primary objects and flush the 'text' field """
        self.__on_tagtext_entry_resume()  # Resume tag text

    def __on_tagtext_entry_keyrelease(self, widget, event, data=None):
        """ activated on all return's of an entry """
        if event.keyval in [Gdk.KEY_Return]:
            obj_name = Gtk.Buildable.get_name(widget)
            obj_name = obj_name.split('_', 1)[1].split('_', 1)[0]
            obj_index = libprogen.TAGOBJECTS.index(obj_name)
            if obj_index < len(libprogen.TAGOBJECTS) - 1:
                obj_index = obj_index + 1
            obj_next = self.glade.get_object('tag_%s_text' % \
                                             libprogen.TAGOBJECTS[obj_index])
            obj_next.grab_focus()

    def __on_tagtext_entry_resume(self):
        """ resume new tagtext from old + file & date variables"""
        for obj in libprogen.TAGOBJECTS:
            tag_obj = self.glade.get_object('tag_%s_text' % obj)
            if not tag_obj.get_sensitive():
                continue

            obj_entry = self.tagobj_values[obj].get_dflttext()
            self.tagobj_values[obj].tag_text.set_entry(obj_entry)
            self.tagtext_methods[obj].update()

    def __on_fname_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'file' attribute """
        self.tagfname_status = not self.tagfname_status

        for obj in libprogen.TAGOBJECTS:
            tag_obj = self.glade.get_object('tag_%s_fname' % obj)
            if not tag_obj.get_sensitive():
                continue

            self.tagfname_methods[obj].set_val(self.tagfname_status)
            tag_obj.set_active(self.tagfname_status)

        self.__on_tagtext_entry_resume()  # Resume tag text

    def __on_fname_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        self.__on_tagtext_entry_resume()

        # switch focus forward
        obj_name = Gtk.Buildable.get_name(widget)
        obj_name = obj_name.split('_', 1)[1].split('_', 1)[0]
        obj_index = libprogen.TAGOBJECTS.index(obj_name)
        if obj_index < len(libprogen.TAGOBJECTS) - 1:
            obj_index = obj_index + 1
        obj_next = self.glade.get_object('tag_%s_fname' % \
                                         libprogen.TAGOBJECTS[obj_index])
        obj_next.grab_focus()

    def __on_date_button_clicked(self, widget=None):
        """ compute all primary objects and toggle the 'date' attribute """
        self.tagdate_status = not self.tagdate_status

        for obj in libprogen.TAGOBJECTS:
            tag_obj = self.glade.get_object('tag_%s_date' % obj)
            if not tag_obj.get_sensitive():
                continue

            self.tagdate_methods[obj].set_val(self.tagdate_status)
            tag_obj.set_active(self.tagdate_status)

        self.__on_tagtext_entry_resume()  # Resume tag text

    def __on_date_button_toggled(self, widget):
        """ compute the primary object and toggle the 'Sensitive' attribute """
        self.__on_tagtext_entry_resume()

        # switch focus forward
        obj_name = Gtk.Buildable.get_name(widget)
        obj_name = obj_name.split('_', 1)[1].split('_', 1)[0]
        obj_index = libprogen.TAGOBJECTS.index(obj_name)
        if obj_index < len(libprogen.TAGOBJECTS) - 1:
            obj_index = obj_index + 1
        obj_next = self.glade.get_object('tag_%s_date' % \
                                         libprogen.TAGOBJECTS[obj_index])
        obj_next.grab_focus()

    def __on_primobj_button_toggled(self, widget):
        """ compute all primary objects and toggle the 'primobj' attribute """
        obj_name = Gtk.Buildable.get_name(widget)
        obj_name = obj_name.split('_', 1)[1].split('_', 1)[0]

        for i, obj_i in enumerate(libprogen.PRIMOBJECTS):
            if obj_name == libprogen.PRIMOBJECTS[i]:
                prim_obj = self.glade.get_object('prim_%s_btn' % obj_i)
                if not prim_obj.get_active():
                    # Prim. object deactivated:
                    # check all in list below and deactivate
                    for obj_ii in libprogen.PRIMOBJECTS[(i + 1):]:
                        sec_obj = self.glade.get_object('prim_%s_btn' % obj_ii)
                        sec_obj.set_active(False)
                    break
                else:
                    # Prim. object activated: check all in list above
                    # if one prim. object is deactive:
                    # deactivate this prim. object too
                    for obj_ii in libprogen.PRIMOBJECTS[:i]:
                        sec_obj = self.glade.get_object('prim_%s_btn' % obj_ii)
                        if not sec_obj.get_active():
                            prim_obj.set_active(False)
                            break

    def __on_surname_button_toggled(self, widget):
        """ compute surname objects and """
        obj_name = Gtk.Buildable.get_name(widget)
        obj_name = obj_name.split('_', 1)[1].split('_', 1)[0]
        obj_status = widget.get_active()

        if (obj_name == 'name-surmale') and (obj_status == True):
            sec_obj = self.glade.get_object('opt_surname-female_btn')
            sec_obj.set_active(False)
        if (obj_name == 'name-surfemale') and (obj_status == True):
            sec_obj = self.glade.get_object('opt_surname-male_btn')
            sec_obj.set_active(False)

    def __on_x_button_clicked(self, widget=None):
        """ cancel the import and close """
        self.fail = True  # Pro-Gen import canceled

    def __on_ok_button_clicked(self, widget=None):
        """ execute the import and close """
        self._collect()
        self.close()

        self.fail = False  # Pro-Gen import proceed

    def __on_cancel_button_clicked(self, widget=None):
        """ cancel the import and close """
        self.close()

        self.fail = True  # Pro-Gen import canceled

    def __on_help_button_clicked(self, widget=None):
        """ display the relevant portion of Gramps manual """
        self.fail = True

        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def build_menu_names_(self, widget=None):
        """ The menu name """
        return (_('Main window'), _("Import Pro-Gen"))

    def _display(self):
        """ organize Glade 'Import Pro-Gen' window """

        # get the main window from glade
        self.glade = Glade('importprogen.glade')
        self.set_window(self.glade.toplevel, self.glade.get_object('title'),
                        _('Import Pro-Gen'))

        # calculate all entries and update Glade window
        # Text for Source / Citation objects
        for obj in ('source_btn', 'citation_btn'):
            widget = self.glade.get_object('imp_%s' % obj)
            set_import = eval('self.imp_values.%s.set_value' % obj)
            get_import = eval('self.imp_values.%s.get_value' % obj)
            self.import_methods[obj] = MonitoredCheckbox(\
                widget, widget, set_import, get_import, self.dbase.readonly)
        for obj in ('source_title', 'source_attr', 'citation_page',
                    'citation_attr'):
            widget = self.glade.get_object('imp_%s' % obj)
            set_import = eval('self.imp_values.%s.set_entry' % obj)
            get_import = eval('self.imp_values.%s.get_entry' % obj)
            self.import_methods[obj] = MonitoredEntry(\
                widget, set_import, get_import, self.dbase.readonly)
        widget = self.glade.get_object('imp_citation_conf')
        self.import_methods['conf'] = MonitoredMenu(
            widget, self.imp_values.citation_conf.set_value,
            self.imp_values.citation_conf.get_value,
            [(_('Very Low'), Citation.CONF_VERY_LOW),
             (_('Low'), Citation.CONF_LOW),
             (_('Normal'), Citation.CONF_NORMAL),
             (_('High'), Citation.CONF_HIGH),
             (_('Very High'), Citation.CONF_VERY_HIGH)], self.dbase.readonly)
        widget = self.glade.get_object('imp_source_priv')
        get_import = eval('self.imp_values.source_priv')
        self.import_methods['source_priv'] = PrivacyButton(\
            widget, get_import, self.dbase.readonly)
        widget = self.glade.get_object('imp_citation_priv')
        get_import = eval('self.imp_values.citation_priv')
        self.import_methods['citation_priv'] = PrivacyButton(\
            widget, get_import, self.dbase.readonly)

        # Text (w. Defaults) for Tags
        for obj in ('text', 'fname'):
            widget = self.glade.get_object('tag_default_%s' % obj)
            set_import = eval('self.default_values.%s.set_entry' % obj)
            get_import = eval('self.default_values.%s.get_entry' % obj)
            self.default_methods[obj] = MonitoredEntry(\
                widget, set_import, get_import, self.dbase.readonly)
        date = Today()
        datebase = DateBase()
        datebase.set_date_object(date)
        self.default_methods['date'] = MonitoredDate(\
            self.glade.get_object('tag_default_date'),
            self.glade.get_object('tag_default_date_btn'),
            datebase.get_date_object(),
            self.uistate, [], self.dbase.readonly)

        for obj in libprogen.TAGOBJECTS:
            # populate object fields with values
            widget = self.glade.get_object('tag_%s_obj' % obj)
            self.tagobj_methods[obj] = MonitoredCheckbox(
                widget, widget, self.tagobj_values[obj].tag_obj.set_value,
                self.tagobj_values[obj].tag_obj.get_value)
            widget = self.glade.get_object('tag_%s_text' % obj)
            self.tagtext_methods[obj] = MonitoredEntry(
                widget, self.tagobj_values[obj].tag_text.set_entry,
                self.tagobj_values[obj].tag_text.get_entry)
            widget = self.glade.get_object('tag_%s_fname' % obj)
            self.tagfname_methods[obj] = MonitoredCheckbox(
                widget, widget, self.tagobj_values[obj].tag_fname.set_value,
                self.tagobj_values[obj].tag_fname.get_value)
            widget = self.glade.get_object('tag_%s_date' % obj)
            self.tagdate_methods[obj] = MonitoredCheckbox(
                widget, widget, self.tagobj_values[obj].tag_date.set_value,
                self.tagobj_values[obj].tag_date.get_value)

        # button's for primary objects
        for obj in libprogen.PRIMOBJECTS:
            # populate pirm. Object buttons with values
            widget = self.glade.get_object('prim_%s_btn' % obj)
            set_import = eval("self.primobj_values['%s'].set_value" % obj)
            get_import = eval("self.primobj_values['%s'].get_value" % obj)
            self.primobj_methods[obj] = MonitoredCheckbox(\
                widget, widget, set_import, get_import, self.dbase.readonly)

        # button's for miscallaneous option's
        for obj in libprogen.OPTOBJECTS:
            # populate option buttons with values
            widget = self.glade.get_object('opt_%s_btn' % obj)
            set_import = eval("self.option_values['%s'].set_value" % obj)
            get_import = eval("self.option_values['%s'].get_value" % obj)
            self.option_methods[obj] = MonitoredCheckbox(\
                widget, widget, set_import, get_import, self.dbase.readonly)

        # connect signals
        self.glade.connect_signals({
            "on_source_button_toggled":
            self.__on_source_button_toggled,
            "on_citation_button_toggled":
            self.__on_citation_button_toggled,
            "on_import_entry_keyrelease":
            self.__on_import_entry_keyrelease,
            "on_tagtext_entry_keyrelease":
            self.__on_tagtext_entry_keyrelease,
            "on_object_button_clicked":
            self.__on_object_button_clicked,
            "on_object_button_toggled":
            self.__on_object_button_toggled,
            "on_text_button_clicked":
            self.__on_text_button_clicked,
            "on_fname_button_clicked":
            self.__on_fname_button_clicked,
            "on_fname_button_toggled":
            self.__on_fname_button_toggled,
            "on_date_button_clicked":
            self.__on_date_button_clicked,
            "on_date_button_toggled":
            self.__on_date_button_toggled,
            "on_primobj_button_toggled":
            self.__on_primobj_button_toggled,
            "on_surname_button_toggled":
            self.__on_surname_button_toggled,
            "on_x_button_clicked":
            self.__on_x_button_clicked,
            "on_help_button_clicked":
            self.__on_help_button_clicked,
            "on_cancel_button_clicked":
            self.__on_cancel_button_clicked,
            "on_ok_button_clicked":
            self.__on_ok_button_clicked
        })

        # state of two objects trigged form configuration
        widget = self.glade.get_object('imp_source_btn')
        self.__on_source_button_toggled(widget)
        widget = self.glade.get_object('imp_citation_btn')
        self.__on_citation_button_toggled(widget)
        widget = self.glade.get_object('import_ok')
        widget.grab_focus()

        # creates a modal window and display immediatly!
        self.show()
        self.glade.toplevel.run()

    def _collect(self):
        """ collect all options """

        self.option['imp_source'] = self.imp_values.source_btn.get_value()
        self.option['imp_source_priv'] = self.imp_values.source_priv.get_privacy() \
            if self.option['imp_source'] else False
        if self.option['imp_source']:
            self.option[
                'imp_source_title'] = self.imp_values.source_title.get_entry()
            sourceattr = self.imp_values.source_attr.get_entry()
            # Expand if exists possible strftime directives
            if ('%Y' or '%m' or '%d' or '%H' or '%M' or '%S') in sourceattr:
                sourceattr = time.strftime(sourceattr)
            self.option['imp_source_attr'] = sourceattr
        else:
            self.option['imp_source_title'] = ''
            self.option['imp_source_attr'] = ''

        self.option['imp_citation'] = self.imp_values.citation_btn.get_value()
        self.option['imp_citation_conf'] = self.imp_values.citation_conf.get_value() \
            if self.option['imp_citation'] else Citation.CONF_HIGH
        self.option['imp_citation_priv'] = self.imp_values.citation_priv.get_privacy() \
            if self.option['imp_citation'] else False
        if self.option['imp_citation']:
            citationpage = self.imp_values.citation_page.get_entry()
            if ('%Y' or '%m' or '%d' or '%H' or '%M' or '%S') in citationpage:
                citationpage = time.strftime(citationpage)
            self.option['imp_citation_page'] = citationpage
            citationattr = self.imp_values.citation_attr.get_entry()
            if ('%Y' or '%m' or '%d' or '%H' or '%M' or '%S') in citationattr:
                citationattr = time.strftime(citationattr)
            self.option['imp_citation_attr'] = citationattr
        else:
            self.option['imp_citation_page'] = ''
            self.option['imp_citation_attr'] = ''

        for obj in libprogen.TAGOBJECTS:
            if self.tagobj_values[obj].tag_obj.get_value():
                tagtext = self.tagobj_values[obj].tag_text.get_entry()
                if ('%Y' or '%m' or '%d' or '%H' or '%M' or '%S') in tagtext:
                    tagtext = time.strftime(tagtext)
                self.option['tag_{}'.format(obj)] = tagtext
            else:
                self.option['tag_{}'.format(obj)] = ''

        for obj in libprogen.PRIMOBJECTS:
            self.option['prim_{}'.format(obj)] = \
                self.primobj_values[obj].get_value()
        for obj in libprogen.OPTOBJECTS:
            self.option['opt_{}'.format(obj)] = \
                self.option_values[obj].get_value()

        self.fail = False  # Pro-Gen import proceed
Beispiel #38
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.title = _('Find database loop')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.dbstate = dbstate
        self.uistate = uistate
        self.db = dbstate.db

        topDialog = Glade()

        topDialog.connect_signals({
            "destroy_passed_object" : self.close,
            "on_help_clicked"       : self.on_help_clicked,
            "on_delete_event"       : self.close,
        })

        window = topDialog.toplevel
        title = topDialog.get_object("title")
        self.set_window(window, title, self.title)

        # start the progress indicator
        self.progress = ProgressMeter(self.title,_('Starting'),
                                      parent=self.window)
        self.progress.set_pass(_('Looking for possible loop for each person'),
                               self.db.get_number_of_people())

        self.model = Gtk.ListStore(
            GObject.TYPE_STRING,    # 0==father id
            GObject.TYPE_STRING,    # 1==father
            GObject.TYPE_STRING,    # 2==son id
            GObject.TYPE_STRING,    # 3==son
            GObject.TYPE_STRING)    # 4==family gid

        self.treeView = topDialog.get_object("treeview")
        self.treeView.set_model(self.model)
        col1 = Gtk.TreeViewColumn(_('Gramps ID'),     Gtk.CellRendererText(), text=0)
        col2 = Gtk.TreeViewColumn(_('Ancestor'),   Gtk.CellRendererText(), text=1)
        col3 = Gtk.TreeViewColumn(_('Gramps ID'),     Gtk.CellRendererText(), text=2)
        col4 = Gtk.TreeViewColumn(_('Descendant'),     Gtk.CellRendererText(), text=3)
        col5 = Gtk.TreeViewColumn(_('Family ID'), Gtk.CellRendererText(), text=4)
        col1.set_resizable(True)
        col2.set_resizable(True)
        col3.set_resizable(True)
        col4.set_resizable(True)
        col5.set_resizable(True)
        col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        col1.set_sort_column_id(0)
        col2.set_sort_column_id(1)
        col3.set_sort_column_id(2)
        col4.set_sort_column_id(3)
        col5.set_sort_column_id(4)
        self.treeView.append_column(col1)
        self.treeView.append_column(col2)
        self.treeView.append_column(col3)
        self.treeView.append_column(col4)
        self.treeView.append_column(col5)
        self.treeSelection = self.treeView.get_selection()
        self.treeView.connect('row-activated', self.rowactivated)

        people = self.db.get_person_handles()
        count = 0
        for person_handle in people:
            person = self.db.get_person_from_handle(person_handle)
            count += 1
            self.current = person
            self.parent = None
            self.descendants(person_handle, set())
            self.progress.set_header("%d/%d" % (count, len(people)))
            self.progress.step()

        # close the progress bar
        self.progress.close()

        self.show()
Beispiel #39
0
class PatchNames(tool.BatchTool, ManagedWindow):
    titleid = 1
    nickid  = 2
    pref1id = 3
    compid  = 4

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Name and title extraction tool')
        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.set_window(Gtk.Window(), Gtk.Label(), '')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        winprefix = Gtk.Dialog(_("Default prefix and connector settings"),
                                self.uistate.window,
                                Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                (_('_OK'), Gtk.ResponseType.ACCEPT))

        winprefix.vbox.set_spacing(5)
        hboxpref = Gtk.Box()
        label = Gtk.Label(label=_('Prefixes to search for:'))
        hboxpref.pack_start(label, False, False, 5)
        self.prefixbox = Gtk.Entry()
        self.prefixbox.set_text(', '.join(PREFIX_LIST))
        hboxpref.pack_start(self.prefixbox, True, True, 0)
        winprefix.vbox.pack_start(hboxpref, True, True, 0)
        hboxcon = Gtk.Box()
        label = Gtk.Label(label=_('Connectors splitting surnames:'))
        hboxcon.pack_start(label, False, False, 5)
        self.conbox = Gtk.Entry()
        self.conbox.set_text(', '.join(CONNECTOR_LIST))
        hboxcon.pack_start(self.conbox, True, True, 0)
        winprefix.vbox.pack_start(hboxcon, True, True, 0)
        hboxconns = Gtk.Box()
        label = Gtk.Label(label=_('Connectors not splitting surnames:'))
        hboxconns.pack_start(label, False, False, 5)
        self.connsbox = Gtk.Entry()
        self.connsbox.set_text(', '.join(CONNECTOR_LIST_NONSPLIT))
        hboxconns.pack_start(self.connsbox, True, True, 0)
        winprefix.vbox.pack_start(hboxconns, True, True, 0)
        winprefix.show_all()
        winprefix.resize(700, 100)

        response = winprefix.run()
        self.prefix_list = self.prefixbox.get_text().split(',')
        self.prefix_list = list(map(strip, self.prefix_list))
        self.prefixbox = None
        self.connector_list = self.conbox.get_text().split(',')
        self.connector_list = list(map(strip, self.connector_list))
        self.conbox = None
        self.connector_list_nonsplit = self.connsbox.get_text().split(',')
        self.connector_list_nonsplit = list(map(strip, self.connector_list_nonsplit))
        self.connsbox = None

        # Find a prefix in the first_name
        self._fn_prefix_re = re.compile("(\S+)\s+(%s)\s*$" % '|'.join(self.prefix_list),
                           re.IGNORECASE)

        # Find a prefix in the surname
        self._sn_prefix_re = re.compile("^\s*(%s)\s+(.+)" % '|'.join(self.prefix_list),
                           re.IGNORECASE)
        # Find a connector in the surname
        self._sn_con_re = re.compile("^\s*(.+)\s+(%s)\s+(.+)" % '|'.join(self.connector_list),
                           re.IGNORECASE)
        winprefix.destroy()

        self.cb = callback
        self.handle_to_action = {}

        self.progress = ProgressMeter(
            _('Extracting Information from Names'), '',
            parent=self.uistate.window)
        self.progress.set_pass(_('Analyzing names'),
                               self.db.get_number_of_people())

        for person in self.db.iter_people():
            key = person.handle
            name = person.get_primary_name()
            first = name.get_first_name()
            sname = name.get_surname()

            old_prefix = []
            old_surn = []
            old_con = []
            old_prim = []
            old_orig = []
            for surn in name.get_surname_list():
                old_prefix.append(surn.get_prefix())
                old_surn.append(surn.get_surname())
                old_con.append(surn.get_connector())
                old_prim.append(surn.get_primary())
                old_orig.append(surn.get_origintype())

            if name.get_title():
                old_title = [name.get_title()]
            else:
                old_title = []
            new_title = []

            match = _title_re.match(first)
            while match:
                groups = match.groups()
                first = groups[1]
                new_title.append(groups[0])
                match = _title_re.match(first)
            matchnick = _nick_re.match(first)

            if new_title:
                titleval = (" ".join(old_title+new_title), first)
                if key in self.handle_to_action:
                    self.handle_to_action[key][self.titleid] = titleval
                else:
                    self.handle_to_action[key] = {self.titleid: titleval}
            elif matchnick:
                # we check for nick, which changes given name like title
                groups = matchnick.groups()
                nickval = (groups[0], groups[1])
                if key in self.handle_to_action:
                    self.handle_to_action[key][self.nickid] = nickval
                else:
                    self.handle_to_action[key] = {self.nickid: nickval}
            else:
                # Try to find the name prefix in the given name, also this
                # changes given name
                match = self._fn_prefix_re.match(first)
                if match:
                    groups = match.groups()
                    if old_prefix[0]:
                        # Put the found prefix before the old prefix
                        new_prefix = " ".join([groups[1], old_prefix[0]])
                    else:
                        new_prefix = groups[1]
                    pref1val = (groups[0], new_prefix, groups[1])
                    if key in self.handle_to_action:
                        self.handle_to_action[key][self.pref1id] = pref1val
                    else:
                        self.handle_to_action[key] = {self.pref1id: pref1val}

            #check for Gedcom import of compound surnames
            if len(old_surn) == 1 and old_con[0] == '':
                prefixes = old_prefix[0].split(',')
                surnames = old_surn[0].split(',')
                if len(prefixes) > 1 and len(prefixes) == len(surnames):
                    #assume a list of prefix and a list of surnames
                    prefixes = list(map(strip, prefixes))
                    surnames = list(map(strip, surnames))
                    primaries = [False] * len(prefixes)
                    primaries[0] = True
                    origs = []
                    for ind in range(len(prefixes)):
                        origs.append(NameOriginType())
                    origs[0] = old_orig[0]
                    compoundval = (surnames, prefixes, ['']*len(prefixes),
                                    primaries, origs)
                    if key in self.handle_to_action:
                        self.handle_to_action[key][self.compid] = compoundval
                    else:
                        self.handle_to_action[key] = {self.compid: compoundval}
                    #we cannot check compound surnames, so continue the loop
                    continue

            # Next, try to split surname in compounds: prefix surname connector
            found = False
            new_prefix_list = []
            new_surname_list = []
            new_connector_list = []
            new_prim_list = []
            new_orig_list = []
            ind = 0
            cont = True
            for pref, surn, con, prim, orig in zip(old_prefix, old_surn,
                                        old_con, old_prim, old_orig):
                surnval = surn.split()
                if surnval == []:
                    new_prefix_list.append(pref)
                    new_surname_list.append('')
                    new_connector_list.append(con)
                    new_prim_list.append(prim)
                    new_orig_list.append(orig)
                    cont = False
                    continue
                val = surnval.pop(0)
                while cont:
                    new_prefix_list.append(pref)
                    new_surname_list.append('')
                    new_connector_list.append(con)
                    new_prim_list.append(prim)
                    new_orig_list.append(orig)

                    while cont and (val.lower() in self.prefix_list):
                        found = True
                        if new_prefix_list[-1]:
                            new_prefix_list[-1] += ' ' + val
                        else:
                            new_prefix_list[-1] = val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #after prefix we have a surname
                    if cont:
                        new_surname_list[-1] = val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #if value after surname indicates continue, then continue
                    while cont and (val.lower() in self.connector_list_nonsplit):
                        #add this val to the current surname
                        new_surname_list[-1] += ' ' + val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    # if previous is non-splitting connector, then add new val to
                    # current surname
                    if cont and (new_surname_list[-1].split()[-1].lower()
                                    in self.connector_list_nonsplit):
                        new_surname_list[-1] += ' ' + val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #if next is a connector, add it to the surname
                    if cont and val.lower() in self.connector_list:
                        found = True
                        if new_connector_list[-1]:
                            new_connector_list[-1] = ' ' + val
                        else:
                            new_connector_list[-1] = val
                        try:
                            val = surnval.pop(0)
                        except IndexError:
                            val = ''
                            cont = False
                    #initialize for a next surname in case there are still
                    #val
                    if cont:
                        found = True  # we split surname
                        pref=''
                        con = ''
                        prim = False
                        orig = NameOriginType()
                ind += 1
            if found:
                compoundval = (new_surname_list, new_prefix_list,
                            new_connector_list, new_prim_list, new_orig_list)
                if key in self.handle_to_action:
                    self.handle_to_action[key][self.compid] = compoundval
                else:
                    self.handle_to_action[key] = {self.compid: compoundval}

            self.progress.step()

        if self.handle_to_action:
            self.display()
        else:
            self.progress.close()
            self.close()
            OkDialog(_('No modifications made'),
                     _("No titles, nicknames or prefixes were found"),
                     parent=self.uistate.window)

    def build_menu_names(self, obj):
        return (self.label, None)

    def toggled(self, cell, path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]
        self.model.row_changed(path, row.iter)

    def display(self):

        self.top = Glade()
        window = self.top.toplevel
        self.top.connect_signals({
            "destroy_passed_object" : self.close,
            "on_ok_clicked" : self.on_ok_clicked,
            "on_help_clicked" : self.on_help_clicked,
            "on_delete_event"   : self.close,
            })

        self.list = self.top.get_object("list")
        self.set_window(window, self.top.get_object('title'), self.label)

        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING)

        r = Gtk.CellRendererToggle()
        r.connect('toggled', self.toggled)
        c = Gtk.TreeViewColumn(_('Select'), r, active=0)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('ID'), Gtk.CellRendererText(), text=1)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Type'), Gtk.CellRendererText(), text=2)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Value'), Gtk.CellRendererText(), text=3)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Current Name'), Gtk.CellRendererText(), text=4)
        self.list.append_column(c)

        self.list.set_model(self.model)

        self.nick_hash = {}
        self.title_hash = {}
        self.prefix1_hash = {}
        self.compound_hash = {}

        self.progress.set_pass(_('Building display'),
                               len(list(self.handle_to_action.keys())))

        for key, data in self.handle_to_action.items():
            p = self.db.get_person_from_handle(key)
            gid = p.get_gramps_id()
            if self.nickid in data:
                given, nick = data[self.nickid]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Nickname'))
                self.model.set_value(handle, 3, nick)
                self.model.set_value(handle, 4, p.get_primary_name().get_name())
                self.nick_hash[key] = handle

            if self.titleid in data:
                title, given = data[self.titleid]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Person|Title'))
                self.model.set_value(handle, 3, title)
                self.model.set_value(handle, 4, p.get_primary_name().get_name())
                self.title_hash[key] = handle

            if self.pref1id in data:
                given, prefixtotal, new_prefix = data[self.pref1id]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Prefix in given name'))
                self.model.set_value(handle, 3, prefixtotal)
                self.model.set_value(handle, 4, p.get_primary_name().get_name())
                self.prefix1_hash[key] = handle

            if self.compid in data:
                surn_list, pref_list, con_list, prims, origs = data[self.compid]
                handle = self.model.append()
                self.model.set_value(handle, 0, 1)
                self.model.set_value(handle, 1, gid)
                self.model.set_value(handle, 2, _('Compound surname'))
                newval = ''
                for sur, pre, con in zip(surn_list, pref_list, con_list):
                    if newval:
                        newval += '-['
                    else:
                        newval =  '['
                    newval += pre + ',' + sur
                    if con:
                        newval += ',' + con + ']'
                    else:
                        newval += ']'
                self.model.set_value(handle, 3, newval)
                self.model.set_value(handle, 4, p.get_primary_name().get_name())
                self.compound_hash[key] = handle

            self.progress.step()

        self.progress.close()
        self.show()

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)

    def on_ok_clicked(self, obj):
        with DbTxn(_("Extract information from names"), self.db, batch=True
                   ) as trans:
            self.db.disable_signals()

            for key, data in self.handle_to_action.items():
                p = self.db.get_person_from_handle(key)
                if self.nickid in data:
                    modelhandle = self.nick_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        given, nick = data[self.nickid]
                        name = p.get_primary_name()
                        name.set_first_name(given.strip())
                        name.set_nick_name(nick.strip())

                if self.titleid in data:
                    modelhandle = self.title_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        title, given = data[self.titleid]
                        name = p.get_primary_name()
                        name.set_first_name(given.strip())
                        name.set_title(title.strip())

                if self.pref1id in data:
                    modelhandle = self.prefix1_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        given, prefixtotal, prefix = data[self.pref1id]
                        name = p.get_primary_name()
                        name.set_first_name(given.strip())
                        oldpref = name.get_surname_list()[0].get_prefix().strip()
                        if oldpref == '' or oldpref == prefix.strip():
                            name.get_surname_list()[0].set_prefix(prefix)
                        else:
                            name.get_surname_list()[0].set_prefix('%s %s' % (prefix, oldpref))

                if self.compid in data:
                    modelhandle = self.compound_hash[key]
                    val = self.model.get_value(modelhandle, 0)
                    if val:
                        surns, prefs, cons, prims, origs = data[self.compid]
                        name = p.get_primary_name()
                        new_surn_list = []
                        for surn, pref, con, prim, orig in zip(surns, prefs, cons,
                                                                prims, origs):
                            new_surn_list.append(Surname())
                            new_surn_list[-1].set_surname(surn.strip())
                            new_surn_list[-1].set_prefix(pref.strip())
                            new_surn_list[-1].set_connector(con.strip())
                            new_surn_list[-1].set_primary(prim)
                            new_surn_list[-1].set_origintype(orig)
                        name.set_surname_list(new_surn_list)

                self.db.commit_person(p, trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        self.close()
        self.cb()
Beispiel #40
0
class ChangeNames(tool.BatchTool, ManagedWindow):

    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Capitalization changes')
        self.cb = callback

        ManagedWindow.__init__(self,uistate,[],self.__class__)
        self.set_window(Gtk.Window(),Gtk.Label(),'')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        self.progress = ProgressMeter(_('Checking Family Names'),'')
        self.progress.set_pass(_('Searching family names'),
                               len(self.db.get_surname_list()))
        self.name_list = []

        for name in self.db.get_surname_list():
            name.strip()
            namesplitSP= name.split()
            lSP = len(namesplitSP)
            namesplitHY= name.split('-')
            lHY = len(namesplitHY)
            if lSP == lHY == 1:
                if name != name.capitalize():
                    # Single surname without hyphen(s)
                    self.name_list.append(name)
            #if lSP == 1 and lHY > 1:
                #print "LSP==1", name, name.capitalize()
                #if name != name.capitalize():
                    # Single surname with hyphen(s)
                    #self.name_list.append(name)
            if lSP>1 and lHY == 1:
                # more than one string in surname but no hyphen
                # check if first string is in prefix_list, if so test for cap in rest
                s1 = 0
                if namesplitSP[0].lower() in prefix_list:
                    s1 = 1
                for x in range(len(namesplitSP)-s1):
                    # check if any subsurname is not cap
                    notcap = False
                    if namesplitSP[s1+x] != namesplitSP[s1+x].capitalize():
                        notcap = True
                        break
                if notcap:
                    # Multiple surnames possibly after prefix
                    self.name_list.append(name)
            if lHY > 1:
                # more than one string in surname but hyphen(s) exists
                # check if first string is in prefix_list, if so test for cap
                if namesplitSP[0].lower() in prefix_list:
                    namesplitHY[0] = namesplitHY[0].replace(namesplitSP[0],'').strip()
                for x in range(len(namesplitHY)):
                    # check if any subsurname is not cap
                    notcap = False
                    if namesplitHY[x] != namesplitHY[x].capitalize():
                        notcap = True
                        break
                if notcap:
                    # Multiple surnames possibly after frefix
                    self.name_list.append(name)

            if uistate:
                self.progress.step()

        if self.name_list:
            self.display()
        else:
            self.progress.close()
            self.close()
            OkDialog(_('No modifications made'),
                     _("No capitalization changes were detected."),
                     parent=uistate.window)

    def name_cap(self, name):
        name.strip()
        namesplitSP = name.split()
        lSP = len(namesplitSP)
        lHY = len(name.split('-'))
        namesep = ' '
        if lHY > 1:
            namesep = '-'
            namesplitSP = name.replace(namesep,' ').split()
            lSP= len(namesplitSP)
        if lSP == lHY == 1:
            #if name != name.capitalize():
            # Single surname without space(s) or hyphen(s), normal case
            return name.capitalize()
        else:
            # more than one string in surname but no hyphen
            # check if first string is in prefix_list, if so CAP the rest
            # Names like (von) Kohl(-)Brandt
            result = ""
            s1 = 0
            if namesplitSP[0].lower() in prefix_list:
                s1 = 1
                result = namesplitSP[0].lower()+ ' '
            for x in range(lSP-s1):
                # CAP all subsurnames
                result = result + namesplitSP[s1+x].capitalize() + namesep
            return result[:-1]

    def display(self):

        self.top = Glade()
        window = self.top.toplevel
        self.top.connect_signals({
            "destroy_passed_object" : self.close,
            "on_ok_clicked" : self.on_ok_clicked,
            "on_help_clicked" : self.on_help_clicked,
            "on_delete_event"   : self.close,
            })

        self.list = self.top.get_object("list")
        self.set_window(window,self.top.get_object('title'),self.label)

        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING)

        r = Gtk.CellRendererToggle()
        r.connect('toggled',self.toggled)
        c = Gtk.TreeViewColumn(_('Select'),r,active=0)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Original Name'),
                               Gtk.CellRendererText(),text=1)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Capitalization Change'),
                               Gtk.CellRendererText(),text=2)
        self.list.append_column(c)

        self.list.set_model(self.model)

        self.iter_list = []
        self.progress.set_pass(_('Building display'),len(self.name_list))
        for name in self.name_list:
            handle = self.model.append()
            self.model.set_value(handle,0,True)
            self.model.set_value(handle,1, name)
            namecap = self.name_cap(name)
            self.model.set_value(handle,2, namecap)
            self.iter_list.append(handle)
            self.progress.step()
        self.progress.close()

        self.show()

    def toggled(self,cell,path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]

    def build_menu_names(self, obj):
        return (self.label,None)

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(WIKI_HELP_PAGE , WIKI_HELP_SEC)

    def on_ok_clicked(self, obj):
        with DbTxn(_("Capitalization changes"), self.db, batch=True
                   ) as self.trans:
            self.db.disable_signals()
            changelist = set(self.model.get_value(node,1)
                            for node in self.iter_list
                                if self.model.get_value(node,0))

            #with self.db.get_person_cursor(update=True, commit=True) as cursor:
            #  for handle, data in cursor:
            for handle in self.db.get_person_handles(False):
                person = self.db.get_person_from_handle(handle)
                #person = Person(data)
                change = False
                for name in [person.get_primary_name()] + person.get_alternate_names():
                    sname = find_surname_name(handle, name.serialize())
                    if sname in changelist:
                        change = True
                        for surn in name.get_surname_list():
                            sname = self.name_cap(surn.get_surname())
                            surn.set_surname(sname)
                if change:
                    #cursor.update(handle, person.serialize())
                    self.db.commit_person(person, transaction=self.trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        # FIXME: this probably needs to be removed, and bookmarks
        # should always be rebuilt on a commit_person via signals
        # self.parent.bookmarks.redraw()
        self.close()
        self.cb()
Beispiel #41
0
class ChangeNames(tool.BatchTool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        self.label = _('Capitalization changes')
        self.cb = callback

        ManagedWindow.__init__(self, uistate, [], self.__class__)
        self.set_window(Gtk.Window(), Gtk.Label(), '')

        tool.BatchTool.__init__(self, dbstate, user, options_class, name)
        if self.fail:
            return

        self.progress = ProgressMeter(  # parent-OK
            _('Checking Family Names'),
            '',
            parent=uistate.window)
        self.progress.set_pass(_('Searching family names'),
                               len(self.db.get_surname_list()))
        self.name_list = []

        for name in self.db.get_surname_list():
            name.strip()
            namesplitSP = name.split()
            lSP = len(namesplitSP)
            namesplitHY = name.split('-')
            lHY = len(namesplitHY)
            if lSP == lHY == 1:
                if name != name.capitalize():
                    # Single surname without hyphen(s)
                    self.name_list.append(name)
            #if lSP == 1 and lHY > 1:
            #print "LSP==1", name, name.capitalize()
            #if name != name.capitalize():
            # Single surname with hyphen(s)
            #self.name_list.append(name)
            if lSP > 1 and lHY == 1:
                # more than one string in surname but no hyphen
                # check if first string is in prefix_list, if so test for cap in rest
                s1 = 0
                if namesplitSP[0].lower() in prefix_list:
                    s1 = 1
                for x in range(len(namesplitSP) - s1):
                    # check if any subsurname is not cap
                    notcap = False
                    if namesplitSP[s1 + x] != namesplitSP[s1 + x].capitalize():
                        notcap = True
                        break
                if notcap:
                    # Multiple surnames possibly after prefix
                    self.name_list.append(name)
            if lHY > 1:
                # more than one string in surname but hyphen(s) exists
                # check if first string is in prefix_list, if so test for cap
                if namesplitSP[0].lower() in prefix_list:
                    namesplitHY[0] = namesplitHY[0].replace(
                        namesplitSP[0], '').strip()
                for x in range(len(namesplitHY)):
                    # check if any subsurname is not cap
                    notcap = False
                    if namesplitHY[x] != namesplitHY[x].capitalize():
                        notcap = True
                        break
                if notcap:
                    # Multiple surnames possibly after frefix
                    self.name_list.append(name)

            if uistate:
                self.progress.step()

        if self.name_list:
            self.display()
        else:
            self.progress.close()
            self.close()
            OkDialog(
                _('No modifications made'),  # parent-OK
                _("No capitalization changes were detected."),
                parent=uistate.window)

    def name_cap(self, name):
        name.strip()
        namesplitSP = name.split()
        lSP = len(namesplitSP)
        lHY = len(name.split('-'))
        namesep = ' '
        if lHY > 1:
            namesep = '-'
            namesplitSP = name.replace(namesep, ' ').split()
            lSP = len(namesplitSP)
        if lSP == lHY == 1:
            #if name != name.capitalize():
            # Single surname without space(s) or hyphen(s), normal case
            return name.capitalize()
        else:
            # more than one string in surname but no hyphen
            # check if first string is in prefix_list, if so CAP the rest
            # Names like (von) Kohl(-)Brandt
            result = ""
            s1 = 0
            if namesplitSP[0].lower() in prefix_list:
                s1 = 1
                result = namesplitSP[0].lower() + ' '
            for x in range(lSP - s1):
                # CAP all subsurnames
                result = result + namesplitSP[s1 + x].capitalize() + namesep
            return result[:-1]

    def display(self):

        self.top = Glade()
        window = self.top.toplevel
        self.top.connect_signals({
            "destroy_passed_object": self.close,
            "on_ok_clicked": self.on_ok_clicked,
            "on_help_clicked": self.on_help_clicked,
            "on_delete_event": self.close,
        })

        self.list = self.top.get_object("list")
        self.set_window(window, self.top.get_object('title'), self.label)

        self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
                                   GObject.TYPE_STRING)

        r = Gtk.CellRendererToggle()
        r.connect('toggled', self.toggled)
        c = Gtk.TreeViewColumn(_('Select'), r, active=0)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Original Name'),
                               Gtk.CellRendererText(),
                               text=1)
        self.list.append_column(c)

        c = Gtk.TreeViewColumn(_('Capitalization Change'),
                               Gtk.CellRendererText(),
                               text=2)
        self.list.append_column(c)

        self.list.set_model(self.model)

        self.iter_list = []
        self.progress.set_pass(_('Building display'), len(self.name_list))
        for name in self.name_list:
            handle = self.model.append()
            self.model.set_value(handle, 0, True)
            self.model.set_value(handle, 1, name)
            namecap = self.name_cap(name)
            self.model.set_value(handle, 2, namecap)
            self.iter_list.append(handle)
            self.progress.step()
        self.progress.close()

        self.show()

    def toggled(self, cell, path_string):
        path = tuple(map(int, path_string.split(':')))
        row = self.model[path]
        row[0] = not row[0]

    def build_menu_names(self, obj):
        return (self.label, None)

    def on_help_clicked(self, obj):
        """Display the relevant portion of GRAMPS manual"""
        display_help(WIKI_HELP_PAGE, WIKI_HELP_SEC)

    def on_ok_clicked(self, obj):
        with DbTxn(_("Capitalization changes"), self.db,
                   batch=True) as self.trans:
            self.db.disable_signals()
            changelist = set(
                self.model.get_value(node, 1) for node in self.iter_list
                if self.model.get_value(node, 0))

            #with self.db.get_person_cursor(update=True, commit=True) as cursor:
            #  for handle, data in cursor:
            for handle in self.db.get_person_handles(False):
                person = self.db.get_person_from_handle(handle)
                #person = Person(data)
                change = False
                for name in [person.get_primary_name()
                             ] + person.get_alternate_names():
                    sname = find_surname_name(handle, name.serialize())
                    if sname in changelist:
                        change = True
                        for surn in name.get_surname_list():
                            sname = self.name_cap(surn.get_surname())
                            surn.set_surname(sname)
                if change:
                    #cursor.update(handle, person.serialize())
                    self.db.commit_person(person, self.trans)

        self.db.enable_signals()
        self.db.request_rebuild()
        # FIXME: this probably needs to be removed, and bookmarks
        # should always be rebuilt on a commit_person via signals
        # self.parent.bookmarks.redraw()
        self.close()
        self.cb()