update everything

This commit is contained in:
Michael Becker 2024-09-08 23:53:42 -04:00
parent 0ba989aa59
commit b39add339b
13 changed files with 2123 additions and 14 deletions

22
apply
View File

@ -1,20 +1,14 @@
#!/bin/sh #!/bin/bash
# Person Thumbnails in Family Editor DIRS=$(ls -d */)
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editfamily.py person-view-age-calculator/gramps/gui/editors/editfamily.py.patch
patch /usr/lib/python3/dist-packages/gramps/gui/glade/editfamily.glade person-view-age-calculator/gramps/gui/glade/editfamily.glade.patch
# Person View Age Calculator for d in $DIRS; do
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editperson.py person-view-age-calculator/gramps/gui/editors/editperson.py.patch
patch /usr/lib/python3/dist-packages/gramps/gui/glade/editperson.glade person-view-age-calculator/gramps/gui/glade/editperson.glade.patch
# Hyperlink Person Associations pushd $d
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editpersonref.py hyperlink-person-associations/gramps/gu/editors/editpersonref.py.patch
# Enhanced TODO Gramplet ./apply
patch /usr/lib/python3/dist-packages/gramps/plugins/gramplet/todogramplet.py enhanced-todo-gramplet/gramps/plugins/gramplet/todogramplet.py.patch
# GeoClose, GeoFamClose popd
patch /usr/lib/python3/dist-packages/gramps/plugins/view/geoclose.py geo-view-select-active-person/gramps/plugins/view/geoclose.py.patch
patch /usr/lib/python3/dist-packages/gramps/plugins/view/geofamclose.py geo-view-select-active-person/gramps/plugins/view/geofamclose.py.patch done

4
editor-tabs/apply Executable file
View File

@ -0,0 +1,4 @@
patch /usr/lib/python3/dist-packages/gramps/gen/plug/_pluginreg.py gramps/gen/plug/_pluginreg.py.patch
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editprimary.py gramps/gui/editors/editprimary.py.patch
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editsecondary.py gramps/gui/editors/editsecondary.py.patch

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
75a76,78
>
> EDITORTAB = 14
>
77c80
< MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR, DATABASE, RULE]
---
> MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR, DATABASE, RULE, EDITORTAB]
92c95,96
< RULE: _('Rule')
---
> RULE: _('Rule'),
> EDITORTAB: _('Editor Tab')
454a459,461
> #EDITORTAB attr
> self._tabclass = None
> self._tabviews = None
1021a1029,1048
> #EDITORTAB attr
> def _set_tabclass(self, data):
> if self._ptype != EDITORTAB:
> raise ValueError('tabclass may only be set for EDITORTAB plugins')
> self._tabclass = data
>
> def _get_tabclass(self):
> return self._tabclass
>
> def _set_tabviews(self, data):
> if self._ptype != EDITORTAB:
> raise ValueError('tabviews may only be set for EDITORTAB plugins')
> self._tabviews = data
>
> def _get_tabviews(self):
> return self._tabviews
>
> tabclass = property(_get_tabclass, _set_tabclass)
> tabviews = property(_get_tabviews, _set_tabviews)
>
1074a1102
> 'EDITORTAB': EDITORTAB,
1390a1419,1424
>
> def editortab_plugins(self):
> """
> Return a list of :class:`PluginData` that are of type EDITORTAB
> """
> return self.type_plugins(EDITORTAB)

View File

@ -0,0 +1,375 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# 2009 Gary Burton
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import abc
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
from gi.repository.Gio import SimpleActionGroup
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from ..managedwindow import ManagedWindow
from gramps.gen.datehandler import displayer, parser
from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.config import config
from ..utils import is_right_click
from ..display import display_help
from ..dialog import SaveDialog
from gramps.gen.lib import PrimaryObject
from ..dbguielement import DbGUIElement
from ..uimanager import ActionGroup
class EditPrimary(ManagedWindow, DbGUIElement, metaclass=abc.ABCMeta):
QR_CATEGORY = -1
def __init__(self, state, uistate, track, obj, get_from_handle,
get_from_gramps_id, callback=None):
"""
Create an edit window.
Associate a person with the window.
"""
self.dp = parser
self.dd = displayer
self.name_displayer = name_displayer
self.obj = obj
self.dbstate = state
self.uistate = uistate
self.db = state.db
self.callback = callback
self.ok_button = None
self.get_from_handle = get_from_handle
self.get_from_gramps_id = get_from_gramps_id
self.contexteventbox = None
self.__tabs = []
self.action_group = None
ManagedWindow.__init__(self, uistate, track, obj)
DbGUIElement.__init__(self, self.db)
self.original = None
if self.obj.handle:
self.original = self.get_from_handle(self.obj.handle)
self._local_init()
# self.set_size() is called by self._local_init()'s self.setup_configs
self._create_tabbed_pages()
self._setup_fields()
self._connect_signals()
#if the database is changed, all info shown is invalid and the window
# should close
self.dbstate_connect_key = self.dbstate.connect('database-changed',
self._do_close)
self.show()
self._post_init()
def _local_init(self):
"""
Derived class should do any pre-window initalization in this task.
"""
pass
def _post_init(self):
"""
Derived class should do any post-window initalization in this task.
"""
pass
def _setup_fields(self):
pass
def _create_tabbed_pages(self):
pass
def _connect_signals(self):
pass
def build_window_key(self, obj):
if obj and obj.get_handle():
return obj.get_handle()
else:
return id(self)
def _setup_notebook_tabs(self, notebook):
for child in notebook.get_children():
label = notebook.get_tab_label(child)
page_no = notebook.page_num(child)
label.drag_dest_set(0, [], 0)
label.connect('drag_motion',
self._switch_page_on_dnd,
notebook,
page_no)
child.set_parent_notebook(notebook)
notebook.connect('key-press-event', self.key_pressed, notebook)
def key_pressed(self, obj, event, notebook):
"""
Handles the key being pressed on the notebook, pass to key press of
current page.
"""
pag = notebook.get_current_page()
if not pag == -1:
notebook.get_nth_page(pag).key_pressed(obj, event)
def _switch_page_on_dnd(self, widget, context, x, y, time, notebook,
page_no):
if notebook.get_current_page() != page_no:
notebook.set_current_page(page_no)
def _add_tab(self, notebook, page):
self.__tabs.append(page)
notebook.insert_page(page, page.get_tab_widget(), -1)
page.label.set_use_underline(True)
return page
def _cleanup_on_exit(self):
"""Unset all things that can block garbage collection.
Finalize rest
"""
for tab in self.__tabs:
if hasattr(tab, '_cleanup_on_exit'):
tab._cleanup_on_exit()
self.__tabs = None
def object_is_empty(self):
return self.obj.serialize()[1:] == self.empty_object().serialize()[1:]
def define_ok_button(self, button, function):
self.ok_button = button
button.connect('clicked', function)
button.set_sensitive(not self.db.readonly)
def define_cancel_button(self, button):
button.connect('clicked', self.close)
def define_help_button(self, button, webpage='', section=''):
button.connect('clicked', lambda x: display_help(webpage,
section))
def _do_close(self, *obj):
self._cleanup_db_connects()
self.dbstate.disconnect(self.dbstate_connect_key)
self._cleanup_connects()
self._cleanup_on_exit()
if self.action_group:
self.uistate.uimanager.remove_action_group(self.action_group)
self.get_from_handle = None
self.get_from_gramps_id = None
ManagedWindow.close(self)
self.dbstate = None
self.uistate = None
self.db = None
def _cleanup_db_connects(self):
"""
All connects that happened to signals of the db must be removed on
closed. This implies two things:
1. The connects on the main view must be disconnected
2. Connects done in subelements must be disconnected
"""
#cleanup callbackmanager of this editor
self._cleanup_callbacks()
for tab in self.__tabs:
if hasattr(tab, 'callman'):
tab._cleanup_callbacks()
def _cleanup_connects(self):
"""
Connects to interface elements to things outside the element should be
removed before destroying the interface
"""
self._cleanup_local_connects()
for tab in [tab for tab in self.__tabs if hasattr(tab, '_cleanup_local_connects')]:
tab._cleanup_local_connects()
def _cleanup_local_connects(self):
"""
Connects to interface elements to things outside the element should be
removed before destroying the interface. This methods cleans connects
of the main interface, not of the displaytabs.
"""
pass
def check_for_close(self, handles):
"""
Callback method for delete signals.
If there is a delete signal of the primary object we are editing, the
editor (and all child windows spawned) should be closed
"""
if self.obj.get_handle() in handles:
self._do_close()
def close(self, *obj):
"""If the data has changed, give the user a chance to cancel
the close window"""
if not config.get('interface.dont-ask') and self.data_has_changed():
SaveDialog(
_('Save Changes?'),
_('If you close without saving, the changes you '
'have made will be lost'),
self._do_close,
self.save,
parent=self.window)
return True
else:
self._do_close()
return False
@abc.abstractmethod
def empty_object(self):
""" empty_object should be overridden in child class """
def data_has_changed(self):
if self.db.readonly:
return False
if self.original:
cmp_obj = self.original
else:
cmp_obj = self.empty_object()
return cmp_obj.serialize()[1:] != self.obj.serialize()[1:]
def save(self, *obj):
""" Save changes and close. Inheriting classes must implement this
"""
self.close()
def set_contexteventbox(self, eventbox):
"""Set the contextbox that grabs button presses if not grabbed
by overlying widgets.
"""
self.contexteventbox = eventbox
self.contexteventbox.connect('button-press-event',
self._contextmenu_button_press)
def _contextmenu_button_press(self, obj, event):
"""
Button press event that is caught when a mousebutton has been
pressed while on contexteventbox
It opens a context menu with possible actions
"""
if is_right_click(event):
if self.obj.get_handle() == 0 :
return False
#build the possible popup menu
menu_model = self._build_popup_ui()
if not menu_model:
return False
#set or unset sensitivity in popup
self._post_build_popup_ui()
menu = Gtk.Menu.new_from_model(menu_model)
menu.attach_to_widget(obj, None)
menu.show_all()
if Gtk.MINOR_VERSION < 22:
# ToDo The following is reported to work poorly with Wayland
menu.popup(None, None, None, None,
event.button, event.time)
else:
menu.popup_at_pointer(event)
return True
return False
def _build_popup_ui(self):
"""
Create actions and ui of context menu
If you don't need a popup, override this and return None
"""
from ..plug.quick import create_quickreport_menu
prefix = str(id(self))
#get custom ui and actions
(ui_top, actions) = self._top_contextmenu(prefix)
#see which quick reports are available now:
ui_qr = ''
if self.QR_CATEGORY > -1 :
(ui_qr, reportactions) = create_quickreport_menu(
self.QR_CATEGORY, self.dbstate, self.uistate,
self.obj, prefix, track=self.track)
actions.extend(reportactions)
popupui = '''<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="Popup">''' + ui_top + '''
<section>
''' + ui_qr + '''
</section>
</menu>
</interface>'''
builder = Gtk.Builder.new_from_string(popupui, -1)
self.action_group = ActionGroup('EditPopup' + prefix, actions,
prefix)
act_grp = SimpleActionGroup()
self.window.insert_action_group(prefix, act_grp)
self.window.set_application(self.uistate.uimanager.app)
self.uistate.uimanager.insert_action_group(self.action_group, act_grp)
return builder.get_object('Popup')
def _top_contextmenu(self, prefix):
"""
Derived class can create a ui with menuitems and corresponding list of
actiongroups
"""
return "", []
def _post_build_popup_ui(self):
"""
Derived class should do extra actions here on the menu
"""
pass
def _uses_duplicate_id(self):
"""
Check whether a changed or added Gramps ID already exists in the DB.
Return True if a duplicate Gramps ID has been detected.
"""
idval = self.obj.get_gramps_id()
existing = self.get_from_gramps_id(idval)
if existing:
if existing.get_handle() == self.obj.get_handle():
return (False, 0)
else:
return (True, idval)
else:
return (False, 0)

View File

@ -0,0 +1,56 @@
54a55
> from gramps.gui.editors.displaytabs.grampstab import GrampsTab
127a129,153
>
> def _create_plugin_tab(self, plugin):
> from gramps.gui.pluginmanager import GuiPluginManager
> pmgr = GuiPluginManager.get_instance()
> mod = pmgr.load_plugin(plugin)
> if not mod is None:
>
> done = False
> tab_views = plugin.tabviews
> if tab_views is None:
> done = True
> else:
> for tab_view in tab_views:
> if tab_view == 'EditPrimary' or tab_view == type(self).__name__:
> done = True
> break
>
> if done:
>
> tab_class = getattr(mod, plugin.tabclass)
> tab = tab_class(self.dbstate, self.uistate, self.track)
>
> return tab
>
> return None
129a156,168
> # load custom tabs from EDITORTAB plugins
> from gramps.gui.pluginmanager import PluginRegister
> plugs = PluginRegister.get_instance().editortab_plugins()
> for plug in plugs:
> print("found plugin " + plug.name)
> tab = self._create_plugin_tab(plug)
> if tab is not None:
> tab.obj = self.obj
> if hasattr(tab, 'load'):
> tab.load()
>
> self._add_tab(notebook, tab)
>
172a212,218
>
> def _ok_button_click(self, widget):
> for tab in self.__tabs:
> if hasattr(tab, 'save'):
> tab.save()
>
> self.ok_button_callback(widget)
176c222,224
< button.connect('clicked', function)
---
> self.ok_button_callback = function
>
> button.connect('clicked', self._ok_button_click)

View File

@ -0,0 +1,179 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# 2009 Gary Burton
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from ..managedwindow import ManagedWindow
from ..display import display_help
from gramps.gen.config import config
from ..dbguielement import DbGUIElement
class EditSecondary(ManagedWindow, DbGUIElement):
def __init__(self, state, uistate, track, obj, callback=None):
"""Create an edit window. Associates a person with the window."""
self.obj = obj
self.old_obj = obj.serialize()
self.dbstate = state
self.uistate = uistate
self.db = state.db
self.callback = callback
self.__tabs = []
ManagedWindow.__init__(self, uistate, track, obj)
DbGUIElement.__init__(self, self.db)
self._local_init()
self._set_size()
self._create_tabbed_pages()
self._setup_fields()
self._connect_signals()
self.show()
self._post_init()
def _local_init(self):
"""
Derived class should do any pre-window initalization in this task.
"""
pass
def _post_init(self):
"""
Derived class should do any post-window initalization in this task.
"""
pass
def _connect_signals(self):
pass
def _setup_fields(self):
pass
def _create_tabbed_pages(self):
pass
def build_window_key(self, obj):
return id(obj)
def _setup_notebook_tabs(self, notebook):
for child in notebook.get_children():
label = notebook.get_tab_label(child)
page_no = notebook.page_num(child)
label.drag_dest_set(0, [], 0)
label.connect('drag_motion',
self._switch_page_on_dnd,
notebook,
page_no)
child.set_parent_notebook(notebook)
notebook.connect('key-press-event', self.key_pressed, notebook)
def key_pressed(self, obj, event, notebook):
"""
Handles the key being pressed on the notebook, pass to key press of
current page.
"""
pag = notebook.get_current_page()
if not pag == -1:
notebook.get_nth_page(pag).key_pressed(obj, event)
def _switch_page_on_dnd(self, widget, context, x, y, time, notebook, page_no):
if notebook.get_current_page() != page_no:
notebook.set_current_page(page_no)
def _add_tab(self, notebook,page):
self.__tabs.append(page)
notebook.insert_page(page, page.get_tab_widget(), -1)
page.label.set_use_underline(True)
return page
def _cleanup_on_exit(self):
"""Unset all things that can block garbage collection.
Finalize rest
"""
for tab in self.__tabs:
if hasattr(tab, '_cleanup_on_exit'):
tab._cleanup_on_exit()
self.__tabs = None
self.dbstate = None
self.uistate = None
self.obj = None
self.db = None
self.callback = None
self.callman.database = None
self.callman = None
def define_ok_button(self,button,function):
button.connect('clicked',function)
button.set_sensitive(not self.db.readonly)
def define_cancel_button(self,button):
button.connect('clicked', self.canceledits)
def define_help_button(self, button, webpage='', section=''):
button.connect('clicked', lambda x: display_help(webpage,
section))
def canceledits(self, *obj):
"""
Undo the edits that happened on this secondary object
"""
self.obj.unserialize(self.old_obj)
self.close(obj)
def close(self, *obj):
self._cleanup_db_connects()
self._cleanup_connects()
ManagedWindow.close(self)
self._cleanup_on_exit()
def _cleanup_db_connects(self):
"""
All connects that happened to signals of the db must be removed on
closed. This implies two things:
1. The connects on the main view must be disconnected
2. Connects done in subelements must be disconnected
"""
#cleanup callbackmanager of this editor
self._cleanup_callbacks()
for tab in [tab for tab in self.__tabs if hasattr(tab, 'callman')]:
tab._cleanup_callbacks()
def _cleanup_connects(self):
"""
Connects to interface elements to things outside the element should be
removed before destroying the interface
"""
self._cleanup_local_connects()
for tab in [tab for tab in self.__tabs if hasattr(tab, '_cleanup_local_connects')]:
tab._cleanup_local_connects()
def _cleanup_local_connects(self):
"""
Connects to interface elements to things outside the element should be
removed before destroying the interface. This methods cleans connects
of the main interface, not of the displaytabs.
"""
pass

View File

@ -0,0 +1,40 @@
79a80,104
>
> def _create_plugin_tab(self, plugin):
> from gramps.gui.pluginmanager import GuiPluginManager
> pmgr = GuiPluginManager.get_instance()
> mod = pmgr.load_plugin(plugin)
> if not mod is None:
>
> done = False
> tab_views = plugin.tabviews
> if tab_views is None:
> done = True
> else:
> for tab_view in tab_views:
> if tab_view == 'EditSecondary' or tab_view == type(self).__name__:
> done = True
> break
>
> if done:
>
> tab_class = getattr(mod, plugin.tabclass)
> tab = tab_class(self.dbstate, self.uistate, self.track)
>
> return tab
>
> return None
81a107,115
> # load custom tabs from EDITORTAB plugins
> from gramps.gui.pluginmanager import PluginRegister
> plugs = PluginRegister.get_instance().editortab_plugins()
> for plug in plugs:
> print("found plugin " + plug.name)
> tab = self._create_plugin_tab(plug)
> if tab is not None:
> tab.obj = self.obj
> if hasattr(tab, 'load'):
> tab.load()
>
> self._add_tab(notebook, tab)
>

3
enhanced-todo-gramplet/apply Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
patch /usr/lib/python3/dist-packages/gramps/plugins/gramplet/todogramplet.py gramps/plugins/gramplet/todogramplet.py.patch

View File

@ -0,0 +1,4 @@
#!/bin/sh
patch /usr/lib/python3/dist-packages/gramps/plugins/view/geoclose.py gramps/plugins/view/geoclose.py.patch
patch /usr/lib/python3/dist-packages/gramps/plugins/view/geofamclose.py gramps/plugins/view/geofamclose.py.patch

View File

@ -0,0 +1,3 @@
#!/bin/sh
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editpersonref.py gramps/gui/editors/editpersonref.py.patch

View File

@ -0,0 +1,4 @@
#!/bin/sh
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editfamily.py gramps/gui/editors/editfamily.py.patch
patch /usr/lib/python3/dist-packages/gramps/gui/glade/editfamily.glade gramps/gui/glade/editfamily.glade.patch

View File

@ -0,0 +1,4 @@
#!/bin/sh
patch /usr/lib/python3/dist-packages/gramps/gui/editors/editperson.py gramps/gui/editors/editperson.py.patch
patch /usr/lib/python3/dist-packages/gramps/gui/glade/editperson.glade gramps/gui/glade/editperson.glade.patch