def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/SelectTrees/icon_selecttrees.png' self.add_action(icon_path, self.tr(u'Selecció arbres'), self.run, self.iface.mainWindow(), "F8") # Create the dock widget and dock it but hide it waiting the end of qgis loading self.dlg = SelectTreesDockWidget(self.iface.mainWindow()) self.iface.mainWindow().addDockWidget(Qt.LeftDockWidgetArea, self.dlg) self.dlg.setVisible(False) # Set signals self.dlg.findChild(QPushButton, "btnReset").clicked.connect(self.reset) btnZoom = self.dlg.findChild(QPushButton, "btnZoom") if btnZoom: btnZoom.clicked.connect(self.zoom) for i in range(0, self.TOTAL): combo = self.dlg.findChild(QComboBox, "cboField"+str(i)) combo.currentIndexChanged.connect(self.performSelect)
class SelectTrees(QObject): """QGIS Plugin Implementation.""" #connectionEstablished = pyqtSignal() def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ super(SelectTrees, self).__init__() # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) self.pluginName = os.path.basename(self.plugin_dir) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] self.locale_path = os.path.join(self.plugin_dir, 'i18n', 'SelectTrees_{}.qm'.format(locale)) if os.path.exists(self.locale_path): self.translator = QTranslator() self.translator.load(self.locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # load local settings of the plugin settingFile = os.path.join(self.plugin_dir, 'config', 'SelectTrees.config') self.settings = QSettings(settingFile, QSettings.IniFormat) #self.settings.setIniCodec(sys.stdout.encoding) # load plugin settings self.loadPluginSettings() # Declare instance attributes self.actions = [] self.menu = self.tr(u'&SelectTrees') self.annotations = [] self.mem_layer = None self.layer = None self.initialize = False # establish connection when all is completely running self.iface.initializationCompleted.connect(self.populateGui) def loadPluginSettings(self): ''' Load plugin settings ''' # Get main credentials self.TOTAL = 6 self.SECTION = "main/" # Get layer name self.layer_name = self.settings.value(self.SECTION+'LAYER_NAME', 'Arbres') self.mem_layer_name = self.settings.value(self.SECTION+'MEM_LAYER_NAME', 'Arbres seleccionats') # Get field alias self.field_alias = [] for i in range(0, self.TOTAL): cur_value = self.settings.value(self.SECTION+'FIELD_ALIAS_'+str(i), '') self.field_alias.append(cur_value) # Get field names self.field_name = [] for i in range(0, self.TOTAL): cur_value = self.settings.value(self.SECTION+'FIELD_NAME_'+str(i), '') self.field_name.append(cur_value) # Get default zoom scale self.minZoomScale = int(self.settings.value('status/minZoomScale', 500)) # Get path to QML file self.path_qml = self.settings.value(self.SECTION+'PATH_QML', 'styles/arbres.qml') self.path_qml = self.plugin_dir+"/"+self.path_qml if not os.path.exists(self.path_qml): QgsMessageLog.logMessage(u"QML file not found at: "+self.path_qml, "selectTrees", QgsMessageLog.WARNING) # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('SelectTrees', message) def add_action(self, icon_path, text, callback, parent, shortcut=None, enabled_flag=True, add_to_menu=True, add_to_toolbar=False, status_tip=None, whats_this=None): icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if shortcut is not None: self.iface.registerMainWindowAction(action, shortcut) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) else: self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/SelectTrees/icon_selecttrees.png' self.add_action(icon_path, self.tr(u'Selecció arbres'), self.run, self.iface.mainWindow(), "F8") # Create the dock widget and dock it but hide it waiting the end of qgis loading self.dlg = SelectTreesDockWidget(self.iface.mainWindow()) self.iface.mainWindow().addDockWidget(Qt.LeftDockWidgetArea, self.dlg) self.dlg.setVisible(False) # Set signals self.dlg.findChild(QPushButton, "btnReset").clicked.connect(self.reset) btnZoom = self.dlg.findChild(QPushButton, "btnZoom") if btnZoom: btnZoom.clicked.connect(self.zoom) for i in range(0, self.TOTAL): combo = self.dlg.findChild(QComboBox, "cboField"+str(i)) combo.currentIndexChanged.connect(self.performSelect) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu(self.tr(u'&SelectTrees'), action) self.iface.removeToolBarIcon(action) if self.dlg: self.dlg.deleteLater() del self.dlg def checkLayer(self): if self.layer is not None: return self.iface.setActiveLayer(self.layer) # Iterate over all layers to get the one set in config file layers = self.iface.mapCanvas().layers() for cur_layer in layers: if cur_layer.name() == self.layer_name: self.layer = cur_layer self.feature_count = self.layer.featureCount() return self.iface.setActiveLayer(self.layer) if cur_layer.name() == self.mem_layer_name: self.mem_layer = cur_layer return False def populateGui(self): ''' Populate the interface with values get from active layer ''' #QgsMessageLog.logMessage(u"populateGui: init", "selectTrees", QgsMessageLog.INFO) # Check if layer exists if not self.checkLayer(): QgsMessageLog.logMessage(u"populateGui: Error getting layer of trees", "selectTrees", QgsMessageLog.INFO) self.iface.mainWindow().removeDockWidget(self.dlg) return # Get counter label self.lblCountSelect = self.dlg.findChild(QLabel, "lblCountSelect") # Load field labels for i in range(0, self.TOTAL): label = self.dlg.findChild(QLabel, "lblField"+str(i)) label.setText(self.field_alias[i]) # Load field combos for i in range(0, self.TOTAL): values = set() field_name = self.field_name[i] for feature in self.layer.getFeatures(): if type(feature[field_name]) is not QPyNullVariant: values.add(feature[field_name]) combo = self.dlg.findChild(QComboBox, "cboField"+str(i)) combo.blockSignals(True) combo.clear() combo.addItem('') for elem in sorted(values): if type(elem) is int or type(elem) is long: elem = str(elem) combo.addItem(elem) combo.blockSignals(False) # Update counter self.updateCounter() self.initialize = True def updateCounter(self): msg = "Seleccionats "+str(self.layer.selectedFeatureCount())+" de "+str(self.feature_count)+" arbres" self.lblCountSelect.setText(msg) def run(self): """Run method activated by the toolbar action button""" if not self.initialize: self.populateGui() else: # Get layer set in config file if not self.checkLayer(): self.dlg.setVisible(False) return if self.dlg and not self.dlg.isVisible(): # check if the plugin is active if not self.pluginName in active_plugins: pass # Not working: Try to set plugin to left dock widget area by default self.iface.mainWindow().addDockWidget(Qt.LeftDockWidgetArea, self.dlg) self.dlg.show() def deleteFeatures(self, layer): if layer is not None: it = layer.getFeatures() ids = [i.id() for i in it] layer.dataProvider().deleteFeatures(ids) # Copy from Arbres to memory layer def copySelected(self): # Create memory layer if not already set if self.mem_layer is None: uri = "Point?crs=epsg:25831" self.mem_layer = QgsVectorLayer(uri, self.mem_layer_name, "memory") self.mem_layer.loadNamedStyle(self.path_qml) # Copy attributes from main layer to memory layer attrib_names = self.layer.dataProvider().fields() names_list = attrib_names.toList() newattributeList=[] for attrib in names_list: aux = self.mem_layer.fieldNameIndex(attrib.name()) if aux == -1: newattributeList.append(QgsField(attrib.name(), attrib.type())) self.mem_layer.dataProvider().addAttributes(newattributeList) self.mem_layer.updateFields() QgsMapLayerRegistry.instance().addMapLayer(self.mem_layer) # Prepare memoory layer for editing self.mem_layer.startEditing() # Delete previous features self.deleteFeatures(self.mem_layer) # Iterate over selected features cfeatures = [] for sel_feature in self.layer.selectedFeatures(): attributes = [] attributes.extend(sel_feature.attributes()) cfeature = QgsFeature() cfeature.setGeometry(sel_feature.geometry()) cfeature.setAttributes(attributes) cfeatures.append(cfeature) # Add features, commit changes and refresh canvas self.mem_layer.dataProvider().addFeatures(cfeatures) self.mem_layer.commitChanges() self.iface.mapCanvas().refresh() # Signals def performSelect(self): # Get values from every combo expr_list = [] for i in range(0, self.TOTAL): combo = self.dlg.findChild(QComboBox, "cboField"+str(i)) value = combo.currentText() if value != '': field_name = self.field_name[i] value = value.replace("'", "\\'") aux = field_name+" = '"+value+"'" expr_list.append(aux) # Build new expression aux = '' for i in range(len(expr_list)): if aux != '': aux+= ' and ' aux+= expr_list[i] expr = QgsExpression(aux) if expr.hasParserError(): QgsMessageLog.logMessage(expr.parserErrorString() + ": " + aux, "selectTrees", QgsMessageLog.INFO) return # Get a featureIterator from an expression # Build a list of feature Ids from the previous result # Select features with the ids obtained it = self.layer.getFeatures(QgsFeatureRequest(expr)) ids = [i.id() for i in it] self.layer.setSelectedFeatures(ids) # Update counter self.updateCounter() # Copy selected features to memory layer self.copySelected() def reset(self): # Reset combos, remove selection and update counter for i in range(0, self.TOTAL): combo = self.dlg.findChild(QComboBox, "cboField"+str(i)) combo.blockSignals(True) combo.setCurrentIndex(0) combo.blockSignals(False) self.layer.removeSelection() self.deleteFeatures(self.mem_layer) self.updateCounter() self.iface.mapCanvas().refresh() def zoom(self): if self.checkLayer(): action = self.iface.actionZoomToSelected() action.trigger() if self.iface.mapCanvas().scale() < self.minZoomScale: self.iface.mapCanvas().zoomScale(self.minZoomScale)