Example #1
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #2
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.VBox(homogeneous=False)

        hbox = Gtk.HBox()
        self.left = SimpleButton(Gtk.STOCK_GO_BACK, self.left_clicked)
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton(Gtk.STOCK_GO_FORWARD, self.right_clicked)
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #3
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        
        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)
        
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #4
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.VBox(homogeneous=False)
        
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        self.set_text()
        
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #5
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton(Gtk.STOCK_GO_BACK, self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton(Gtk.STOCK_GO_FORWARD, self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton(Gtk.STOCK_EDIT, self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton(Gtk.STOCK_NEW, self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        self.title = Gtk.Label()
        self.title.set_alignment(0, 0)
        self.title.set_line_wrap(True)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(self.title, False, False, 4)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #6
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        self.set_text()
        
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #7
0
    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton('gtk-edit', self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton('document-new', self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        self.title = Gtk.Label(halign=Gtk.Align.START)
        self.title.set_line_wrap(True)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(self.title, False, False, 4)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
Example #8
0
class ToDoGramplet(Gramplet):
    """
    Displays all the To Do notes in the database.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton('gtk-edit', self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton('document-new', self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        self.title = Gtk.Label(halign=Gtk.Align.START)
        self.title.set_line_wrap(True)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(self.title, False, False, 4)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def main(self):
        self.get_notes()

    def get_note_list(self):
        """
        Get a list of all To Do notes.
        """
        all_notes = self.dbstate.db.get_note_handles()
        FilterClass = GenericFilterFactory('Note')
        filter = FilterClass()
        filter.add_rule(rules.note.HasType(["To Do"]))
        note_list = filter.apply(self.dbstate.db, all_notes)
        return note_list

    def get_notes(self):
        """
        Display all the To Do notes.
        """
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = self.get_note_list()
        self.page.set_text('')
        self.title.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            self.edit.set_sensitive(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.title.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        obj = [x for x in self.dbstate.db.find_backlink_handles(note_handle)]
        if obj:
            name, obj = navigation_label(self.dbstate.db, obj[0][0], obj[0][1])
            self.title.set_text(name)
        else:
            self.title.set_text(_("Unattached"))
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(_('%(current)d of %(total)d') %
                           {'current': self.current + 1,
                            'total': len(self.note_list)})

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self):
        """
        Return True if the gramplet has data, else return False.
        """
        if self.get_note_list():
            return True
        return False

    def edit_clicked(self, obj):
        """
        Edit current To Do note.
        """
        from gramps.gui.editors import EditNote
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except AttributeError:
            pass

    def new_clicked(self, obj):
        """
        Create a new To Do note.
        """
        from gramps.gui.editors import EditNote
        note = Note()
        note.set_type(NoteType.TODO)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except AttributeError:
            pass

    def update_has_data(self):
        self.set_has_data(self.get_has_data())

    def db_changed(self):
        self.connect(self.dbstate.db, 'note-add', self.update)
        self.connect(self.dbstate.db, 'note-delete', self.update)
        self.connect(self.dbstate.db, 'note-update', self.update)
Example #9
0
class WelcomeGramplet(Gramplet):
    """
    Displays a welcome note to the user.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        self.set_text()
        
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def set_text(self):
        """
        Display the welcome text.
        """
        welcome = boldst(_('Intro')) + '\n\n'
        welcome += _(
        'Gramps is a software package designed for genealogical research.'
        ' Although similar to other genealogical programs, Gramps offers '
        'some unique and powerful features.\n\n')
        welcome += boldst(_('Links')) + '\n\n'
        welcome += linkst(_('Home Page'), URL_HOMEPAGE) + '\n'
        welcome += linkst(_('Start with Genealogy and Gramps'), 
                          '%(gramps_wiki_url)sStart_with_Genealogy' %
                              {'gramps_wiki_url': URL_WIKISTRING} ) + '\n'
        welcome += linkst(_('Gramps online manual'), 
            URL_WIKISTRING + URL_MANUAL_PAGE + _('locale_suffix|')) + '\n'
        welcome += linkst(_('Ask questions on gramps-users mailing list'),
                          '%(gramps_home_url)scontact/' %
                              {'gramps_home_url': URL_HOMEPAGE} ) + '\n\n'
        
        welcome += boldst(_('Who makes Gramps?')) + '\n\n' + _(
        'Gramps is created by genealogists for genealogists, organized in the'
        ' Gramps Project.'
        ' Gramps is an Open Source Software package, which means you are '
        'free to make copies and distribute it to anyone you like. It\'s '
        'developed and maintained by a worldwide team of volunteers whose'
        ' goal is to make Gramps powerful, yet easy to use.\n\n')
        welcome += boldst(_('Getting Started')) + '\n\n' + _(
        'The first thing you must do is to create a new Family Tree. To '
        'create a new Family Tree (sometimes called \'database\') select '
        '"Family Trees" from the menu, pick "Manage Family Trees", press '
        '"New" and name your Family Tree. For more details, please read the '
        'information at the links above\n\n')
        welcome += boldst(_('Dashboard View')) + '\n\n' + _(
        'You are currently reading from the "Dashboard" view, where you can'
        ' add your own gramplets. You can also add gramplets to any view by'
        ' adding a sidebar and/or bottombar, and right-clicking to the right'
        ' of the tab.\n\n'
        'You can click the configuration icon in the toolbar to add additional'
        ' columns, while right-click on the background allows to add gramplets.'
        ' You can also drag the Properties button to reposition the gramplet '
        ' on this page, and detach the gramplet to float above Gramps.'
        )

        self.texteditor.set_text(welcome)

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        return True
Example #10
0
    def write_media(self, media_list, event):
        for media_ref in media_list:

            mobj = self.dbstate.db.get_media_from_handle(media_ref.ref)
            button = self.get_thumbnail(media_ref, size=SIZE_LARGE)
            if button:

                self.vbox2.add(button)

                vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

                if event:
                    etype = str(event.get_type())
                    label = Gtk.Label(etype)
                    vbox.pack_start(label, False, False, 0)
                    who = get_participant_from_event(self.dbstate.db, event.handle)
                    label = Gtk.Label(who)
                    vbox.pack_start(label, False, False, 0)
                    date_place = self.format_event(event)
                    label = Gtk.Label(date_place)
                    vbox.pack_start(label, False, False, 0)

                notes = mobj.get_note_list()
                if len(notes) > 0:
                    note = self.dbstate.db.get_note_from_handle(notes[0])
                    texteditor = StyledTextEditor()
                    texteditor.set_editable(False)
                    texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
                    texteditor.set_text(note.get_styledtext())
                    texteditor.set_hexpand(True)
                    texteditor.show()
                    vbox.pack_start(texteditor, True, True, 0)
                    vbox.show_all()

                self.vbox2.attach_next_to(vbox, button,
                                          Gtk.PositionType.RIGHT, 1, 1)
Example #11
0
class Notes(Gramplet):
    """
    Displays the notes for an object.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        
        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)
        
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top
        
    def get_notes(self, obj):
        """
        Get the note list for the current object.
        """
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = obj.get_note_list()
        self.page.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(_('%(current)d of %(total)d') % {'current': self.current + 1,
                                            'total': len(self.note_list)})

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        if obj is None: 
            return False
        if obj.get_note_list():
            return True
        return False
Example #12
0
class WelcomeGramplet(Gramplet):
    """
    Displays a welcome note to the user.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        self.set_text()

        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def set_text(self):
        """
        Display the welcome text.
        """
        welcome = boldst(_('Intro')) + '\n\n'
        welcome += _(
            'Gramps is a software package designed for genealogical research.'
            ' Although similar to other genealogical programs, Gramps offers '
            'some unique and powerful features.\n\n')
        welcome += boldst(_('Links')) + '\n\n'
        welcome += linkst(_('Home Page'), URL_HOMEPAGE) + '\n'
        welcome += linkst(
            _('Start with Genealogy and Gramps'),
            '%(gramps_wiki_url)sStart_with_Genealogy' %
            {'gramps_wiki_url': URL_WIKISTRING}) + '\n'
        welcome += linkst(
            _('Gramps online manual'),
            URL_WIKISTRING + URL_MANUAL_PAGE + _('locale_suffix|')) + '\n'
        welcome += linkst(
            _('Ask questions on gramps-users mailing list'),
            '%(gramps_home_url)scontact/' %
            {'gramps_home_url': URL_HOMEPAGE}) + '\n\n'

        welcome += boldst(_('Who makes Gramps?')) + '\n\n' + _(
            'Gramps is created by genealogists for genealogists, organized in the'
            ' Gramps Project.'
            ' Gramps is an Open Source Software package, which means you are '
            'free to make copies and distribute it to anyone you like. It\'s '
            'developed and maintained by a worldwide team of volunteers whose'
            ' goal is to make Gramps powerful, yet easy to use.\n\n')
        welcome += boldst(_('Getting Started')) + '\n\n' + _(
            'The first thing you must do is to create a new Family Tree. To '
            'create a new Family Tree (sometimes called \'database\') select '
            '"Family Trees" from the menu, pick "Manage Family Trees", press '
            '"New" and name your Family Tree. For more details, please read the '
            'information at the links above\n\n')
        welcome += boldst(_('Dashboard View')) + '\n\n' + _(
            'You are currently reading from the "Dashboard" view, where you can'
            ' add your own gramplets. You can also add gramplets to any view by'
            ' adding a sidebar and/or bottombar, and right-clicking to the right'
            ' of the tab.\n\n'
            'You can click the configuration icon in the toolbar to add additional'
            ' columns, while right-click on the background allows to add gramplets.'
            ' You can also drag the Properties button to reposition the gramplet '
            ' on this page, and detach the gramplet to float above Gramps.')

        self.texteditor.set_text(welcome)

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        return True
Example #13
0
class NoteCleanup(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

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

        self.window_name = _('Note Cleanup Tool')
        ManagedWindow.__init__(self, uistate, [], self.__class__)

        self.dbstate = dbstate
        self.trans = None
        self.moved_files = []
        self.titles = [_('Cleaned Notes'), _('Links Only'),
                       _('Issues')]
        self.models = []
        self.views = []
        self.changelist = []
        self.changelistidx = 0

        window = MyWindow(self.dbstate, self.uistate, [])
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox.set_homogeneous(True)
        rvbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2, width_request=400)
        vbox.pack_start(hbox, True, True, 5)
        self.notebook = Gtk.Notebook()
        self.notebook.set_scrollable(True)
        self.notebook.connect('switch-page', self.pagesw)
        for title in self.titles:
            self.create_tab(title)
        hbox.pack_start(self.notebook, True, True, 3)
        hbox.pack_start(rvbox, True, True, 3)

        bbox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
        vbox.pack_start(bbox, False, False, 5)
        close = Gtk.Button(_('Close'))
        close.set_tooltip_text(_('Close the Note Cleanup Tool'))
        close.connect('clicked', self.close)
        save = Gtk.Button(_('Save All'))
        save.set_tooltip_text(_('Save All Changes'))
        save.connect('clicked', self.saveit)
        search = Gtk.Button(_('Search'))
        search.set_tooltip_text(_('Search for Untidy Notes'))
        search.connect('clicked', self.cleanup)
        testnote = Gtk.Button(_('Generate Test Notes'))
        testnote.set_tooltip_text(_(
            'Generate Test notes in range N99996-N99999.\n'
            'These are added to your database, so you may want to work with'
            ' a test database or delete them later.'))
        testnote.connect('clicked', self.gentest)
        export = Gtk.Button(_('Export'))
        export.set_tooltip_text(_('Export the results to a text file'))
        export.connect('clicked', self.export_results)
        bbox.add(search)
        bbox.add(testnote)
        bbox.add(export)
        bbox.add(save)
        bbox.add(close)
        self.tb = StyledTextEditor()
        self.tb.set_editable(False)
        self.tb.set_wrap_mode(Gtk.WrapMode.WORD)
        tbw = Gtk.ScrolledWindow()
        tbw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        tbw.add(self.tb)
        rvbox.pack_start(tbw, True, True, 0)
        self.ta = StyledTextEditor()
        self.ta.set_editable(True)
        self.ta.set_wrap_mode(Gtk.WrapMode.WORD)
        taw = Gtk.ScrolledWindow()
        taw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        taw.add(self.ta)
        tat=self.ta.get_toolbar()
        tat.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR)
        tatb=tat.get_nth_item(5)
        tat.remove(tatb)
        tatb=tat.get_nth_item(5)
        tat.remove(tatb)
        rvbox.pack_start(tat, False, False, 0)
        rvbox.pack_start(taw, True, True, 0)
        self.clear_models()
        vbox.show_all()
        window.add(vbox)
        window.set_size_request(800, 400)
        self.set_window(window, None, self.window_name)
        self.show()

        self.show_tabs()
        WarningDialog(self.window_name,
              _("Please back up your database before running this tool.\n\n"
              "Start the tool by pressing the 'Search' button, then review"
              " the results.\n"
              "When satisifed press the 'Save All' button to save your work.\n"
              "You may export a summary list of the notes that"
              " were found using the 'Export' button."),
                self.window)


    def build_menu_names(self, obj):
        return (_('Clean up Notes'),
                self.window_name)

    def create_tab(self, title):
        """
        Create a page in the notebook.
        """
        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                   Gtk.PolicyType.AUTOMATIC)
        view = Gtk.TreeView()
        column = Gtk.TreeViewColumn(_('Notes'))
        view.append_column(column)
        cell = Gtk.CellRendererText()
        column.pack_start(cell, True)
        column.add_attribute(cell, 'text', 0)
        column.set_sort_column_id(0)
        column.set_sort_indicator(True)
        model = Gtk.ListStore(str, int)
        view.set_model(model)
        page = self.notebook.get_n_pages()
        view.connect('button-press-event', self.button_press, page)
        selection = view.get_selection()
        selection.connect('changed', self.selection_changed, page)
        scrolled_window.add(view)
        self.models.append(model)
        self.views.append(view)
        label = Gtk.Label(title)
        self.notebook.append_page(scrolled_window, label)

    def button_press(self, view, event, page):
        """
        Called when a button is pressed on a treeview.
        """
        if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
            model, iter_ = view.get_selection().get_selected()
            if iter_:
                value = model.get_value(iter_, 1)
                self.edit(value)


    def selection_changed(self, selection, page):
        """
        Called when selection changed within the notebook tab
        """
        model, iter_ = selection.get_selected()
        if iter_:
            value = model.get_value(iter_, 1)
            self.showit(value)

    def pagesw(self, notebook, page, pagenum):
        """
        called when we switch tabs in the notebook
        """
        selection = self.views[pagenum].get_selection()
        model, iter_ = selection.get_selected()
        if iter_:
            value = model.get_value(iter_, 1)
            self.showit(value)


    def edit(self,indx):
        """
        Edit the note object with the given handle.
        """
        handle = self.changelist[indx][0]
        note = self.db.get_note_from_handle(handle)
        try:
            EditNote(self.dbstate, self.uistate, [], note)
        except WindowActiveError:
            pass

    def showit(self, indx):
        """
        Show the selection on right hand panes
        """
        self.update_changelist()
        self.indx = indx
        value = self.changelist[indx]
        self.tb.set_text(value[1])
        self.ta.set_text(value[2])

    def update_changelist(self):
        if self.indx != []:
            y=self.ta.get_text()
            z=self.changelist[self.indx][2]
            if y.serialize() != z.serialize():    # if y != z: doesn't work!!!
                x=(self.changelist[self.indx][0],\
                    self.changelist[self.indx][1], y)
                self.changelist[self.indx] = x

    def gentest(self, button):
        """
        Create some test notes.
        """
        with DbTxn(_("Cleanup Test Notes"), self.db) as trans:
            gid = 'N99996'
            text='A note with &lt;a target=new href=&quot;'\
                'http://seekingmichigan.org&quot;&gt;'\
                'http://seekingmichigan.org&lt;/a&gt;.'
            self.add_note(gid, text, trans)
            gid = 'N99997'
            text='http://www.google.com'
            self.add_note(gid, text, trans)
            gid = 'N99998'
            text= 'Quick test of <i>italics</i>, <b>bold</b>, <u>underline'\
                '</u>, and <a href="http://www.google.com">Google</a>.'
            self.add_note(gid, text, trans)
            gid = 'N99999'
            text = 'An <??>issue</??> with this note'
            self.add_note(gid, text, trans)

    def add_note(self, gid, text, trans):
        new_note = self.db.get_note_from_gramps_id(gid)
        if new_note:
            new_note.set(text)
            self.db.commit_note(new_note, trans)
            msg = _("Add Test Note")
        else:
            new_note = Note(text)
            new_note.set_gramps_id(gid)
            self.db.add_note(new_note, trans)
            msg = _("Add Test Note")
        trans.set_description(msg)


    def export_results(self, button):
        """
        Export the results to a text file.
        """
        chooser = Gtk.FileChooserDialog(
            _("Export results to a text file"),
            self.uistate.window,
            Gtk.FileChooserAction.SAVE,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
        chooser.set_do_overwrite_confirmation(True)

        while True:
            value = chooser.run()
            filename = chooser.get_filename()
            if value == Gtk.ResponseType.OK:
                if filename:
                    chooser.destroy()
                    break
            else:
                chooser.destroy()
                return
        try:
            with io.open(filename, 'w') as report_file:
                for title, model in zip(self.titles, self.models):
                    self.export_page(report_file, title, model)
        except IOError as err:
            WarningDialog(self.window_name,
                          _('Error when writing the report: %s') % err.strerror,
                            self.window)

    def export_page(self, report_file, title, model):
        """
        Export a page of the report to a text file.
        """
        if len(model) == 0:
            return
        report_file.write(title + '\n')
        for row in model:
            report_file.write('    %s\n' % row[0])

    def show_tabs(self):
        """
        Show notebook tabs containing data.
        """
        for page, model in enumerate(self.models):
            tab = self.notebook.get_nth_page(page)
            if len(model) > 0:
                selection = self.views[page].get_selection()
                selection.select_path(Gtk.TreePath.new_first())
                tab.show()
            else:
                tab.hide()

    def clear_models(self):
        """
        Clear the models.
        """
        for model in self.models:
            model.clear()
        self.changelist = []
        self.indx =[]
        self.tb.set_text(StyledText(_('\n\n'
            'Notes selected on the left pane are shown Before cleanup in'
            ' this box.')))
        self.ta.set_text(StyledText(_('\n\n'
            'Notes selected on the left pane are shown After cleanup in this'
            ' box.\n'
            'If you wish to make changes, you can make them here and'
            ' use the style controls in the toolbar above.')))

    def saveit(self, button):
        """
        Commit the changes to the database
        """
        self.update_changelist()
        progress = ProgressMeter(self.window_name, can_cancel=True,
                                 parent=self.window)

        length = len(self.changelist)
        progress.set_pass(_('Saving Notes'), length)

        with DbTxn(_("Saving Cleaned Notes"), self.db, batch=False) as trans:
            for changed in self.changelist:
                note = self.db.get_note_from_handle(changed[0])
                note.set_styledtext(changed[2])
                self.db.commit_note(note, trans)
                msg = _("Note Cleanup")
                trans.set_description(msg)
                progress.step()
                if progress.get_cancelled():
                    break
        self.clear_models()
        self.show_tabs()
        progress.close()


    def cleanup(self, button):
        """
        Cleanup Notes.
        """
        self.clear_models()

        progress = ProgressMeter(self.window_name, can_cancel=True,
                                 parent=self.window)

        length = self.db.get_number_of_notes()
        progress.set_pass(_('Scanning Notes'), length)

        for handle in self.db.get_note_handles():
            note = self.db.get_note_from_handle(handle)
            g_id = note.gramps_id
            stext = note.get_styledtext()
            optype = -1
            ## find the notes and do cleanup
            if not stext.tags:
                result = self.convert_to_styled(stext.string)
                indx = len(self.changelist)
                for styledtext_tag in result.tags:
                    if int(styledtext_tag.name) == StyledTextTagType.HIGHLIGHT:
                        optype = ISSUE
                        break
                    elif int(styledtext_tag.name) == StyledTextTagType.LINK:
                        optype = LINK
                while True:
                    if optype == ISSUE:
                        # make list of notes with errors
                        self.models[ISSUE].append((self.preview(stext, g_id), indx))
                    elif stext.string != result.string:
                        # Make list of edited notes
                        self.models[CLEANED].append((self.preview(stext, g_id), indx))
                    elif optype == LINK:
                        # make list of notes with only links
                        self.models[LINK].append((self.preview(stext, g_id), indx))
                    else:
                        break
                    self.changelist.append((handle, stext, result))
                    break

            progress.step()
            if progress.get_cancelled():
                break

        self.show_tabs()
        progress.close()

    def preview(self, stext, g_id):
        prev = " ".join(str(stext).split())
        if len(prev) > 80:
            text = '%s -> %s' % (g_id, prev[:80] + "...")
        else:
            text = '%s -> %s' % (g_id, prev)
        return text

    def convert_to_styled(self, data):
        """
        This scans incoming notes for possible html.  It converts a select few
        tags into StyledText and removes the rest of the tags.  Notes of this
        type occur in data from FTM and ancestry.com.  Result is a much
        cleaner note.

        @param data: a string of text possibly containg html
        @type data: str

        """
        token_specification = [
            # Italics: must not be nested, any tag terminates
            ('ITALIC',  r'<i>.*?(?=<)'),
            # bolds: must not be nested, any tag terminates
            ('BOLD',    r'<b>.*?(?=<)'),
            # Underlines: must not be nested, any tag terminates
            ('UNDER',   r'<u>.*?(?=<)'),
            # Table Header Begin (start Bold)
            ('TBLHDRB', r'<tr><th>'),
            # Table Header End (end Bold and \n)
            ('TBLHDRE', r'</th></tr>'),
            # Table Header Cell (repl with ': ')
            ('TBLHDRC', r'(<\th>)?<th>'),
            # Table Cell break (repl with ':  ')
            ('TBLCELL', r'</td><td>'),
            # Table
            ('TABLE',   r'</?table.*?>'),
            # Href start to end
            ('HREF',    r'<+a .*?href=["\' ]*(?P<HREFL>.*?)'\
                        r'["\' ].*?>(?P<HREFT>.*?)</a>+'),
            # HTTP start to end (have to rstrip(' .:') for link)
            ('HTTP',    r'https?:.*?(\s|$)'),
            # Paragraph end
            ('PARAEND', r'</p>|</li>|<tr>|<br>'),
            # Skip over these tags
            ('SKIP',    r'<ul>|</ul>|<li>|<p>|</tr>|<td>|</td>|<th>|'\
                        r'</a>|</i>|</b>|</u>'),
            # Unimplemented HTTP tags
            ('UNKNWN',  r'<.*?>'),
            ]
        tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)

        prev = 0
        chunkpos = 0
        chunks = []
        italics = []
        bolds = []
        unders = []
        links = []
        reds = []
        bldpos = -1
        data = html.unescape(data)      # clean up escaped html "&lt;" etc.
        for mo in re.finditer(tok_regex, data, flags=(re.DOTALL | re.I)):
            kind = mo.lastgroup
            st_txt = mo.group(kind)
            in_start = mo.start()
            in_end = mo.end()
            if kind == 'SKIP' or kind == 'TABLE':
                if prev != in_start:
                    chunks.append(data[prev:in_start])
                    chunkpos += (in_start - prev)
            elif kind == 'PARAEND':
                chunks.append(data[prev:in_start] + '\n')
                chunkpos += (in_start - prev + 1)
            elif kind == 'ITALIC':
                chunks.append(data[prev:in_start] + data[(in_start + 3):in_end])
                newpos = chunkpos - prev + in_end - 3
                italics.append((chunkpos + in_start - prev, newpos))
                chunkpos = newpos
            elif kind == 'BOLD':
                chunks.append(data[prev:in_start] + data[(in_start + 3):in_end])
                newpos = chunkpos - prev + in_end - 3
                bolds.append((chunkpos + in_start - prev, newpos))
                chunkpos = newpos
            elif kind == 'UNDER':
                chunks.append(data[prev:in_start] + data[(in_start + 3):in_end])
                newpos = chunkpos - prev + in_end - 3
                unders.append((chunkpos + in_start - prev, newpos))
                chunkpos = newpos
            elif kind == 'HTTP':      #HTTP found
                st_txt = mo.group('HTTP')
                oldpos = chunkpos + in_start - prev
                chunks.append(data[prev:in_start] + st_txt)
                chunkpos += (in_start - prev + len(st_txt))
                st_txt = st_txt.rstrip(' .:)')
                newpos = oldpos + len(st_txt)
                links.append((st_txt, oldpos, newpos))
            elif kind == 'HREF':      #HREF found
                st_txt = mo.group('HREFT')
                lk_txt = mo.group('HREFL')
                # fix up relative links emmitted by ancestry.com
                if lk_txt.startswith("/search/dbextra") \
                            or lk_txt.startswith("/handler/domain"):
                    lk_txt = "http://search.ancestry.com" + lk_txt
                oldpos = chunkpos + in_start - prev
                # if tag (minus any trailing '.') is substring of link
                if st_txt[0:-1] in lk_txt:
                    st_txt = lk_txt   # just use the link
                else:                 # use link and tag
                    st_txt = " " + lk_txt + " (" + st_txt + ")"
                newpos = oldpos + len(st_txt)
                chunks.append(data[prev:in_start] + st_txt)
                chunkpos += (in_start - prev + len(st_txt))
                links.append((lk_txt, oldpos, newpos))
            elif kind == 'TBLCELL' or kind == 'TBLHDRC':      #Table cell break
                chunks.append(data[prev:in_start] + ':  ')
                chunkpos += (in_start - prev + 3)
            elif kind == 'TBLHDRB':      #header start
                if prev != in_start:
                    chunks.append(data[prev:in_start])
                    chunkpos += (in_start - prev)
                bldpos = chunkpos
            elif kind == 'TBLHDRE':      #Header end
                if bldpos == -1:
                    if prev != in_start:
                        chunks.append(data[prev:in_end])
                        newpos = chunkpos - prev + in_end
                        reds.append((chunkpos + in_start - prev, newpos))
                        chunkpos = newpos
                    print('Invalid table header, no start tag found')
                else:
                    if prev != in_start:
                        chunks.append(data[prev:in_start])
                        chunkpos += (in_start - prev)
                    bolds.append((bldpos, chunkpos))
                    bldpos = -1
            elif kind == 'UNKNWN':
                if prev != in_start:
                    chunks.append(data[prev:in_end])
                    newpos = chunkpos - prev + in_end
                    reds.append((chunkpos + in_start - prev, newpos))
                    chunkpos = newpos
                print('Unexpected or unimplemented HTML tag', st_txt)
            else: print("shouldn't get here")

            prev = in_end
        chunks.append(data[prev:])

        result = ''.join(chunks)
        tags = []
        for link in links:
            tags.append(StyledTextTag(StyledTextTagType.LINK, link[0], [(link[1], link[2])]))
        if italics:
            tags.append(StyledTextTag(StyledTextTagType.ITALIC, False , italics))
        if bolds:
            tags.append(StyledTextTag(StyledTextTagType.BOLD, False , bolds))
        if unders:
            tags.append(StyledTextTag(StyledTextTagType.UNDERLINE, False , unders))
        if reds:
            tags.append(StyledTextTag(StyledTextTagType.HIGHLIGHT, '#FFFF00' , reds))
        return StyledText(result,tags)
Example #14
0
class Notes(Gramplet):
    """
    Displays the notes for an object.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def get_notes(self, obj):
        """
        Get the note list for the current object.
        """
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = obj.get_note_list()
        self.page.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(
            _('%(current)d of %(total)d') % {
                'current': self.current + 1,
                'total': len(self.note_list)
            })

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        if obj is None:
            return False
        if obj.get_note_list():
            return True
        return False
Example #15
0
class ToDo(Gramplet):
    """
    Displays the To Do notes for an object.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton('gtk-edit', self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton('document-new', self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def get_note_list(self, obj):
        """
        Get a list of To Do notes for the current object.
        """
        note_list = []
        for note_handle in obj.get_note_list():
            note = self.dbstate.db.get_note_from_handle(note_handle)
            if int(note.get_type()) == NoteType.TODO:
                note_list.append(note.get_handle())
        return note_list

    def get_notes(self, obj):
        """
        Display the To Do notes for the current object.
        """
        self.obj = obj
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = self.get_note_list(obj)
        self.page.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            self.edit.set_sensitive(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(
            _('%(current)d of %(total)d') % {
                'current': self.current + 1,
                'total': len(self.note_list)
            })

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        if obj is None:
            return False
        if self.get_note_list(obj):
            return True
        return False

    def edit_clicked(self, obj):
        """
        Edit current To Do note.
        """
        from gramps.gui.editors import EditNote
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except WindowActiveError:
            pass

    def new_clicked(self, obj):
        """
        Create a new To Do note.
        """
        nav_type = self.uistate.viewmanager.active_page.navigation_type()
        active_handle = self.get_active(nav_type)
        if active_handle:
            from gramps.gui.editors import EditNote
            note = Note()
            note.set_type(NoteType.TODO)
            try:
                EditNote(self.gui.dbstate, self.gui.uistate, [], note,
                         self.created)
            except WindowActiveError:
                pass
        else:
            WarningDialog(
                _("No active object"),
                _("First select the object to which you want to attach a note")
                + _(":") + _(nav_type),
                parent=self.uistate.window)
Example #16
0
class NoteCleanup(tool.Tool, ManagedWindow):
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

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

        self.window_name = _('Note Cleanup Tool')
        ManagedWindow.__init__(self, uistate, [], self.__class__)

        self.dbstate = dbstate
        self.trans = None
        self.moved_files = []
        self.titles = [_('Cleaned Notes'), _('Links Only'),
                       _('Issues')]
        self.models = []
        self.views = []
        self.changelist = []
        self.changelistidx = 0

        window = MyWindow(self.dbstate, self.uistate, [])
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox.set_homogeneous(True)
        rvbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2,
                        width_request=400)
        vbox.pack_start(hbox, True, True, 5)
        self.notebook = Gtk.Notebook()
        self.notebook.set_scrollable(True)
        self.notebook.connect('switch-page', self.pagesw)
        for title in self.titles:
            self.create_tab(title)
        hbox.pack_start(self.notebook, True, True, 3)
        hbox.pack_start(rvbox, True, True, 3)

        bbox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
        vbox.pack_start(bbox, False, False, 5)
        close = Gtk.Button(label=_('Close'))
        close.set_tooltip_text(_('Close the Note Cleanup Tool'))
        close.connect('clicked', self.close)
        save = Gtk.Button(label=_('Save All'))
        save.set_tooltip_text(_('Save All Changes'))
        save.connect('clicked', self.saveit)
        search = Gtk.Button(label=_('Search'))
        search.set_tooltip_text(_('Search for Untidy Notes'))
        search.connect('clicked', self.cleanup)
        testnote = Gtk.Button(label=_('Generate Test Notes'))
        testnote.set_tooltip_text(_(
            'Generate Test notes in range N99996-N99999.\n'
            'These are added to your database, so you may want to work with'
            ' a test database or delete them later.'))
        testnote.connect('clicked', self.gentest)
        export = Gtk.Button(label=_('Export'))
        export.set_tooltip_text(_('Export the results to a text file'))
        export.connect('clicked', self.export_results)
        bbox.add(search)
        bbox.add(testnote)
        bbox.add(export)
        bbox.add(save)
        bbox.add(close)
        self.tb = StyledTextEditor()
        self.tb.set_editable(False)
        self.tb.set_wrap_mode(Gtk.WrapMode.WORD)
        tbw = Gtk.ScrolledWindow()
        tbw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        tbw.add(self.tb)
        rvbox.pack_start(tbw, True, True, 0)
        self.ta = StyledTextEditor()
        self.ta.set_transient_parent(window)
        self.ta.set_editable(True)
        self.ta.set_wrap_mode(Gtk.WrapMode.WORD)
        taw = Gtk.ScrolledWindow()
        taw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        taw.add(self.ta)
        # tat=self.ta.get_toolbar()
        tat, self.action_group = self.ta.create_toolbar(
            uistate.uimanager, window)
        tat.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR)
        tatb = tat.get_nth_item(5)
        tat.remove(tatb)
        tatb = tat.get_nth_item(5)
        tat.remove(tatb)
        rvbox.pack_start(tat, False, False, 0)
        rvbox.pack_start(taw, True, True, 0)
        self.clear_models()
        vbox.show_all()
        window.add(vbox)
        window.set_size_request(800, 400)
        self.set_window(window, None, self.window_name)
        self.show()

        self.show_tabs()
        WarningDialog(
            self.window_name,
            _("Please back up your database before running this tool.\n\n"
              "Start the tool by pressing the 'Search' button, then review"
              " the results.\n"
              "When satisifed press the 'Save All' button to save your work.\n"
              "You may export a summary list of the notes that"
              " were found using the 'Export' button."),
            self.window)

    def build_menu_names(self, _obj):
        return (_('Clean up Notes'),
                self.window_name)

    def create_tab(self, title):
        """
        Create a page in the notebook.
        """
        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                   Gtk.PolicyType.AUTOMATIC)
        view = Gtk.TreeView()
        column = Gtk.TreeViewColumn(_('Notes'))
        view.append_column(column)
        cell = Gtk.CellRendererText()
        column.pack_start(cell, True)
        column.add_attribute(cell, 'text', 0)
        column.set_sort_column_id(0)
        column.set_sort_indicator(True)
        model = Gtk.ListStore(str, int)
        view.set_model(model)
        page = self.notebook.get_n_pages()
        view.connect('button-press-event', self.button_press, page)
        selection = view.get_selection()
        selection.connect('changed', self.selection_changed, page)
        scrolled_window.add(view)
        self.models.append(model)
        self.views.append(view)
        label = Gtk.Label(label=title)
        self.notebook.append_page(scrolled_window, label)

    def button_press(self, view, event, _page):
        """
        Called when a button is pressed on a treeview.
        """
        if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
            model, iter_ = view.get_selection().get_selected()
            if iter_:
                value = model.get_value(iter_, 1)
                self.edit(value)

    def selection_changed(self, selection, _page):
        """
        Called when selection changed within the notebook tab
        """
        model, iter_ = selection.get_selected()
        if iter_:
            value = model.get_value(iter_, 1)
            self.showit(value)

    def pagesw(self, _notebook, _page, pagenum):
        """
        called when we switch tabs in the notebook
        """
        selection = self.views[pagenum].get_selection()
        model, iter_ = selection.get_selected()
        if iter_:
            value = model.get_value(iter_, 1)
            self.showit(value)

    def edit(self, indx):
        """
        Edit the note object with the given handle.
        """
        handle = self.changelist[indx][0]
        note = self.db.get_note_from_handle(handle)
        try:
            EditNote(self.dbstate, self.uistate, [], note)
        except WindowActiveError:
            pass

    def showit(self, indx):
        """
        Show the selection on right hand panes
        """
        self.update_changelist()
        self.indx = indx
        value = self.changelist[indx]
        self.tb.set_text(value[1])
        self.ta.set_text(value[2])

    def update_changelist(self):
        if self.indx != []:
            y = self.ta.get_text()
            z = self.changelist[self.indx][2]
            if y.serialize() != z.serialize():    # if y != z: doesn't work!!!
                x = (self.changelist[self.indx][0],
                     self.changelist[self.indx][1], y)
                self.changelist[self.indx] = x

    def gentest(self, _button):
        """
        Create some test notes.
        """
        with DbTxn(_("Cleanup Test Notes"), self.db) as trans:
            gid = 'N99996'
            text = 'A note with &lt;a target=new href=&quot;'\
                   'http://seekingmichigan.org&quot;&gt;'\
                   'http://seekingmichigan.org&lt;/a&gt;.'
            self.add_note(gid, text, trans)
            gid = 'N99997'
            text = 'http://www.google.com'
            self.add_note(gid, text, trans)
            gid = 'N99998'
            text = 'Quick test of <i>italics</i>, <b>bold</b>, <u>underline'\
                '</u>, and <a href="http://www.google.com">Google</a>.'
            self.add_note(gid, text, trans)
            gid = 'N99999'
            text = 'An <??>issue</??> with this note'
            self.add_note(gid, text, trans)

    def add_note(self, gid, text, trans):
        new_note = self.db.get_note_from_gramps_id(gid)
        if new_note:
            new_note.set(text)
            self.db.commit_note(new_note, trans)
            msg = _("Add Test Note")
        else:
            new_note = Note(text)
            new_note.set_gramps_id(gid)
            self.db.add_note(new_note, trans)
            msg = _("Add Test Note")
        trans.set_description(msg)

    def export_results(self, _button):
        """
        Export the results to a text file.
        """
        chooser = Gtk.FileChooserDialog(
            _("Export results to a text file"),
            self.uistate.window,
            Gtk.FileChooserAction.SAVE,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
        chooser.set_do_overwrite_confirmation(True)

        while True:
            value = chooser.run()
            filename = chooser.get_filename()
            if value == Gtk.ResponseType.OK:
                if filename:
                    chooser.destroy()
                    break
            else:
                chooser.destroy()
                return
        try:
            with io.open(filename, 'w') as report_file:
                for title, model in zip(self.titles, self.models):
                    self.export_page(report_file, title, model)
        except IOError as err:
            WarningDialog(self.window_name,
                          _('Error when writing the report: %s') %
                          err.strerror, self.window)

    def export_page(self, report_file, title, model):
        """
        Export a page of the report to a text file.
        """
        if len(model) == 0:
            return
        report_file.write(title + '\n')
        for row in model:
            report_file.write('    %s\n' % row[0])

    def show_tabs(self):
        """
        Show notebook tabs containing data.
        """
        for page, model in enumerate(self.models):
            tab = self.notebook.get_nth_page(page)
            if len(model) > 0:
                selection = self.views[page].get_selection()
                selection.select_path(Gtk.TreePath.new_first())
                tab.show()
            else:
                tab.hide()

    def clear_models(self):
        """
        Clear the models.
        """
        for model in self.models:
            model.clear()
        self.changelist = []
        self.indx = []
        self.tb.set_text(StyledText(_(
            '\n\nNotes selected on the left pane are shown Before cleanup in'
            ' this box.')))
        self.ta.set_text(StyledText(_(
            '\n\n'
            'Notes selected on the left pane are shown After cleanup in this'
            ' box.\n'
            'If you wish to make changes, you can make them here and'
            ' use the style controls in the toolbar above.')))

    def saveit(self, _button):
        """
        Commit the changes to the database
        """
        self.update_changelist()
        progress = ProgressMeter(self.window_name, can_cancel=True,
                                 parent=self.window)

        length = len(self.changelist)
        progress.set_pass(_('Saving Notes'), length)

        with DbTxn(_("Saving Cleaned Notes"), self.db, batch=False) as trans:
            for changed in self.changelist:
                note = self.db.get_note_from_handle(changed[0])
                note.set_styledtext(changed[2])
                self.db.commit_note(note, trans)
                msg = _("Note Cleanup")
                trans.set_description(msg)
                progress.step()
                if progress.get_cancelled():
                    break
        self.clear_models()
        self.show_tabs()
        progress.close()

    def cleanup(self, _button):
        """
        Cleanup Notes.
        """
        self.clear_models()

        progress = ProgressMeter(self.window_name, can_cancel=True,
                                 parent=self.window)

        length = self.db.get_number_of_notes()
        progress.set_pass(_('Scanning Notes'), length)

        for handle in self.db.get_note_handles():
            note = self.db.get_note_from_handle(handle)
            g_id = note.gramps_id
            stext = note.get_styledtext()
            optype = -1
            # find the notes and do cleanup
            if not stext.tags:
                result = self.convert_to_styled(stext.string)
                indx = len(self.changelist)
                for styledtext_tag in result.tags:
                    if int(styledtext_tag.name) == StyledTextTagType.HIGHLIGHT:
                        optype = ISSUE
                        break
                    elif int(styledtext_tag.name) == StyledTextTagType.LINK:
                        optype = LINK
                while True:
                    if optype == ISSUE:
                        # make list of notes with errors
                        self.models[ISSUE].append((self.preview(stext, g_id),
                                                   indx))
                    elif stext.string != result.string:
                        # Make list of edited notes
                        self.models[CLEANED].append((self.preview(stext, g_id),
                                                     indx))
                    elif optype == LINK:
                        # make list of notes with only links
                        self.models[LINK].append((self.preview(stext, g_id),
                                                  indx))
                    else:
                        break
                    self.changelist.append((handle, stext, result))
                    break

            progress.step()
            if progress.get_cancelled():
                break

        self.show_tabs()
        progress.close()

    def preview(self, stext, g_id):
        prev = " ".join(str(stext).split())
        if len(prev) > 80:
            text = '%s -> %s' % (g_id, prev[:80] + "...")
        else:
            text = '%s -> %s' % (g_id, prev)
        return text

    def convert_to_styled(self, data):
        """
        This scans incoming notes for possible html.  It converts a select few
        tags into StyledText and removes the rest of the tags.  Notes of this
        type occur in data from FTM and ancestry.com.  Result is a much
        cleaner note.

        @param data: a string of text possibly containg html
        @type data: str

        """
        token_specification = [
            # Italics: must not be nested, any tag terminates
            ('ITALIC',  r'<i>.*?(?=<)'),
            # bolds: must not be nested, any tag terminates
            ('BOLD',    r'<b>.*?(?=<)'),
            # Underlines: must not be nested, any tag terminates
            ('UNDER',   r'<u>.*?(?=<)'),
            # Table Header Begin (start Bold)
            ('TBLHDRB', r'<tr><th>'),
            # Table Header End (end Bold and \n)
            ('TBLHDRE', r'</th></tr>'),
            # Table Header Cell (repl with ': ')
            ('TBLHDRC', r'(<\th>)?<th>'),
            # Table Cell break (repl with ':  ')
            ('TBLCELL', r'</td><td>'),
            # Table
            ('TABLE',   r'</?table.*?>'),
            # Href start to end
            ('HREF',    r'<+a .*?href=["\' ]*(?P<HREFL>.*?)'\
                        r'["\' ].*?>(?P<HREFT>.*?)</a>+'),
            # HTTP start to end (have to rstrip(' .:') for link)
            ('HTTP',    r'https?:.*?(\s|$)'),
            # Paragraph end
            ('PARAEND', r'</p>|</li>|<tr>|<br>'),
            # Skip over these tags
            ('SKIP',    r'<ul>|</ul>|<li>|<p>|</tr>|<td>|</td>|<th>|'\
                        r'</a>|</i>|</b>|</u>'),
            # Unimplemented HTTP tags
            ('UNKNWN',  r'<.*?>'), ]
        tok_regex = '|'.join('(?P<%s>%s)' % pair for
                             pair in token_specification)

        prev = 0
        chunkpos = 0
        chunks = []
        italics = []
        bolds = []
        unders = []
        links = []
        reds = []
        bldpos = -1
        data = html.unescape(data)      # clean up escaped html "&lt;" etc.
        for mo in re.finditer(tok_regex, data, flags=(re.DOTALL | re.I)):
            kind = mo.lastgroup
            st_txt = mo.group(kind)
            in_start = mo.start()
            in_end = mo.end()
            if kind == 'SKIP' or kind == 'TABLE':
                if prev != in_start:
                    chunks.append(data[prev:in_start])
                    chunkpos += (in_start - prev)
            elif kind == 'PARAEND':
                chunks.append(data[prev:in_start] + '\n')
                chunkpos += (in_start - prev + 1)
            elif kind == 'ITALIC':
                chunks.append(data[prev:in_start] +
                              data[(in_start + 3):in_end])
                newpos = chunkpos - prev + in_end - 3
                italics.append((chunkpos + in_start - prev, newpos))
                chunkpos = newpos
            elif kind == 'BOLD':
                chunks.append(data[prev:in_start] +
                              data[(in_start + 3):in_end])
                newpos = chunkpos - prev + in_end - 3
                bolds.append((chunkpos + in_start - prev, newpos))
                chunkpos = newpos
            elif kind == 'UNDER':
                chunks.append(data[prev:in_start] +
                              data[(in_start + 3):in_end])
                newpos = chunkpos - prev + in_end - 3
                unders.append((chunkpos + in_start - prev, newpos))
                chunkpos = newpos
            elif kind == 'HTTP':      # HTTP found
                st_txt = mo.group('HTTP')
                oldpos = chunkpos + in_start - prev
                chunks.append(data[prev:in_start] + st_txt)
                chunkpos += (in_start - prev + len(st_txt))
                st_txt = st_txt.rstrip(' .:)')
                newpos = oldpos + len(st_txt)
                links.append((st_txt, oldpos, newpos))
            elif kind == 'HREF':      # HREF found
                st_txt = mo.group('HREFT')
                lk_txt = mo.group('HREFL')
                # fix up relative links emmitted by ancestry.com
                if(lk_txt.startswith("/search/dbextra") or
                   lk_txt.startswith("/handler/domain")):
                    lk_txt = "http://search.ancestry.com" + lk_txt
                oldpos = chunkpos + in_start - prev
                # if tag (minus any trailing '.') is substring of link
                if st_txt[0:-1] in lk_txt:
                    st_txt = lk_txt   # just use the link
                else:                 # use link and tag
                    st_txt = " " + lk_txt + " (" + st_txt + ")"
                newpos = oldpos + len(st_txt)
                chunks.append(data[prev:in_start] + st_txt)
                chunkpos += (in_start - prev + len(st_txt))
                links.append((lk_txt, oldpos, newpos))
            elif kind == 'TBLCELL' or kind == 'TBLHDRC':     # Table cell break
                chunks.append(data[prev:in_start] + ':  ')
                chunkpos += (in_start - prev + 3)
            elif kind == 'TBLHDRB':      # header start
                if prev != in_start:
                    chunks.append(data[prev:in_start])
                    chunkpos += (in_start - prev)
                bldpos = chunkpos
            elif kind == 'TBLHDRE':      # Header end
                if bldpos == -1:
                    if prev != in_start:
                        chunks.append(data[prev:in_end])
                        newpos = chunkpos - prev + in_end
                        reds.append((chunkpos + in_start - prev, newpos))
                        chunkpos = newpos
                    print('Invalid table header, no start tag found')
                else:
                    if prev != in_start:
                        chunks.append(data[prev:in_start])
                        chunkpos += (in_start - prev)
                    bolds.append((bldpos, chunkpos))
                    bldpos = -1
            elif kind == 'UNKNWN':
                if prev != in_start:
                    chunks.append(data[prev:in_end])
                    newpos = chunkpos - prev + in_end
                    reds.append((chunkpos + in_start - prev, newpos))
                    chunkpos = newpos
                print('Unexpected or unimplemented HTML tag', st_txt)
            else:
                print("shouldn't get here")

            prev = in_end
        chunks.append(data[prev:])

        result = ''.join(chunks)
        tags = []
        for link in links:
            tags.append(StyledTextTag(StyledTextTagType.LINK, link[0],
                                      [(link[1], link[2])]))
        if italics:
            tags.append(StyledTextTag(StyledTextTagType.ITALIC, False ,
                                      italics))
        if bolds:
            tags.append(StyledTextTag(StyledTextTagType.BOLD, False , bolds))
        if unders:
            tags.append(StyledTextTag(StyledTextTagType.UNDERLINE, False ,
                                      unders))
        if reds:
            tags.append(StyledTextTag(StyledTextTagType.HIGHLIGHT, '#FFFF00',
                                      reds))
        return StyledText(result, tags)
Example #17
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

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

        self.window_name = _('Note Cleanup Tool')
        ManagedWindow.__init__(self, uistate, [], self.__class__)

        self.dbstate = dbstate
        self.trans = None
        self.moved_files = []
        self.titles = [_('Cleaned Notes'), _('Links Only'),
                       _('Issues')]
        self.models = []
        self.views = []
        self.changelist = []
        self.changelistidx = 0

        window = MyWindow(self.dbstate, self.uistate, [])
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox.set_homogeneous(True)
        rvbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2,
                        width_request=400)
        vbox.pack_start(hbox, True, True, 5)
        self.notebook = Gtk.Notebook()
        self.notebook.set_scrollable(True)
        self.notebook.connect('switch-page', self.pagesw)
        for title in self.titles:
            self.create_tab(title)
        hbox.pack_start(self.notebook, True, True, 3)
        hbox.pack_start(rvbox, True, True, 3)

        bbox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
        vbox.pack_start(bbox, False, False, 5)
        close = Gtk.Button(label=_('Close'))
        close.set_tooltip_text(_('Close the Note Cleanup Tool'))
        close.connect('clicked', self.close)
        save = Gtk.Button(label=_('Save All'))
        save.set_tooltip_text(_('Save All Changes'))
        save.connect('clicked', self.saveit)
        search = Gtk.Button(label=_('Search'))
        search.set_tooltip_text(_('Search for Untidy Notes'))
        search.connect('clicked', self.cleanup)
        testnote = Gtk.Button(label=_('Generate Test Notes'))
        testnote.set_tooltip_text(_(
            'Generate Test notes in range N99996-N99999.\n'
            'These are added to your database, so you may want to work with'
            ' a test database or delete them later.'))
        testnote.connect('clicked', self.gentest)
        export = Gtk.Button(label=_('Export'))
        export.set_tooltip_text(_('Export the results to a text file'))
        export.connect('clicked', self.export_results)
        bbox.add(search)
        bbox.add(testnote)
        bbox.add(export)
        bbox.add(save)
        bbox.add(close)
        self.tb = StyledTextEditor()
        self.tb.set_editable(False)
        self.tb.set_wrap_mode(Gtk.WrapMode.WORD)
        tbw = Gtk.ScrolledWindow()
        tbw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        tbw.add(self.tb)
        rvbox.pack_start(tbw, True, True, 0)
        self.ta = StyledTextEditor()
        self.ta.set_transient_parent(window)
        self.ta.set_editable(True)
        self.ta.set_wrap_mode(Gtk.WrapMode.WORD)
        taw = Gtk.ScrolledWindow()
        taw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        taw.add(self.ta)
        # tat=self.ta.get_toolbar()
        tat, self.action_group = self.ta.create_toolbar(
            uistate.uimanager, window)
        tat.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR)
        tatb = tat.get_nth_item(5)
        tat.remove(tatb)
        tatb = tat.get_nth_item(5)
        tat.remove(tatb)
        rvbox.pack_start(tat, False, False, 0)
        rvbox.pack_start(taw, True, True, 0)
        self.clear_models()
        vbox.show_all()
        window.add(vbox)
        window.set_size_request(800, 400)
        self.set_window(window, None, self.window_name)
        self.show()

        self.show_tabs()
        WarningDialog(
            self.window_name,
            _("Please back up your database before running this tool.\n\n"
              "Start the tool by pressing the 'Search' button, then review"
              " the results.\n"
              "When satisifed press the 'Save All' button to save your work.\n"
              "You may export a summary list of the notes that"
              " were found using the 'Export' button."),
            self.window)
Example #18
0
    def __init__(self, dbstate, user, options_class, name, callback=None):
        uistate = user.uistate

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

        self.window_name = _('Note Cleanup Tool')
        ManagedWindow.__init__(self, uistate, [], self.__class__)

        self.dbstate = dbstate
        self.trans = None
        self.moved_files = []
        self.titles = [_('Cleaned Notes'), _('Links Only'),
                       _('Issues')]
        self.models = []
        self.views = []
        self.changelist = []
        self.changelistidx = 0

        window = MyWindow(self.dbstate, self.uistate, [])
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox.set_homogeneous(True)
        rvbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2, width_request=400)
        vbox.pack_start(hbox, True, True, 5)
        self.notebook = Gtk.Notebook()
        self.notebook.set_scrollable(True)
        self.notebook.connect('switch-page', self.pagesw)
        for title in self.titles:
            self.create_tab(title)
        hbox.pack_start(self.notebook, True, True, 3)
        hbox.pack_start(rvbox, True, True, 3)

        bbox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
        vbox.pack_start(bbox, False, False, 5)
        close = Gtk.Button(_('Close'))
        close.set_tooltip_text(_('Close the Note Cleanup Tool'))
        close.connect('clicked', self.close)
        save = Gtk.Button(_('Save All'))
        save.set_tooltip_text(_('Save All Changes'))
        save.connect('clicked', self.saveit)
        search = Gtk.Button(_('Search'))
        search.set_tooltip_text(_('Search for Untidy Notes'))
        search.connect('clicked', self.cleanup)
        testnote = Gtk.Button(_('Generate Test Notes'))
        testnote.set_tooltip_text(_(
            'Generate Test notes in range N99996-N99999.\n'
            'These are added to your database, so you may want to work with'
            ' a test database or delete them later.'))
        testnote.connect('clicked', self.gentest)
        export = Gtk.Button(_('Export'))
        export.set_tooltip_text(_('Export the results to a text file'))
        export.connect('clicked', self.export_results)
        bbox.add(search)
        bbox.add(testnote)
        bbox.add(export)
        bbox.add(save)
        bbox.add(close)
        self.tb = StyledTextEditor()
        self.tb.set_editable(False)
        self.tb.set_wrap_mode(Gtk.WrapMode.WORD)
        tbw = Gtk.ScrolledWindow()
        tbw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        tbw.add(self.tb)
        rvbox.pack_start(tbw, True, True, 0)
        self.ta = StyledTextEditor()
        self.ta.set_editable(True)
        self.ta.set_wrap_mode(Gtk.WrapMode.WORD)
        taw = Gtk.ScrolledWindow()
        taw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        taw.add(self.ta)
        tat=self.ta.get_toolbar()
        tat.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR)
        tatb=tat.get_nth_item(5)
        tat.remove(tatb)
        tatb=tat.get_nth_item(5)
        tat.remove(tatb)
        rvbox.pack_start(tat, False, False, 0)
        rvbox.pack_start(taw, True, True, 0)
        self.clear_models()
        vbox.show_all()
        window.add(vbox)
        window.set_size_request(800, 400)
        self.set_window(window, None, self.window_name)
        self.show()

        self.show_tabs()
        WarningDialog(self.window_name,
              _("Please back up your database before running this tool.\n\n"
              "Start the tool by pressing the 'Search' button, then review"
              " the results.\n"
              "When satisifed press the 'Save All' button to save your work.\n"
              "You may export a summary list of the notes that"
              " were found using the 'Export' button."),
                self.window)
Example #19
0
class ToDo(Gramplet):
    """
    Displays the To Do notes for an object.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.VBox(homogeneous=False)

        hbox = Gtk.HBox()
        self.left = SimpleButton(Gtk.STOCK_GO_BACK, self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton(Gtk.STOCK_GO_FORWARD, self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton(Gtk.STOCK_EDIT, self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton(Gtk.STOCK_NEW, self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def get_note_list(self, obj):
        """
        Get a list of To Do notes for the current object.
        """
        note_list = []
        for note_handle in obj.get_note_list():
            note = self.dbstate.db.get_note_from_handle(note_handle)
            if int(note.get_type()) == NoteType.TODO:
                note_list.append(note.get_handle())
        return note_list

    def get_notes(self, obj):
        """
        Display the To Do notes for the current object.
        """
        self.obj = obj
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = self.get_note_list(obj)
        self.page.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            self.edit.set_sensitive(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(
            _('%(current)d of %(total)d') % {
                'current': self.current + 1,
                'total': len(self.note_list)
            })

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        if obj is None:
            return False
        if self.get_note_list(obj):
            return True
        return False

    def edit_clicked(self, obj):
        """
        Edit current To Do note.
        """
        from gramps.gui.editors import EditNote
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except AttributeError:
            pass

    def new_clicked(self, obj):
        """
        Create a new To Do note.
        """
        from gramps.gui.editors import EditNote
        note = Note()
        note.set_type(NoteType.TODO)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note,
                     self.created)
        except AttributeError:
            pass
Example #20
0
class ToDoGramplet(Gramplet):
    """
    Displays all the To Do notes in the database.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton('gtk-edit', self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton('document-new', self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        self.title = Gtk.Label(halign=Gtk.Align.START)
        self.title.set_line_wrap(True)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(self.title, False, False, 4)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def main(self):
        self.get_notes()

    def get_note_list(self):
        """
        Get a list of all To Do notes.
        """
        all_notes = self.dbstate.db.get_note_handles()
        FilterClass = GenericFilterFactory('Note')
        filter = FilterClass()
        filter.add_rule(rules.note.HasType(["To Do"]))
        note_list = filter.apply(self.dbstate.db, all_notes)
        return note_list

    def get_notes(self):
        """
        Display all the To Do notes.
        """
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = self.get_note_list()
        self.page.set_text('')
        self.title.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            self.edit.set_sensitive(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.title.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        obj = [x for x in self.dbstate.db.find_backlink_handles(note_handle)]
        if obj:
            name, obj = navigation_label(self.dbstate.db, obj[0][0], obj[0][1])
            self.title.set_text(name)
        else:
            self.title.set_text(_("Unattached"))
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(
            _('%(current)d of %(total)d') % {
                'current': self.current + 1,
                'total': len(self.note_list)
            })

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self):
        """
        Return True if the gramplet has data, else return False.
        """
        if self.get_note_list():
            return True
        return False

    def edit_clicked(self, obj):
        """
        Edit current To Do note.
        """
        from gramps.gui.editors import EditNote
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except AttributeError:
            pass

    def new_clicked(self, obj):
        """
        Create a new To Do note.
        """
        from gramps.gui.editors import EditNote
        note = Note()
        note.set_type(NoteType.TODO)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except AttributeError:
            pass

    def update_has_data(self):
        self.set_has_data(self.get_has_data())

    def db_changed(self):
        self.dbstate.db.connect('note-add', self.update)
        self.dbstate.db.connect('note-delete', self.update)
        self.dbstate.db.connect('note-update', self.update)
Example #21
0
class ToDo(Gramplet):
    """
    Displays the To Do notes for an object.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        hbox = Gtk.Box()
        self.left = SimpleButton('go-previous', self.left_clicked)
        self.left.set_tooltip_text(_('Previous To Do note'))
        self.left.set_sensitive(False)
        hbox.pack_start(self.left, False, False, 0)
        self.right = SimpleButton('go-next', self.right_clicked)
        self.right.set_tooltip_text(_('Next To Do note'))
        self.right.set_sensitive(False)
        hbox.pack_start(self.right, False, False, 0)
        self.edit = SimpleButton('gtk-edit', self.edit_clicked)
        self.edit.set_tooltip_text(_('Edit the selected To Do note'))
        self.edit.set_sensitive(False)
        hbox.pack_start(self.edit, False, False, 0)
        self.new = SimpleButton('document-new', self.new_clicked)
        self.new.set_tooltip_text(_('Add a new To Do note'))
        hbox.pack_start(self.new, False, False, 0)
        self.page = Gtk.Label()
        hbox.pack_end(self.page, False, False, 10)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        top.pack_start(hbox, False, False, 0)
        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def get_note_list(self, obj):
        """
        Get a list of To Do notes for the current object.
        """
        note_list = []
        for note_handle in obj.get_note_list():
            note = self.dbstate.db.get_note_from_handle(note_handle)
            if int(note.get_type()) == NoteType.TODO:
                note_list.append(note.get_handle())
        return note_list

    def get_notes(self, obj):
        """
        Display the To Do notes for the current object.
        """
        self.obj = obj
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.note_list = self.get_note_list(obj)
        self.page.set_text('')
        if len(self.note_list) > 0:
            self.set_has_data(True)
            self.edit.set_sensitive(True)
            if len(self.note_list) > 1:
                self.right.set_sensitive(True)
            self.current = 0
            self.display_note()
        else:
            self.set_has_data(False)

    def clear_text(self):
        self.left.set_sensitive(False)
        self.right.set_sensitive(False)
        self.edit.set_sensitive(False)
        self.texteditor.set_text(StyledText())
        self.page.set_text('')
        self.current = 0

    def display_note(self):
        """
        Display the current note.
        """
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        self.texteditor.set_text(note.get_styledtext())
        self.page.set_text(_('%(current)d of %(total)d') %
                                    {'current': self.current + 1,
                                     'total': len(self.note_list)})

    def left_clicked(self, button):
        """
        Display the previous note.
        """
        if self.current > 0:
            self.current -= 1
            self.right.set_sensitive(True)
            if self.current == 0:
                self.left.set_sensitive(False)
            self.display_note()

    def right_clicked(self, button):
        """
        Display the next note.
        """
        if self.current < len(self.note_list) - 1:
            self.current += 1
            self.left.set_sensitive(True)
            if self.current == len(self.note_list) - 1:
                self.right.set_sensitive(False)
            self.display_note()

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        if obj is None:
            return False
        if self.get_note_list(obj):
            return True
        return False

    def edit_clicked(self, obj):
        """
        Edit current To Do note.
        """
        from gramps.gui.editors import EditNote
        note_handle = self.note_list[self.current]
        note = self.dbstate.db.get_note_from_handle(note_handle)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note)
        except AttributeError:
            pass

    def new_clicked(self, obj):
        """
        Create a new To Do note.
        """
        from gramps.gui.editors import EditNote
        note = Note()
        note.set_type(NoteType.TODO)
        try:
            EditNote(self.gui.dbstate, self.gui.uistate, [], note, self.created)
        except AttributeError:
            pass
Example #22
0
class WelcomeGramplet(Gramplet):
    """
    Displays a welcome note to the user.
    """
    def init(self):
        self.gui.WIDGET = self.build_gui()
        self.gui.get_container_widget().remove(self.gui.textview)
        self.gui.get_container_widget().add(self.gui.WIDGET)
        self.gui.WIDGET.show()

    def build_gui(self):
        """
        Build the GUI interface.
        """
        top = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
                                  Gtk.PolicyType.AUTOMATIC)
        self.texteditor = StyledTextEditor()
        self.texteditor.set_editable(False)
        self.texteditor.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.texteditor)

        self.display_text()

        top.pack_start(scrolledwindow, True, True, 0)
        top.show_all()
        return top

    def display_text(self):
        """
        Display the welcome text.
        """
        welcome = boldst(_('Intro')) + '\n\n'
        welcome += _(
            'Gramps is a software package designed for genealogical research.'
            ' Although similar to other genealogical programs, Gramps offers'
            ' some unique and powerful features.\n\n')
        welcome += linkst(_('Home Page'), URL_HOMEPAGE) + '\n\n'

        welcome += boldst(_('Who makes Gramps?')) + '\n\n' + _(
            'Gramps is created by genealogists for genealogists, organized in'
            ' the Gramps Project. '
            'Gramps is an Open Source Software package, which means you are'
            ' free to make copies and distribute it to anyone you like. It\'s'
            ' developed and maintained by a worldwide team of volunteers whose'
            ' goal is to make Gramps powerful, yet easy to use.\n\n')
        welcome += _(
            'There is an active community of users available on the mailing'
            ' lists and Discourse forum to share ideas and techniques.\n\n')
        welcome += linkst(_('Gramps online manual'), wiki(
            '', manual=True)) + '\n\n'
        welcome += linkst(
            _('Ask questions on gramps-users mailing list'),
            '%(gramps_home_url)scontact/' %
            {'gramps_home_url': URL_HOMEPAGE}) + '\n\n'
        welcome += linkst(_('Gramps Discourse Forum'),
                          'https://gramps.discourse.group/') + '\n\n'
        welcome += boldst(_('Getting Started')) + '\n\n' + _(
            'The first time Gramps is started all of the Views are blank. There'
            ' are very few menu options. A Family Tree is needed for any activity'
            ' to happen.\n\n'
            'To create a new Family Tree (sometimes called \'database\') select'
            ' "Family Trees" from the menu, pick "Manage Family Trees", press'
            ' "New" and name your Family Tree. "Load Family Tree" to make the'
            ' tree active and ready to accept data by entering your first'
            ' family, or importing a family tree. For more details, please'
            ' read the information at the links below.\n\n')
        welcome += linkst(_('Start with Genealogy and Gramps'),
                          wiki('Start_with_Genealogy')) + '\n\n'
        welcome += boldst(_('Enter your first Family')) + '\n\n' + _(
            'You will now want to start entering your first Family and that'
            ' starts with the first Person.\n\n'
            'Switch to the "People" view and from the menu clicking "Add" and then'
            ' clicking "Person" (or using the [+] icon) will bring up the window'
            ' to enter a person. Entering the basic information and saving the'
            ' record gives you a starting point. Select this Person\'s record and'
            ' now switch to the "Relationships" view.\n\n'
            'With this first person, all of the menu options and icon functions'
            ' have become available. Spend some time moving your mouse over the'
            ' icons. As your cursor passes over an icon, a message will appear'
            ' telling you the icon\'s function. The same is true for any of the'
            ' edit windows. Moving the mouse cursor over an item will tell you'
            ' what it will do.\n\n'
            'You can now create families by adding parents, a spouse and children.'
            ' Once started, you will be able to add Events to People and Families.'
            ' You can provide Sources and Citations to provide documentation for'
            ' your entries.\n\n'
            'As you start using Gramps, you will find that information can be'
            ' entered from all the various Views. There are multiple ways of'
            ' doing most activities in Gramps. The flexibility allows you to'
            ' choose which fits your work style.\n\n')
        welcome += linkst(
            _('Entering and editing data (brief)'),
            wiki('_-_Entering_and_editing_data:_brief', manual=True)) + '\n\n'
        welcome += boldst(_('Importing a Family Tree')) + '\n\n' + _(
            'To import a Family Tree from another program first create'
            ' a GEDCOM (or other data) file from the previous program.\n\n'
            'Once you have created a new Gramps database file, use the "Import"'
            ' option under the "Family Trees" menu to import the GEDCOM data.\n\n'
        )
        welcome += linkst(
            _('Import from another genealogy program'),
            wiki('Import_from_another_genealogy_program')) + '\n\n'
        welcome += boldst(_('Dashboard View')) + '\n\n' + _(
            'You are currently reading from the "Dashboard" view, where you can'
            ' add your own gramplets. You can also add gramplets to any view by'
            ' adding a sidebar and/or bottombar, and right-clicking to the'
            ' right of the tab.\n\n'
            'You can click the configuration icon in the toolbar to add'
            ' additional columns, while right-click on the background allows to'
            ' add gramplets. You can also drag the Properties button to'
            ' reposition the gramplet on this page, and detach the gramplet to'
            ' float above Gramps.')
        welcome += '\n\n'
        welcome += linkst(_('Gramps View Categories'),
                          wiki('_-_Categories', manual=True)) + '\n\n'
        welcome += boldst(_('Addons and "Gramplets"')) + '\n\n' + _(
            'There many Addons or "Gramplets" that are available to assist you'
            ' in data entry and visualizing your family tree. Many of these tools'
            ' are already available to you. Many more are available to download'
            ' and install.\n\n')
        welcome += linkst(_('Addons and "Gramplets"'),
                          wiki(WIKI_EXTRAPLUGINS)) + '\n\n'
        welcome += boldst(_('Example Database')) + '\n\n' + _(
            'Want to see Gramps in use. Create and Import the Example database.\n\n'
            'Create a new Family Tree as described above. Suggest that you name'
            ' the Family Tree “EXAMPLE”.\n\n'
            'Import the Gramps file example.gramps.\n\n'
            'Follow the instructions for the location of the file stored with'
            ' the Gramps program.\n\n')
        welcome += linkst(_('Example.gramps'), wiki('Example.gramps')) + '\n\n'

        self.texteditor.set_text(welcome)

    def get_has_data(self, obj):
        """
        Return True if the gramplet has data, else return False.
        """
        return True