Skip to content

GUI: Add Copy drop-down menu and Paste parameters button to module dialogs - #7237

Merged
pesekon2 merged 6 commits into
OSGeo:mainfrom
polucifier:gui-copy-python
May 4, 2026
Merged

pesekon2 merged 6 commits into
OSGeo:mainfrom
polucifier:gui-copy-python

Conversation

@polucifier

@polucifier polucifier commented Mar 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

Note: This PR description was updated post-merge to accurately reflect the final, expanded scope of the implemented features.

This PR enhances the user experience in the GRASS GUI module dialogs by introducing advanced options for copying and pasting module configurations. It streamlines the transition between GUI workflows, command-line execution, and Python scripting.

Key Features

  • Advanced Copy Drop-down: Enhances the existing Copy button by adding a drop-down arrow that reveals multiple export formats.
  • Copy Options Included: Shell command, Python (Script API), Python (Tools API), Python (PyGRASS), and JSON settings.
  • Paste JSON Settings Button: Adds a dedicated, standalone button that allows users to instantly populate the module dialog inputs by pasting previously exported JSON settings.

@echoix

echoix commented Mar 29, 2026

Copy link
Copy Markdown
Member

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)

@github-actions github-actions Bot added GUI wxGUI related Python Related code is in Python labels Mar 29, 2026
Comment thread gui/wxpython/gui_core/forms.py Resolved
Comment thread gui/wxpython/gui_core/forms.py Resolved
@polucifier

Copy link
Copy Markdown
Contributor Author

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)

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:

  • Copy as Shell command (default)
  • Copy as Python script (using the logic from this PR)
  • Copy as JSON (as you suggested)

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.

@polucifier
polucifier marked this pull request as draft March 29, 2026 11:16
@ninsbl

ninsbl commented Mar 29, 2026

Copy link
Copy Markdown
Member

Nice. Did you consider returning tools API syntax?

@polucifier

Copy link
Copy Markdown
Contributor Author

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.

@polucifier

Copy link
Copy Markdown
Contributor Author

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:
image

The dropdown menu offers various formats, including the new Tools API and JSON:
image

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:
Shell command:

v.distance -p -s --overwrite from=durham@user1 to=bridges@PERMANENT upload=dist format=plain

Python (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:
Paste.webm

@polucifier
polucifier marked this pull request as ready for review March 30, 2026 00:48
@ninsbl

ninsbl commented Mar 30, 2026

Copy link
Copy Markdown
Member

Cool. Just for clarification: does Copy as JSON copy json equivalent to --json, or just the the parameters that were set with their values?

@ninsbl

ninsbl commented Mar 30, 2026

Copy link
Copy Markdown
Member

I now see the JSON structure in your comment above... Background for my question has been: #6697

Comment thread gui/wxpython/gui_core/forms.py Resolved
Comment thread gui/wxpython/gui_core/forms.py Resolved
Comment thread gui/wxpython/gui_core/forms.py Resolved
@polucifier
polucifier requested a review from petrasovaa April 9, 2026 21:58
@landam landam added this to the 8.6.0 milestone Apr 15, 2026
@pesekon2

Copy link
Copy Markdown
Contributor

The functionality is great. I really like it. I would have some doubts about the usability of the Paste button but if @echoix says he can imagine users for that, why not having it.

I tested the functionality and it seems fine to me. However, I don't see the arrow on the dropout of the Copy button. It seems seems to me more like a wxPython issue than being connected to the PR. What is your version of wx? Mine is 4.2.3.

Screenshot from 2026-04-15 15-48-40

@landam landam added the enhancement New feature or request label Apr 15, 2026
Comment thread gui/wxpython/gui_core/forms.py Resolved
@polucifier

Copy link
Copy Markdown
Contributor Author

Hi @pesekon2, thanks for the feedback! I'm glad the functionality works well for you.

Regarding the missing arrow: I have the same version of wxPython (4.2.3). You were right—the issue was most likely caused by the previous implementation using a text-based character for the chevron, which renders inconsistently across different platforms and themes.

To resolve this and ensure a professional look on all systems, I have completely overhauled the visual implementation in the latest commit.

Technical Improvements:

  • Custom Drawing with wx.GCDC: Instead of relying on text characters, I am now drawing the chevron icon manually. Using wx.GCDC ensures smooth, anti-aliased lines.
  • True Transparency: I switched to wx.Bitmap.FromRGBA to create a 32-bit bitmap. This eliminates "black box" artifacts and ensures the button background blends perfectly with the native UI.
  • Automatic Theme Support: The icon color is now dynamically pulled from wx.SYS_COLOUR_BTNTEXT, making it fully compatible with both light and dark system themes.
  • Pixel-Perfect Alignment: I've implemented platform-specific vertical offsets (including a -2px shift for Windows). The chevron is now mathematically and visually aligned with the baseline of the "Copy" text (specifically the letter 'C'), verified down to the pixel in GIMP.

Here is the final result across different environments:

Linux - Dark Theme
linux_dark

Linux - Light Theme
linux_bright

Windows - Light Theme
windows_bright

Comment thread gui/wxpython/gui_core/forms.py Resolved
@pesekon2

Copy link
Copy Markdown
Contributor

Thanks. Now I got the arrow there. A weird and ugly one but something is there.

Screenshot from 2026-04-21 15-06-19

But I got two more points:

  1. The button Paste is not really self-exlanatory. Could the text be clearer? Like Paste JSON settings? I don't want to make the bar too long (but cannot come with anything shorter now) but currently, the user doesn't really know what type should s/he paste there. Which comes to:
  2. It should raise a clearer error message if something wrong is pasted. Currently, I just get Paste Error: Expecting value: line 1 column 1 (char 0).

Comment thread gui/wxpython/gui_core/forms.py Resolved
@polucifier
polucifier marked this pull request as draft April 21, 2026 14:42
@pesekon2

pesekon2 commented Apr 22, 2026 •

Copy link
Copy Markdown
Contributor
2. It should raise a clearer error message if something wrong is pasted. Currently, I just get `Paste Error: Expecting value: line 1 column 1 (char 0)`.

Just an update on this: I get that error message if pasting a different thing than JSON. If pasting JSON from another module, I don't get any error message, it just doesn't do anything for the non-existing parameters and set those existing in the one they are pasted into.

polucifier and others added 5 commits April 29, 2026 02:32
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.
…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.
…t alignment

Improved the visual appearance of the Copy button's dropdown arrow by
replacing the text-based character with a custom-drawn chevron.

Key improvements:
- Switched to wx.GCDC for smooth, anti-aliased drawing of the chevron.
- Utilized 32-bit RGBA bitmaps to ensure perfect transparency and
  compatibility with both light and dark system themes.
- Implemented precise vertical offsets (-2px on Windows) to align the
  chevron's tip perfectly with the text baseline based on GIMP-verified
  measurements.
- Refined the split-button "glue" on Windows to ensure a seamless
  native-looking border.
@polucifier

Copy link
Copy Markdown
Contributor Author

Changes:

  • Native UI: Dropdown arrow now uses wx.RendererNative (size 23) for pixel-perfect consistency with other GRASS widgets.
  • Renamed Label: Changed to _("Paste JSON settings") for better clarity.
  • Module Safety: Added a validation check to warn users when pasting settings from a different GRASS module.
  • Error Handling: Implemented try-except blocks with user-friendly error messages for invalid clipboard data.

Screenshots:

1. Consistent Native Arrow:
Screenshot_20260429_022419

2. Module Mismatch Warning:
Screenshot_20260429_022058

3. Invalid Data Handling:
Screenshot_20260429_022318

@polucifier
polucifier marked this pull request as ready for review April 29, 2026 00:38
@polucifier
polucifier requested a review from pesekon2 April 29, 2026 00:38
- Use native renderer for the dropdown arrow (size 23) to ensure
  visual consistency and sharpness across different platforms.
- Update button label to "Paste JSON settings" for better clarity
  as requested by reviewer.
- Implement a module mismatch check in OnPaste to warn users when
  applying settings from a different GRASS module.
- Enhance error handling for clipboard content with user-friendly
  messages for invalid JSON data.

@pesekon2 pesekon2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine from my side. Approving.

@echoix: As I am not a target user for the Paste button, I am waiting for your opinion before merging it.

@echoix

echoix commented May 4, 2026

Copy link
Copy Markdown
Member

Im still favorable, as I use the equivalent with QGIS. My grass development setup is broken, so I can’t test it right away. I saw that you were able to make it run before, and checked out the rendering.

@pesekon2

pesekon2 commented May 4, 2026

Copy link
Copy Markdown
Contributor

Im still favorable, as I use the equivalent with QGIS. My grass development setup is broken, so I can’t test it right away. I saw that you were able to make it run before, and checked out the rendering.

Yes, I tested it again today before approving and all seem smooth. So I take your favorable approach as yes and merge it. Thanks, @polucifier.

@pesekon2
pesekon2 merged commit 1f8fa71 into OSGeo:main May 4, 2026
26 checks passed
@polucifier polucifier changed the title GUI: Add "Copy in Python" button to module dialogs GUI: Add Copy drop-down menu and Paste parameters button to module dialogs May 4, 2026
dhdeangelis pushed a commit to dhdeangelis/grass that referenced this pull request May 4, 2026
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.script library (standard gs alias).

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.
ninsbl pushed a commit to ninsbl/grass that referenced this pull request Jul 7, 2026
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.script library (standard gs alias).

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.
ninsbl pushed a commit to ninsbl/grass that referenced this pull request Jul 7, 2026
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.script library (standard gs alias).

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request GUI wxGUI related libraries Python Related code is in Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants