Skip to content

Commit b434f90

Browse files
committed
Add FormActions dialog.
This dialog present a list of possible actions to the user. The user selects one or more actions to be run when OK is clicked.
1 parent 6e6eace commit b434f90

File tree

4 files changed

+244
-1
lines changed

4 files changed

+244
-1
lines changed

Form/actionbase.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#
2+
# Gramps - a GTK+/GNOME based genealogy program
3+
#
4+
# Copyright (C) 2019 Steve Youngs
5+
#
6+
# This program is free software; you can redistribute it and/or modify
7+
# it under the terms of the GNU General Public License as published by
8+
# the Free Software Foundation; either version 2 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# This program is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19+
#
20+
21+
"""
22+
ActionBase definitions.
23+
"""
24+
25+
from gramps.gen.display.name import displayer as name_displayer
26+
from gramps.gen.lib import (Event, EventType, EventRef, EventRoleType,
27+
Person)
28+
29+
class ActionBase():
30+
"""
31+
A class to read form definitions from an XML file.
32+
"""
33+
def __init__(self):
34+
pass

Form/form.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Gramps - a GTK+/GNOME based genealogy program
33
#
44
# Copyright (C) 2009-2015 Nick Hall
5+
# Copyright (C) 2019 Steve Youngs
56
#
67
# This program is free software; you can redistribute it and/or modify
78
# it under the terms of the GNU General Public License as published by
@@ -82,6 +83,11 @@
8283
CONFIG.register('interface.form-horiz-position', -1)
8384
CONFIG.register('interface.form-vert-position', -1)
8485

86+
CONFIG.register('interface.form-actions-width', 600)
87+
CONFIG.register('interface.form-actions-height', 400)
88+
CONFIG.register('interface.form-actions-horiz-position', -1)
89+
CONFIG.register('interface.form-actions-vert-position', -1)
90+
8591
CONFIG.init()
8692

8793
#------------------------------------------------------------------------

Form/formactions.py

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#
2+
# Gramps - a GTK+/GNOME based genealogy program
3+
#
4+
# Copyright (C) 2019 Steve Youngs
5+
#
6+
# This program is free software; you can redistribute it and/or modify
7+
# it under the terms of the GNU General Public License as published by
8+
# the Free Software Foundation; either version 2 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# This program is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19+
#
20+
21+
"""
22+
Form action chooser
23+
"""
24+
import importlib.util
25+
import inspect
26+
import os
27+
import gobject
28+
29+
#------------------------------------------------------------------------
30+
#
31+
# GTK modules
32+
#
33+
#------------------------------------------------------------------------
34+
from gi.repository import Gtk, GObject
35+
36+
#------------------------------------------------------------------------
37+
#
38+
# Gramps modules
39+
#
40+
#------------------------------------------------------------------------
41+
from gramps.gui.managedwindow import ManagedWindow
42+
from gramps.gen.config import config
43+
from gramps.gen.datehandler import get_date
44+
from gramps.gen.db import DbTxn
45+
46+
#------------------------------------------------------------------------
47+
#
48+
# Gramplet modules
49+
#
50+
#------------------------------------------------------------------------
51+
from editform import find_form_event
52+
from form import (get_form_id, get_form_type)
53+
from actionbase import ActionBase
54+
55+
#------------------------------------------------------------------------
56+
#
57+
# Internationalisation
58+
#
59+
#------------------------------------------------------------------------
60+
from gramps.gen.const import GRAMPS_LOCALE as glocale
61+
try:
62+
_trans = glocale.get_addon_translator(__file__)
63+
except ValueError:
64+
_trans = glocale.translation
65+
_ = _trans.gettext
66+
67+
#------------------------------------------------------------------------
68+
#
69+
# FormActions class
70+
#
71+
#------------------------------------------------------------------------
72+
class FormActions(object):
73+
"""
74+
Form Action selector.
75+
"""
76+
77+
def __init__(self, dbstate, uistate, track, citation):
78+
self.dbstate = dbstate
79+
self.uistate = uistate
80+
self.track = track
81+
self.db = dbstate.db
82+
self.citation = citation
83+
source_handle = self.citation.get_reference_handle()
84+
self.source = self.db.get_source_from_handle(source_handle)
85+
self.form_id = get_form_id(self.source)
86+
87+
self.actions_module = None
88+
# for security reasons provide the full path to the actions_module .py file
89+
full_path = os.path.join(os.path.dirname(__file__), f'{self.form_id}.py')
90+
if os.path.exists(full_path):
91+
spec = importlib.util.spec_from_file_location('form.action.', full_path)
92+
self.actions_module = importlib.util.module_from_spec(spec)
93+
spec.loader.exec_module(self.actions_module)
94+
95+
self.event = find_form_event(self.db, self.citation)
96+
97+
self.top = self._create_dialog(self.get_dialog_title())
98+
99+
self._config = config.get_manager('form')
100+
width = self._config.get('interface.form-actions-width')
101+
height = self._config.get('interface.form-actions-height')
102+
self.top.resize(width, height)
103+
horiz_position = self._config.get('interface.form-actions-horiz-position')
104+
vert_position = self._config.get('interface.form-actions-vert-position')
105+
if horiz_position != -1:
106+
self.top.move(horiz_position, vert_position)
107+
108+
def _create_dialog(self, title):
109+
"""
110+
Create and display the GUI components of the action selector.
111+
"""
112+
top = Gtk.Dialog(title)
113+
top.set_modal(True)
114+
top.set_transient_for(self.uistate.window)
115+
top.vbox.set_spacing(5)
116+
117+
box = Gtk.Box()
118+
top.vbox.pack_start(box, True, True, 5)
119+
120+
self.model = Gtk.TreeStore(str, str, GObject.TYPE_PYOBJECT)
121+
self.tree = Gtk.TreeView(model=self.model)
122+
renderer = Gtk.CellRendererText()
123+
column1 = Gtk.TreeViewColumn(_("Action"), renderer, text=0)
124+
column1.set_sort_column_id(1)
125+
column2 = Gtk.TreeViewColumn(_("Detail"), renderer, text=1)
126+
self.tree.append_column(column1)
127+
self.tree.append_column(column2)
128+
129+
self.tree.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
130+
131+
slist = Gtk.ScrolledWindow()
132+
slist.add(self.tree)
133+
slist.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
134+
box.pack_start(slist, True, True, 5)
135+
136+
top.add_button(_('_Cancel'), Gtk.ResponseType.CANCEL)
137+
top.add_button(_('_OK'), Gtk.ResponseType.OK)
138+
top.set_default_response(Gtk.ResponseType.OK)
139+
140+
top.show_all()
141+
142+
return top
143+
144+
def _populate_model(self):
145+
form_id = get_form_id(self.source)
146+
if self.actions_module:
147+
# get all classes defined in actions_module which are a subclass of ActionBase (but exclude ActionBase itself)
148+
action_classes = inspect.getmembers(self.actions_module, lambda obj: inspect.isclass(obj) and obj is not ActionBase and issubclass(obj, ActionBase))
149+
150+
for action_class in action_classes:
151+
action = (action_class[1])()
152+
action.populate_model(self.db, self.citation, self.event, self.model)
153+
154+
def run(self):
155+
"""
156+
Run the dialog and return the result.
157+
"""
158+
self._populate_model()
159+
self.tree.expand_all()
160+
while True:
161+
response = self.top.run()
162+
if response == Gtk.ResponseType.HELP:
163+
display_help(webpage='Form_Addons')
164+
else:
165+
break
166+
167+
(width, height) = self.top.get_size()
168+
self._config.set('interface.form-actions-width', width)
169+
self._config.set('interface.form-actions-height', height)
170+
(root_x, root_y) = self.top.get_position()
171+
self._config.set('interface.form-actions-horiz-position', root_x)
172+
self._config.set('interface.form-actions-vert-position', root_y)
173+
self._config.save()
174+
175+
# run the selected actions
176+
with DbTxn("FormActions", self.db) as trans:
177+
(model, pathlist) = self.tree.get_selection().get_selected_rows()
178+
for path in pathlist :
179+
tree_iter = model.get_iter(path)
180+
181+
command = model.get_value(tree_iter, 2)
182+
if command:
183+
(command)(self.db, trans)
184+
185+
self.top.destroy()
186+
187+
return None
188+
189+
def help_clicked(self, obj):
190+
"""
191+
Display the relevant portion of Gramps manual
192+
"""
193+
display_help(webpage='Form_Addons')
194+
195+
def get_dialog_title(self):
196+
"""
197+
Get the title of the dialog.
198+
"""
199+
dialog_title = _('Form: %s: %s') % (self.source.get_title(), self.citation.get_page())
200+
201+
return dialog_title

Form/formgramplet.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from gramps.gen.errors import WindowActiveError
4646
from gramps.gen.lib import Citation
4747
from editform import EditForm
48+
from formactions import FormActions
4849
from selectform import SelectForm
4950
from form import get_form_citation
5051

@@ -183,7 +184,8 @@ def __form_actions(self, widget, selection):
183184
if iter_:
184185
citation = model.get_value(iter_, 0)
185186
try:
186-
pass
187+
actions = FormActions(self.gui.dbstate, self.gui.uistate, [], citation)
188+
actions.run()
187189
except WindowActiveError:
188190
pass
189191

0 commit comments

Comments
 (0)