Creating UI

For now, we need 2 user inputs:

  • Input vector layer
  • Output target directory

Task

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

Use objectName attribute to name the objects: dlg_layers and output_dir.

Consider using Horizontal and Vertical layouts.

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

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 some more Qgs modules

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

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, program will not fail, if no directory is selected

Hint

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

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

Fig. 20 Final files stored in output dir