def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/python/plugins/distromap" # initialize locale localePath = "" locale = QSettings().value("locale/userLocale")[0:2] if QFileInfo(self.plugin_dir).exists(): localePath = self.plugin_dir + "/i18n/distromap_" + locale + ".qm" if QFileInfo(localePath).exists(): self.translator = QTranslator() self.translator.load(localePath) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = DistroMapDialog()
class DistroMap: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/python/plugins/distromap" # initialize locale localePath = "" locale = QSettings().value("locale/userLocale")[0:2] if QFileInfo(self.plugin_dir).exists(): localePath = self.plugin_dir + "/i18n/distromap_" + locale + ".qm" if QFileInfo(localePath).exists(): self.translator = QTranslator() self.translator.load(localePath) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = DistroMapDialog() def confirm(self): # runs when OK button is pressed # initialise input parameters self.BASE_LAYER = self.dlg.ui.comboBase.currentItemData() self.SECONDARY_LAYER = self.dlg.ui.comboSecondary.currentItemData() self.SURFACE_LAYER = self.dlg.ui.comboSurface.currentItemData() self.LOCALITIES_LAYER = self.dlg.ui.comboLocalities.currentItemData() self.TAXON_FIELD_INDEX = self.dlg.ui.comboTaxonField.currentItemData()[0] self.GRID_LAYER = self.dlg.ui.comboGrid.currentItemData() self.X_MIN = float(self.dlg.ui.leMinX.text()) self.Y_MIN = float(self.dlg.ui.leMinY.text()) self.X_MAX = float(self.dlg.ui.leMaxX.text()) self.Y_MAX = float(self.dlg.ui.leMaxY.text()) self.OUT_WIDTH = self.dlg.ui.spnOutWidth.value() self.OUT_HEIGHT = self.dlg.ui.spnOutHeight.value() self.OUT_DIR = self.dlg.ui.leOutDir.text() try: self.getUniqueValues() except: message = "Could not get unique values from localities layer. " message += "Check that the localities layer and taxon identifier " message += "field are properly specified." QMessageBox.information(self.dlg,"Distribution Map Generator", message) return question = "This will generate " + str(self.UNIQUE_COUNT) question += " maps. Are you sure you want to continue?" reply = QMessageBox.question(self.dlg,'Distribution Map Generator', question, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.process() QMessageBox.information(self.dlg,"Distribution Map Generator", "Map processing complete.") self.dlg.ui.progressBar.setValue(0) QDialog.accept(self.dlg) else: return def initGui(self): # Create action that will start plugin configuration self.action = QAction( QIcon(self.plugin_dir + "/icon.svg"), u"Distribution Map Generator...", self.iface.mainWindow()) # connect the action to the run method self.action.triggered.connect(self.run) self.dlg.ui.buttonBox.accepted.connect(self.confirm) # Add toolbar button and menu item self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu(u"&Distribution Map Generator", self.action) # Set colour for output background colour chooser: self.BACKGROUND_COLOUR = QColor(192,192,255) self.dlg.ui.frmColour.setStyleSheet("QWidget { background-color: %s }" % self.BACKGROUND_COLOUR.name()) def unload(self): # Remove the plugin menu item and icon self.iface.removePluginMenu(u"&Distribution Map Generator", self.action) self.iface.removeToolBarIcon(self.action) def loadTaxonFields(self): self.dlg.ui.comboTaxonField.clear() try: layer=getLayerFromId(self.dlg.ui.comboLocalities.currentItemData()) provider=layer.dataProvider() except: #Crashes without valid shapefiles log("Could not access the localities layer. Is it a valid vector layer?") return try: fieldmap=provider.fieldNameMap() for (name,index) in fieldmap.iteritems(): self.dlg.ui.comboTaxonField.addItem(name,index) except: log("Could not load the field names for the localities layer.") def loadOutDir(self): #newname = QFileDialog.getExistingDirectory(None, "Output Maps Directory", self.dlg.ui.leOutDir.displayText()) newname = QFileDialog.getExistingDirectory(None, "Output Maps Directory") if newname != None: self.dlg.ui.leOutDir.setText(newname) def getCurrentExtent(self): extent = self.iface.mapCanvas().extent() # {"{0:.6f}".format() shows the float with 6 decimal places self.dlg.ui.leMinX.setText(str("{0:.6f}".format(extent.xMinimum()))) self.dlg.ui.leMinY.setText(str("{0:.6f}".format(extent.yMinimum()))) self.dlg.ui.leMaxX.setText(str("{0:.6f}".format(extent.xMaximum()))) self.dlg.ui.leMaxY.setText(str("{0:.6f}".format(extent.yMaximum()))) def getUniqueValues(self): layer = getLayerFromId(self.LOCALITIES_LAYER) self.UNIQUE_VALUES = layer.dataProvider().uniqueValues(int(self.TAXON_FIELD_INDEX)) self.UNIQUE_COUNT = len(self.UNIQUE_VALUES) def selectByAttribute(self, value): layer = getLayerFromId(self.LOCALITIES_LAYER) selectindex = self.TAXON_FIELD_INDEX readcount = 0 selected = [] for feature in layer.getFeatures(): if unicode(str(feature.attributes()[int(selectindex)])) == unicode(str(value)): selected.append(feature.id()) layer.setSelectedFeatures(selected) def selectByLocation(self): inputLayer = getLayerFromId(self.GRID_LAYER) selectLayer = getLayerFromId(self.LOCALITIES_LAYER) inputProvider = inputLayer.dataProvider() index = QgsSpatialIndex() feat = QgsFeature() for feat in inputLayer.getFeatures(): index.insertFeature(feat) feat = QgsFeature() geom = QgsGeometry() selectedSet = [] feats = features(selectLayer) for f in feats: geom = QgsGeometry(f.geometry()) intersects = index.intersects(geom.boundingBox()) for i in intersects: request = QgsFeatureRequest().setFilterFid(i) feat = inputLayer.getFeatures(request).next() tmpGeom = QgsGeometry( feat.geometry() ) if geom.intersects(tmpGeom): selectedSet.append(feat.id()) inputLayer.setSelectedFeatures(selectedSet) def saveSelected(self): inputLayer = getLayerFromId(self.GRID_LAYER) provider = inputLayer.dataProvider() # create layer outputLayer = QgsVectorLayer("Polygon", "taxon", "memory") outProvider = outputLayer.dataProvider() # add features outGrids = features(inputLayer) for grid in outGrids: outProvider.addFeatures([grid]) outputLayer.updateExtents() self.TAXON_GRID_LAYER = outputLayer def setBackgroundColour(self): col = QColorDialog.getColor() if col.isValid(): self.BACKGROUND_COLOUR = col self.dlg.ui.frmColour.setStyleSheet("QWidget { background-color: %s }" % self.BACKGROUND_COLOUR.name()) def printMap(self,taxon): # copy style from grid layer to output layer outstyle = tempfile.gettempdir() + os.sep + "output.qml" getLayerFromId(self.GRID_LAYER).saveNamedStyle(outstyle) self.TAXON_GRID_LAYER.loadNamedStyle(outstyle) # create image (dimensions 325x299) img = QImage(QSize(self.OUT_WIDTH,self.OUT_HEIGHT), QImage.Format_ARGB32_Premultiplied) # set image's background color color = self.BACKGROUND_COLOUR img.fill(color.rgb()) # create painter p = QPainter() p.begin(img) p.setRenderHint(QPainter.Antialiasing) render = QgsMapRenderer() # create layer set baseLayer = getLayerFromId(self.BASE_LAYER) if self.SECONDARY_LAYER != None: secondaryLayer = getLayerFromId(self.SECONDARY_LAYER) else: secondaryLayer = None if self.SURFACE_LAYER != None: surfaceLayer = getLayerFromId(self.SURFACE_LAYER) else: surfaceLayer = None lst = [] lst.append(self.TAXON_GRID_LAYER.id()) if self.SURFACE_LAYER != unicode(""): lst.append(self.SURFACE_LAYER) if self.SECONDARY_LAYER != unicode(""): lst.append(self.SECONDARY_LAYER) lst.append(self.BASE_LAYER) render.setLayerSet(lst) # set extent (xmin,ymin,xmax,ymax) rect = QgsRectangle(self.X_MIN,self.Y_MIN,self.X_MAX,self.Y_MAX) render.setExtent(rect) # set output size render.setOutputSize(img.size(), img.logicalDpiX()) # do the rendering render.render(p) p.end() # save image outdir = self.OUT_DIR img.save(outdir+os.sep+unicode(str(taxon))+".png","png") def process(self): self.dlg.ui.progressBar.setMaximum(len(self.UNIQUE_VALUES)) # process all unique taxa getLayerFromId(self.LOCALITIES_LAYER).setSelectedFeatures([]) # use global projection oldValidation = QSettings().value( "/Projections/defaultBehaviour", "useGlobal", type=str ) QSettings().setValue( "/Projections/defaultBehaviour", "useGlobal" ) for taxon in self.UNIQUE_VALUES: self.selectByAttribute(taxon) self.selectByLocation() self.saveSelected() #load newly created memory layer QgsMapLayerRegistry.instance().addMapLayer(self.TAXON_GRID_LAYER) self.printMap(taxon) #unload memory layer QgsMapLayerRegistry.instance().removeMapLayers([self.TAXON_GRID_LAYER.id()]) self.TAXON_GRID_LAYER = None self.dlg.ui.progressBar.setValue(self.dlg.ui.progressBar.value()+1) #restore saved default projection setting QSettings().setValue( "/Projections/defaultBehaviour", oldValidation ) #clear selection getLayerFromId(self.LOCALITIES_LAYER).removeSelection() getLayerFromId(self.GRID_LAYER).removeSelection() # run method that performs all the real work def run(self): # first clear combo boxes so they don't get duplicate entries: self.dlg.ui.comboBase.clear() self.dlg.ui.comboSecondary.clear() self.dlg.ui.comboSurface.clear() self.dlg.ui.comboLocalities.clear() self.dlg.ui.comboGrid.clear() # populate combo boxes: self.dlg.ui.comboSecondary.addItem("None",None) self.dlg.ui.comboSurface.addItem("None",None) for layer in self.iface.mapCanvas().layers(): self.dlg.ui.comboBase.addItem(layer.name(),layer.id()) self.dlg.ui.comboSecondary.addItem(layer.name(),layer.id()) self.dlg.ui.comboSurface.addItem(layer.name(),layer.id()) #vector only layers: if type(layer).__name__ == "QgsVectorLayer": self.dlg.ui.comboLocalities.addItem(layer.name(),layer.id()) self.dlg.ui.comboGrid.addItem(layer.name(),layer.id()) self.loadTaxonFields() # define the signal connectors #QObject.connect(self.dlg.ui.comboLocalities,SIGNAL('currentIndexChanged (int)'),self.loadTaxonFields) self.dlg.ui.comboLocalities.currentIndexChanged.connect(self.loadTaxonFields) #QObject.connect(self.dlg.ui.btnBrowse,SIGNAL('clicked()'),self.loadOutDir) self.dlg.ui.btnBrowse.clicked.connect(self.loadOutDir) #QObject.connect(self.dlg.ui.btnExtent,SIGNAL('clicked()'),self.getCurrentExtent) self.dlg.ui.btnExtent.clicked.connect(self.getCurrentExtent) #QObject.connect(self.dlg.ui.btnColour,SIGNAL('clicked()'),self.setBackgroundColour) self.dlg.ui.btnColour.clicked.connect(self.setBackgroundColour) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_()