6

Following the example of getting the QGIS canvas in a plugin window (as described here), I'm trying to add the QgsLayoutDesignerInterface into a plugin widget.

My goal is to simply display (no edit settings needed) a map layout in a plugin widget as soon as the related map is chosen from a combobox (see image below).

Then the layout (added to the project via the project.layoutManager) can wether be directly exported as a pdf file or opened and edited in the main LayoutDesigner (no help needed for this part since I already implemented it)

enter image description here

I tried to promote the QWidget as a QgsLayoutDesignerInterface class to display my automated layout but I get the following error message TypeError: qgis._gui.QgsLayoutDesignerInterface represents a C++ abstract class and cannot be instantiated

1 Answer 1

6
+100

Based on this quote from your question:

My goal is to simply display (no edit settings needed) a map layout in a plugin widget as soon as the related map is chosen from a combobox .

My guess is that you don't want the entire layout designer interface embedded in your widget, just the layout and associated items.

Because the QgsLayout class inherits from the QGraphicsScene base class, You can create a QGraphicsView object, and display a layout inside it by calling the setScene() method, and passing a QgsPrintLayoutObject.

Below is a basic example which you can adapt for your plugin (you can also run this in the Python console to test).

class MyDialog(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.setGeometry(200, 200, 1500, 800)
        self.hbox = QHBoxLayout(self)
        self.side_panel = QWidget(self)
        self.side_panel.setMinimumWidth(300)
        self.cb = QComboBox(self.side_panel)
        self.layout_names = [l.name() for l in QgsProject.instance().layoutManager().layouts()]
        self.cb.addItems(self.layout_names)
        self.cb.currentTextChanged.connect(self.show_layout)
        self.hbox.addWidget(self.side_panel)
        self.layout = QgsProject.instance().layoutManager().layoutByName(self.cb.currentText()).clone()
        # Create a QGraphicsView
        self.view = QGraphicsView(self)
        self.view.setMinimumSize(800, 800)
        # Call setScene(), passing a QgsPrintLayout object
        self.view.setScene(self.layout)
        # Resize layout inside the viewport (just hardcoded here)
        self.view.scale(3, 3)
        self.hbox.addWidget(self.view)
        self.cb.setCurrentText(self.layout.name())
        
    def show_layout(self):
        layout_name = self.cb.currentText()
        self.layout = QgsProject.instance().layoutManager().layoutByName(layout_name).clone()
        self.view.setScene(self.layout)
        
        
dlg = MyDialog()
dlg.show()

Result:

enter image description here

An example with Qt Designer:

enter image description here

from PyQt5 import uic

Dlg, QtBaseClass  = uic.loadUiType('C:\\Path\\To\\layoutsDialog.ui')

class LayoutsDialog(QDialog, Dlg):
    def __init__(self, parent=None):
        QDialog.__init__(self)
        Dlg.__init__(self)
        self.setupUi(self)
        self.setGeometry(100, 100, 1400, 900)
        self.setWindowTitle('Display Layouts')
        
        self.layout_names = [l.name() for l in QgsProject.instance().layoutManager().layouts()]
        self.layoutCB.addItems(self.layout_names)
        self.print_layout = QgsProject.instance().layoutManager().layoutByName(self.layoutCB.currentText())
        self.layoutView.setScene(self.print_layout)
        self.layoutView.scale(3, 3)
        self.layoutCB.currentTextChanged.connect(self.show_layout)
        
    def show_layout(self):
        self.print_layout = QgsProject.instance().layoutManager().layoutByName(self.layoutCB.currentText())
        self.layoutView.setScene(self.print_layout)
        

dlg = LayoutsDialog()
dlg.show()

enter image description here

4
  • 2
    Thank you so much Ben ! :)
    – wanderzen
    Commented Aug 29, 2022 at 7:28
  • @wanderzen, no problem :-)
    – Ben W
    Commented Aug 29, 2022 at 7:38
  • Sorry for the late bounty award @Ben W, I was convinced I already validated your answer ! My bad !
    – wanderzen
    Commented Sep 2, 2022 at 22:22
  • @wanderzen, no worries- all good! Thanks :-)
    – Ben W
    Commented Sep 3, 2022 at 7:30

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.