Adding Custom Actions to Form Gramplet

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Adding Custom Actions to Form Gramplet

Steve Youngs
Hi,

I'm interested in extending the Form gramplet to add support for form
specific "actions". However since I'm new to Gramps I thought I'd seek
some input from those more knowlegable before I "do the wrong thing" or
implement it in a poor way!

Intended use case
-----------------

Having populated a new instance of a form, the data can often be used
for additional purposes such as creating additional events, creating
Families, adding children etc. etc.

For example if you enter details of a person in the UK1851 form, you
could use the 'Age' value to create a Birth event, with the birth event
date set to the form date minus the 'Age' and the source citation set to
the census event. If a Birth event already exists you may just want to
add an additional source citation (having checked the birth date agrees
to some tolerance)

You could use the 'Occupation' value to create an Occupation event,
again with the event date and source citation set.

Possible Implementation
-----------------------

Form defintions are generic, so the implementation of actions must be
equally flexible.

The user may want to run none, some or all actions, either when the form
is first created, or at a later date. The user may want to run an action
for all rows in a Family or Multi type section of a form.

Extend the form XML to have one or more action tags per column

            <column>
                 <_attribute>Age</_attribute>
                 <size>5</size>
                 <action title='Create Birth event' command='#python
code to implement action'/>
             </column>

Each action element defines a title attribute, used to dynamically
extend the popup menu shown for the relevant Gtk.Entry control and a
command attribute, containing Python code which will be run via exec()
when the action is activated.

I've experimented to the point where I have a dynamic popup showing and,
when activated, the "action" command is setting the text in the
Gtk.Entry control, of a forms multi section EntryGrid, to a static
string. Here's the full action string:

     <action title='Create Birth event'
command='entrygrid.widgets[row][column].set_text("set from XML")'/>

This gives me some confidence that the overall goal is achievable.

Questions
---------

1. Is an extension like this generally useful to users other than myself?

2. @Nick Hall, since you created the Form addon, is an enhancement in
this direction something that, in principle, you could accept?

3. I need to decide which globals to pass into exec(). I'm currently
thinking about passing in the EditForm instance.
     a. the command implementor will probably also want to know which
section and column was clicked. For some sections the row number is also
required.
     b. I'm nervous about binding the command implementation to the UI
class (EditForm) implementation.
     c. Is there a good pattern to follow to make the EditForm available
at the point where the popup 'activate' event is handled? I've currently
implement the activate callback in EntityGrid

Sorry for such a long post!

Kind regards

Steve





_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel
Reply | Threaded
Open this post in threaded view
|

Re: Adding Custom Actions to Form Gramplet

GRAMPS - Dev mailing list
On 24/12/2019 18:10, Steve Youngs wrote:
> Questions
> ---------
>
> 1. Is an extension like this generally useful to users other than myself?


Yes.


>
> 2. @Nick Hall, since you created the Form addon, is an enhancement in
> this direction something that, in principle, you could accept?


Yes.


>
> 3. I need to decide which globals to pass into exec(). I'm currently
> thinking about passing in the EditForm instance.
>     a. the command implementor will probably also want to know which
> section and column was clicked. For some sections the row number is
> also required.
>     b. I'm nervous about binding the command implementation to the UI
> class (EditForm) implementation.
>     c. Is there a good pattern to follow to make the EditForm
> available at the point where the popup 'activate' event is handled?
> I've currently implement the activate callback in EntityGrid


Creating objects from a transcription is a good idea that will be
popular, however I don't like your implementation.

In general, the use of "exec()" should be avoided.  Including code in
the form definition is not a good idea.  What we can do is add an extra
field for the data type.  The attribute was originally intended to serve
this purpose, but not all the form definitions follow the same naming
conventions.

I'd also like to see a separation between the transcription entry and
object creation.  Perhaps after the transcription has been entered the
user could select the objects to be created from a list?


Nick.




_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel
Reply | Threaded
Open this post in threaded view
|

Re: Adding Custom Actions to Form Gramplet

Steve Youngs
On 27/12/2019 18:33, Nick Hall via Gramps-devel wrote:
> On 24/12/2019 18:10, Steve Youngs wrote:
>
[snip]

>>
>> 3. I need to decide which globals to pass into exec(). I'm currently
>> thinking about passing in the EditForm instance.
>>     a. the command implementor will probably also want to know which
>> section and column was clicked. For some sections the row number is
>> also required.
>>     b. I'm nervous about binding the command implementation to the UI
>> class (EditForm) implementation.
>>     c. Is there a good pattern to follow to make the EditForm
>> available at the point where the popup 'activate' event is handled?
>> I've currently implement the activate callback in EntityGrid
>
>
> Creating objects from a transcription is a good idea that will be
> popular, however I don't like your implementation.
>
> In general, the use of "exec()" should be avoided.  Including code in
> the form definition is not a good idea.  What we can do is add an
> extra field for the data type.  The attribute was originally intended
> to serve this purpose, but not all the form definitions follow the
> same naming conventions.
>
> I'd also like to see a separation between the transcription entry and
> object creation.  Perhaps after the transcription has been entered the
> user could select the objects to be created from a list?
>
I can see your approach would solve some of the challenges I envisaged
with my current design. Good. But it probably requires some further
discussion to come to an agreed design (that I can understand!)

Revised Design

- Add a new "actions" button to the FormGramplet window. Located beside
the current New and Edit buttons.

- When the user selects a (single) form and clicks the "actions" button,
display the form dialog itself (using the existing EditForm code,
possibly in read-only mode) and a new "actions" dialog with a list
containing two columns: column 1 a list of actions, column 2 a list of
"things" to apply the action to. Consider a hyopthetical form for a
family of four (two parents, two children, name, relation to head of
household, age in years, occupation. Only one adult has an occupation given)

Action               Apply to
Add alternate name   John Smith
                      Jane Smith
                      Fred Smith
                      Sarah Smith
Add name citation    John Smith
                      Jane Smith
                      Fred Smith
                      Sarah Smith
Add Birth event John Smith
                      Jane Smith
                      Fred Smith
                      Sarah Smith
Add Occupation event John Smith
Add Residence event  John Smith, Jane Smith, Fred Smith, Sarah Smith
Add Family John Smith, Jane Smith, Fred Smith, Sarah Smith
Add to Family        Jane Smith
                      Fred Smith
                      Jane Smith

Cancel and OK buttons.

The user selects zero, one or more rows from the "Apply to" column. When
they click OK, the selected "actions" are performed.

Note how the "Apply to" only shows relevant entries e.g. you cannot add
an Occupation event for Jane Smith because she has no occupation
specified on the source form.

Why show the form dialog as well? Personally I would like to see the
form data when selecting which actions to apply.

Concern: The list of actions can potentially get very long for multi
column forms with 8/10/12 people. Think about UI layouts. Needs a good
UX; quick and efficient.

- The list of "actions" is read from a python module having the same
name as the form id (e.g. UK1841.py) and stored in the same directory as
the form XML file. The module is dynamically loaded. In the module,
there is one class per action. At runtime we can inspect the module to
get a list of the classes provided. Each class would provide a method to
populate the "actions" dialog and a method to "do" the action. I need to
think about what arguments to pass into these methods. Form specific
logic can be implemented in each module, and a base module of common
functionality can be provided.

Why use dynamic modules? I want to permit "actions" for custom forms. It
should not be necessary to revise the Gramplet to add or modify an
"action".

- Some actions may choose to display a dialog to allow the user to
manually adjust and confirm the action. e.g. Add Family may default to
including all household members from a census form. e.g. Add to Family
in this example may show a list of all Families including John Smith

So far, I've not needed the extra data type field you mentioned adding
to the the form XML. What have I missed?

Steve


_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel
Reply | Threaded
Open this post in threaded view
|

Re: Adding Custom Actions to Form Gramplet

GRAMPS - Dev mailing list
On 28/12/2019 10:04, Steve Youngs wrote:
> Revised Design
>
> - Add a new "actions" button to the FormGramplet window. Located
> beside the current New and Edit buttons.


Yes.


>
> - When the user selects a (single) form and clicks the "actions"
> button, display the form dialog itself (using the existing EditForm
> code, possibly in read-only mode) and a new "actions" dialog with a
> list containing two columns: column 1 a list of actions, column 2 a
> list of "things" to apply the action to. Consider a hyopthetical form
> for a family of four (two parents, two children, name, relation to
> head of household, age in years, occupation. Only one adult has an
> occupation given)
>
> Action               Apply to
> Add alternate name   John Smith
>                      Jane Smith
>                      Fred Smith
>                      Sarah Smith
> Add name citation    John Smith
>                      Jane Smith
>                      Fred Smith
>                      Sarah Smith
> Add Birth event John Smith
>                      Jane Smith
>                      Fred Smith
>                      Sarah Smith
> Add Occupation event John Smith
> Add Residence event  John Smith, Jane Smith, Fred Smith, Sarah Smith
> Add Family John Smith, Jane Smith, Fred Smith, Sarah Smith
> Add to Family        Jane Smith
>                      Fred Smith
>                      Jane Smith
>
> Cancel and OK buttons.
>
> The user selects zero, one or more rows from the "Apply to" column.
> When they click OK, the selected "actions" are performed.
>
> Note how the "Apply to" only shows relevant entries e.g. you cannot
> add an Occupation event for Jane Smith because she has no occupation
> specified on the source form.


This is a good approach.  Use a Gtk TreeView with a column of
checkboxes.  Selecting a top-level item could automatically select all
sub-items by default.

Consider adding extra columns for date, place and description.


>
> Why show the form dialog as well? Personally I would like to see the
> form data when selecting which actions to apply.


Start with the new dialog.  We can always add this option later.


>
> Concern: The list of actions can potentially get very long for multi
> column forms with 8/10/12 people. Think about UI layouts. Needs a good
> UX; quick and efficient.


I suggest getting something working and then refining the design of
necessary.


>
> - The list of "actions" is read from a python module having the same
> name as the form id (e.g. UK1841.py) and stored in the same directory
> as the form XML file. The module is dynamically loaded. In the module,
> there is one class per action. At runtime we can inspect the module to
> get a list of the classes provided. Each class would provide a method
> to populate the "actions" dialog and a method to "do" the action. I
> need to think about what arguments to pass into these methods. Form
> specific logic can be implemented in each module, and a base module of
> common functionality can be provided.
>
> Why use dynamic modules? I want to permit "actions" for custom forms.
> It should not be necessary to revise the Gramplet to add or modify an
> "action".


Don't do this.  I will mean that we will have to check custom
definitions for malicious code.  A fairly small list of standard action
should be sufficient.


>
> - Some actions may choose to display a dialog to allow the user to
> manually adjust and confirm the action. e.g. Add Family may default to
> including all household members from a census form. e.g. Add to Family
> in this example may show a list of all Families including John Smith


Possible, but I'd eventually like to see relationships recorded as part
of the transcription process.  We should also bear in mind that in the
future we want to generate objects from transcriptions of free-form text
such as wills.  This could involve transcribing using a markup language
such as STEMMA.  Forms may just become an easy way to generate
transcriptions.


>
> So far, I've not needed the extra data type field you mentioned adding
> to the the form XML. What have I missed?


In the original design I intended that all occupation type fields would
use the attribute "Occupation" and that the actual wording on the form
be stored in the longname.  This is no longer the case and attributes
such as "Profession" and "Trade" have been used. Perhaps we should
consider a extending the tag, for example: <_attribute
type="Occupation">Profession</_attribute>


Nick.




_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel
Reply | Threaded
Open this post in threaded view
|

Re: Adding Custom Actions to Form Gramplet

Steve Youngs

On 29/12/2019 15:57, Nick Hall via Gramps-devel wrote:
> On 28/12/2019 10:04, Steve Youngs wrote:
>
>> Why show the form dialog as well? Personally I would like to see the
>> form data when selecting which actions to apply.
>
> Start with the new dialog.  We can always add this option later.
>
I believe I've overcome this concern with the "Detail" column which
shows relevant data for the action.

>
>>
>> - The list of "actions" is read from a python module having the same
>> name as the form id (e.g. UK1841.py) and stored in the same directory
>> as the form XML file. The module is dynamically loaded. In the
>> module, there is one class per action. At runtime we can inspect the
>> module to get a list of the classes provided. Each class would
>> provide a method to populate the "actions" dialog and a method to
>> "do" the action. I need to think about what arguments to pass into
>> these methods. Form specific logic can be implemented in each module,
>> and a base module of common functionality can be provided.
>>
>> Why use dynamic modules? I want to permit "actions" for custom forms.
>> It should not be necessary to revise the Gramplet to add or modify an
>> "action".
>
>
> Don't do this.  I will mean that we will have to check custom
> definitions for malicious code.  A fairly small list of standard
> action should be sufficient.
>
I'm not sure I see the problem with this. I agree that code shipped as
part of the gramplet much be checked and tested before being released.
If an end user chooses to add their own form in custom.xml and write
their own actions, then it is their job to check their code. They could
just as easily modify formgramplet.py to do whatever malicious action
you envisage.

>
>>
>> - Some actions may choose to display a dialog to allow the user to
>> manually adjust and confirm the action. e.g. Add Family may default
>> to including all household members from a census form. e.g. Add to
>> Family in this example may show a list of all Families including John
>> Smith
>
>
> Possible, but I'd eventually like to see relationships recorded as
> part of the transcription process.  We should also bear in mind that
> in the future we want to generate objects from transcriptions of
> free-form text such as wills.  This could involve transcribing using a
> markup language such as STEMMA.  Forms may just become an easy way to
> generate transcriptions.


Sounds good. I'd like to able to complete a form by screen scraping, or
calling a remote server REST API.

One step at a time.

>
>>
>> So far, I've not needed the extra data type field you mentioned
>> adding to the the form XML. What have I missed?
>
>
> In the original design I intended that all occupation type fields
> would use the attribute "Occupation" and that the actual wording on
> the form be stored in the longname.  This is no longer the case and
> attributes such as "Profession" and "Trade" have been used. Perhaps we
> should consider a extending the tag, for example: <_attribute
> type="Occupation">Profession</_attribute>
>
I've reworked my change along these overall lines. See the updated PR on
github for details. It is however still dynamic.

There's alot still to do but for now I want to get the basic approach
agreed. Overall this new method "feels" much better. Generally a good sign.

Steve



_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel
Reply | Threaded
Open this post in threaded view
|

Re: Adding Custom Actions to Form Gramplet

GRAMPS - Dev mailing list
On 29/12/2019 18:03, Steve Youngs wrote:

Don't do this.  I will mean that we will have to check custom definitions for malicious code.  A fairly small list of standard action should be sufficient.

I'm not sure I see the problem with this. I agree that code shipped as part of the gramplet much be checked and tested before being released. If an end user chooses to add their own form in custom.xml and write their own actions, then it is their job to check their code. They could just as easily modify formgramplet.py to do whatever malicious action you envisage.

The problem is with users sharing form definitions.  At the moment, a badly written definition can't cause any serious damage to another user's database.


Nick.




_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel
Reply | Threaded
Open this post in threaded view
|

Re: Adding Custom Actions to Form Gramplet

GRAMPS - Dev mailing list
In reply to this post by Steve Youngs
On 29/12/2019 18:03, Steve Youngs wrote:
> I've reworked my change along these overall lines. See the updated PR
> on github for details. It is however still dynamic.
>
> There's alot still to do but for now I want to get the basic approach
> agreed. Overall this new method "feels" much better. Generally a good
> sign.

Thanks.  I'll have a look at the PR.


Nick.




_______________________________________________
Gramps-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gramps-devel