def runLabel(self): self.iface.mapCanvas().freeze(1) sourceLayer = self.iface.activeLayer() # keepUserSelection = False try: if not sourceLayer: iface.messageBar().pushMessage( "Error", QtGui.QApplication.translate( "EasyCustomLabeling", "There is no layer currently selected, \n please click on the vector layer you need to label", None, QtGui.QApplication.UnicodeUTF8), level=0, duration=3) return if not sourceLayer.type() == sourceLayer.VectorLayer: iface.messageBar().pushMessage( "Error", QtGui.QApplication.translate( "EasyCustomLabeling", "Current active layer is not a vector layer. \n Please click on the vector layer you need to label", None, QtGui.QApplication.UnicodeUTF8), level=0, duration=3) return # detect if selection exists on that layer #debug nbSelectedObjects = sourceLayer.selectedFeatureCount() # print '# nbSelectedObjects: ' + str(nbSelectedObjects) ret = 0 if not nbSelectedObjects == 0: #dialog to ask if user wants to use current selection or not msgBox = QMessageBox() msgBox.setIcon(QtGui.QMessageBox.Question) msgBox.setWindowTitle("EasyCustomLabeling") msgBox.setText( QtGui.QApplication.translate( "EasyCustomLabeling", "Use %n selected object(s) only for labeling ?", None, QtGui.QApplication.UnicodeUTF8, nbSelectedObjects)) msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Ok) ret = msgBox.exec_() #ret_val = 16384 si OK, 4194304 sinon if ret == 4194304: # cancel button finish program self.iface.mapCanvas().freeze(0) print 'dialog keep selection: ' + str(ret) return elif ret == 65536: # No button65536 use entire layer print 'use entire layer' elif ret == 16384: print 'use selection' nbSelectedObjects = sourceLayer.selectedFeatureCount() if sourceLayer.selectedFeatureCount( ) > 500: #alert if many objects selected msgBox = QMessageBox() msgBox.setText( QtGui.QApplication.translate( "EasyCustomLabeling", "Your layer contains many objects. Continue anyway?", None, QtGui.QApplication.UnicodeUTF8)) msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) msgBox.setDefaultButton( QMessageBox.Ok) # This function was introduced in Qt 4.3. ret2 = msgBox.exec_() #ret_val = 1024 si OK, 4194304 sinon # print 'dialog many objects: ' + str(ret) if ret2 != 1024: print 'user cancel on too many object question' return #end of general tests and user interaction -------------------------------------------------- sourceLayerProvider = sourceLayer.dataProvider() sourceLayerFields = sourceLayerProvider.fields() feat = QgsFeature() #asks for default field to use as labeling (thanks to Victor Axbom Layer to labeled layer plugin) # create the dialog self.dlg = EasyCustomLabelingDialog(sourceLayerProvider) ret_dlg_field = self.dlg.exec_() #cancels if user cancels dialog: if ret_dlg_field == 0: return # show the dialog # if self.dlg.exec_(): # return True# print 'dialog execution' # else : # return # self.iface.mapCanvas().refresh() # returns self.dlg.labelfield.currentText() # creates new memory labelLayer and provider #labelLayer = QgsVectorLayer( "Point", "Label", "memory") # creates points memory layer labelLayer = QgsVectorLayer( "LineString", "Label", "memory") # creates lines memory layer - test v0.6 labelLayer.setLayerName("Label_" + sourceLayer.name()) labelLayer.setCrs(sourceLayer.crs()) labelLayerProvider = labelLayer.dataProvider() labelLayerFields = labelLayerProvider.fields() # print 'nom du champ 1 : ' + str(sourceLayerFields[1].name()) #convert field map to a list sourceLayerFieldsList = [] for f in sourceLayerFields: # print 'debug date : champ: ' + str(f.name()) + 'type_champ ' + str(f.typeName()) if f.type() == 14: f.setType(10) sourceLayerFieldsList.append(f) #print 'sourceLayerFieldsList: ' + str(sourceLayerFieldsList) #copy sourceLayer fields into it r = labelLayerProvider.addAttributes(sourceLayerFieldsList) #print 'ajout des champs source: ' + str(r) # # adds specific fields for data driven custom labeling labelFields = [ QgsField("LblField", QVariant.String, "varchar", 255), QgsField("LblX", QVariant.String, "varchar", 255), QgsField("LblY", QVariant.String, "varchar", 255), QgsField("LblAlignH", QVariant.String, "varchar", 12), QgsField("LblAlignV", QVariant.String, "varchar", 12), QgsField("LblSize", QVariant.Int, "integer", 2), QgsField("LblRot", QVariant.Double, "numeric", 10, 2), QgsField("LblBold", QVariant.Int, "integer", 1), QgsField("LblItalic", QVariant.Int, "integer", 1), QgsField("LblColor", QVariant.String, "varchar", 7), QgsField("LblFont", QVariant.String, "varchar", 64), QgsField("LblUnder", QVariant.Int, "integer", 1), QgsField("LblStrike", QVariant.Int, "integer", 1), QgsField("LblShow", QVariant.Int, "integer", 1), QgsField("LblShowCO", QVariant.Int, "integer", 1), QgsField("LblAShow", QVariant.Int, "integer", 1) ] r = labelLayerProvider.addAttributes(labelFields) # print 'ajout des champs de labeling: ' + str(r) labelFields = labelLayerProvider.fields( ) # replace labelFields with source FIELDS + labelingFields # iterate objects of layer to load new destination labelLayerProvider # print 'start loop on source layer attributes' if ret == 16384: selectedFeatures = sourceLayer.selectedFeatures() else: selectedFeatures = sourceLayer.getFeatures() for sourceFeat in selectedFeatures: labelLayerFields = labelLayerProvider.fields() # print 'length of field map: ' + str(len(labelLayerFields)) # for f in labelLayerFields: # print str(f.name()) labelFeature = QgsFeature(labelLayerFields) geom = sourceFeat.geometry() #labelFeature.setGeometry(QgsGeometry.fromPoint(geom.centroid().asPoint())) # create geometry as centroid WKTLine = 'LINESTRING(' + str( geom.centroid().asPoint().x() + 0.0001) + ' ' + str( geom.centroid().asPoint().y() + 0.0001) + ' , ' + str( geom.centroid().asPoint().x()) + ' ' + str( geom.centroid().asPoint().y()) + ')' # print 'WKTLine: '+ WKTLine labelFeature.setGeometry(QgsGeometry.fromWkt( WKTLine)) # create geometry as centroid attrs = sourceFeat.attributes() sourceFieldCount = len(attrs) # print 'length of copied attributes : '+ str(len(attrs)) # print 'attributs sources ' + str(attrs) for i, a in enumerate(attrs): #print str(i) + ' ' + str(a) labelFeature[i] = a #labelFeature.setAttributes(attrs) labelFeature['LblField'] = sourceFeat[ self.dlg.labelfield.currentText( )] #gets fields chosen by user in dialog labelFeature['LblShow'] = 1 labelFeature['LblSize'] = 9 labelFeature['LblAShow'] = 1 labelFeature['LblAlignV'] = 'Half' labelFeature['LblAlignH'] = 'Center' # displayFieldName = sourceLayer.displayField() # if displayFieldName : # # print ' valeur du champ label : ' + str(sourceFeat[displayFieldName]) # labelFeature['LblField'] = str(sourceFeat[displayFieldName]) # else: # labelFeature['LblField'] = str(sourceFeat[0]) #-- prefill some attributes examples (default = deactivated) # labelFeature['LblX'] = str(geom.centroid().asPoint().x()) # coord x # labelFeature['LblY'] = str(geom.centroid().asPoint().y()) # coord x labelLayerProvider.addFeatures([labelFeature]) labelLayer.updateExtents() labelMapLayer = QgsMapLayerRegistry.instance().addMapLayer( labelLayer, True) # adds map layer to map registry # # customize style rendererV2 = labelMapLayer.rendererV2() # creates default style for label (transparent point, default labeling ) style_path = os.path.join(os.path.dirname(__file__), "label_style.qml") (errorMsg, result) = labelMapLayer.loadNamedStyle(style_path) # for QGIS 2.1 and > , use data defined pen size >0 with $length / $scale > 0.05 to display arrows only # or use a flag , and compute it to 1 if label is moved. how to hide easily if needed ? ## parameters for advanced labeling -- picked up from a qgs model file # #generic labeling properties labelMapLayer.setCustomProperty( "labeling/fieldName", "LblField") # TODO replace default value with dialog input labelMapLayer.setCustomProperty( "labeling", "pal") # new gen labeling activated labelMapLayer.setCustomProperty("labeling/fontSize", "8") # default value labelMapLayer.setCustomProperty("labeling/multiLineLabels", "true") # default value labelMapLayer.setCustomProperty("labeling/enabled", "true") # default value #labelMapLayer.setCustomProperty("labeling/displayAll", "true") # force all labels to display labelMapLayer.setCustomProperty( "labeling/priority", "10") # puts a high priority to labeling layer labelMapLayer.setCustomProperty("labeling/multilineAlign", "1") # multiline align to center #labelMapLayer.setCustomProperty("labeling/wrapChar", "%") # multiline break symbol #line properties case labelMapLayer.setCustomProperty("labeling/placement", "4") # #data defined properties labelMapLayer.setCustomProperty("labeling/dataDefined/PositionX", "1~~0~~~~LblX") labelMapLayer.setCustomProperty("labeling/dataDefined/PositionY", "1~~0~~~~LblY") labelMapLayer.setCustomProperty("labeling/dataDefined/Hali", "1~~0~~~~LblAlignH") labelMapLayer.setCustomProperty("labeling/dataDefined/Vali", "1~~0~~~~LblAlignV") labelMapLayer.setCustomProperty("labeling/dataDefined/Size", "1~~0~~~~LblSize") labelMapLayer.setCustomProperty("labeling/dataDefined/Rotation", "1~~0~~~~LblRot") labelMapLayer.setCustomProperty("labeling/dataDefined/Bold", "1~~0~~~~LblBold") labelMapLayer.setCustomProperty("labeling/dataDefined/Italic", "1~~0~~~~LblItalic") labelMapLayer.setCustomProperty("labeling/dataDefined/Underline", "1~~0~~~~LblUnder") labelMapLayer.setCustomProperty("labeling/dataDefined/Strikeout", "1~~0~~~~LblStrike") labelMapLayer.setCustomProperty("labeling/dataDefined/Color", "1~~0~~~~LblColor") labelMapLayer.setCustomProperty("labeling/dataDefined/Family", "1~~0~~~~LblFont") labelMapLayer.setCustomProperty("labeling/dataDefined/Show", "1~~0~~~~LblShow") labelMapLayer.setCustomProperty("labeling/dataDefined/AlwaysShow", "1~~0~~~~LblAShow") # sets a tag in abstract metadata to help reconnect layer on project read (avoid having to read data, which causes problem with mem Layer Saver still populating data) labelMapLayer.setAbstract( '<labeling_layer> do not remove - used by EasyCustomLabeling plugin to reconnect labeling layers' ) labelLayer.updateExtents() # activates editing self.iface.setActiveLayer(labelMapLayer) labelLayer.startEditing() self.iface.actionToggleEditing().trigger() # connects label layer attributes values changed to labelLayerModified function labelLayer.attributeValueChanged.connect(self.labelLayerModified) #redraws registry and mapcanvas. if hasattr(labelMapLayer, "setCacheImage") and QGis.QGIS_VERSION_INT < 20600: labelMapLayer.setCacheImage(None) labelMapLayer.triggerRepaint() self.iface.legendInterface().refreshLayerSymbology(labelMapLayer) self.iface.actionToggleEditing().trigger() iface.messageBar().pushMessage( "Avertissement", QtGui.QApplication.translate( "EasyCustomLabeling", "Turn on editing mode on label layer to start customizing labels" ), level=0, duration=3) except: # print 'runLabel exception loop ' # if sourceLayer and not keepUserSelection : # sourceLayer.removeSelection() print 'exception caught' raise finally: if QGis.QGIS_VERSION_INT < 20600: QgsMapLayerRegistry.instance().clearAllLayerCaches( ) #clean cache to allow mask layer to appear on refresh # if sourceLayer and not keepUserSelection : # sourceLayer.removeSelection() self.iface.mapCanvas().freeze(0) self.iface.mapCanvas().refresh()