Exemplo n.º 1
0
class SaveDialog(object):
    def __init__(self, msg1, msg2, task1, task2, parent=None):
        self.xml = Glade(toplevel='savedialog')
        
        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)
        
        self.dontask = self.xml.get_object('dontask')
        self.task1 = task1
        self.task2 = task2
        
        label1 = self.xml.get_object('sd_label1')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)
        
        label2 = self.xml.get_object('sd_label2')
        label2.set_text(msg2)
        label2.set_use_markup(True)
        if parent:
            self.top.set_transient_for(parent)
        self.top.show()
        response = self.top.run()
        if response == Gtk.ResponseType.NO:
            self.task1()
        elif response == Gtk.ResponseType.YES:
            self.task2()

        config.set('interface.dont-ask', self.dontask.get_active())
        self.top.destroy()
Exemplo n.º 2
0
class InfoDialog(object):
    """
    Non modal dialog to show selectable info in a scrolled window
    """
    def __init__(self, msg1, infotext, parent=None, monospaced=False):
        self.xml = Glade(toplevel='infodialog')
              
        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        label = self.xml.get_object('toplabel')
        label.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label.set_use_markup(True)
        
        infoview = self.xml.get_object('infoview')
        infobuffer = Gtk.TextBuffer()
        infobuffer.set_text(infotext)
        if monospaced:
            startiter, enditer = infobuffer.get_bounds()
            tag = infobuffer.create_tag(family="Monospace")
            infobuffer.apply_tag(tag, startiter, enditer)
        infoview.set_buffer(infobuffer)

        if parent:
            self.top.set_transient_for(parent)
        self.top.connect('response', self.destroy)
        self.top.show()

    def destroy(self, dialog, response_id):
        #no matter how it finishes, destroy dialog
        dialog.destroy()
Exemplo n.º 3
0
class MessageHideDialog(object):
    
    def __init__(self, title, message, key, parent=None):
        self.xml = Glade(toplevel='hidedialog')
              
        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % title)

        dont_show = self.xml.get_object('dont_show')
        dont_show.set_active(config.get(key))
        title_label = self.xml.get_object('title')
        title_label.set_text(
            '<span size="larger" weight="bold">%s</span>' % title)
        title_label.set_use_markup(True)
        
        self.xml.get_object('message').set_text(message)
        
        dont_show.connect('toggled', self.update_checkbox, key)
        self.top.run()
        self.top.destroy()

    def update_checkbox(self, obj, constant):
        config.set(constant, obj.get_active())
        config.save()
Exemplo n.º 4
0
class QuestionDialog2(object):
    def __init__(self, msg1, msg2, label_msg1, label_msg2, parent=None):
        self.xml = Glade(toplevel='questiondialog')
              
        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        label1 = self.xml.get_object('qd_label1')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)
        
        label2 = self.xml.get_object('qd_label2')
        # see https://github.com/emesene/emesene/issues/723
        label2.connect('activate-link', on_activate_link)
        label2.set_text(msg2)
        label2.set_use_markup(True)

        self.xml.get_object('okbutton').set_label(label_msg1)
        self.xml.get_object('okbutton').set_use_underline(True)
        self.xml.get_object('no').set_label(label_msg2)
        self.xml.get_object('no').set_use_underline(True)
        
        if parent:
            self.top.set_transient_for(parent)
        self.top.show()

    def run(self):
        response = self.top.run()
        self.top.destroy()
        return (response == Gtk.ResponseType.ACCEPT)
Exemplo n.º 5
0
class OptionDialog(object):
    def __init__(self, msg1, msg2, btnmsg1, task1, btnmsg2, task2, parent=None):
        self.xml = Glade(toplevel='optiondialog')
              
        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        label1 = self.xml.get_object('od_label1')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)
        
        label2 = self.xml.get_object('od_label2')
        label2.set_text(msg2)
        label2.set_use_markup(True)

        self.xml.get_object('option1').set_label(btnmsg1)
        self.xml.get_object('option2').set_label(btnmsg2)
        if parent:
            self.top.set_transient_for(parent)
        self.top.show()
        self.response = self.top.run()
        if self.response == Gtk.ResponseType.NO:
            if task1:
                task1()
        else:
            if task2:
                task2()
        self.top.destroy()

    def get_response(self):
        return self.response
Exemplo n.º 6
0
class QuestionDialog(object):
    def __init__(self, msg1, msg2, label, task, parent=None):
        self.xml = Glade(toplevel='questiondialog')
                
        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        label1 = self.xml.get_object('qd_label1')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)
        
        label2 = self.xml.get_object('qd_label2')
        label2.set_text(msg2)
        label2.set_use_markup(True)

        self.xml.get_object('okbutton').set_label(label)

        if parent:
            self.top.set_transient_for(parent)
        self.top.show()
        response = self.top.run()
        self.top.destroy()
        if response == Gtk.ResponseType.ACCEPT:
            task()
Exemplo n.º 7
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)
Exemplo n.º 8
0
class MissingMediaDialog:
    def __init__(self, msg1, msg2, task1, task2, task3, parent=None):
        self.xml = Glade(toplevel='missmediadialog')

        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        self.task1 = task1
        self.task2 = task2
        self.task3 = task3

        label1 = self.xml.get_object('label4')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)

        label2 = self.xml.get_object('label3')
        label2.set_text(msg2)
        label2.set_use_markup(True)

        check_button = self.xml.get_object('use_always')

        if parent:
            self.top.set_transient_for(parent)
            parent_modal = parent.get_modal()
            if parent_modal:
                parent.set_modal(False)
        self.top.show()
        self.top.connect('delete_event', self.warn)
        response = Gtk.ResponseType.DELETE_EVENT

        # Need some magic here, because an attempt to close the dialog
        # with the X button not only emits the 'delete_event' signal
        # but also exits with the RESPONSE_DELETE_EVENT
        while response == Gtk.ResponseType.DELETE_EVENT:
            response = self.top.run()

        if response == 1:
            self.task1()
        elif response == 2:
            self.task2()
        elif response == 3:
            self.task3()
        if check_button.get_active():
            self.default_action = response
        else:
            self.default_action = 0
        self.top.destroy()
        if parent and parent_modal:
            parent.set_modal(True)

    def warn(self, obj, obj2):
        WarningDialog(
            _("Attempt to force closing the dialog"),
            _("Please do not force closing this important dialog.\n"
              "Instead select one of the available options"),
            parent=self.top)
        return True
Exemplo n.º 9
0
    def birth_editor(self, widget, data=None):
        """
        Experimental call of the birth editor (see rather 'birth.py')
        """

        glade_file = os.path.join(USER_PLUGINS, "SourceIndex", "birth.glade")

        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")

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

            self.glade.add_from_file(glade_file)

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

            b = self.glade.get_object('edit_birth')

            self.set_window(b, self.glade.get_object('title'), self.label)

            #self.wit_button = self.glade.get_object('add_wit')
            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')

        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            top = Glade(glade_file)
            b = top.toplevel
            self.set_window(b, title=None, text=glade_file)

            #self.wit_button = top.get_object('add_wit')
            self.ok_button = top.get_object('ok')
            self.quit_button = top.get_object('cancel')

        #self.wit_button.connect('clicked', GtkHandlers.on_witness_clicked)
        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)

        #add_item()
        #close_item()
        #close_track()

        #b.connect('delete-event', GladeHandlers.on_quit_clicked)

        #b.hide()
        b.show()
Exemplo n.º 10
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()
Exemplo n.º 11
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()
Exemplo n.º 12
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,
            "on_delete_event": self.close,
        })

        # fetch the popup menu
        self.menu = topDialog.get_object("popup_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()
Exemplo n.º 13
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'))

        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()
Exemplo n.º 14
0
    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()
Exemplo n.º 16
0
    def marriage_editor(self, widget, data=None):
        """
        Experimental call of the marriage editor (see rather 'marriage.py')
        """

        glade_file = os.path.join(USER_PLUGINS, "SourceIndex",
                                  "marriage.glade")

        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")

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

            self.glade.add_from_file(glade_file)

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

            m = self.glade.get_object('edit_marriage')

            self.set_window(m, self.glade.get_object('title'), self.label)

            #self.wit_button = self.glade.get_object('add_wit')
            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')

        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            top = Glade(glade_file)
            m = top.toplevel
            self.set_window(m, title=None, text=glade_file)

            #self.wit_button = top.get_object('add_wit')
            self.ok_button = top.get_object('ok')
            self.quit_button = top.get_object('cancel')

        #self.wit_button.connect('clicked', GtkHandlers.on_witness_clicked)
        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)

        #m.hide()
        m.show()
Exemplo n.º 17
0
class OptionDialog:
    def __init__(self,
                 msg1,
                 msg2,
                 btnmsg1,
                 task1,
                 btnmsg2,
                 task2,
                 parent=None):
        self.xml = Glade(toplevel='optiondialog')

        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        label1 = self.xml.get_object('od_label1')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)

        label2 = self.xml.get_object('od_label2')
        label2.set_text(msg2)
        label2.set_use_markup(True)

        self.xml.get_object('option1').set_label(btnmsg1)
        self.xml.get_object('option2').set_label(btnmsg2)
        if parent:
            self.top.set_transient_for(parent)
            parent_modal = parent.get_modal()
            if parent_modal:
                parent.set_modal(False)
        self.top.show()
        self.response = self.top.run()
        if self.response == Gtk.ResponseType.NO:
            if task1:
                task1()
        else:
            if task2:
                task2()
        self.top.destroy()
        if parent and parent_modal:
            parent.set_modal(True)

    def get_response(self):
        return self.response
Exemplo n.º 18
0
    def census_editor(self, widget, data=None):
        """
        Experimental call of the census editor (see rather 'census.py')
        """

        glade_file = os.path.join(USER_PLUGINS, "SourceIndex", "census.glade")

        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")

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

            self.glade.add_from_file(glade_file)

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

            c = self.glade.get_object('edit_census')

            self.set_window(c, self.glade.get_object('title'), self.label)

            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')

        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            top = Glade(glade_file)
            c = top.toplevel
            self.set_window(c, title=None, text=glade_file)

            self.ok_button = top.get_object('ok')
            self.quit_button = top.get_object('cancel')

        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)

        #c.hide()
        c.show()
Exemplo n.º 19
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()
Exemplo n.º 20
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()
Exemplo n.º 21
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()
Exemplo n.º 22
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()
Exemplo n.º 23
0
class QuestionDialog2:
    def __init__(self, msg1, msg2, label_msg1, label_msg2, parent=None):
        self.xml = Glade(toplevel='questiondialog')

        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % msg1)

        label1 = self.xml.get_object('qd_label1')
        label1.set_text('<span weight="bold" size="larger">%s</span>' % msg1)
        label1.set_use_markup(True)

        label2 = self.xml.get_object('qd_label2')
        # see https://github.com/emesene/emesene/issues/723
        label2.connect('activate-link', on_activate_link)
        label2.set_text(msg2)
        label2.set_use_markup(True)

        self.xml.get_object('okbutton').set_label(label_msg1)
        self.xml.get_object('okbutton').set_use_underline(True)
        self.xml.get_object('no').set_label(label_msg2)
        self.xml.get_object('no').set_use_underline(True)

        self.parent = parent
        if parent:
            self.top.set_transient_for(parent)
            self.parent_modal = parent.get_modal()
            if self.parent_modal:
                parent.set_modal(False)
        self.top.show()

    def run(self):
        response = self.top.run()
        self.top.destroy()
        if self.parent and self.parent_modal:
            self.parent.set_modal(True)
        return (response == Gtk.ResponseType.ACCEPT)
Exemplo n.º 24
0
class MessageHideDialog(object):
    def __init__(self, title, message, key, parent=None):
        self.xml = Glade(toplevel='hidedialog')

        self.top = self.xml.toplevel
        self.top.set_icon(ICON)
        self.top.set_title("%s - Gramps" % title)

        dont_show = self.xml.get_object('dont_show')
        dont_show.set_active(config.get(key))
        title_label = self.xml.get_object('title')
        title_label.set_text('<span size="larger" weight="bold">%s</span>' %
                             title)
        title_label.set_use_markup(True)

        self.xml.get_object('message').set_text(message)

        dont_show.connect('toggled', self.update_checkbox, key)
        self.top.run()
        self.top.destroy()

    def update_checkbox(self, obj, constant):
        config.set(constant, obj.get_active())
        config.save()
Exemplo n.º 25
0
 def __init__(self, database):
     self.db = database
     self.url = None
     self.connector = None
     
     top = Glade("phpgedview.glade")
     self.url_entry = top.get_object('url_entry')
     self.version_label = top.get_object('version_label')
     self.version_label.set_text("")
     self.file_combo = top.get_object('file_combo')
     self.file_combo.hide()
     self.username_entry = top.get_object('username_entry')
     self.username_entry.hide()
     self.password_entry = top.get_object('password_entry')
     self.password_entry.hide()
     self.ok_button = top.get_object('ok_button')
     self.ok_button.connect("activate", self.on_next_pressed_cb)
     self.ok_button.connect("button_release_event", self.on_next_pressed_cb)
     self.progressbar = top.get_object('progressbar')
     self.dialog = top.toplevel
     self.dialog.show()
Exemplo n.º 26
0
    def __init__(self, database):
        self.db = database
        self.url = None
        self.connector = None

        top = Glade("phpgedview.glade")
        self.url_entry = top.get_object('url_entry')
        self.version_label = top.get_object('version_label')
        self.version_label.set_text("")
        self.file_combo = top.get_object('file_combo')
        self.file_combo.hide()
        self.username_entry = top.get_object('username_entry')
        self.username_entry.hide()
        self.password_entry = top.get_object('password_entry')
        self.password_entry.hide()
        self.ok_button = top.get_object('ok_button')
        self.ok_button.connect("activate", self.on_next_pressed_cb)
        self.ok_button.connect("button_release_event", self.on_next_pressed_cb)
        self.progressbar = top.get_object('progressbar')
        self.dialog = top.toplevel
        self.dialog.show()
Exemplo n.º 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()
Exemplo n.º 28
0
class RelCalc(tool.Tool, ManagedWindow):

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

        tool.Tool.__init__(self, dbstate, options_class, name)
        ManagedWindow.__init__(self,uistate,[],self.__class__)

        #set the columns to see
        for data in BasePersonView.CONFIGSETTINGS:
            if data[0] == 'columns.rank':
                colord = data[1]
            elif data[0] == 'columns.visible':
                colvis = data[1]
            elif data[0] == 'columns.size':
                colsize = data[1]
        self.colord = []
        for col, size in zip(colord, colsize):
            if col in colvis:
                self.colord.append((1, col, size))
            else:
                self.colord.append((0, col, size))

        self.dbstate = dbstate
        self.relationship = get_relationship_calculator(glocale)
        self.relationship.connect_db_signals(dbstate)

        self.glade = Glade()
        self.person = self.db.get_person_from_handle(
                                            uistate.get_active('Person'))
        name = ''
        if self.person:
            name = name_displayer.display(self.person)
        self.title = _('Relationship calculator: %(person_name)s'
                       ) % {'person_name' : name}
        window = self.glade.toplevel
        self.titlelabel = self.glade.get_object('title')
        self.set_window(window, self.titlelabel,
                        _('Relationship to %(person_name)s'
                          ) % {'person_name' : name},
                        self.title)
        self.setup_configs('interface.relcalc', 600, 400)

        self.tree = self.glade.get_object("peopleList")
        self.text = self.glade.get_object("text1")
        self.textbuffer = Gtk.TextBuffer()
        self.text.set_buffer(self.textbuffer)

        self.model = PersonTreeModel(self.db, uistate)
        self.tree.set_model(self.model)

        self.tree.connect('key-press-event', self._key_press)
        self.selection = self.tree.get_selection()
        self.selection.set_mode(Gtk.SelectionMode.SINGLE)

        #keep reference of column so garbage collection works
        self.columns = []
        for pair in self.colord:
            if not pair[0]:
                continue
            name = column_names[pair[1]]
            column = Gtk.TreeViewColumn(name, Gtk.CellRendererText(),
                                        markup=pair[1])
            column.set_resizable(True)
            column.set_min_width(60)
            column.set_sizing(Gtk.TreeViewColumnSizing.GROW_ONLY)
            self.tree.append_column(column)
            #keep reference of column so garbage collection works
            self.columns.append(column)

        self.sel = self.tree.get_selection()
        self.changedkey = self.sel.connect('changed',self.on_apply_clicked)
        self.closebtn = self.glade.get_object("button5")
        self.closebtn.connect('clicked', self.close)

        if not self.person:
            self.window.hide()
            ErrorDialog(_('Active person has not been set'),
                        _('You must select an active person for this '
                          'tool to work properly.'),
                        parent=uistate.window)
            self.close()
            return

        self.show()

    def close(self, *obj):
        """ Close relcalc tool. Remove non-gtk connections so garbage
            collection can do its magic.
        """
        self.relationship.disconnect_db_signals(self.dbstate)
        self.sel.disconnect(self.changedkey)
        ManagedWindow.close(self, *obj)

    def build_menu_names(self, obj):
        return (_("Relationship Calculator tool"),None)

    def on_apply_clicked(self, obj):
        model, iter_ = self.tree.get_selection().get_selected()
        if not iter_:
            return

        other_person = None
        handle = model.get_handle_from_iter(iter_)
        if handle:
            other_person = self.db.get_person_from_handle(handle)
        if other_person is None:
            self.textbuffer.set_text("")
            return

        #now determine the relation, and print it out
        rel_strings, common_an = self.relationship.get_all_relationships(
                                            self.db, self.person, other_person)

        p1 = name_displayer.display(self.person)
        p2 = name_displayer.display(other_person)

        text = []
        if other_person is None:
            pass
        elif self.person.handle == other_person.handle:
            rstr = _("%(person)s and %(active_person)s are the same person.") % {
                        'person': p1,
                        'active_person': p2
                        }
            text.append((rstr, ""))
        elif len(rel_strings) == 0:
            rstr = _("%(person)s and %(active_person)s are not related.") % {
                            'person': p2,
                            'active_person': p1
                            }
            text.append((rstr, ""))

        for rel_string, common in zip(rel_strings, common_an):
            rstr = _("%(person)s is the %(relationship)s of %(active_person)s."
                        ) % {'person': p2,
                             'relationship': rel_string,
                             'active_person': p1
                            }
            length = len(common)
            if length == 1:
                person = self.db.get_person_from_handle(common[0])
                if common[0] in [other_person.handle, self.person.handle]:
                    commontext = ''
                else :
                    name = name_displayer.display(person)
                    commontext = " " + _("Their common ancestor is %s.") % name
            elif length == 2:
                p1c = self.db.get_person_from_handle(common[0])
                p2c = self.db.get_person_from_handle(common[1])
                p1str = name_displayer.display(p1c)
                p2str = name_displayer.display(p2c)
                commontext = " " + _("Their common ancestors are %(ancestor1)s and %(ancestor2)s.") % {
                                          'ancestor1': p1str,
                                          'ancestor2': p2str
                                          }
            elif length > 2:
                index = 0
                commontext = " " + _("Their common ancestors are: ")
                for person_handle in common:
                    person = self.db.get_person_from_handle(person_handle)
                    if index:
                        # TODO for Arabic, should the next comma be translated?
                        commontext += ", "
                    commontext += name_displayer.display(person)
                    index += 1
                commontext += "."
            else:
                commontext = ""
            text.append((rstr, commontext))

        textval = ""
        for val in text:
            textval += "%s %s\n" % (val[0], val[1])
        self.textbuffer.set_text(textval)

    def _key_press(self, obj, event):
        if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter):
            store, paths = self.selection.get_selected_rows()
            if paths and len(paths[0]) == 1 :
                if self.tree.row_expanded(paths[0]):
                    self.tree.collapse_row(paths[0])
                else:
                    self.tree.expand_row(paths[0], 0)
                return True
        return False
Exemplo n.º 29
0
class MarriageIndex(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.label = _('Sources Index')
        self.base = os.path.dirname(__file__)

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

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

        glade_file = os.path.join(USER_PLUGINS, "SourceIndex",
                                  "marriage.glade")

        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")

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

            self.glade.add_from_file(glade_file)

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

            window = self.glade.get_object('edit_marriage')

            #self.glade.connect_signals({
            #})

            self.set_window(window, self.glade.get_object('title'), self.label)

            #self.wit_button = self.glade.get_object('add_wit')
            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')

        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            self.top = Glade()
            window = self.top.toplevel
            self.set_window(window, None, glade_file)

            #self.wit_button = self.top.get_object('add_wit')
            self.ok_button = self.top.get_object('ok')
            self.quit_button = self.top.get_object('cancel')

        #self.wit_button.connect('clicked', GtkHandlers.on_witness_clicked)
        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)

        self.window.show()

        # tests
        filename = os.path.join(USER_PLUGINS, 'SourceIndex',
                                'test_marriage.xml')
        self.write_xml(filename, 'M0001', 'DATE')
        self.parse_xml(filename)

    def __getitem__(self, key):
        return self.glade.get_widget(key)

    def _setup_fields(self):
        r'''
        Gramps XML storage means ability to also import/manage alone records
        /!\ some attributes are translated keys
        see data_item keys and eventref types of attribute
        '''

        #/database/repositories/repository/rname/text()
        self.rinfo = MonitoredEntry(self.top.get_object("rinfo"),
                                    self.obj.set_rinfo, self.obj.get_rinfo,
                                    self.db.readonly)

        # date of transcription/search
        self.rdate = MonitoredEntry(self.top.get_object("rdate"),
                                    self.obj.set_rdate, self.obj.get_rdate,
                                    self.db.readonly)

        #/database/repositories/repository/@handle
        self.rid = MonitoredEntry(self.top.get_object("rid"), self.obj.set_rid,
                                  self.obj.get_rid, self.db.readonly)

        #/database/sources/source/stitle/text()
        self.aname = MonitoredEntry(self.top.get_object("aname"),
                                    self.obj.set_aname, self.obj.get_aname,
                                    self.db.readonly)

        #/database/sources/source/@handle
        self.aid = MonitoredEntry(self.top.get_object("aid"), self.obj.set_aid,
                                  self.obj.get_aid, self.db.readonly)

        #/database/citations/citation/@handle
        self.aref = MonitoredEntry(self.top.get_object("aref"),
                                   self.obj.set_aref, self.obj.get_aref,
                                   self.db.readonly)

        #/database/citations/citation/page
        # hardcoded /database/citations/citation/confidence
        self.avol = MonitoredEntry(self.top.get_object("avol"),
                                   self.obj.set_avol, self.obj.get_avol,
                                   self.db.readonly)

        #/database/people/person/gender
        self.gen = MonitoredEntry(self.top.get_object("gen"), self.obj.set_gen,
                                  self.obj.get_gen, self.db.readonly)

        #/database/people/person/childof/@hlink
        #/database/people/person/name/surname/surname/text()
        self.pname = MonitoredEntry(self.top.get_object("pname"),
                                    self.obj.set_pname, self.obj.get_pname,
                                    self.db.readonly)

        #/database/people/person/name/first/text()
        self.pfname = MonitoredEntry(self.top.get_object("pfname"),
                                     self.obj.set_pfname, self.obj.get_pfname,
                                     self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        self.pbdate = MonitoredEntry(self.top.get_object("pbdate"),
                                     self.obj.set_pbdate, self.obj.get_pbdate,
                                     self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        self.pblace = MonitoredEntry(self.top.get_object("pblace"),
                                     self.obj.set_pblace, self.obj.get_pblace,
                                     self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        self.pdate = MonitoredEntry(self.top.get_object("pdate"),
                                    self.obj.set_pdate, self.obj.get_pdate,
                                    self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        self.pplace = MonitoredEntry(self.top.get_object("pplace"),
                                     self.obj.set_pplace, self.obj.get_pplace,
                                     self.db.readonly)

        #/database/people/person/eventref/noteref/@hlink
        #/database/notes/note/text/text()
        self.pnote = MonitoredEntry(self.top.get_object("pnote"),
                                    self.obj.set_pnote, self.obj.get_pnote,
                                    self.db.readonly)

        #/database/objects/object/file/@src
        self.fname = MonitoredEntry(self.top.get_object("fname"),
                                    self.obj.set_fname, self.obj.get_fname,
                                    self.db.readonly)

        #/database/people/person/parentin/@hlink
        #/database/people/person/name/first/text()
        self.ffname = MonitoredEntry(self.top.get_object("ffname"),
                                     self.obj.set_ffname, self.obj.get_ffname,
                                     self.db.readonly)

        #/database/people/person/eventref/attribute/@type
        #/database/people/person/eventref/attribute/@value
        self.fage = MonitoredEntry(self.top.get_object("fage"),
                                   self.obj.set_fage, self.obj.get_fage,
                                   self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        self.forig = MonitoredEntry(self.top.get_object("forig"),
                                    self.obj.set_forig, self.obj.get_forig,
                                    self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/description/text()
        self.foccu = MonitoredEntry(self.top.get_object("foccu"),
                                    self.obj.set_foccu, self.obj.get_foccu,
                                    self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        #/database/events/event/description/text()
        self.flive = MonitoredEntry(self.top.get_object("flive"),
                                    self.obj.set_flive, self.obj.get_flive,
                                    self.db.readonly)

        #/database/people/person/parentin/@hlink
        #/database/people/person/name/first/text()
        self.mname = MonitoredEntry(self.top.get_object("mname"),
                                    self.obj.set_mname, self.obj.get_mname,
                                    self.db.readonly)

        self.mfname = MonitoredEntry(self.top.get_object("mfname"),
                                     self.obj.set_mfname, self.obj.get_mfname,
                                     self.db.readonly)

        self.mage = MonitoredEntry(self.top.get_object("mage"),
                                   self.obj.set_mage, self.obj.get_mage,
                                   self.db.readonly)

        self.morigin = MonitoredEntry(self.top.get_object("morigin"),
                                      self.obj.set_morigin,
                                      self.obj.get_morigin, self.db.readonly)

        self.moccu = MonitoredEntry(self.top.get_object("moccu"),
                                    self.obj.set_moccu, self.obj.get_moccu,
                                    self.db.readonly)

        self.mlive = MonitoredEntry(self.top.get_object("mlive"),
                                    self.obj.set_mlive, self.obj.get_mlive,
                                    self.db.readonly)

        self.msname = MonitoredEntry(self.top.get_object("msname"),
                                     self.obj.set_msname, self.obj.get_msname,
                                     self.db.readonly)

        self.mdpdate = MonitoredEntry(self.top.get_object("mdpdate"),
                                      self.obj.set_mdpdate,
                                      self.obj.get_mdpdate, self.db.readonly)

        self.mmdate = MonitoredEntry(self.top.get_object("mmdate"),
                                     self.obj.set_mmdate, self.obj.get_mmdate,
                                     self.db.readonly)

        self.mdplace = MonitoredEntry(self.top.get_object("mdplace"),
                                      self.obj.set_mdplace,
                                      self.obj.get_mdplace, self.db.readonly)

        self.mmplace = MonitoredEntry(self.top.get_object("mmplace"),
                                      self.obj.set_mmplace,
                                      self.obj.get_mmplace, self.db.readonly)

        self.mnote = MonitoredEntry(self.top.get_object("mnote"),
                                    self.obj.set_mnote, self.obj.get_mnote,
                                    self.db.readonly)

        #/database/people/person/parentin/@hlink
        #/database/families/family/mother
        #/database/families/family/father
        self.spname = MonitoredEntry(self.top.get_object("spname"),
                                     self.obj.set_spname, self.obj.get_spname,
                                     self.db.readonly)

        #/database/families/family/eventref/@hlink
        #/database/events/event/dateval/@val
        self.spmdate = MonitoredEntry(self.top.get_object("bannsdate"),
                                      self.obj.set_spmdate,
                                      self.obj.get_spmdate, self.db.readonly)

        #/database/families/family/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        self.spmplace = MonitoredEntry(self.top.get_object("bannsplace"),
                                       self.obj.set_spmplace,
                                       self.obj.get_spmplace, self.db.readonly)

    # PyXMLFAQ -- Python XML Frequently Asked Questions
    # Author: 	Dave Kuhlman
    # [email protected]
    # http://www.rexx.com/~dkuhlman

    def walk_tree(self, node, level):
        fill = self.show_level(level)
        print('%sElement name: %s' % (
            fill,
            node.tag,
        ))
        for (name, value) in node.attrib.items():
            print('%s    Attr -- Name: %s  Value: %s' % (
                fill,
                name,
                value,
            ))
        if node.attrib.get('ID') is not None:
            print('%s    ID: %s' % (
                fill,
                node.attrib.get('ID').value,
            ))
        children = node.getchildren()
        for child in children:
            self.walk_tree(child, level + 1)

    def show_level(self, level):
        s1 = '\t' * level
        return s1

    def parse_xml(self, filename):

        tree = ElementTree.parse(filename)
        root = tree.getroot()
        self.walk_tree(root, 0)

    def write_xml(self, filename, id, date):
        """
        Write the content of data filled into the form
        (currently only a test; no levels)
        """
        '''
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.5.0//EN"
        "http://gramps-project.org/xml/1.5.0/grampsxml.dtd">
        <database xmlns="http://gramps-project.org/xml/1.5.0/">
        <header>
          <created date="2012-07-04" version="3.5.0-0.SVNexported"/>
          <researcher>
          </researcher>
        </header>
        ...
        '''

        node = ElementTree.Element('marriage')
        node.set('id', id)
        node.set('collection', filename)
        node.set('uri', 'file://..')

        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        node1 = ElementTree.SubElement(node, 'dateval')
        node1.text = date

        outfile = open(filename, 'w')
        self.outfile = codecs.getwriter("utf8")(outfile)

        self.outfile.write(ElementTree.tostring(node, encoding="UTF-8"))
        self.outfile.close()
Exemplo n.º 30
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()
Exemplo n.º 31
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()
Exemplo n.º 32
0
class Witness(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.label = _('Sources Index')
        self.base = os.path.dirname(__file__)

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

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

        glade_file = os.path.join(USER_PLUGINS, "SourceIndex", "witness.glade")

        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")

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

            self.glade.add_from_file(glade_file)

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

            window = self.glade.get_object('witness_editor')

            self.set_window(window, self.glade.get_object('title'), self.label)

            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')

        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            self.top = Glade()
            window = self.top.toplevel
            self.set_window(window, None, glade_file)

            self.ok_button = self.top.get_object('ok')
            self.quit_button = self.top.get_object('cancel')

        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)

        self.window.show()

    def __getitem__(self, key):
        return self.glade.get_widget(key)

    def _setup_fields(self):
        r'''
        Gramps XML storage means ability to also import/manage alone records
        /!\ some attributes are translated keys
        see data_item keys and eventref types of attribute
        '''

        #/database/people/person/name/surname/surname/text()
        self.wname = MonitoredEntry(self.top.get_object("wname"),
                                    self.obj.set_wname, self.obj.get_wname,
                                    self.db.readonly)

        #/database/people/person/name/first/text()
        self.wfname = MonitoredEntry(self.top.get_object("wfname"),
                                     self.obj.set_wfname, self.obj.get_wfname,
                                     self.db.readonly)

        #/database/people/person/eventref/attribute/@type
        #/database/people/person/eventref/attribute/@value
        self.wage = MonitoredEntry(self.top.get_object("wage"),
                                   self.obj.set_wage, self.obj.get_wage,
                                   self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        self.worig = MonitoredEntry(self.top.get_object("worig"),
                                    self.obj.set_worig, self.obj.get_worig,
                                    self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/description/text()
        self.woccu = MonitoredEntry(self.top.get_object("woccu"),
                                    self.obj.set_woccu, self.obj.get_woccu,
                                    self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        #/database/events/event/description/text()
        self.wlive = MonitoredEntry(self.top.get_object("wlive"),
                                    self.obj.set_wlive, self.obj.get_wlive,
                                    self.db.readonly)

        #/database/people/person/personref/@hlink
        #/database/people/person/@handle
        #/database/people/person/personref/@rel
        self.wrelation = MonitoredEntry(self.top.get_object("wrelation"),
                                        self.obj.set_wrelation,
                                        self.obj.get_wrelation,
                                        self.db.readonly)
Exemplo n.º 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:
            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)
Exemplo n.º 34
0
class RelCalc(tool.Tool, ManagedWindow):

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

        tool.Tool.__init__(self, dbstate, options_class, name)
        ManagedWindow.__init__(self,uistate,[],self.__class__)

        #set the columns to see
        for data in BasePersonView.CONFIGSETTINGS:
            if data[0] == 'columns.rank':
                colord = data[1]
            elif data[0] == 'columns.visible':
                colvis = data[1]
            elif data[0] == 'columns.size':
                colsize = data[1]
        self.colord = []
        for col, size in zip(colord, colsize):
            if col in colvis:
                self.colord.append((1, col, size))
            else:
                self.colord.append((0, col, size))

        self.dbstate = dbstate
        self.relationship = get_relationship_calculator(glocale)
        self.relationship.connect_db_signals(dbstate)

        self.glade = Glade()
        self.person = self.db.get_person_from_handle(
                                            uistate.get_active('Person'))
        name = ''
        if self.person:
            name = name_displayer.display(self.person)
        self.title = _('Relationship calculator: %(person_name)s'
                       ) % {'person_name' : name}
        window = self.glade.toplevel
        self.titlelabel = self.glade.get_object('title')
        self.set_window(window, self.titlelabel,
                        _('Relationship to %(person_name)s'
                          ) % {'person_name' : name},
                        self.title)
        self.setup_configs('interface.relcalc', 600, 400)

        self.tree = self.glade.get_object("peopleList")
        self.text = self.glade.get_object("text1")
        self.textbuffer = Gtk.TextBuffer()
        self.text.set_buffer(self.textbuffer)

        self.model = PersonTreeModel(self.db)
        self.tree.set_model(self.model)

        self.tree.connect('key-press-event', self._key_press)
        self.selection = self.tree.get_selection()
        self.selection.set_mode(Gtk.SelectionMode.SINGLE)

        #keep reference of column so garbage collection works
        self.columns = []
        for pair in self.colord:
            if not pair[0]:
                continue
            name = column_names[pair[1]]
            column = Gtk.TreeViewColumn(name, Gtk.CellRendererText(),
                                        markup=pair[1])
            column.set_resizable(True)
            column.set_min_width(60)
            column.set_sizing(Gtk.TreeViewColumnSizing.GROW_ONLY)
            self.tree.append_column(column)
            #keep reference of column so garbage collection works
            self.columns.append(column)

        self.sel = self.tree.get_selection()
        self.changedkey = self.sel.connect('changed',self.on_apply_clicked)
        self.closebtn = self.glade.get_object("button5")
        self.closebtn.connect('clicked', self.close)

        if not self.person:
            self.window.hide()
            ErrorDialog(_('Active person has not been set'),
                        _('You must select an active person for this '
                          'tool to work properly.'),
                        parent=uistate.window)
            self.close()
            return

        self.show()

    def close(self, *obj):
        """ Close relcalc tool. Remove non-gtk connections so garbage
            collection can do its magic.
        """
        self.relationship.disconnect_db_signals(self.dbstate)
        self.sel.disconnect(self.changedkey)
        ManagedWindow.close(self, *obj)

    def build_menu_names(self, obj):
        return (_("Relationship Calculator tool"),None)

    def on_apply_clicked(self, obj):
        model, iter_ = self.tree.get_selection().get_selected()
        if not iter_:
            return

        other_person = None
        handle = model.get_handle_from_iter(iter_)
        if handle:
            other_person = self.db.get_person_from_handle(handle)
        if other_person is None:
            self.textbuffer.set_text("")
            return

        #now determine the relation, and print it out
        rel_strings, common_an = self.relationship.get_all_relationships(
                                            self.db, self.person, other_person)

        p1 = name_displayer.display(self.person)
        p2 = name_displayer.display(other_person)

        text = []
        if other_person is None:
            pass
        elif self.person.handle == other_person.handle:
            rstr = _("%(person)s and %(active_person)s are the same person.") % {
                        'person': p1,
                        'active_person': p2
                        }
            text.append((rstr, ""))
        elif len(rel_strings) == 0:
            rstr = _("%(person)s and %(active_person)s are not related.") % {
                            'person': p2,
                            'active_person': p1
                            }
            text.append((rstr, ""))

        for rel_string, common in zip(rel_strings, common_an):
            rstr = _("%(person)s is the %(relationship)s of %(active_person)s."
                        ) % {'person': p2,
                             'relationship': rel_string,
                             'active_person': p1
                            }
            length = len(common)
            if length == 1:
                person = self.db.get_person_from_handle(common[0])
                if common[0] in [other_person.handle, self.person.handle]:
                    commontext = ''
                else :
                    name = name_displayer.display(person)
                    commontext = " " + _("Their common ancestor is %s.") % name
            elif length == 2:
                p1c = self.db.get_person_from_handle(common[0])
                p2c = self.db.get_person_from_handle(common[1])
                p1str = name_displayer.display(p1c)
                p2str = name_displayer.display(p2c)
                commontext = " " + _("Their common ancestors are %(ancestor1)s and %(ancestor2)s.") % {
                                          'ancestor1': p1str,
                                          'ancestor2': p2str
                                          }
            elif length > 2:
                index = 0
                commontext = " " + _("Their common ancestors are: ")
                for person_handle in common:
                    person = self.db.get_person_from_handle(person_handle)
                    if index:
                        commontext += ", "
                    commontext += name_displayer.display(person)
                    index += 1
                commontext += "."
            else:
                commontext = ""
            text.append((rstr, commontext))

        textval = ""
        for val in text:
            textval += "%s %s\n" % (val[0], val[1])
        self.textbuffer.set_text(textval)

    def _key_press(self, obj, event):
        if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter):
            store, paths = self.selection.get_selected_rows()
            if paths and len(paths[0]) == 1 :
                if self.tree.row_expanded(paths[0]):
                    self.tree.collapse_row(paths[0])
                else:
                    self.tree.expand_row(paths[0], 0)
                return True
        return False
Exemplo n.º 35
0
    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)
Exemplo n.º 36
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()
Exemplo n.º 37
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()
Exemplo n.º 38
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()
Exemplo n.º 39
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()
Exemplo n.º 40
0
def importData(database, filename, user):
    """
    Try to handle ANSEL encoded files that are not really ANSEL encoded
    """

    if DbMixin not in database.__class__.__bases__:
        database.__class__.__bases__ = (DbMixin,) +  \
                                        database.__class__.__bases__

    try:
        ifile = open(filename, "rb")
    except IOError:
        return

    ansel = False
    gramps = False
    for index in range(50):
        # Treat the file as though it is UTF-8 since this is the more modern
        # option; and anyway it doesn't really matter as we are only trying to
        # detect a CHAR or SOUR line which is only 7-bit ASCII anyway,  and we
        # ignore anything that can't be translated.
        line = ifile.readline()
        line = line.decode(encoding='utf-8', errors='replace')
        line = line.split()
        if len(line) == 0:
            break
        if len(line) > 2 and line[1][0:4] == 'CHAR' and line[2] == "ANSEL":
            ansel = True
        if len(line) > 2 and line[1][0:4] == 'SOUR' and line[2] == "GRAMPS":
            gramps = True
    ifile.close()

    if not gramps and ansel:
        top = Glade()
        code = top.get_object('codeset')
        code.set_active(0)
        dialog = top.toplevel
        dialog.run()
        enc = ['ANSEL', 'ANSEL', 'ANSI', 'ASCII', 'UTF-8']
        code_set = enc[ code.get_active()]
        dialog.destroy()
    else:
        code_set = ""

    assert(isinstance(code_set, str))

    try:
        ifile = open(filename, "rb")
        stage_one = libgedcom.GedcomStageOne(ifile)
        stage_one.parse()

        if code_set:
            stage_one.set_encoding(code_set)
        ifile.seek(0)
        if database.get_feature("skip-import-additions"): # don't add source or tags
            gedparse = libgedcom.GedcomParser(
                database, ifile, filename, user, stage_one, None, None)
        else:
            gedparse = libgedcom.GedcomParser(
                database, ifile, filename, user, stage_one, 
                config.get('preferences.default-source'),
                (config.get('preferences.tag-on-import-format') if 
                 config.get('preferences.tag-on-import') else None))
    except IOError as msg:
        user.notify_error(_("%s could not be opened\n") % filename, str(msg))
        return
    except GedcomError as msg:
        user.notify_error(_("Invalid GEDCOM file"), 
                          _("%s could not be imported") % filename + "\n" + str(msg))
        return

    try:
        read_only = database.readonly
        database.readonly = False
        database.prepare_import()
        gedparse.parse_gedcom_file(False)
        database.commit_import()
        database.readonly = read_only
        ifile.close()
    except IOError as msg:
        msg = _("%s could not be opened\n") % filename
        user.notify_error(msg, str(msg))
        return
    except DbError as msg:
        user.notify_db_error(str(msg.value))
        return
    except GedcomError as msg:
        user.notify_error(_('Error reading GEDCOM file'), str(msg))
        return
    return ImportInfo({_("Results"): _("done")})
Exemplo n.º 41
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()
Exemplo n.º 42
0
class MultiSelectDialog:  # parent-OK
    def __init__(self,
                 msg1_func,
                 msg2_func,
                 items,
                 lookup,
                 cancel_func=None,
                 no_func=None,
                 yes_func=None,
                 parent=None):
        """
        """
        self.xml = Glade(toplevel='multiselectdialog')

        self.top = self.xml.toplevel
        self.top.set_icon(ICON)

        self.msg1_func = msg1_func
        self.msg2_func = msg2_func
        self.items = items
        self.lookup = lookup
        self.cancel_func = cancel_func
        self.no_func = no_func
        self.yes_func = yes_func

        label1 = self.xml.get_object('label6')
        label2 = self.xml.get_object('label5')
        check_button = self.xml.get_object('apply_to_rest')

        if parent:
            self.top.set_transient_for(parent)
        self.top.connect('delete_event', self.warn)

        default_action = 0
        for selected in items:
            item = self.lookup(selected)
            if default_action == 0:
                msg1 = self.msg1_func(item)
                msg2 = self.msg2_func(item)

                self.top.set_title("%s - Gramps" % msg1)
                label1.set_text('<span weight="bold" size="larger">%s</span>' %
                                msg1)
                label1.set_use_markup(True)
                label2.set_text(msg2)
                label2.set_use_markup(True)
                self.top.show()

                # Need some magic here, because an attempt to close the dialog
                # with the X button not only emits the 'delete_event' signal
                # but also exits with the RESPONSE_DELETE_EVENT
                response = Gtk.ResponseType.DELETE_EVENT
                while response == Gtk.ResponseType.DELETE_EVENT:
                    response = self.top.run()

                if check_button.get_active():
                    default_action = response
            else:
                response = default_action
            ### Now do it
            if response == 1:  # Cancel
                if self.cancel_func:
                    self.cancel_func(item)
                break
            elif response == 2:  # No
                if self.no_func:
                    self.no_func(item)
            elif response == 3:  # Yes
                if self.yes_func:
                    self.yes_func(item)
        self.top.destroy()

    def warn(self, obj, obj2):
        WarningDialog(  # parent-OK
            _("Attempt to force closing the dialog"),
            _("Please do not force closing this important dialog.\n"
              "Instead select one of the available options"),
            parent=self.top)
        return True
Exemplo n.º 43
0
    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)
Exemplo n.º 44
0
class CensusIndex(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

        self.label = _('Sources Index')
        self.base = os.path.dirname(__file__)

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

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

        glade_file = os.path.join(USER_PLUGINS, "SourceIndex", "census.glade")

        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")

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

            self.glade.add_from_file(glade_file)

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

            window = self.glade.get_object('edit_census')

            self.set_window(window, self.glade.get_object('title'), self.label)

            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')

        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            self.top = Glade()
            window = self.top.toplevel
            self.set_window(window, None, glade_file)

            self.ok_button = self.top.get_object('ok')
            self.quit_button = self.top.get_object('cancel')

        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)

        self.window.show()

        # tests
        filename = os.path.join(USER_PLUGINS, 'SourceIndex', 'test_census.xml')
        self.pname = self.pfname = 'éàèôÖàçèœ'
        self.write_xml(
            filename,
            'C0001',
            '',
            self.pfname,
            self.pname
            )
        self.parse_xml(filename)

    def __getitem__(self, key):
        return self.glade.get_widget(key)

    def _setup_fields(self):
        r'''
        Gramps XML storage means ability to also import/manage alone records
        /!\ some attributes are translated keys
        see data_item keys and eventref types of attribute
        '''

        #/database/repositories/repository/rname/text()
        self.rinfo   = MonitoredEntry(
            self.top.get_object("rinfo"),
            self.obj.set_rinfo,
            self.obj.get_rinfo,
            self.db.readonly)

        # date of transcription/search
        self.rdate  = MonitoredEntry(
            self.top.get_object("rdate"),
            self.obj.set_rdate,
            self.obj.get_rdate,
            self.db.readonly)

        #/database/repositories/repository/@handle
        self.rid  = MonitoredEntry(
            self.top.get_object("rid"),
            self.obj.set_rid,
            self.obj.get_rid,
            self.db.readonly)

        #/database/sources/source/stitle/text()
        self.aname  = MonitoredEntry(
            self.top.get_object("aname"),
            self.obj.set_aname,
            self.obj.get_aname,
            self.db.readonly)

        #/database/sources/source/@handle
        self.aid  = MonitoredEntry(
            self.top.get_object("aid"),
            self.obj.set_aid,
            self.obj.get_aid,
            self.db.readonly)

        #/database/citations/citation/@handle
        self.aref  = MonitoredEntry(
            self.top.get_object("aref"),
            self.obj.set_aref,
            self.obj.get_aref,
            self.db.readonly)

        #/database/citations/citation/page
        # hardcoded /database/citations/citation/confidence
        self.avol  = MonitoredEntry(
            self.top.get_object("avol"),
            self.obj.set_avol,
            self.obj.get_avol,
            self.db.readonly)

        #/database/people/person/gender
        self.gen  = MonitoredEntry(
            self.top.get_object("gen"),
            self.obj.set_gen,
            self.obj.get_gen,
            self.db.readonly)

        #/database/people/person/name/surname/surname/text()
        self.pname  = MonitoredEntry(
            self.top.get_object("pname"),
            self.obj.set_pname,
            self.obj.get_pname,
            self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        self.pbdate  = MonitoredEntry(
            self.top.get_object("pbdate"),
            self.obj.set_pbdate,
            self.obj.get_pbdate,
            self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/places/placeobj/@handle
        self.pbplace  = MonitoredEntry(
            self.top.get_object("pbplace"),
            self.obj.set_pbplace,
            self.obj.get_pbplace,
            self.db.readonly)

        #/database/people/person/name/first/text()
        self.pfname  = MonitoredEntry(
            self.top.get_object("pfname"),
            self.obj.set_pfname,
            self.obj.get_pfname,
            self.db.readonly)

        #/database/people/person/eventref/noteref/@hlink
        #/database/notes/note/text/text()
        self.pnote  = MonitoredEntry(
            self.top.get_object("pnote"),
            self.obj.set_pnote,
            self.obj.get_pnote,
            self.db.readonly)

        # Residence event
        #/database/people/person/eventref/@hlink
        #/database/events/event/description/text()
        self.address  = MonitoredEntry(
            self.top.get_object("address"),
            self.obj.set_address,
            self.obj.get_address,
            self.db.readonly)

        #/database/people/person/eventref/@hlink
        #/database/events/event/description/text()
        self.occupation  = MonitoredEntry(
            self.top.get_object("occupation"),
            self.obj.set_occupation,
            self.obj.get_occupation,
            self.db.readonly)

        #/database/people/person/eventref/attribute/@type
        #/database/people/person/eventref/attribute/@value
        self.age  = MonitoredEntry(
            self.top.get_object("age"),
            self.obj.set_age,
            self.obj.get_age,
            self.db.readonly)


    # PyXMLFAQ -- Python XML Frequently Asked Questions
    # Author: 	Dave Kuhlman
    # [email protected]
    # http://www.rexx.com/~dkuhlman

    def walk_tree(self, node, level):
        fill = self.show_level(level)
        print('%sElement name: %s' % (fill, node.tag, ))
        for (name, value) in node.attrib.items():
            print('%s    Attr -- Name: %s  Value: %s' % (fill, name, value,))
        if node.attrib.get('ID') is not None:
            print('%s    ID: %s' % (fill, node.attrib.get('ID').value, ))
        children = node.getchildren()
        for child in children:
            self.walk_tree(child, level + 1)


    def show_level(self, level):
        s1 = '\t' * level
        return s1


    def parse_xml(self, filename):

        tree = ElementTree.parse(filename)
        root = tree.getroot()
        self.walk_tree(root, 0)


    def write_xml(self, filename, id , status, first, surname):
        """
        Write the content of data filled into the form
        (currently only a test; no levels)
        """

        '''
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.5.0//EN"
        "http://gramps-project.org/xml/1.5.0/grampsxml.dtd">
        <database xmlns="http://gramps-project.org/xml/1.5.0/">
        <header>
          <created date="2012-07-04" version="3.5.0-0.SVNexported"/>
          <researcher>
          </researcher>
        </header>
        <events>
          <event handle="_abaa318b6d61a120c1b" change="1341403790" id="E0000">
            <type>Birth</type>
            <dateval val="1845" type="about"/>
            <place hlink="_abaa31688b11e7d1526"/>
            <citationref hlink="_c3332ee70e06bd6867c"/>
          </event>
          <event handle="_abaa342890d322922f7" change="1341403823" id="E0001">
            <type>Census</type>
            <dateval val="1871-04-02"/>
            <place hlink="_abaa340f64a3aa3010e"/>
            <citationref hlink="_c3332ee70e06bd6867c"/>
          </event>
        </events>
        <people>
          <person handle="_abaa31d494e56aba1c1" change="1341403686" id="I0000">
            <gender>M</gender>
            <name type="Birth Name">
              <first>Martin</first>
              <surname>John</surname>
            </name>
            <eventref hlink="_abaa318b6d61a120c1b" role="Primary"/>
            <eventref hlink="_abaa342890d322922f7" role="Primary">
              <attribute priv="1" type="Rang" value="1"/>
              <attribute type="Relation" value="Husband"/>
              <attribute type="Statut familial" value="Head"/>
              <attribute type="Age" value="25 years"/>
              <attribute type="Profession" value="Worker"/>
              <attribute type="Lieu de naissance" value="Wednesbury"/>
            </eventref>
          </person>
        </people>
        <citations>
          <citation handle="_c3332ee70e06bd6867c" change="1341403810" id="C0001">
            <dateval val="1871-04-02"/>
            <page>17/27</page>
            <confidence>2</confidence>
            <sourceref hlink="_abaa371c73f5a827b6f"/>
          </citation>
        </citations>
        <sources>
          <source handle="_abaa371c73f5a827b6f" change="1341403810" id="S0000">
            <stitle>Wednesbury Census between 1871 and 1881</stitle>
            <sauthor>UK Governement</sauthor>
            <spubinfo>www.ancestv.co.uk</spubinfo>
            <data_item key="Recensement" value="UK1871"/>
            <reporef hlink="_abaa3714e242ea05aee" callno="RG 11/2854" medium="Card"/>
          </source>
        </sources>
        <places>
          <placeobj handle="_abaa31688b11e7d1526" change="1179671725" id="P0000">
            <ptitle>Wednesbury Staffordshire</ptitle>
            <location city="Wednesbury" parish="Staffordshire" country="UK"/>
          </placeobj>
          <placeobj handle="_abaa340f64a3aa3010e" change="1179671913" id="P0001">
            <ptitle>Wednesbury Staffordshire, Hope Terrace 17</ptitle>
            <location street="Hope Terrace 17" city="Wednesbury" parish="Staffordshire" country="UK"/>
          </placeobj>
        </places>
        <repositories>
          <repository handle="_abaa3714e242ea05aee" change="1341402429" id="R0000">
            <rname>Civil Parish Wednesbury</rname>
            <type>Library</type>
          </repository>
        </repositories>
      </database>
      '''

        node = ElementTree.Element('census')
        node.set('id', id)
        node.set('collection', filename)
        node.set('uri', 'file://..')
        node1 = ElementTree.SubElement(node, 'status')
        node1.text = status

        #/database/people/person/name/first/text()
        node1 = ElementTree.SubElement(node, 'first')
        node1.text = first

        #/database/people/person/name/surname/surname/text()
        node1 = ElementTree.SubElement(node, 'surname')
        node1.text = surname

        outfile = open(filename, 'w')
        self.outfile = codecs.getwriter("utf8")(outfile)

        self.outfile.write(ElementTree.tostring(node, encoding="UTF-8"))
        self.outfile.close()
Exemplo n.º 45
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)
Exemplo n.º 46
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()
Exemplo n.º 47
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)
Exemplo n.º 48
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
Exemplo n.º 49
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
Exemplo n.º 50
0
def importData(database, filename, user):
    """
    Try to handle ANSEL encoded files that are not really ANSEL encoded
    """

    if DbMixin not in database.__class__.__bases__:
        database.__class__.__bases__ = (DbMixin,) +  \
                                        database.__class__.__bases__
    try:
        # Opening in utf-8 with universal newline to allow cr, lf, and crlf
        # If the file is really UTF16 or a varient, the next block code will not
        # find anything even if it is there, but this is ok since it won't be
        # ANSEL, or is inconsistent...
        with open(filename,
                  "r",
                  encoding='utf-8',
                  errors='replace',
                  newline=None) as ifile:
            ansel = False
            gramps = False
            for index in range(50):
                # Treat the file as though it is UTF-8 since this is the more
                # modern option; and anyway it doesn't really matter as we are
                # only trying to detect a CHAR or SOUR line which is only
                # 7-bit ASCII anyway,  and we ignore anything that can't be
                # translated.
                line = ifile.readline()
                line = line.split()
                if len(line) == 0:
                    break
                if len(line) > 2 and line[1][0:4] == 'CHAR' \
                                 and line[2] == "ANSEL":
                    ansel = True
                if len(line) > 2 and line[1][0:4] == 'SOUR' \
                                 and line[2] == "GRAMPS":
                    gramps = True
    except IOError:
        return

    if not gramps and ansel and user.uistate:
        top = Glade()
        code = top.get_object('codeset')
        code.set_active(0)
        dialog = top.toplevel
        dialog.set_transient_for(user.uistate.window)
        dialog.run()
        enc = ['ANSEL', 'ANSEL', 'ANSI', 'ASCII', 'UTF-8']
        code_set = enc[code.get_active()]
        dialog.destroy()
    else:
        code_set = ""

    assert (isinstance(code_set, str))

    try:
        ifile = open(filename, "rb")
        stage_one = libgedcom.GedcomStageOne(ifile)
        stage_one.parse()

        if code_set:
            stage_one.set_encoding(code_set)
        ifile.seek(0)
        if database.get_feature(
                "skip-import-additions"):  # don't add source or tags
            gedparse = libgedcom.GedcomParser(database, ifile, filename, user,
                                              stage_one, None, None)
        else:
            gedparse = libgedcom.GedcomParser(
                database, ifile, filename, user, stage_one,
                config.get('preferences.default-source'),
                (config.get('preferences.tag-on-import-format')
                 if config.get('preferences.tag-on-import') else None))
    except IOError as msg:
        user.notify_error(_("%s could not be opened\n") % filename, str(msg))
        return
    except GedcomError as msg:
        user.notify_error(
            _("Invalid GEDCOM file"),
            _("%s could not be imported") % filename + "\n" + str(msg))
        return

    try:
        read_only = database.readonly
        database.readonly = False
        gedparse.parse_gedcom_file(False)
        database.readonly = read_only
        ifile.close()
    except IOError as msg:
        msg = _("%s could not be opened\n") % filename
        user.notify_error(msg, str(msg))
        return
    except DbError as msg:
        user.notify_db_error(str(msg.value))
        return
    except GedcomError as msg:
        user.notify_error(_('Error reading GEDCOM file'), str(msg))
        return
    ## a "GEDCOM import report" happens in GedcomParser so this is not needed:
    ## (but the imports_test.py unittest currently requires it, so here it is)
    return ImportInfo({_("Results"): _("done")})
Exemplo n.º 51
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)
Exemplo n.º 52
0
def importData(database, filename, user):
    """
    Try to handle ANSEL encoded files that are not really ANSEL encoded
    """

    if DbMixin not in database.__class__.__bases__:
        database.__class__.__bases__ = (DbMixin,) +  \
                                        database.__class__.__bases__

    try:
        with open(filename, "rb") as ifile:
            ansel = False
            gramps = False
            for index in range(50):
                # Treat the file as though it is UTF-8 since this is the more modern
                # option; and anyway it doesn't really matter as we are only trying to
                # detect a CHAR or SOUR line which is only 7-bit ASCII anyway,  and we
                # ignore anything that can't be translated.
                line = ifile.readline()
                line = line.decode(encoding='utf-8', errors='replace')
                line = line.split()
                if len(line) == 0:
                    break
                if len(line
                       ) > 2 and line[1][0:4] == 'CHAR' and line[2] == "ANSEL":
                    ansel = True
                if len(line) > 2 and line[1][0:4] == 'SOUR' and line[
                        2] == "GRAMPS":
                    gramps = True

    except IOError:
        return

    if not gramps and ansel:
        top = Glade()
        code = top.get_object('codeset')
        code.set_active(0)
        dialog = top.toplevel
        dialog.run()
        enc = ['ANSEL', 'ANSEL', 'ANSI', 'ASCII', 'UTF-8']
        code_set = enc[code.get_active()]
        dialog.destroy()
    else:
        code_set = ""

    assert (isinstance(code_set, str))

    try:
        ifile = open(filename, "rb")
        stage_one = libgedcom.GedcomStageOne(ifile)
        stage_one.parse()

        if code_set:
            stage_one.set_encoding(code_set)
        ifile.seek(0)
        if database.get_feature(
                "skip-import-additions"):  # don't add source or tags
            gedparse = libgedcom.GedcomParser(database, ifile, filename, user,
                                              stage_one, None, None)
        else:
            gedparse = libgedcom.GedcomParser(
                database, ifile, filename, user, stage_one,
                config.get('preferences.default-source'),
                (config.get('preferences.tag-on-import-format')
                 if config.get('preferences.tag-on-import') else None))
    except IOError as msg:
        user.notify_error(_("%s could not be opened\n") % filename, str(msg))
        return
    except GedcomError as msg:
        user.notify_error(
            _("Invalid GEDCOM file"),
            _("%s could not be imported") % filename + "\n" + str(msg))
        return

    try:
        read_only = database.readonly
        database.readonly = False
        gedparse.parse_gedcom_file(False)
        database.readonly = read_only
        ifile.close()
    except IOError as msg:
        msg = _("%s could not be opened\n") % filename
        user.notify_error(msg, str(msg))
        return
    except DbError as msg:
        user.notify_db_error(str(msg.value))
        return
    except GedcomError as msg:
        user.notify_error(_('Error reading GEDCOM file'), str(msg))
        return
    return ImportInfo({_("Results"): _("done")})
Exemplo n.º 53
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()
Exemplo n.º 54
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()
Exemplo n.º 55
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()
Exemplo n.º 56
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()
Exemplo n.º 57
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()
Exemplo n.º 58
0
class BirthIndex(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate
        
        self.label = _('Sources Index')
        self.base = os.path.dirname(__file__)
        
        ManagedWindow.__init__(self, uistate,[], self.__class__)
        self.set_window(Gtk.Window(),Gtk.Label(),'')
        
        tool.Tool.__init__(self, dbstate, options_class, name)
        
        glade_file = os.path.join(USER_PLUGINS, "SourceIndex", "birth.glade")
        
        if gramps.gen.constfunc.lin():
            import locale
            locale.setlocale(locale.LC_ALL, '')
            # This is needed to make gtk.Builder work by specifying the
            # translations directory
            locale.bindtextdomain("addon", self.base + "/locale")
            
            self.glade = Gtk.Builder()
            self.glade.set_translation_domain("addon")
            
            #self.glade = GladeWidgetsWrapper(glade_file, self)
            self.glade.add_from_file(glade_file)
            
            from gi.repository import GObject
            GObject.GObject.__init__(self.glade)
                      
            window = self.glade.get_object('edit_birth')
                
            self.set_window(window, self.glade.get_object('title'), self.label)
            
            #self.wit_button = self.glade.get_object('add_wit')
            self.ok_button = self.glade.get_object('ok')
            self.quit_button = self.glade.get_object('cancel')
                        
        else:

            # Glade class from gui/glade.py and gui/managedwindow.py
            self.glade = Glade(glade_file)
            #self.glade = GladeWidgetsWrapper(glade_file, self)
       
            self.top = Glade()
            window = self.top.toplevel
            self.set_window(window, None, glade_file)
        
            #self.wit_button = self.top.get_object('add_wit')
            self.ok_button = self.top.get_object('ok')
            self.quit_button = self.top.get_object('cancel')
            
        #self.wit_button.connect('clicked', GtkHandlers.on_witness_clicked)
        self.ok_button.connect('clicked', self.close)
        self.quit_button.connect('clicked', self.close)
        
        #GObject.__init__() takes exactly 0 arguments
        #self.text = Gtk.EntryBuffer('Gtk.Entry._get...', 5)
               
        # tests
        path = os.path.join(USER_PLUGINS, 'SourceIndex')
        self.rinfo = 'Library of usercity'
        callnumber = 'BX42_xzertra58364' # inherited or seizure
        source_handle = '_123456789' # or call the source title
        citation_handle = '_987654321'  # or call any id
        self.avol = 'Page 105 n°56'
        self.aname = 'Civil book (Birth 1650)'
        separator = 'ↄ'
        name = self.rinfo + separator + callnumber +  separator \
        + source_handle + separator + citation_handle + separator \
        + self.avol + separator + self.aname + '.xml'
        filename = os.path.join(path, name)
        self.write_xml(
            filename,
            'B0001',
            'DATE', 
            'PRÉNOM'
            )
            
        #self._setup_fields()
        
        self.window.show()
            
        self.parse_xml(filename)
        
                        
    def _setup_fields(self):
        '''
        Gramps XML storage means ability to also import/manage alone records
        /!\ some attributes are translated keys
        see data_item keys and eventref types of attribute
        '''
        
        #/database/repositories/repository/rname/text()
        self.rinfo   = MonitoredText(
            self.top.get_object("rinfo"),
            self.top.get_object("rinfo").set_text(self.rinfo),
            self.top.get_object("rinfo").get_text,
            True)
                    
        # date of transcription/search
        self.rdate = MonitoredText(
            self.top.get_object("rdate"),
            self.top.get_object("rdate").set_text(str(date.Today())),
            #self.top.get_object("rdate").get_date_object(),
            #uistate,
            #track,
            True)
        
        #/database/repositories/repository/@handle
        self.rid  = MonitoredEntry(
            self.top.get_object("rid"),
            self.top.get_object("rid").set_text,
            self.top.get_object("rid").get_text,
            True)
        
        #/database/sources/source/stitle/text()
        self.aname  = MonitoredText(
            self.top.get_object("aname"),
            self.top.get_object("aname").set_text(self.aname),
            self.top.get_object("aname").get_text,
            True)
        
        #/database/sources/source/@handle
        self.aid  = MonitoredEntry(
            self.top.get_object("aid"),
            self.top.get_object("aid").set_text,
            self.top.get_object("aid").get_text,
            True)
        
        #/database/citations/citation/@handle
        self.aref  = MonitoredEntry(
            self.top.get_object("aref"),
            self.top.get_object("aref").set_text,
            self.top.get_object("aref").get_text,
            True)
            
        #/database/citations/citation/dateval/@val
        #self.adate = MonitoredDate(
            #self.top.get_object("adate"),
            #self.top.get_object("adate").set_text,
            #self.top.get_object("adate").get_date_object(),
            #uistate,
            #track,
            #True)
        
        #/database/citations/citation/page
        # hardcoded /database/citations/citation/confidence
        self.avol  = MonitoredEntry(
            self.top.get_object("avol"),
            self.top.get_object("avol").set_text(self.avol),
            self.top.get_object("avol").get_text,
            True)
        
        #/database/people/person/gender
        #self.gen  = MonitoredType(
            #self.top.get_object("gen"),
            #self.top.get_object("gen").set_text,
            #self.top.get_object("gen").get_text,
            #True)
            
        #/database/people/person/childof/@hlink
        #/database/people/person/name/surname/surname/text()
        self.pname  = MonitoredEntry(
            self.top.get_object("pname"),
            self.top.get_object("pname").set_text,
            self.top.get_object("pname").get_text,
            True)
        
        #/database/people/person/name/first/text()
        self.pfname  = MonitoredText(
            self.top.get_object("pfname"),
            self.top.get_object("pfname").set_text,
            self.top.get_object("pfname").get_text,
            True)
                    
        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val 
        #self.pdate = MonitoredDate(
            #self.top.get_object("pdate"),
            #self.top.get_object("pdate_stat"), 
            #self.top.get_object("pdate").get_date_object(),
            #uistate,
            #track,
            #True)
            
        #/database/people/person/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        #self.pplace  = PlaceEntry(
            #dbstate, uistate, track,
            #self.top.get_object("pplace"),
            #self.top.get_object("pplace").set_place_handle,
            #self.top.get_object("pplace").get_place_handle,
            #self.top.get_object('add_del_place'),
            #self.top.get_object('select_place'))
        
        #/database/people/person/eventref/noteref/@hlink
        #/database/notes/note/text/text()
        #self.pnote  = NoteEntry(
            #dbstate, uistate, track,
            #self.top.get_object("pnote"),
            #self.top.get_object("pnote").set_note_handle,
            #self.top.get_object("pnote").get_note_handle,
            #self.top.get_object('add_del_note'),
            #self.top.get_object('select_note'))
        
        #/database/objects/object/file/@src
        #self.fname  = MediaEntry(
            #dbstate, uistate, track,
            #self.top.get_object("fname"),
            #self.top.get_object("fname").set_media_path,
            #self.top.get_object("fname").get_media_path,
            #self.top.get_object('add_del_path'),
            #self.top.get_object('select_path'))
        
        #/database/people/person/parentin/@hlink
        #/database/people/person/name/first/text()
        self.ffname  = MonitoredText(
            self.top.get_object("ffname"),
            self.top.get_object("ffname").set_text,
            self.top.get_object("ffname").get_text,
            True)
        
        #/database/people/person/eventref/attribute/@type
        #/database/people/person/eventref/attribute/@value
        self.fage = MonitoredEntry(
            self.top.get_object("fage"),
            self.top.get_object("fage").set_text,
            self.top.get_object("fage").get_text,
            True)
        
        #/database/people/person/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        #self.forig  = PlaceEntry(
            #dbstate, uistate, track,
            #self.top.get_object("forig"),
            #self.top.get_object("forig").set_place_handle,
            #self.top.get_object("forig").get_place_handle,
            #self.top.get_object('add_del_place'),
            #self.top.get_object('select_place'))
        
        #/database/people/person/eventref/@hlink
        #/database/events/event/description/text()
        self.foccu  = MonitoredEntry(
            self.top.get_object("foccu"),
            self.top.get_object("foccu").set_text,
            self.top.get_object("foccu").get_text,
            True)
        
        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        #/database/events/event/description/text()
        self.flive  = MonitoredEntry(
            self.top.get_object("flive"),
            self.top.get_object("flive").set_text,
            self.top.get_object("flive").get_text,
            True)
        
        #/database/people/person/parentin/@hlink
        #/database/people/person/name/first/text()
        self.mname  = MonitoredText(
            self.top.get_object("mname"),
            self.top.get_object("mname").set_text,
            self.top.get_object("mname").get_text,
            True)
        
        self.mfname  = MonitoredText(
            self.top.get_object("mfname"),
            self.top.get_object("mfname").set_text,
            self.top.get_object("mfname").get_text,
            True)
        
        self.mage  = MonitoredText(
            self.top.get_object("mage"),
            self.top.get_object("mage").set_text,
            self.top.get_object("mage").get_text,
            True)
        
        #self.morigin  = PlaceEntry(
            #dbstate, uistate, track,
            #self.top.get_object("morigin"),
            #self.top.get_object("morigin").set_place_handle,
            #self.top.get_object("morigin").get_place_handle,
            #self.top.get_object('add_del_place'),
            #self.top.get_object('select_place'))
        
        self.moccu  = MonitoredText(
            self.top.get_object("moccu"),
            self.top.get_object("moccu").set_text,
            self.top.get_object("moccu").get_text,
            True)
        
        self.mlive  = MonitoredEntry(
            self.top.get_object("mlive"),
            self.top.get_object("mlive").set_text,
            self.top.get_object("mlive").get_text,
            True)
        
        self.msname  = MonitoredText(
            self.top.get_object("msname"),
            self.top.get_object("msname").set_text,
            self.top.get_object("msname").get_text,
            True)
                    
        #self.mdpdate = MonitoredDate(
            #self.top.get_object("mdpdate"),
            #self.top.get_object("mdpdate_stat"), 
            #self.top.get_object("mdpdate").get_date_object(),
            #uistate,
            #track,
            #True)
                    
        #self.mmdate = MonitoredDate(
            #self.top.get_object("mmdate"),
            #self.top.get_object("mmdate_stat"), 
            #self.top.get_object("mmdate").get_date_object(),
            #uistate,
            #track,
            #True)
        
        #self.mdplace  = PlaceEntry(
            #dbstate, uistate, track,
            #self.top.get_object("mdplace"),
            #self.top.get_object("mdplace").set_place_handle,
            #self.top.get_object("mdplace").get_place_handle,
            #self.top.get_object('add_del_place'),
            #self.top.get_object('select_place'))
        
        #self.mmplace  = PlaceEntry(
            #dbstate, uistate, track,
            #self.top.get_object("mmplace"),
            #self.top.get_object("mmplace").set_place_handle,
            #self.top.get_object("mmplace").get_place_handle,
            #self.top.get_object('add_del_place'),
            #self.top.get_object('select_place'))
            
        #self.mnote  = NoteEntry(
            #dbstate, uistate, track,
            #self.top.get_object("mnote"),
            #self.top.get_object("mnote").set_note_handle,
            #self.top.get_object("mnote").get_note_handle,
            #self.top.get_object('add_del_note'),
            #self.top.get_object('select_note'))
        
        #/database/people/person/parentin/@hlink
        #/database/families/family/mother
        #/database/families/family/father
        #self.spname  = MonitoredText(
            #self.top.get_object("spname"),
            #self.top.get_object("spname").set_text,
            #self.top.get_object("spname").get_text,
            #True)
        
        #/database/families/family/eventref/@hlink
        #/database/events/event/dateval/@val 
        #self.spmdate  = MonitoredEntry(
            #self.top.get_object("spmdate"),
            #self.top.get_object("spmdate").set_text,
            #self.top.get_object("spmdate").get_text,
            #True)
            
        #/database/families/family/eventref/@hlink
        #/database/events/event/place/@hlink
        #/database/places/placeobj/ptitle/text()
        #self.spmplace  = PlaceEntry(
            #dbstate, uistate, track,
            #self.top.get_object("spmplace"),
            #self.top.get_object("spmplace").set_place_handle,
            #self.top.get_object("spmplace").get_place_handle,
            #self.top.get_object('add_del_place'),
            #self.top.get_object('select_place'))
            
            
    def call_witness(self, obj):
        pass
        
            
    # PyXMLFAQ -- Python XML Frequently Asked Questions
    # Author: 	Dave Kuhlman
    # [email protected]
    # http://www.rexx.com/~dkuhlman
           
    def walk_tree(self, node, level):
        fill = self.show_level(level)
        print '%sElement name: %s' % (fill, node.tag, )
        for (name, value) in node.attrib.items():
            print '%s    Attr -- Name: %s  Value: %s' % (fill, name, value,)
        if node.attrib.get('ID') is not None:
            print '%s    ID: %s' % (fill, node.attrib.get('ID').value, )
        children = node.getchildren()
        for child in children:
            self.walk_tree(child, level + 1)


    def show_level(self, level):
        s1 = '\t' * level
        return s1

        
    def parse_xml(self, filename):
        """
        Load and parse the XML filename
        """
        
        tree = ElementTree.parse(filename)
        root = tree.getroot()
        
        self.walk_tree(root, 0)

                
    def write_xml(self, filename, id , date, given):
        """
        Write the content of data filled into the form
        (currently only a test; no levels)
        """
        
        '''
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.5.0//EN"
        "http://gramps-project.org/xml/1.5.0/grampsxml.dtd">
        <database xmlns="http://gramps-project.org/xml/1.5.0/">
        <header>
          <created date="2012-07-04" version="3.5.0-0.SVNexported"/>
          <researcher>
          </researcher>
        </header>
        ...
        '''

        node = ElementTree.Element('birth')
        node.set('id', id)
        node.set('collection', filename)
        node.set('uri', 'file://..')
        
        gramps = ElementTree.SubElement(node, 'database')
        gramps.set('xmlns', 'http://gramps-project.org/xml/1.5.0/')
        
        #/database/people/person/eventref/@hlink
        #/database/events/event/dateval/@val
        events = ElementTree.SubElement(gramps, 'events')
        event = ElementTree.SubElement(events, 'event')
        dateval = ElementTree.SubElement(event, 'dateval')
        dateval.set('val', date)
        
        #/database/people/person/name/first/text()
        people = ElementTree.SubElement(gramps, 'people')
        person = ElementTree.SubElement(people, 'person')
        name = ElementTree.SubElement(person, 'name')
        first = ElementTree.SubElement(name, 'first')
        first.text = given
        
        outfile = open(filename, 'w')
        self.outfile = codecs.getwriter("utf8")(outfile)
        
        self.outfile.write(ElementTree.tostring(node, encoding="UTF-8"))
        self.outfile.close()
Exemplo n.º 59
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)
Exemplo n.º 60
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()