def open_feature_form(self, ilayer, ifeature): """"open feature form based on clicked object on the canvas""" ilayer.startEditing() context = QgsAttributeEditorContext() context.setVectorLayerTools(self.iface.vectorLayerTools()) self.attributeForm = QgsAttributeForm(ilayer, ifeature, context) self.stackedWidget.addWidget(self.attributeForm) self.stackedWidget.setCurrentWidget(self.attributeForm) self.iface.setActiveLayer(ilayer) self.terug.clicked.connect(lambda: self.close_stacked(ilayer, ifeature))
def _newDialog(self, cloneFeature): feature = QgsFeature() if (cloneFeature): feature = QgsFeature(self._feature) else: feature = self._feature context = QgsAttributeEditorContext() myDa = QgsDistanceArea() myDa.setSourceCrs(self._layer.crs()) myDa.setEllipsoidalMode( self._iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) myDa.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) context.setDistanceArea(myDa) context.setVectorLayerTools(self._iface.vectorLayerTools()) dialog = QgsAttributeDialog(self._layer, feature, cloneFeature, None, True, context) if (self._layer.actions().size() > 0): dialog.setContextMenuPolicy(Qt.ActionsContextMenu) a = QAction(self.tr('Run actions'), dialog) a.setEnabled(False) dialog.addAction(a) i = 0 for action in self._layer.actions(): if (action.runable()): a = FeatureAction(action.name(), feature, self._layer, i, -1, self._iface, dialog) dialog.addAction(a) a.triggered.connect(a.execute) pb = dialog.findChild(action.name()) if (pb): pb.clicked.connect(a.execute) i += 1 return dialog
def setLayer(self, layer): if layer == self.layer: return if self.layer: try: self.layer.destroyed.disconnect(self.onLayerRemoved) except TypeError: # Do not care if it is not connected pass self.layer = layer if self.layer: self.layer.destroyed.connect(self.onLayerRemoved) self.layerComboBox.setLayer(layer) if self.attributeForm: try: self.attributeForm.deleteLater() except RuntimeError: # Sometimes the form has already been deleted, that's ok for us pass if self.layer is not None: context = QgsAttributeEditorContext() context.setVectorLayerTools(self.iface.vectorLayerTools()) context.setFormMode(QgsAttributeEditorContext.StandaloneDialog) self.attributeForm = QgsAttributeForm(self.layer, QgsFeature(), context) self.attributeForm.hideButtonBox() try: self.layer.updatedFields.disconnect( self.attributeForm.onUpdatedFields) except TypeError: pass fields = self.layer.fields() self.feature = QgsFeature(fields) for idx in range(self.layer.fields().count()): self.feature.setAttribute(idx, self.layer.defaultValue(idx)) self.feature.setValid(True) self.attributeForm.setFeature(self.feature) self.attributeForm.widgetValueChanged.connect( self.onAttributeChanged) self.formWidget.layout().addWidget(self.attributeForm) self.layerChanged.emit(self.layer)
def __init__(self, iface, data, data_path=""): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() self.data = data self.currentProjectId = None self.channelNameEdit.setFocus() self.cancel = False self.data_path_line_edit.setText(data_path) self.pdf_path_widget.setDefaultRoot(data_path) self.cannotImportLabel.hide() self.progressBar.setTextVisible(True) self.progressBar.hide() self.cancelButton.hide() self.pdf_path_widget.setDefaultRoot(data_path) self.relationWidgetWrapper = None maintenance_layer = QgsMapLayerRegistry.instance().mapLayer(self.settings.value("maintenance_layer")) if maintenance_layer is not None: field_idx = maintenance_layer.fieldNameIndex('fk_operating_company') widget_config = maintenance_layer.editorWidgetV2Config(field_idx) editor_context = QgsAttributeEditorContext() editor_context.setVectorLayerTools(iface.vectorLayerTools()) self.relationWidgetWrapper = QgsEditorWidgetRegistry.instance().create("ValueRelation", maintenance_layer, field_idx, widget_config, self.operatingCompanyComboBox, self, editor_context) self.sectionWidget.finish_init(iface, self.data) for p_id, project in self.data.items(): self.projectCombo.addItem(project['Name'], p_id) self.channelNameEdit.setText('')
def _newDialog(self, cloneFeature): feature = QgsFeature() if (cloneFeature): feature = QgsFeature(self._feature) else: feature = self._feature context = QgsAttributeEditorContext() myDa = QgsDistanceArea() myDa.setSourceCrs(self._layer.crs()) myDa.setEllipsoidalMode(self._iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) myDa.setEllipsoid(QgsProject.instance().readEntry('Measure', '/Ellipsoid', GEO_NONE)[0]) context.setDistanceArea(myDa) context.setVectorLayerTools(self._iface.vectorLayerTools()) dialog = QgsAttributeDialog(self._layer, feature, cloneFeature, None, True, context) if (self._layer.actions().size() > 0): dialog.setContextMenuPolicy(Qt.ActionsContextMenu) a = QAction(self.tr('Run actions'), dialog) a.setEnabled(False) dialog.addAction(a) i = 0 for action in self._layer.actions(): if (action.runable()): a = ArkFeatureAction(action.name(), feature, self._layer, i, -1, self._iface, dialog) dialog.addAction(a) a.triggered.connect(a.execute) pb = dialog.findChild(action.name()) if (pb): pb.clicked.connect(a.execute) i += 1 return dialog
def createWrapper(self, layer, filter=None): """ Basic setup of a relation widget wrapper. Will create a new wrapper and set its feature to the one and only book in the table. It will also assign some instance variables to help * self.widget The created widget * self.table_view The table view of the widget :return: The created wrapper """ if layer == self.vl_books: relation = self.rel_b nmrel = self.rel_a else: relation = self.rel_a nmrel = self.rel_b self.wrapper = QgsRelationWidgetWrapper(layer, relation) self.wrapper.setConfig({'nm-rel': nmrel.id()}) context = QgsAttributeEditorContext() context.setMapCanvas(self.mapCanvas) context.setVectorLayerTools(self.vltools) self.wrapper.setContext(context) self.widget = self.wrapper.widget() self.widget.show() request = QgsFeatureRequest() if filter: request.setFilterExpression(filter) book = next(layer.getFeatures(request)) self.wrapper.setFeature(book) self.table_view = self.widget.findChild(QTableView) return self.wrapper
def createWrapper(self, layer, filter=None): """ Basic setup of a relation widget wrapper. Will create a new wrapper and set its feature to the one and only book in the table. It will also assign some instance variables to help * self.widget The created widget * self.table_view The table view of the widget :return: The created wrapper """ if layer == self.vl_b: relation = self.rel_b nmrel = self.rel_a else: relation = self.rel_a nmrel = self.rel_b parent = QWidget() self.wrapper = QgsRelationWidgetWrapper(layer, relation) self.wrapper.setConfig({'nm-rel': nmrel.id()}) context = QgsAttributeEditorContext() context.setVectorLayerTools(self.vltools) self.wrapper.setContext(context) self.widget = self.wrapper.widget() self.widget.show() request = QgsFeatureRequest() if filter: request.setFilterExpression(filter) book = layer.getFeatures(request).next() self.wrapper.setFeature(book) self.table_view = self.widget.findChild(QTableView) return self.wrapper
def test_add_feature_geometry(self): """ Test to add a feature with a geometry """ vl_pipes = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'pk\' table="qgis_test"."pipes" (geom) sql=', 'pipes', 'postgres') vl_leaks = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'pk\' table="qgis_test"."leaks" (geom) sql=', 'leaks', 'postgres') vl_leaks.startEditing() QgsProject.instance().addMapLayer(vl_pipes) QgsProject.instance().addMapLayer(vl_leaks) self.assertEqual(vl_pipes.featureCount(), 2) self.assertEqual(vl_leaks.featureCount(), 3) rel = QgsRelation() rel.setReferencingLayer(vl_leaks.id()) rel.setReferencedLayer(vl_pipes.id()) rel.addFieldPair('pipe', 'id') rel.setId('rel_pipe_leak') self.assertTrue(rel.isValid()) self.relMgr.addRelation(rel) # Mock vector layer tool to just set default value on created feature class DummyVlTools(QgsVectorLayerTools): def addFeature(self, layer, defaultValues, defaultGeometry): f = QgsFeature(layer.fields()) for idx, value in defaultValues.items(): f.setAttribute(idx, value) f.setGeometry(defaultGeometry) ok = layer.addFeature(f) return ok, f wrapper = QgsRelationWidgetWrapper(vl_leaks, rel) context = QgsAttributeEditorContext() vltool = DummyVlTools() context.setVectorLayerTools(vltool) context.setMapCanvas(self.mapCanvas) cadDockWidget = QgsAdvancedDigitizingDockWidget(self.mapCanvas) context.setCadDockWidget(cadDockWidget) wrapper.setContext(context) widget = wrapper.widget() widget.show() pipe = next(vl_pipes.getFeatures()) self.assertEqual(pipe.id(), 1) wrapper.setFeature(pipe) table_view = widget.findChild(QTableView) self.assertEqual(table_view.model().rowCount(), 1) btn = widget.findChild(QToolButton, 'mAddFeatureGeometryButton') self.assertTrue(btn.isVisible()) self.assertTrue(btn.isEnabled()) btn.click() self.assertTrue(self.mapCanvas.mapTool()) feature = QgsFeature(vl_leaks.fields()) feature.setGeometry(QgsGeometry.fromWkt('POINT(0 0.8)')) self.mapCanvas.mapTool().digitizingCompleted.emit(feature) self.assertEqual(table_view.model().rowCount(), 2) self.assertEqual(vl_leaks.featureCount(), 4) request = QgsFeatureRequest() request.addOrderBy("id", False) # get new created feature feat = next(vl_leaks.getFeatures('"id" is NULL')) self.assertTrue(feat.isValid()) self.assertTrue(feat.geometry().equals( QgsGeometry.fromWkt('POINT(0 0.8)'))) vl_leaks.rollBack()
class LinkerDock(QDockWidget, Ui_linker, SettingDialog): def __init__(self, iface): # QGIS self.iface = iface self.settings = MySettings() self.linkRubber = QgsRubberBand(self.iface.mapCanvas()) self.featureHighlight = None # Relation management self.relationManager = QgsProject.instance().relationManager() self.relationManager.changed.connect(self.loadRelations) self.relation = QgsRelation() self.referencingFeature = QgsFeature() self.relationWidgetWrapper = None self.editorContext = QgsAttributeEditorContext() self.editorContext.setVectorLayerTools(self.iface.vectorLayerTools()) # GUI QDockWidget.__init__(self) self.setupUi(self) SettingDialog.__init__(self, MySettings(), False, True) self.drawButton.setChecked(self.settings.value("drawEnabled")) self.relationReferenceWidget.setAllowMapIdentification(True) self.relationReferenceWidget.setEmbedForm(False) self.mapTool = QgsMapToolIdentifyFeature(self.iface.mapCanvas()) self.mapTool.setButton(self.identifyReferencingFeatureButton) # Connect signal/slot self.relationComboBox.currentIndexChanged.connect(self.currentRelationChanged) self.mapTool.featureIdentified.connect(self.setReferencingFeature) # load relations at start self.loadRelations() def showEvent(self, QShowEvent): self.drawLink() def closeEvent(self, e): self.iface.mapCanvas().unsetMapTool(self.mapTool) self.linkRubber.reset() self.deleteHighlight() self.deleteWrapper() self.disconnectLayer() def disconnectLayer(self): if self.relation.isValid(): self.relation.referencingLayer().editingStarted.disconnect(self.relationEditableChanged) self.relation.referencingLayer().editingStopped.disconnect(self.relationEditableChanged) self.relation.referencingLayer().attributeValueChanged.disconnect(self.layerValueChangedOutside) def runForFeature(self, relationId, layer, feature): index = self.relationComboBox.findData(relationId) self.relationComboBox.setCurrentIndex(index) self.setReferencingFeature(feature) self.show() if not layer.isEditable(): self.iface.messageBar().pushMessage("Link It", "Cannot set a new related feature since %s is not editable" % layer.name(), QgsMessageBar.WARNING, 4) else: self.relationReferenceWidget.mapIdentification() @pyqtSlot(name="on_identifyReferencingFeatureButton_clicked") def activateMapTool(self): self.iface.mapCanvas().setMapTool(self.mapTool) def deactivateMapTool(self): self.iface.mapCanvas().unsetMapTool(self.mapTool) def loadRelations(self): self.deleteWrapper() self.disconnectLayer() self.relation = QgsRelation() self.referencingFeature = QgsFeature() self.relationComboBox.currentIndexChanged.disconnect(self.currentRelationChanged) self.relationComboBox.clear() for relation in self.relationManager.referencedRelations(): if relation.referencingLayer().hasGeometryType(): self.relationComboBox.addItem(relation.name(), relation.id()) self.relationComboBox.setCurrentIndex(-1) self.relationComboBox.currentIndexChanged.connect(self.currentRelationChanged) self.currentRelationChanged(-1) def currentRelationChanged(self, index): # disconnect previous relation if self.relation.isValid(): try: self.relation.referencingLayer().editingStarted.disconnect(self.relationEditableChanged) self.relation.referencingLayer().editingStopped.disconnect(self.relationEditableChanged) self.relation.referencingLayer().attributeValueChanged.disconnect(self.layerValueChangedOutside) except TypeError: pass self.referencingFeatureLayout.setEnabled(index >= 0) relationId = self.relationComboBox.itemData(index) self.relation = self.relationManager.relation(relationId) self.mapTool.setLayer(self.relation.referencingLayer()) self.setReferencingFeature() # connect if self.relation.isValid(): self.relation.referencingLayer().editingStarted.connect(self.relationEditableChanged) self.relation.referencingLayer().editingStopped.connect(self.relationEditableChanged) self.relation.referencingLayer().attributeValueChanged.connect(self.layerValueChangedOutside) def setReferencingFeature(self, feature=QgsFeature()): self.deactivateMapTool() self.referencingFeature = QgsFeature(feature) self.deleteWrapper() # disable relation reference widget if no referencing feature self.referencedFeatureLayout.setEnabled(feature.isValid()) # set line edit if not self.relation.isValid() or not feature.isValid(): self.referencingFeatureLineEdit.clear() return self.referencingFeatureLineEdit.setText("%s" % feature.id()) fieldIdx = self.referencingFieldIndex() widgetConfig = self.relation.referencingLayer().editorWidgetV2Config(fieldIdx) self.relationWidgetWrapper = QgsEditorWidgetRegistry.instance().create("RelationReference", self.relation.referencingLayer(), fieldIdx, widgetConfig, self.relationReferenceWidget, self, self.editorContext) self.relationWidgetWrapper.setEnabled(self.relation.referencingLayer().isEditable()) self.relationWidgetWrapper.setValue(feature[fieldIdx]) self.relationWidgetWrapper.valueChanged.connect(self.foreignKeyChanged) # override field definition to allow map identification self.relationReferenceWidget.setAllowMapIdentification(True) self.relationReferenceWidget.setEmbedForm(False) # update drawn link self.highlightReferencingFeature() self.drawLink() def deleteWrapper(self): if self.relationWidgetWrapper is not None: self.relationWidgetWrapper.valueChanged.disconnect(self.foreignKeyChanged) self.relationWidgetWrapper.setValue(None) del self.relationWidgetWrapper self.relationWidgetWrapper = None def foreignKeyChanged(self, newKey): if not self.relation.isValid() or not self.relation.referencingLayer().isEditable() or not self.referencingFeature.isValid(): self.drawLink() return if not self.relation.referencingLayer().editBuffer().changeAttributeValue(self.referencingFeature.id(), self.referencingFieldIndex(), newKey): self.iface.messageBar().pushMessage("Link It", "Cannot change attribute value.", QgsMessageBar.CRITICAL) self.drawLink() def relationEditableChanged(self): if self.relationWidgetWrapper is not None: self.relationWidgetWrapper.setEnabled(self.relation.isValid() and self.relation.referencingLayer().isEditable()) def layerValueChangedOutside(self, fid, fieldIdx, value): if not self.relation.isValid() or not self.referencingFeature.isValid() or self.relationWidgetWrapper is None: return # not the correct feature if fid != self.referencingFeature.id(): return # not the correct field if fieldIdx != self.referencingFieldIndex(): return # widget already has this value if value == self.relationWidgetWrapper.value(): return self.relationWidgetWrapper.valueChanged.disconnect(self.foreignKeyChanged) self.relationWidgetWrapper.setValue(value) self.relationWidgetWrapper.valueChanged.connect(self.foreignKeyChanged) def referencingFieldIndex(self): if not self.relation.isValid(): return -1 fieldName = self.relation.fieldPairs().keys()[0] fieldIdx = self.relation.referencingLayer().fieldNameIndex(fieldName) return fieldIdx @pyqtSlot(bool, name="on_drawButton_toggled") def drawLink(self): self.settings.setValue("drawEnabled", self.drawButton.isChecked()) self.linkRubber.reset() if not self.drawButton.isChecked() or not self.referencingFeature.isValid() or not self.relation.isValid(): return referencedFeature = self.relationReferenceWidget.referencedFeature() if not referencedFeature.isValid(): return p1 = self.centroid(self.relation.referencedLayer(), referencedFeature) p2 = self.centroid(self.relation.referencingLayer(), self.referencingFeature) geom = arc(p1, p2) self.linkRubber.setToGeometry(geom, None) self.linkRubber.setWidth(self.settings.value("rubberWidth")) self.linkRubber.setColor(self.settings.value("rubberColor")) self.linkRubber.setLineStyle(Qt.DashLine) def centroid(self, layer, feature): geom = feature.geometry() if geom.type() == QGis.Line: geom = geom.interpolate(geom.length()/2) else: geom = geom.centroid() return self.iface.mapCanvas().mapSettings().layerToMapCoordinates(layer, geom.asPoint()) @pyqtSlot(name="on_highlightReferencingFeatureButton_clicked") def highlightReferencingFeature(self): self.deleteHighlight() if not self.relation.isValid() or not self.referencingFeature.isValid(): return self.featureHighlight = QgsHighlight(self.iface.mapCanvas(), self.referencingFeature.geometry(), self.relation.referencingLayer()) settings = QSettings() color = QColor( settings.value("/Map/highlight/color", QGis.DEFAULT_HIGHLIGHT_COLOR.name())) alpha = int(settings.value("/Map/highlight/colorAlpha", QGis.DEFAULT_HIGHLIGHT_COLOR.alpha())) bbuffer = float(settings.value("/Map/highlight/buffer", QGis.DEFAULT_HIGHLIGHT_BUFFER_MM)) minWidth = float(settings.value("/Map/highlight/minWidth", QGis.DEFAULT_HIGHLIGHT_MIN_WIDTH_MM)) self.featureHighlight.setColor(color) color.setAlpha(alpha) self.featureHighlight.setFillColor(color) self.featureHighlight.setBuffer(bbuffer) self.featureHighlight.setMinWidth(minWidth) self.featureHighlight.show() timer = QTimer(self) timer.setSingleShot(True) timer.timeout.connect(self.deleteHighlight) timer.start(3000) def deleteHighlight(self): if self.featureHighlight: del self.featureHighlight self.featureHighlight = None
class LinkerDock(QDockWidget, Ui_linker, SettingDialog): def __init__(self, iface): # QGIS self.iface = iface self.settings = MySettings() self.linkRubber = QgsRubberBand(self.iface.mapCanvas()) self.featureHighlight = None # Relation management self.relationManager = QgsProject.instance().relationManager() self.relationManager.changed.connect(self.loadRelations) self.relation = QgsRelation() self.referencingFeature = QgsFeature() self.relationWidgetWrapper = None self.editorContext = QgsAttributeEditorContext() self.editorContext.setVectorLayerTools(self.iface.vectorLayerTools()) # GUI QDockWidget.__init__(self) self.setupUi(self) SettingDialog.__init__(self, MySettings(), False, True) self.drawButton.setChecked(self.settings.value("drawEnabled")) self.relationReferenceWidget.setAllowMapIdentification(True) self.relationReferenceWidget.setEmbedForm(False) self.mapTool = QgsMapToolIdentifyFeature(self.iface.mapCanvas()) self.mapTool.setButton(self.identifyReferencingFeatureButton) # Connect signal/slot self.relationComboBox.currentIndexChanged.connect( self.currentRelationChanged) self.mapTool.featureIdentified.connect(self.setReferencingFeature) # load relations at start self.loadRelations() def showEvent(self, QShowEvent): self.drawLink() def closeEvent(self, e): self.iface.mapCanvas().unsetMapTool(self.mapTool) self.linkRubber.reset() self.deleteHighlight() self.deleteWrapper() self.disconnectLayer() def disconnectLayer(self): if self.relation.isValid(): self.relation.referencingLayer().editingStarted.disconnect( self.relationEditableChanged) self.relation.referencingLayer().editingStopped.disconnect( self.relationEditableChanged) self.relation.referencingLayer().attributeValueChanged.disconnect( self.layerValueChangedOutside) def runForFeature(self, relationId, layer, feature): index = self.relationComboBox.findData(relationId) self.relationComboBox.setCurrentIndex(index) self.setReferencingFeature(feature) self.show() if not layer.isEditable(): self.iface.messageBar().pushMessage( "Link It", "Cannot set a new related feature since %s is not editable" % layer.name(), QgsMessageBar.WARNING, 4) else: self.relationReferenceWidget.mapIdentification() @pyqtSlot(name="on_identifyReferencingFeatureButton_clicked") def activateMapTool(self): self.iface.mapCanvas().setMapTool(self.mapTool) def deactivateMapTool(self): self.iface.mapCanvas().unsetMapTool(self.mapTool) def loadRelations(self): self.deleteWrapper() self.disconnectLayer() self.relation = QgsRelation() self.referencingFeature = QgsFeature() self.relationComboBox.currentIndexChanged.disconnect( self.currentRelationChanged) self.relationComboBox.clear() for relation in self.relationManager.referencedRelations(): if relation.referencingLayer().hasGeometryType(): self.relationComboBox.addItem(relation.name(), relation.id()) self.relationComboBox.setCurrentIndex(-1) self.relationComboBox.currentIndexChanged.connect( self.currentRelationChanged) self.currentRelationChanged(-1) def currentRelationChanged(self, index): # disconnect previous relation if self.relation.isValid(): try: self.relation.referencingLayer().editingStarted.disconnect( self.relationEditableChanged) self.relation.referencingLayer().editingStopped.disconnect( self.relationEditableChanged) self.relation.referencingLayer( ).attributeValueChanged.disconnect( self.layerValueChangedOutside) except TypeError: pass self.referencingFeatureLayout.setEnabled(index >= 0) relationId = self.relationComboBox.itemData(index) self.relation = self.relationManager.relation(relationId) self.mapTool.setLayer(self.relation.referencingLayer()) self.setReferencingFeature() # connect if self.relation.isValid(): self.relation.referencingLayer().editingStarted.connect( self.relationEditableChanged) self.relation.referencingLayer().editingStopped.connect( self.relationEditableChanged) self.relation.referencingLayer().attributeValueChanged.connect( self.layerValueChangedOutside) def setReferencingFeature(self, feature=QgsFeature()): self.deactivateMapTool() self.referencingFeature = QgsFeature(feature) self.deleteWrapper() # disable relation reference widget if no referencing feature self.referencedFeatureLayout.setEnabled(feature.isValid()) # set line edit if not self.relation.isValid() or not feature.isValid(): self.referencingFeatureLineEdit.clear() return self.referencingFeatureLineEdit.setText("%s" % feature.id()) fieldIdx = self.referencingFieldIndex() widgetConfig = self.relation.referencingLayer().editorWidgetV2Config( fieldIdx) self.relationWidgetWrapper = QgsEditorWidgetRegistry.instance().create( "RelationReference", self.relation.referencingLayer(), fieldIdx, widgetConfig, self.relationReferenceWidget, self, self.editorContext) self.relationWidgetWrapper.setEnabled( self.relation.referencingLayer().isEditable()) self.relationWidgetWrapper.setValue(feature[fieldIdx]) self.relationWidgetWrapper.valueChanged.connect(self.foreignKeyChanged) # override field definition to allow map identification self.relationReferenceWidget.setAllowMapIdentification(True) self.relationReferenceWidget.setEmbedForm(False) # update drawn link self.highlightReferencingFeature() self.drawLink() def deleteWrapper(self): if self.relationWidgetWrapper is not None: self.relationWidgetWrapper.valueChanged.disconnect( self.foreignKeyChanged) self.relationWidgetWrapper.setValue(None) del self.relationWidgetWrapper self.relationWidgetWrapper = None def foreignKeyChanged(self, newKey): if not self.relation.isValid() or not self.relation.referencingLayer( ).isEditable() or not self.referencingFeature.isValid(): self.drawLink() return if not self.relation.referencingLayer().editBuffer( ).changeAttributeValue(self.referencingFeature.id(), self.referencingFieldIndex(), newKey): self.iface.messageBar().pushMessage( "Link It", "Cannot change attribute value.", QgsMessageBar.CRITICAL) self.drawLink() def relationEditableChanged(self): if self.relationWidgetWrapper is not None: self.relationWidgetWrapper.setEnabled( self.relation.isValid() and self.relation.referencingLayer().isEditable()) def layerValueChangedOutside(self, fid, fieldIdx, value): if not self.relation.isValid() or not self.referencingFeature.isValid( ) or self.relationWidgetWrapper is None: return # not the correct feature if fid != self.referencingFeature.id(): return # not the correct field if fieldIdx != self.referencingFieldIndex(): return # widget already has this value if value == self.relationWidgetWrapper.value(): return self.relationWidgetWrapper.valueChanged.disconnect( self.foreignKeyChanged) self.relationWidgetWrapper.setValue(value) self.relationWidgetWrapper.valueChanged.connect(self.foreignKeyChanged) def referencingFieldIndex(self): if not self.relation.isValid(): return -1 fieldName = self.relation.fieldPairs().keys()[0] fieldIdx = self.relation.referencingLayer().fieldNameIndex(fieldName) return fieldIdx @pyqtSlot(bool, name="on_drawButton_toggled") def drawLink(self): self.settings.setValue("drawEnabled", self.drawButton.isChecked()) self.linkRubber.reset() if not self.drawButton.isChecked( ) or not self.referencingFeature.isValid( ) or not self.relation.isValid(): return referencedFeature = self.relationReferenceWidget.referencedFeature() if not referencedFeature.isValid(): return p1 = self.centroid(self.relation.referencedLayer(), referencedFeature) p2 = self.centroid(self.relation.referencingLayer(), self.referencingFeature) geom = arc(p1, p2) self.linkRubber.setToGeometry(geom, None) self.linkRubber.setWidth(self.settings.value("rubberWidth")) self.linkRubber.setColor(self.settings.value("rubberColor")) self.linkRubber.setLineStyle(Qt.DashLine) def centroid(self, layer, feature): geom = feature.geometry() if geom.type() == QGis.Line: geom = geom.interpolate(geom.length() / 2) else: geom = geom.centroid() return self.iface.mapCanvas().mapSettings().layerToMapCoordinates( layer, geom.asPoint()) @pyqtSlot(name="on_highlightReferencingFeatureButton_clicked") def highlightReferencingFeature(self): self.deleteHighlight() if not self.relation.isValid() or not self.referencingFeature.isValid( ): return self.featureHighlight = QgsHighlight( self.iface.mapCanvas(), self.referencingFeature.geometry(), self.relation.referencingLayer()) settings = QSettings() color = QColor( settings.value("/Map/highlight/color", QGis.DEFAULT_HIGHLIGHT_COLOR.name())) alpha = int( settings.value("/Map/highlight/colorAlpha", QGis.DEFAULT_HIGHLIGHT_COLOR.alpha())) bbuffer = float( settings.value("/Map/highlight/buffer", QGis.DEFAULT_HIGHLIGHT_BUFFER_MM)) minWidth = float( settings.value("/Map/highlight/minWidth", QGis.DEFAULT_HIGHLIGHT_MIN_WIDTH_MM)) self.featureHighlight.setColor(color) color.setAlpha(alpha) self.featureHighlight.setFillColor(color) self.featureHighlight.setBuffer(bbuffer) self.featureHighlight.setMinWidth(minWidth) self.featureHighlight.show() timer = QTimer(self) timer.setSingleShot(True) timer.timeout.connect(self.deleteHighlight) timer.start(3000) def deleteHighlight(self): if self.featureHighlight: del self.featureHighlight self.featureHighlight = None