GUI: Add "Copy in Python" button to module dialogs#7237
GUI: Add "Copy in Python" button to module dialogs#7237polucifier wants to merge 4 commits intoOSGeo:mainfrom
Conversation
|
I like the concept, similar to what there is in QGIS, even if I never used these in qgis (only the copy as json and paste it again later on to rehave the same parameters set) |
439daef to
d2e00d3
Compare
Thanks for the feedback, @echoix! I really like the QGIS workflow you mentioned. I'm going to convert this PR to a Draft for now while I refine the UI. My plan is to replace the standalone 'Copy in Python' button with a MenuButton (dropdown) integrated into the main 'Copy' button. It will include:
To complete the loop, I will also try to implement a 'Paste' button that can take a JSON string and automatically populate the dialog fields. I'll push these updates later this evening. |
|
Nice. Did you consider returning tools API syntax? |
Hi @ninsbl, thank you very much for the suggestion! That's a great idea. Since I'm already reworking the 'Copy' button into a dropdown menu, I'll add two more options to it: 'Copy as Python (Tools API)' and 'Copy as Python (PyGRASS)'. Combined with the Script API and JSON options, this should cover all the major Python workflows in GRASS. I'll push the updates later. |
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…dialogs This commit introduces advanced clipboard functionality to the GRASS module dialogs, drastically improving reproducibility and workflow sharing. New Features: - Replaced the standard "Copy" button with a backwards-compatible split button (using wx.BoxSizer to support older wxPython versions). - Added a dropdown to copy module parameters in multiple formats: Shell command (default), Python (Script API), Python (Tools API), PyGRASS, and JSON. - Added a "Paste" button that reads a JSON payload from the system clipboard and automatically populates the module dialog parameters and flags. Paste Logic Improvements: - Robustly handles wx widget type coercion (e.g., wx.SpinCtrl, wx.Choice, ColourSelect, and multi-selection wx.CheckBox arrays). - Accurately mimics command-line behavior by resetting any omitted parameters to their standard defaults and actively unchecking omitted flags. - Safely parses shorthand flags (e.g., "flags": "ps") without triggering false positives on full flag names. - Explicitly ignores "ModelParam" widgets to prevent interference with the Graphical Modeler.
|
I have implemented a new Split Copy Button and a Paste functionality for the module dialogs. This update provides users with multiple export formats and a way to quickly restore or share tool parameters via JSON. New UI layout with the Split Copy button and the Paste button: The dropdown menu offers various formats, including the new Tools API and JSON: The following examples demonstrate the generated output. Note that Python reserved keywords (e.g., from) are correctly handled using dictionary unpacking to ensure valid, executable code: v.distance -p -s --overwrite from=durham@user1 to=bridges@PERMANENT upload=dist format=plainPython (Script API): gs.run_command('v.distance', flags='ps', overwrite=True, to='bridges@PERMANENT', upload='dist', format='plain', **{'from': 'durham@user1'})Python (Tools API): Tools().v_distance(flags='ps', overwrite=True, to='bridges@PERMANENT', upload='dist', format='plain', **{'from': 'durham@user1'})Python (PyGRASS): Module('v.distance', flags='ps', overwrite=True, to='bridges@PERMANENT', upload='dist', format='plain', **{'from': 'durham@user1'})JSON format: {
"module": "v.distance",
"params": {
"flags": "ps",
"overwrite": "True",
"from": "durham@user1",
"to": "bridges@PERMANENT",
"upload": "dist",
"format": "plain"
}
}Demonstration of the Paste functionality, which populates dialog fields and updates the command preview in real-time: |
|
Cool. Just for clarification: does |
|
I now see the JSON structure in your comment above... Background for my question has been: #6697 |
…d formatting - forms.py: Catch specific exceptions (json.JSONDecodeError, ValueError) in OnPaste instead of a bare Exception to avoid swallowing unrelated bugs. - forms.py: Fix a formatting bug where the generated Python command started with a leading comma when no flags were present. - forms.py/task.py: Move _get_formatted_params and _extract_params_dict from GUI forms to grass.script.task (as cmd_to_python_args and cmd_to_dict) so they can be reused outside the GUI.
|
The functionality is great. I really like it. I would have some doubts about the usability of the I tested the functionality and it seems fine to me. However, I don't see the arrow on the dropout of the
|
| win.SetValue( | ||
| val | ||
| if isinstance(val, bool) | ||
| else str(val).lower() in ("true", "1", "yes") |
There was a problem hiding this comment.
[ruff] reported by reviewdog 🐶
| else str(val).lower() in ("true", "1", "yes") | |
| else str(val).lower() in {"true", "1", "yes"} |



Description
This PR introduces a new button "Copy in Python" to all GRASS module dialogs in the wxGUI. While the existing "Copy" button provides the shell command, this new feature generates valid Python syntax using the
grass.scriptlibrary (standardgsalias).The goal is to streamline the workflow for users transitioning from the GUI to Python scripting and to provide a quick way to prototype scripts directly from the interface.
Key Features & Improvements
gs.run_command()pattern, which is the most common entry point for GRASS scripting.repr()function for parameter values. This ensures that Windows file paths (backslashes), quotes, and special characters are handled correctly without breaking the Python string literal.from,in,global). If a module parameter name conflicts with a keyword, the PR uses dictionary unpacking (e.g.,**{'from': 'map'}) to ensure the generated code is syntactically valid.--overwrite,--verbose, and--quietinto their PythonicTrue/Falsearguments.--) that might be introduced by third-party addons.Example Output
For a module like
v.distance -p -s --overwrite from=durham@user1 to=bridges@PERMANENT upload=dist format=plain, the button generates:Testing