Creating UI

For now, we need two user inputs:

  • Input vector layer
  • Output target directory

Task

In the Qt Designer create two required inputs. Use QgsMapLayerComboBox for layer selection, QgsFileWidget for output dir name.

Use objectName attribute to name the objects: layers, output_dir and submit.

Consider using grid layout and horizontal/vertical spacers.

../_images/plugin-ui-final.svg

Fig. 21 Example of plugin UI design.

The Code

The run() method of the SaveViews class has to do following tasks:

  1. Initialize some initial form inputs
  2. Get the user input data
  3. Call the saving function
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    def run(self):
        """Run method that loads and starts the plugin"""


        if not self.pluginIsActive:
            self.pluginIsActive = True

            #print "** STARTING SaveViews"

            # dockwidget may not exist if:
            #    first run of plugin
            #    removed on close (see self.onClosePlugin method)
            if self.dockwidget == None:
                # Create the dockwidget (after translation) and keep reference
                self.dockwidget = SaveViewsDockWidget()
                self.dockwidget.layers.setFilters(QgsMapLayerProxyModel.VectorLayer)
                self.dockwidget.output_dir.setStorageMode(QgsFileWidget.GetDirectory)
                self.dockwidget.submit.clicked.connect(self.save_views)

            # connect to provide cleanup on closing of dockwidget
            self.dockwidget.closingPlugin.connect(self.onClosePlugin)

            # show the dockwidget
            # TODO: fix to allow choice of dock location
            self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockwidget)
            self.dockwidget.show()

Note, that we had to import QGIS Python modules

1
2
3
4
from PyQt5.QtGui import QColor, QPixmap
from qgis.utils import iface
from qgis.core import QgsMapLayerProxyModel
from qgis.gui import QgsFileWidget

Tip

For testing purpose we can hardcode output path

self.dockwidget.output_dir.setFilePath("/tmp/output")

Image save function

Finally, we approach to the heart of the plugin: the save_views() method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    def save_views(self):
         """
         save graphical output for every row in attribute table
         """

         layer = self.dockwidget.layers.currentLayer()

         for feature in layer.getFeatures():
             layer.selectByIds([feature.id()])
             self.iface.mapCanvas().setSelectionColor(QColor("transparent"))
             box = layer.boundingBoxOfSelected()
             self.iface.mapCanvas().setExtent(box)
             pixmap = QPixmap(self.iface.mapCanvas().mapSettings().outputSize().width(),
                              self.iface.mapCanvas().mapSettings().outputSize().height()
             )
             mapfile = os.path.join(
                     self.dockwidget.output_dir.filePath(),
                     '{0}_{1:03d}.png'.format(layer.name(), feature.id())
             )
             self.iface.mapCanvas().saveAsImage(mapfile, pixmap)
             layer.removeSelection()

         # save also full extend of vector layer                            
         canvas = self.iface.mapCanvas()
         canvas.setExtent(layer.extent())
         pixmap = QPixmap(self.iface.mapCanvas().mapSettings().outputSize().width(),
                          self.iface.mapCanvas().mapSettings().outputSize().height()
         )
         mapfile = os.path.join(
                    self.dockwidget.output_dir.filePath(),
                    '{}_full.png'.format(layer.name())
        )
         self.iface.mapCanvas().saveAsImage(mapfile, pixmap) 
../_images/plugin-ui-final2.png

Task

Make sure that the plugin will not fail, if no target directory is selected.

Hint

In case that you want to change plugin icon, modify the icon.png file as you wish.

../_images/save-views-result.png

Fig. 22 Example of image files stored in output directory.