2

I'm creating a small plugin, where you can copy-paste values from one layer to the other by selecting relevant features in both layer (see here : QGIS: PlugIn for semiautomating copying attribute values from one layer to another?). In essence, a person should be able to use the plugin as follows:

  1. select the two relevant layer and the relevant fields from which to copy and paste in a dialog with comboboxes and click 'ok' (see here: PyQGIS Plugin: After setting Layer and Field in combobex, how to refer to them in the processing code?). Now, the relevant layers and fields are set.Then
  2. open a small dialogue box with an 'okay' button and a 'close' symbol in the right corner.
  3. Now select the relevant features, and if you want to copy-paste your selection, click the 'okay'-button
  4. The 3rd step should be able to be done as often as the user needs to be. And if she is ready with copy-pasting, then press the 'close'-symbol in the right corner. This should stop the plug in.

Now, how do I create such an 'open' dialogue box in Qt? I created already the dialogue, where you are able to select layers and fields when initializing the tool.However, I'm now stucked on how to do this second dialogue with a simple 'okay'-button.

5
  • 1
    IMHO, a QDockWidget with a QGridLayout would be a better approach, resulting in a better UX than multiple, small pop-up dialogs. A dock widget could accommodate all your comboboxes, plus a simple button to copy attributes from the selected field of selected feature in source layer to selected field for selected feature/s in target error. Push a message bar warning if no features are selected.
    – Ben W
    May 2, 2023 at 10:30
  • This sounds very good! However, how do I integrate a QDockWidget with a QGridLayout in the QGIS plugin code template?
    – i.i.k.
    May 2, 2023 at 10:46
  • 1
    Probably you will need to do a bit research and study. Absolute basic concept: create a .ui file in QtDesigner with a QDockWidget instead of a QDialog and replace the plugin builder generated .ui file. Then in plugin code instead of self.dlg.show() do self.iface.mainWindow().addDockWidget(Qt.TopDockWidgetArea, self.dlg). You can probably find many examples online. Once you learn some PyQt gui development, QGIS plugin code makes so much more sense. You should also look at the official Qt docs.
    – Ben W
    May 2, 2023 at 11:18
  • 1
    You can also have a look at one of my plugins which uses a QDockWidget here: github.com/benwirf/measure_selected_features I did not use plugin builder or QtDesigner though.
    – Ben W
    May 2, 2023 at 11:21
  • Thank you @Ben W. I think this is something for version 2.0 :) I will first try the hopefully easier approach with a second dialog.
    – i.i.k.
    May 2, 2023 at 12:40

2 Answers 2

3

Based on the answer of @Maryla my tool seems to work as expected after I did the following :

  1. I created a new Qt-object in QT Designer. I chose for an empty QDialog and created there a QBushButton with the name 'acceptButton' and a QTextEdit. The text describes the steps you need to do, and the button is an 'Apply'-button. I stored this as accept_dialog.ui in the plugin folder. So I now have two .ui documents in the folder.

enter image description here

  1. In the plugin folder I created a new python script with the name accept_dialog.py which includes the following code:
import os
from qgis.PyQt import uic
from qgis.PyQt import QtWidgets
FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'accept_dialog.ui'))


class AcceptDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        """Constructor."""
        super(AcceptDialog, self).__init__(parent)
        self.setupUi(self)

enter image description here

  1. I import the newly created dialog-class into the plugin pythonscript with
from .accept_dialog import AcceptDialog

and then I call and show the newly and second dialog after the ok-button of the first dialog is pressed and run the main processing code (which happens in a newly defined function copy_paste) with the following code:

        # See if OK was pressed
        if result:
            self.dlg2 = AcceptDialog()
            self.dlg2.show()
            # When button is clicked call the copy_paste function
            self.dlg2.acceptButton.clicked.connect(self.copy_paste)

I tested it a couple of times, and it seems to work as I hoped to, so when I click 'Apply' the values are copied from the source feature field to the target feature field(s). However, it feels a bit, well, 'hacked'. I'm glad for feedback, if there may be something which may cause 'unexpected behavior' or so. For example, can I make sure, that the plugin is disabled when I close the second dialog by clicking the closing button in the right corner?

2

To create a dialog box with okay and cancel button open Qt Designer and it should show you a few templates for creating dialogs. If not, after opening Qt Designer choose File -> New... and then choose Dialog with Buttons Bottom template: enter image description here

Then save dialog inside your plugin folder. Compile it to .py script using pyuic5 command or create a class in .py script which loads .ui file. Next import this dialog inside you plugin script and create a variable reffering to this dialog, eg:

from .my_dialog import MyDialog
self.dlg = MyDialog()

If I understand you correctly you want to open a small dialogue box with an 'okay' button and a 'close' symbol in the right corner after setting relevant layers and fileds. I think I would open this new dialog after setting layers and fields and clicking OK in your current Copy_n_Paste dialog. This can be done by connecting a function after clicking a button in the first dialog like this, eg:

self.dlg.btnOk.clicked.connect(self.select_features)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.