diff --git a/210910-teksi-drink-logos-en-01_20pp.png b/210910-teksi-drink-logos-en-01_20pp.png deleted file mode 100644 index d121dee..0000000 Binary files a/210910-teksi-drink-logos-en-01_20pp.png and /dev/null differ diff --git a/210910-teksi-drink-logos-en-01_45pp.png b/210910-teksi-drink-logos-en-01_45pp.png deleted file mode 100644 index 4a6d482..0000000 Binary files a/210910-teksi-drink-logos-en-01_45pp.png and /dev/null differ diff --git a/210910-teksi-drink-logos-en-01_96pp.png b/210910-teksi-drink-logos-en-01_96pp.png deleted file mode 100644 index ff9f765..0000000 Binary files a/210910-teksi-drink-logos-en-01_96pp.png and /dev/null differ diff --git a/210910-teksi-drink-logos-en-03.png b/210910-teksi-drink-logos-en-03.png deleted file mode 100644 index 10acdec..0000000 Binary files a/210910-teksi-drink-logos-en-03.png and /dev/null differ diff --git a/210910-teksi-drink-logos-en-03_45pp.png b/210910-teksi-drink-logos-en-03_45pp.png deleted file mode 100644 index cbb4eb4..0000000 Binary files a/210910-teksi-drink-logos-en-03_45pp.png and /dev/null differ diff --git a/README.rst b/README.rst index 12fbccb..6c1dd60 100644 --- a/README.rst +++ b/README.rst @@ -1,15 +1,13 @@ -.. image:: 210910-teksi-drink-logos-en-01_96pp.png +.. image:: qwat.png -TEKSI drinking water module (Project QWAT) -========================================================= - -Open source water distribution network module based on QGIS / Postgis +QWAT: QGIS Water Module +======================= Documentation ------------- -Hosted version here: https://qwat.github.io/docs/ +Hosted version here: https://qwat.github.io/docs/master/en/html/ The documentation has its own repository at https://github.com/qwat/docs @@ -18,12 +16,12 @@ Requirements Server side software components are: -* `PostgreSQL `_ (> 10) -* `PostGIS `_, the spatial extension (> 2.5) +* `PostgreSQL `_ (> 9.6) +* `PostGIS `_, the spatial extension (> 2.3) * `Python `_, for installation and update (> 3.5) * `PUM `_ for upgrade -Supported and tested versions are PostgreSQL 10 and Postgis 2.5. +Supported and tested versions are PostgreSQL 9.6 and Postgis 2.3. The exact required hardware configuration is very dependant on the data sizes. However, water network data tend not to be huge volumes, and the minimal required configuration is very low. diff --git a/qgis-project/actions/action_incident.py b/qgis-project/actions/action_incident.py new file mode 100644 index 0000000..09c2a07 --- /dev/null +++ b/qgis-project/actions/action_incident.py @@ -0,0 +1,142 @@ +""" +This action code should be added to the pipe layer in the QGIS project +""" + +from PyQt5.QtGui import QColor +from PyQt5.QtCore import QVariant +from qgis.utils import iface +from PyQt5 import uic +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtWidgets import * + +GROUP_NAME = "Incident réseau" +LAYER_RESULAT_NAME = "Vannes à fermer" + +VALVE_SOURCE_NAME = '"qwat_od"."valve"' + +class SearchOpenedValvesDialog(QDialog): + def __init__(self, parent, pipe_id, x, y): + super(SearchOpenedValvesDialog, self).__init__(parent) + self.pipe_id = pipe_id + self.setWindowTitle("Incident sur le réseau") + self.point = QgsGeometry() + self.startFeature = None + self.endFeature = None + self.x = x + self.y = y + + # Get CRS from settings table + query = "(select id, value from qwat_sys.settings)" + source = """{} key='id' table="({})" ()""".format("service=qwat", query) + crsLayer = QgsVectorLayer(source, "temporary", "postgres") + if crsLayer.isValid(): + for feature in crsLayer.getFeatures(): + self.crs = feature["value"] + break + + self.layout = QGridLayout() + self.layout.setContentsMargins(10, 10, 10, 10) + + self.kmLabel = QLabel("Km max. : ") + self.layout.addWidget(self.kmLabel, 0, 0) + self.kmSpinBox = QDoubleSpinBox() + self.kmSpinBox.setDecimals(2) + self.kmSpinBox.setMinimum(0.1) + self.kmSpinBox.setMaximum(50) + self.kmSpinBox.setValue(1) + self.layout.addWidget(self.kmSpinBox, 1, 0) + + self.checkNetworkValves = QCheckBox("S'arrêter uniquement aux vannes réseaux") + self.checkNetworkValves.setChecked(True) + self.layout.addWidget(self.checkNetworkValves, 2, 0) + + buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel + self.buttonBox = QDialogButtonBox(buttons) + self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.searchOpenedValves) + self.buttonBox.rejected.connect(self.reject) + self.layout.addWidget(self.buttonBox, 3, 0) + + self.setLayout(self.layout) + + def showEvent(self, event): + self.setupLayers() + + def setupLayers(self): + layers = QgsProject.instance().mapLayers() + valve_layername = None + for layer_id, layer in layers.items(): + if layer.dataProvider().uri().quotedTablename() == VALVE_SOURCE_NAME: + valve_layername = layer.name() + break + if (valve_layername is None): + QgsMessageLog.logMessage("Valve layer does not exist in QGIS project !", 'Messages', Qgis.Critical) + iface.messageBar().pushMessage("Error", "Valve layer does not exist in QGIS project !", level=Qgis.Critical) + QTimer.singleShot(0, self.reject) + return + self.valve_layer = QgsProject.instance().mapLayersByName(valve_layername)[0] + + def searchOpenedValves(self): + km = self.kmSpinBox.value() + stopOnNetworkValves = str(self.checkNetworkValves.isChecked()) + + # Check if the result layer already exists + self.cleanResults() + + # Set query for a temporary layer which will retreive the data only one time + query = """(select * from qwat_network.ft_search_opened_valves({pipe_id},{x},{y},{km},{stopOnNetworkValves}))""".format(pipe_id=str(self.pipe_id), x=str(self.x), y=str(self.y), km=str(km), stopOnNetworkValves=str(stopOnNetworkValves)) + + # Set connection to database + source = """{} key='id' table="{}" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("Point?crs=epsg:" + self.crs, LAYER_RESULAT_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + # Join valve layer + join = QgsVectorLayerJoinInfo() + join.setJoinFieldName('id') + join.setTargetFieldName('id') + join.setJoinLayerId(self.valve_layer.id()) + join.setUsingMemoryCache(True) + join.setJoinLayer(self.valve_layer) + layer.addJoin(join) + + layer.renderer().symbol().setSize(10) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + map_layer = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(map_layer) + self.close() + self.reorderLayers(self.group) + + def cleanResults(self): + root = QgsProject.instance().layerTreeRoot() + self.group = root.findGroup(GROUP_NAME) + if self.group: + self.group.removeAllChildren() + else: + self.group = root.insertGroup(0, GROUP_NAME) + + def reorderLayers(self, group): + bridge = iface.layerTreeCanvasBridge() + order = bridge.rootGroup().customLayerOrder() + for layer in group.children(): + order.insert(0, order.pop(order.index(layer.layer()))) + bridge.rootGroup().setCustomLayerOrder(order) + +sp = SearchOpenedValvesDialog(iface.mainWindow(), [% "ID" %], [% @click_x %], [% @click_y %]) +sp.show() diff --git a/qgis-project/actions/action_interruption.py b/qgis-project/actions/action_interruption.py new file mode 100644 index 0000000..6a859b4 --- /dev/null +++ b/qgis-project/actions/action_interruption.py @@ -0,0 +1,415 @@ +from PyQt5.QtGui import QColor +from qgis.utils import iface +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtWidgets import * + +GROUP_NAME = "Interruption réseau" +PIPE_LAYER_NAME = "Conduites" +HYDRANT_LAYER_NAME = "Bornes hydrantes" +METER_LAYER_NAME = "Compteurs réseau" +SUBSCRIBER_LAYER_NAME = "Abonnés" +SUBSCRIBER_REF_LAYER_NAME = "Renvois d'abonnés" + +VALVE_SOURCE_NAME = '"qwat_od"."valve"' +PIPE_SOURCE_NAME = '"qwat_od"."pipe"' + +class selectTool(QgsMapToolIdentifyFeature): + def __init__(self, iface, layer): + self.iface = iface + self.canvas = self.iface.mapCanvas() + self.layer = layer + QgsMapToolIdentifyFeature.__init__(self, self.canvas, self.layer) + +class NetworkInterruptionDialog(QDialog): + def __init__(self, parent, valve_id): + super().__init__(parent) + self.setWindowTitle("Interruption réseau") + uri = QgsDataSourceUri() + uri.setConnection("qwat", "", "", "") + uri.setDataSource("qwat_network", "network", "geometry", "") + self.network_layer = QgsVectorLayer(uri.uri(), "Network", "postgres") + + # Get CRS from settings table + query = "(select id, value from qwat_sys.settings)" + source = """{} key='id' table="({})" ()""".format("service=qwat", query) + crsLayer = QgsVectorLayer(source, "temporary", "postgres") + if crsLayer.isValid(): + for feature in crsLayer.getFeatures(): + self.crs = feature["value"] + break + + self.startPoint = QgsPoint() + self.pipeFeature = None + self.valves = [] + self.status = [] + + # Store result pipes, sources and targets in lists + self.resultPipes = [] + self.resultSources = [] + self.resultTargets = [] + # Store result subscribers in list + self.resultSubscribers = [] + + self.layout = QGridLayout() + self.layout.setContentsMargins(10, 10, 10, 10) + + + self.valvesLabel = QLabel("Sélectionner les vannes à fermer") + self.valvesList = QListWidget() + self.valvesList.setSelectionMode(QAbstractItemView.MultiSelection) + self.valveVerticalLayout = QVBoxLayout() + self.selectValveToolButton = QToolButton() + self.selectValveToolButton.setIcon(QgsApplication.instance().getThemeIcon('symbologyAdd.svg')) + self.selectValveToolButton.setFixedSize(25, 25) + self.selectValveToolButton.setToolTip('Sélectionner une vanne...') + self.selectValveToolButton.setObjectName('SelectValvesButton') + self.selectValveToolButton.clicked.connect(self.selectValves) + self.removeValveToolButton = QToolButton() + self.removeValveToolButton.setIcon(QgsApplication.instance().getThemeIcon('symbologyRemove.svg')) + self.removeValveToolButton.setFixedSize(25, 25) + self.removeValveToolButton.setToolTip('Supprimer la vanne sélectionnée') + self.removeValveToolButton.setObjectName('RemoveValveButton') + self.removeValveToolButton.clicked.connect(self.removeValves) + self.valveVerticalLayout.addStretch() + self.valveVerticalLayout.addWidget(self.selectValveToolButton) + self.valveVerticalLayout.addWidget(self.removeValveToolButton) + self.layout.addWidget(self.valvesLabel, 0, 0) + self.layout.addWidget(self.valvesList, 1, 0) + self.layout.addLayout(self.valveVerticalLayout, 1, 1) + + self.pipeLabel = QLabel("Sélectionner une conduite") + self.pipeText = QTextEdit() + self.pipeText.setReadOnly(True) + self.pipeVerticalLayout = QVBoxLayout() + self.selectPipeToolButton = QToolButton() + self.selectPipeToolButton.setIcon(QgsApplication.instance().getThemeIcon('symbologyAdd.svg')) + self.selectPipeToolButton.setFixedSize(25, 25) + self.selectPipeToolButton.setToolTip('Sélectionner une conduite...') + self.selectPipeToolButton.setObjectName('SelectPipeButton') + self.selectPipeToolButton.clicked.connect(self.selectPipe) + self.pipeVerticalLayout.addStretch() + self.pipeVerticalLayout.addWidget(self.selectPipeToolButton) + self.layout.addWidget(self.pipeLabel, 2, 0) + self.layout.addWidget(self.pipeText, 3, 0) + self.layout.addLayout(self.pipeVerticalLayout, 3, 1) + + self.kmMaxLabel = QLabel("Km max. : ") + self.layout.addWidget(self.kmMaxLabel, 4, 0) + self.kmMaxSpinBox = QDoubleSpinBox() + self.kmMaxSpinBox.setDecimals(2) + self.kmMaxSpinBox.setMinimum(0.1) + self.kmMaxSpinBox.setMaximum(50) + self.kmMaxSpinBox.setValue(1) + self.layout.addWidget(self.kmMaxSpinBox, 4, 1) + + buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel + self.buttonBox = QDialogButtonBox(buttons) + self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.searchNetwork) + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + self.buttonBox.rejected.connect(self.reject) + self.layout.addWidget(self.buttonBox) + + self.setLayout(self.layout) + + # Add valve where action was launched from + self.valvesList.addItem(str(valve_id)) + self.valves.append(valve_id) + + def showEvent(self, event): + self.setupLayers() + + def setupLayers(self): + layers = QgsProject.instance().mapLayers() + valve_layername = None + pipe_layername = None + for layer_id, layer in layers.items(): + if (layer.dataProvider().uri().quotedTablename() == VALVE_SOURCE_NAME) \ + and (layer.dataProvider().uri().geometryColumn() == 'geometry'): + valve_layername = layer.name() + break + for layer_id, layer in layers.items(): + if (layer.dataProvider().uri().quotedTablename() == PIPE_SOURCE_NAME) \ + and (layer.dataProvider().uri().geometryColumn() == 'geometry'): + pipe_layername = layer.name() + break + if (valve_layername is None) or (pipe_layername is None): + QgsMessageLog.logMessage("Valve layer or Pipe layer does not exist in QGIS project !", 'Messages', Qgis.Critical) + iface.messageBar().pushMessage("Error", "Valve layer or Pipe layer does not exist in QGIS project !", level=Qgis.Critical) + QTimer.singleShot(0, self.reject) + return + self.valve_layer = QgsProject.instance().mapLayersByName(valve_layername)[0] + self.valvesMapTool = selectTool(iface, self.valve_layer) + self.pipe_layer = QgsProject.instance().mapLayersByName(pipe_layername)[0] + self.pipeMapTool = selectTool(iface, self.network_layer) + + def onValveIdentified(self, feature): + QgsMessageLog.logMessage("Vanne : " + str(feature.id()) + " sélectionnée", 'Messages', Qgis.Info) + if feature.id() not in self.valves: + self.valvesList.addItem(str(feature.id())) + self.valves.append(feature.id()) + self.status.append(feature['closed']) + else: + QgsMessageLog.logMessage("La vanne " + str(feature.id()) + " est déjà sélectionnée.", 'Messages', Qgis.Info) + if (self.valves and self.pipeFeature): + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) + + def selectValves(self): + self.valvesMapTool.featureIdentified.connect(self.onValveIdentified) + iface.mapCanvas().setMapTool(self.valvesMapTool) + + def removeValves(self): + selectedValves = [item.text() for item in self.valvesList.selectedItems()] + if selectedValves: + self.valves = [v for v in self.valves if str(v) not in selectedValves] + for item in self.valvesList.selectedItems(): + self.valvesList.takeItem(self.valvesList.row(item)) + iface.mapCanvas().setMapTool(self.valvesMapTool) + + def onPipeIdentified(self, feature): + QgsMessageLog.logMessage("Conduite : " + str(feature['id']) + " sélectionnée", 'Messages', Qgis.Info) + self.pipeText.setText('Conduite : ' + str(feature['id'])) + self.pipeFeature = feature + + if (self.valves and self.pipeFeature): + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) + + iface.mapCanvas().unsetMapTool(self.pipeMapTool) + + def selectPipe(self): + self.pipeMapTool.featureIdentified.connect(self.onPipeIdentified) + iface.mapCanvas().setMapTool(self.pipeMapTool) + + def searchNetwork(self): + self.resultPipes.clear() + self.resultSources.clear() + self.resultTargets.clear() + self.resultSubscribers.clear() + if (not self.pipeFeature is None) or (not self.valves): + root = QgsProject.instance().layerTreeRoot() + self.group = root.findGroup(GROUP_NAME) + if self.group: + self.group.removeAllChildren() + else: + self.group = root.insertGroup(0, GROUP_NAME) + self.searchPipes() + if self.resultPipes: + self.searchHydrants() + self.searchMeters() + self.searchSubscribers() + if self.resultSubscribers: + self.searchSubscribersReferences() + if self.resultPipes: + self.reorderLayers(self.group) + self.close() + + def searchPipes(self): + QgsMessageLog.logMessage("Recherche des conduites", 'Messages', Qgis.Info) + networkId = self.pipeFeature['network_id'] + pipeId = self.pipeFeature['id'] + kmMax = self.kmMaxSpinBox.value() + QgsMessageLog.logMessage("Recherche de chemins depuis la conduite " + str(pipeId), 'Messages', Qgis.Info) + QgsMessageLog.logMessage("Vannes fermées : " + str(self.valves), 'Messages', Qgis.Info) + # Set query + query = "(select * from qwat_network.ft_network_cutoff(array{valves}, {networkId}, {kmmax}))"\ + .format(valves=str(self.valves), networkId=str(networkId), kmmax=str(kmMax)) + # Set connection to database + source = """{} key='id,source,target' table="({})" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("LineString?crs=epsg:" + self.crs, PIPE_LAYER_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + self.resultPipes.append(feature['id']) + self.resultSources.append(feature['source']) + self.resultTargets.append(feature['target']) + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + # Join pipe layer + join = QgsVectorLayerJoinInfo() + join.setJoinFieldName('id') + join.setTargetFieldName('id') + join.setJoinLayerId(self.pipe_layer.id()) + join.setUsingMemoryCache(True) + join.setJoinLayer(self.pipe_layer) + layer.addJoin(join) + + layer.renderer().symbol().setWidth(3.0) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + l = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(l) + else: + QgsMessageLog.logMessage("Layer not valid in search pipes", 'Messages', Qgis.Critical) + + + def searchHydrants(self): + QgsMessageLog.logMessage("Recherche des bornes hydrantes", 'Messages', Qgis.Info) + networkId = self.pipeFeature['network_id'] + kmMax = self.kmMaxSpinBox.value() + # Set query + query = """ + with pipes as + ( + select * from qwat_network.ft_network_cutoff(array{valves}, {networkId}, {kmmax}) + where qwat_network.ft_check_node_is_hydrant(source) + or qwat_network.ft_check_node_is_hydrant(target) + ) + select h.* from qwat_od.vw_element_hydrant h, pipes where h.id in (pipes.target) or h.id in (pipes.source) + """.format(valves=str(self.valves), networkId=str(networkId), kmmax=str(kmMax)) + # query = """ + # select h.id, h.geometry + # from qwat_od.vw_element_hydrant h + # where h.id in ({targets}) or h.id in ({sources}) + # """.format(targets=', '.join(repr(t) for t in self.resultTargets), + # sources=', '.join(repr(s) for s in self.resultSources)) + # Set connection to database + source = """{} key='id' table="({})" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("Point?crs=epsg:" + self.crs, HYDRANT_LAYER_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + layer.renderer().symbol().setSize(10) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + l = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(l) + + def searchMeters(self): + QgsMessageLog.logMessage("Recherche des compteurs réseau", 'Messages', Qgis.Info) + # Set query + query = """ + select * + from qwat_od.vw_element_meter m + where m.id in ({pipes}) + """.format(pipes=', '.join(repr(p) for p in self.resultPipes)) + # Set connection to database + source = """{} key='id' table="({})" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("Point?crs=epsg:" + self.crs, METER_LAYER_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + layer.renderer().symbol().setSize(8) + layer.renderer().symbol().symbolLayer(0).setShape(QgsSimpleMarkerSymbolLayerBase.Square) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + l = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(l) + + def searchSubscribers(self): + QgsMessageLog.logMessage("Recherche des abonnés", 'Messages', Qgis.Info) + # Set query + query = """ + select * from qwat_od.vw_element_subscriber + where fk_pipe in ({pipes}) + """.format(pipes=', '.join(repr(p) for p in self.resultPipes)) + # Set connection to database + source = """{} key='id' table="({})" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("Point?crs=epsg:" + self.crs, SUBSCRIBER_LAYER_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + self.resultSubscribers.append(feature['ID']) + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + layer.renderer().symbol().setSize(10) + layer.renderer().symbol().symbolLayer(0).setShape(QgsSimpleMarkerSymbolLayerBase.Pentagon) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + l = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(l) + + def searchSubscribersReferences(self): + QgsMessageLog.logMessage("Recherche des renvois abonnés", 'Messages', Qgis.Info) + # Set query + query = """ + select * from qwat_od.subscriber_reference + where fk_subscriber in ({subscribers}) + """.format(subscribers=', '.join(repr(s) for s in self.resultSubscribers)) + # Set connection to database + source = """{} key='id' table="({})" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("Point?crs=epsg:" + self.crs, SUBSCRIBER_REF_LAYER_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + layer.renderer().symbol().setSize(8) + layer.renderer().symbol().symbolLayer(0).setShape(QgsSimpleMarkerSymbolLayerBase.Hexagon) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + l = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(l) + + def reorderLayers(self, group): + bridge = iface.layerTreeCanvasBridge() + order = bridge.rootGroup().customLayerOrder() + for layer in group.children(): + order.insert(0, order.pop(order.index(layer.layer()))) + bridge.rootGroup().setCustomLayerOrder(order) + +nc = NetworkInterruptionDialog(iface.mainWindow(), [% "ID" %]) +nc.show() diff --git a/qgis-project/actions/action_pollution.py b/qgis-project/actions/action_pollution.py new file mode 100644 index 0000000..f3905a1 --- /dev/null +++ b/qgis-project/actions/action_pollution.py @@ -0,0 +1,198 @@ +""" +This action code should be added to the pipe layer in the QGIS project +""" + +from PyQt5.QtGui import QColor +from PyQt5.QtCore import QVariant +from qgis.utils import iface +from PyQt5 import uic +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtWidgets import * + +GROUP_NAME = "Pollution réseau" +LAYER_RESULAT_NAME = "Conduites touchées" +SUBSCRIBER_LAYER_NAME = "Abonnés" + +PIPE_SOURCE_NAME = '"qwat_od"."pipe"' + +class SearchPipesDialog(QDialog): + def __init__(self, parent, pipe_id, x, y): + super(SearchPipesDialog, self).__init__(parent) + self.pipe_id = pipe_id + self.x = x + self.y = y + self.setWindowTitle("Pollution sur le réseau") + self.point = QgsGeometry() + self.startFeature = None + self.endFeature = None + + # Get CRS from settings table + query = "(select id, value from qwat_sys.settings)" + source = """{} key='id' table="({})" ()""".format("service=qwat", query) + crsLayer = QgsVectorLayer(source, "temporary", "postgres") + if crsLayer.isValid(): + for feature in crsLayer.getFeatures(): + self.crs = feature["value"] + break + + # Store result pipes, sources and targets in lists + self.resultPipes = [] + + self.layout = QGridLayout() + self.layout.setContentsMargins(10, 10, 10, 10) + + self.kmLabel = QLabel("Km max. : ") + self.layout.addWidget(self.kmLabel, 0, 0) + self.kmSpinBox = QDoubleSpinBox() + self.kmSpinBox.setDecimals(2) + self.kmSpinBox.setMinimum(0.1) + self.kmSpinBox.setMaximum(50) + self.kmSpinBox.setValue(1) + self.layout.addWidget(self.kmSpinBox, 1, 0) + + self.stopOnNetworkValves = QCheckBox("S'arrêter aux vannes réseaux") + self.stopOnNetworkValves.setChecked(False) + self.layout.addWidget(self.stopOnNetworkValves, 2, 0) + + self.stopOnSubscriberValves = QCheckBox("S'arrêter aux vannes abonnés") + self.stopOnSubscriberValves.setChecked(True) + self.layout.addWidget(self.stopOnSubscriberValves, 3, 0) + + self.stopOnCurrentPressureZone = QCheckBox("Limiter à la zone de pression courante") + self.stopOnCurrentPressureZone.setChecked(True) + self.layout.addWidget(self.stopOnCurrentPressureZone, 4, 0) + + buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel + self.buttonBox = QDialogButtonBox(buttons) + self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.searchNetwork) + self.buttonBox.rejected.connect(self.reject) + self.layout.addWidget(self.buttonBox, 5, 0) + + self.setLayout(self.layout) + + def showEvent(self, event): + self.setupLayers() + + def setupLayers(self): + layers = QgsProject.instance().mapLayers() + pipe_layername = None + for layer_id, layer in layers.items(): + if layer.dataProvider().uri().quotedTablename() == PIPE_SOURCE_NAME: + pipe_layername = layer.name() + break + if (pipe_layername is None): + QgsMessageLog.logMessage("Pipe layer does not exist in QGIS project !", 'Messages', Qgis.Critical) + iface.messageBar().pushMessage("Error", "Pipe layer does not exist in QGIS project !", level=Qgis.Critical) + QTimer.singleShot(0, self.reject) + return + self.pipe_layer = QgsProject.instance().mapLayersByName(pipe_layername)[0] + + def searchNetwork(self): + # Check if the result layer already exists + self.cleanResults() + self.resultPipes.clear() + + self.searchPipes() + if self.resultPipes: + self.searchSubscribers() + self.reorderLayers(self.group) + + def searchPipes(self): + km = self.kmSpinBox.value() + stopOnNetworkValves = self.stopOnNetworkValves.isChecked() + stopOnSubscriberValves = self.stopOnSubscriberValves.isChecked() + stopOnCurrentPressureZone = self.stopOnCurrentPressureZone.isChecked() + + # Set query for a temporary layer which will retreive the data only one time + query = """(select * from qwat_network.ft_search_network_and_subscribers({pipe_id},{x},{y},{km},{stopOnNetworkValves},{stopOnSubscriberValves},{stopOnCurrentPressureZone}))""".format(pipe_id=str(self.pipe_id), x=str(self.x), y=str(self.y), km=str(km), stopOnNetworkValves=str(stopOnNetworkValves), stopOnSubscriberValves=str(stopOnSubscriberValves), stopOnCurrentPressureZone=str(stopOnCurrentPressureZone)) + + # Set connection to database + source = """{} key='id' table="{}" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("LineString?crs=epsg:" + self.crs, LAYER_RESULAT_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + self.resultPipes.append(feature['id']) + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + # Join pipe layer + join = QgsVectorLayerJoinInfo() + join.setJoinFieldName('id') + join.setTargetFieldName('id_pipe') + join.setJoinLayerId(self.pipe_layer.id()) + join.setUsingMemoryCache(True) + join.setJoinLayer(self.pipe_layer) + layer.addJoin(join) + + layer.renderer().symbol().setWidth(5) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + map_layer = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(map_layer) + self.close() + + def searchSubscribers(self): + QgsMessageLog.logMessage("Recherche des abonnés", 'Messages', Qgis.Info) + # Set query + query = """ + select * from qwat_od.vw_element_subscriber + where fk_pipe in (select id from qwat_network.network where network_id in ({pipes})) + """.format(pipes=', '.join(repr(p) for p in self.resultPipes)) + # Set connection to database + source = """{} key='id' table="({})" (geometry)""".format("service=qwat", query) + + tmpLayer = QgsVectorLayer(source, "temporary", "postgres") + if tmpLayer.isValid(): + # Create a memory layer (the final one which will be display to the user) + layer = QgsVectorLayer("Point?crs=epsg:" + self.crs, SUBSCRIBER_LAYER_NAME, "memory") + + # Copy feature from temporary layer to final one (memory) + attr = tmpLayer.dataProvider().fields().toList() + features = [] + for feature in tmpLayer.getFeatures(): + features.append(feature) + + layer.startEditing() + dataP = layer.dataProvider() + dataP.addAttributes(attr) + layer.updateFields() + dataP.addFeatures(features) + layer.commitChanges() + + layer.renderer().symbol().setSize(10) + layer.renderer().symbol().symbolLayer(0).setShape(QgsSimpleMarkerSymbolLayerBase.Pentagon) + layer.renderer().symbol().setColor(QColor(255, 0, 0)) + map_layer = QgsProject.instance().addMapLayer(layer, False) + self.group.addLayer(map_layer) + + def cleanResults(self): + root = QgsProject.instance().layerTreeRoot() + self.group = root.findGroup(GROUP_NAME) + if self.group: + self.group.removeAllChildren() + else: + self.group = root.insertGroup(0, GROUP_NAME) + + def reorderLayers(self, group): + bridge = iface.layerTreeCanvasBridge() + order = bridge.rootGroup().customLayerOrder() + for layer in group.children(): + order.insert(0, order.pop(order.index(layer.layer()))) + bridge.rootGroup().setCustomLayerOrder(order) + +sp = SearchPipesDialog(iface.mainWindow(), [% "ID" %], [% @click_x %], [% @click_y %]) +sp.show() diff --git a/qgis-project/qwat.qgs b/qgis-project/qwat.qgs index 8709e48..2b7df21 100644 --- a/qgis-project/qwat.qgs +++ b/qgis-project/qwat.qgs @@ -1,5 +1,5 @@ - + QWAT demo project for QGIS 3.22 - DB model 1.4 @@ -30,7 +30,7 @@ - + - + - + - - - + + @@ -28047,15 +28055,15 @@ def my_form_open(dialog, layer, feature): - - + + @@ -28076,15 +28084,15 @@ def my_form_open(dialog, layer, feature): - - + + @@ -28104,21 +28112,21 @@ def my_form_open(dialog, layer, feature): - - - + + @@ -28138,15 +28146,15 @@ def my_form_open(dialog, layer, feature): - - + + @@ -28166,15 +28174,15 @@ def my_form_open(dialog, layer, feature): - - + + @@ -28194,15 +28202,15 @@ def my_form_open(dialog, layer, feature): - - + + @@ -28222,15 +28230,15 @@ def my_form_open(dialog, layer, feature): - - + + @@ -28251,9 +28259,9 @@ def my_form_open(dialog, layer, feature): @@ -28262,36 +28270,36 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - + + + - - - @@ -28305,23 +28313,23 @@ def my_form_open(dialog, layer, feature): 0 1 - - + + - + - @@ -28334,8 +28342,8 @@ def my_form_open(dialog, layer, feature): @@ -28344,14 +28352,14 @@ def my_form_open(dialog, layer, feature): @@ -28360,14 +28368,14 @@ def my_form_open(dialog, layer, feature): @@ -28376,8 +28384,8 @@ def my_form_open(dialog, layer, feature): @@ -28386,8 +28394,8 @@ def my_form_open(dialog, layer, feature): @@ -28396,8 +28404,8 @@ def my_form_open(dialog, layer, feature): @@ -28406,8 +28414,8 @@ def my_form_open(dialog, layer, feature): @@ -28416,8 +28424,8 @@ def my_form_open(dialog, layer, feature): @@ -28426,8 +28434,8 @@ def my_form_open(dialog, layer, feature): @@ -28436,8 +28444,8 @@ def my_form_open(dialog, layer, feature): @@ -28446,8 +28454,8 @@ def my_form_open(dialog, layer, feature): @@ -28456,8 +28464,8 @@ def my_form_open(dialog, layer, feature): @@ -28466,8 +28474,8 @@ def my_form_open(dialog, layer, feature): @@ -28476,8 +28484,8 @@ def my_form_open(dialog, layer, feature): @@ -28486,8 +28494,8 @@ def my_form_open(dialog, layer, feature): @@ -28496,14 +28504,14 @@ def my_form_open(dialog, layer, feature): @@ -28512,14 +28520,14 @@ def my_form_open(dialog, layer, feature): @@ -28528,8 +28536,8 @@ def my_form_open(dialog, layer, feature): @@ -28538,14 +28546,14 @@ def my_form_open(dialog, layer, feature): @@ -28554,14 +28562,14 @@ def my_form_open(dialog, layer, feature): @@ -28570,14 +28578,14 @@ def my_form_open(dialog, layer, feature): @@ -28586,14 +28594,14 @@ def my_form_open(dialog, layer, feature): @@ -28602,8 +28610,8 @@ def my_form_open(dialog, layer, feature): @@ -28612,8 +28620,8 @@ def my_form_open(dialog, layer, feature): @@ -28622,8 +28630,8 @@ def my_form_open(dialog, layer, feature): @@ -28632,8 +28640,8 @@ def my_form_open(dialog, layer, feature): @@ -28642,8 +28650,8 @@ def my_form_open(dialog, layer, feature): @@ -28652,8 +28660,8 @@ def my_form_open(dialog, layer, feature): @@ -28662,8 +28670,8 @@ def my_form_open(dialog, layer, feature): @@ -28672,8 +28680,8 @@ def my_form_open(dialog, layer, feature): @@ -28682,8 +28690,8 @@ def my_form_open(dialog, layer, feature): @@ -28692,8 +28700,8 @@ def my_form_open(dialog, layer, feature): @@ -28702,8 +28710,8 @@ def my_form_open(dialog, layer, feature): @@ -28712,8 +28720,8 @@ def my_form_open(dialog, layer, feature): @@ -28722,8 +28730,8 @@ def my_form_open(dialog, layer, feature): @@ -28732,8 +28740,8 @@ def my_form_open(dialog, layer, feature): @@ -28742,8 +28750,8 @@ def my_form_open(dialog, layer, feature): @@ -28773,13 +28781,13 @@ def my_form_open(dialog, layer, feature): @@ -28789,8 +28797,8 @@ def my_form_open(dialog, layer, feature): @@ -28799,13 +28807,13 @@ def my_form_open(dialog, layer, feature): @@ -28814,14 +28822,14 @@ def my_form_open(dialog, layer, feature): @@ -28830,14 +28838,14 @@ def my_form_open(dialog, layer, feature): @@ -28846,8 +28854,8 @@ def my_form_open(dialog, layer, feature): @@ -28856,8 +28864,8 @@ def my_form_open(dialog, layer, feature): @@ -28866,8 +28874,8 @@ def my_form_open(dialog, layer, feature): @@ -28876,8 +28884,8 @@ def my_form_open(dialog, layer, feature): @@ -28886,14 +28894,14 @@ def my_form_open(dialog, layer, feature): @@ -28902,14 +28910,14 @@ def my_form_open(dialog, layer, feature): @@ -28918,8 +28926,8 @@ def my_form_open(dialog, layer, feature): @@ -28928,8 +28936,8 @@ def my_form_open(dialog, layer, feature): @@ -28938,8 +28946,8 @@ def my_form_open(dialog, layer, feature): @@ -28948,8 +28956,8 @@ def my_form_open(dialog, layer, feature): @@ -28958,8 +28966,8 @@ def my_form_open(dialog, layer, feature): @@ -28968,8 +28976,8 @@ def my_form_open(dialog, layer, feature): @@ -28978,8 +28986,8 @@ def my_form_open(dialog, layer, feature): @@ -28988,8 +28996,8 @@ def my_form_open(dialog, layer, feature): @@ -28998,8 +29006,8 @@ def my_form_open(dialog, layer, feature): @@ -29008,14 +29016,14 @@ def my_form_open(dialog, layer, feature): @@ -29024,8 +29032,8 @@ def my_form_open(dialog, layer, feature): @@ -29034,8 +29042,8 @@ def my_form_open(dialog, layer, feature): @@ -29044,8 +29052,8 @@ def my_form_open(dialog, layer, feature): @@ -29054,8 +29062,8 @@ def my_form_open(dialog, layer, feature): @@ -29064,14 +29072,14 @@ def my_form_open(dialog, layer, feature): @@ -29080,8 +29088,8 @@ def my_form_open(dialog, layer, feature): @@ -29090,8 +29098,8 @@ def my_form_open(dialog, layer, feature): @@ -29100,8 +29108,8 @@ def my_form_open(dialog, layer, feature): @@ -29110,8 +29118,8 @@ def my_form_open(dialog, layer, feature): @@ -29120,14 +29128,14 @@ def my_form_open(dialog, layer, feature): @@ -29136,14 +29144,14 @@ def my_form_open(dialog, layer, feature): @@ -29152,8 +29160,8 @@ def my_form_open(dialog, layer, feature): @@ -29162,8 +29170,8 @@ def my_form_open(dialog, layer, feature): @@ -29172,8 +29180,8 @@ def my_form_open(dialog, layer, feature): @@ -29182,10 +29190,10 @@ def my_form_open(dialog, layer, feature): @@ -29194,8 +29202,8 @@ def my_form_open(dialog, layer, feature): @@ -29204,14 +29212,14 @@ def my_form_open(dialog, layer, feature): @@ -29220,13 +29228,13 @@ def my_form_open(dialog, layer, feature): @@ -29235,13 +29243,13 @@ def my_form_open(dialog, layer, feature): @@ -29250,14 +29258,14 @@ def my_form_open(dialog, layer, feature): @@ -29266,11 +29274,11 @@ def my_form_open(dialog, layer, feature): @@ -29279,8 +29287,8 @@ def my_form_open(dialog, layer, feature): @@ -29289,8 +29297,8 @@ def my_form_open(dialog, layer, feature): @@ -29299,14 +29307,14 @@ def my_form_open(dialog, layer, feature): @@ -29315,8 +29323,8 @@ def my_form_open(dialog, layer, feature): @@ -29325,8 +29333,8 @@ def my_form_open(dialog, layer, feature): @@ -29335,8 +29343,8 @@ def my_form_open(dialog, layer, feature): @@ -29345,8 +29353,8 @@ def my_form_open(dialog, layer, feature): @@ -29355,8 +29363,8 @@ def my_form_open(dialog, layer, feature): @@ -29365,11 +29373,11 @@ def my_form_open(dialog, layer, feature): @@ -29378,8 +29386,8 @@ def my_form_open(dialog, layer, feature): @@ -29388,8 +29396,8 @@ def my_form_open(dialog, layer, feature): @@ -29398,8 +29406,8 @@ def my_form_open(dialog, layer, feature): @@ -29408,8 +29416,8 @@ def my_form_open(dialog, layer, feature): @@ -29418,8 +29426,8 @@ def my_form_open(dialog, layer, feature): @@ -29428,8 +29436,8 @@ def my_form_open(dialog, layer, feature): @@ -29438,8 +29446,8 @@ def my_form_open(dialog, layer, feature): @@ -29448,8 +29456,8 @@ def my_form_open(dialog, layer, feature): @@ -29458,8 +29466,8 @@ def my_form_open(dialog, layer, feature): @@ -29468,8 +29476,8 @@ def my_form_open(dialog, layer, feature): @@ -29478,8 +29486,8 @@ def my_form_open(dialog, layer, feature): @@ -29488,329 +29496,329 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -29921,112 +29929,112 @@ def my_form_open(dialog, layer, feature): - + - @@ -30147,109 +30155,109 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -30270,49 +30278,49 @@ def my_form_open(dialog, layer, feature): 1 0 - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - - - + + + - + - + - - + + - + @@ -67239,7 +67253,7 @@ def closeProject(): - + @@ -67254,7 +67268,7 @@ def closeProject(): - + - + - - + + - + @@ -67362,7 +67376,7 @@ def closeProject(): - + - + - + @@ -67434,10 +67448,10 @@ def closeProject(): - + - + @@ -67452,13 +67466,13 @@ def closeProject(): - + - printmap20130304110011400 + printmap20130304110011400 - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + @@ -67713,10 +67727,10 @@ def closeProject(): - + - + @@ -67731,10 +67745,10 @@ def closeProject(): - + - + @@ -67749,10 +67763,10 @@ def closeProject(): - + - + @@ -67767,10 +67781,10 @@ def closeProject(): - + - + @@ -67785,10 +67799,10 @@ def closeProject(): - + - + @@ -67803,10 +67817,10 @@ def closeProject(): - + - + @@ -67821,281 +67835,281 @@ def closeProject(): - + - vw_node_installation20150918153835436 - subscriber20130304110011459 - od_subscriber_reference20131206105928067 - od_meter20131120073630165 - od_meter_reference20140304165835390 - valve20130304110011497 - hydrant20130304110004848 - od_part20140429113327995 - node20130304110005126 - od_crossing20141023083754327 - conduites_copy20130709141244955 - od_remote20150116100522170 - od_annotationline20131203095020365 - od_annotationpoint20131203095020392 - dimension20130807094904783 - od_dimension_orientation20131202111155806 - printmap20130304110011400 + vw_node_installation20150918153835436 + subscriber20130304110011459 + od_subscriber_reference20131206105928067 + od_meter20131120073630165 + od_meter_reference20140304165835390 + valve20130304110011497 + hydrant20130304110004848 + od_part20140429113327995 + node20130304110005126 + od_crossing20141023083754327 + conduites_copy20130709141244955 + od_remote20150116100522170 + od_annotationline20131203095020365 + od_annotationpoint20131203095020392 + dimension20130807094904783 + od_dimension_orientation20131202111155806 + printmap20130304110011400 - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + @@ -68125,8 +68139,8 @@ def closeProject(): - - + + @@ -68156,8 +68170,8 @@ def closeProject(): - - + + @@ -68187,8 +68201,8 @@ def closeProject(): - - + + @@ -68218,8 +68232,8 @@ def closeProject(): - - + + @@ -68249,8 +68263,8 @@ def closeProject(): - - + + @@ -68280,8 +68294,8 @@ def closeProject(): - - + + @@ -68311,8 +68325,8 @@ def closeProject(): - - + + @@ -68342,8 +68356,8 @@ def closeProject(): - - + + @@ -68373,8 +68387,8 @@ def closeProject(): - - + + @@ -68404,8 +68418,8 @@ def closeProject(): - - + + @@ -68435,8 +68449,8 @@ def closeProject(): - - + + @@ -68466,8 +68480,8 @@ def closeProject(): - - + + @@ -68497,8 +68511,8 @@ def closeProject(): - - + + @@ -68528,8 +68542,8 @@ def closeProject(): - - + + @@ -68547,8 +68561,8 @@ def closeProject(): - - + + @@ -68582,7 +68596,7 @@ def closeProject(): - + @@ -68617,8 +68631,8 @@ def closeProject(): - - + + @@ -68648,8 +68662,8 @@ def closeProject(): - - + + @@ -68679,8 +68693,8 @@ def closeProject(): - - + + @@ -68710,8 +68724,8 @@ def closeProject(): - - + + @@ -68741,8 +68755,8 @@ def closeProject(): - - + + @@ -68772,8 +68786,8 @@ def closeProject(): - - + + @@ -68817,77 +68831,77 @@ def closeProject(): - - - - - - - + + + + + + + - - - + + + - + - - - - - - - + + + + + + + - - + + - - - - - - - + + + + + + + - - + + - - - - - - - + + + + + + + - - + + - - - - - - - + + + + + + + - - + + @@ -69061,37 +69075,37 @@ def closeProject(): - - + + - + . - - + + ./ui_forms/pipe.ui @@ -69143,26 +69157,26 @@ def my_form_open(dialog, layer, feature): 1 - - + + - + - + - + - + - + - - + + @@ -69328,20 +69342,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -69771,36 +69785,36 @@ def my_form_open(dialog, layer, feature): - - + + - + . - + ./ui_forms/hydrant.ui @@ -69833,63 +69847,63 @@ def my_form_open(dialog, layer, feature): 0 - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + @@ -69916,8 +69930,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -69948,8 +69962,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -69980,8 +69994,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -70012,8 +70026,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -70219,36 +70233,36 @@ def my_form_open(dialog, layer, feature): - - + + - + . - + . @@ -70281,35 +70295,35 @@ def my_form_open(dialog, layer, feature): 0 - - + + - + - + - + - + - + - + - + - + - - + + @@ -70473,20 +70487,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - - + + @@ -70706,20 +70720,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -70827,7 +70841,7 @@ def my_form_open(dialog, layer, feature): - + @@ -70872,8 +70886,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -71062,20 +71076,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - - + + @@ -71281,20 +71295,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -71648,40 +71662,40 @@ def my_form_open(dialog, layer, feature): . - - - - - - - - - + + + + + + + + + - + ./ui_forms/meter.ui @@ -71698,23 +71712,23 @@ def my_form_open(dialog, layer, feature): 0 - - + + - + - + - + - + - - + + @@ -71909,20 +71923,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + @@ -72113,8 +72127,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -72145,8 +72159,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -72177,8 +72191,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -72208,8 +72222,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -72406,36 +72420,36 @@ def my_form_open(dialog, layer, feature): - - + + - + . - + ./ui_forms/part.ui @@ -72468,80 +72482,80 @@ def my_form_open(dialog, layer, feature): 0 - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -72741,36 +72755,36 @@ def my_form_open(dialog, layer, feature): - - + + - + . - + . @@ -72803,23 +72817,23 @@ def my_form_open(dialog, layer, feature): 1 - - + + - + - + - + - + - - + + @@ -73014,20 +73028,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -73368,42 +73382,42 @@ def my_form_open(dialog, layer, feature): - - + + - + . - - - - + + + + - + . @@ -73436,154 +73450,154 @@ def my_form_open(dialog, layer, feature): 2 - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - + - - + + @@ -73611,8 +73625,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -73640,8 +73654,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -73669,8 +73683,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -73698,8 +73712,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -73727,8 +73741,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -73756,8 +73770,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -73955,48 +73969,48 @@ def my_form_open(dialog, layer, feature): - - + + - + . - - - - - - - - - + + + + + + + + + - - + + ./ui_forms/subscriber.ui @@ -74033,241 +74047,241 @@ def my_form_open(dialog, layer, feature): 0 - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - + + @@ -74295,8 +74309,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74324,8 +74338,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74353,8 +74367,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74382,8 +74396,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74414,8 +74428,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74443,8 +74457,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74472,8 +74486,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74501,8 +74515,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74530,8 +74544,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -74742,51 +74756,51 @@ def my_form_open(dialog, layer, feature): - - + + - + . - - - - - - - - - - - - - + + + + + + + + + + + + + - + ./ui_forms/valve.ui @@ -74819,125 +74833,125 @@ def my_form_open(dialog, layer, feature): 0 - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -74947,230 +74961,230 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + @@ -75197,8 +75211,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75217,8 +75231,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75237,8 +75251,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75257,8 +75271,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75277,8 +75291,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75297,8 +75311,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75325,8 +75339,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75345,8 +75359,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75365,8 +75379,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75393,8 +75407,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75413,8 +75427,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75434,8 +75448,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75454,8 +75468,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75474,8 +75488,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75498,8 +75512,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75518,8 +75532,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75538,8 +75552,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75558,8 +75572,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75578,8 +75592,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -75764,31 +75778,31 @@ def my_form_open(dialog, layer, feature): - - + + - + . @@ -75814,9 +75828,9 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - - - + + + - + - + - + @@ -76136,7 +76150,7 @@ def my_form_open(dialog, layer, feature): - + - + - - + + - + @@ -76199,7 +76213,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -76271,7 +76285,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -76344,7 +76358,7 @@ def my_form_open(dialog, layer, feature): - + @@ -76359,10 +76373,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -76377,10 +76391,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -76395,10 +76409,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -76413,12 +76427,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -76816,12 +76830,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -77219,10 +77233,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -77237,10 +77251,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -77255,10 +77269,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -77273,10 +77287,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -77291,10 +77305,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -77309,7 +77323,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -77381,7 +77395,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -77453,7 +77467,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -77525,7 +77539,7 @@ def my_form_open(dialog, layer, feature): - + - + - - + + - + @@ -77633,27 +77647,27 @@ def my_form_open(dialog, layer, feature): - + - subscriber20130304110011459 - od_subscriber_reference20131206105928067 - od_meter20131120073630165 - od_meter_reference20140304165835390 - valve20130304110011497 - hydrant20130304110004848 - node20130304110005126 - od_part20140429113327995 - conduites_copy20130709141244955 - od_crossing20141023083754327 - od_annotationline20131203095020365 - od_annotationpoint20131203095020392 - dimension20130807094904783 - od_dimension_orientation20131202111155806 - printmap20130304110011400 + subscriber20130304110011459 + od_subscriber_reference20131206105928067 + od_meter20131120073630165 + od_meter_reference20140304165835390 + valve20130304110011497 + hydrant20130304110004848 + node20130304110005126 + od_part20140429113327995 + conduites_copy20130709141244955 + od_crossing20141023083754327 + od_annotationline20131203095020365 + od_annotationpoint20131203095020392 + dimension20130807094904783 + od_dimension_orientation20131202111155806 + printmap20130304110011400 - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - - - + + + - + - + - + @@ -77973,7 +77987,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -78034,7 +78048,7 @@ def my_form_open(dialog, layer, feature): - + @@ -78049,10 +78063,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78067,10 +78081,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78085,10 +78099,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78103,12 +78117,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -78506,12 +78520,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -78909,10 +78923,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78927,10 +78941,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78945,10 +78959,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78963,10 +78977,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -78981,10 +78995,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -79000,7 +79014,7 @@ def my_form_open(dialog, layer, feature): - + @@ -79015,7 +79029,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -79087,7 +79101,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -79159,43 +79173,43 @@ def my_form_open(dialog, layer, feature): - + - valve20130304110011497 - od_meter20131120073630165 - od_annotationpoint20131203095020392 - hydrant20130304110004848 - conduites_copy20130709141244955 - od_annotationline20131203095020365 - od_dimension_orientation20131202111155806 - od_remote20150116100522170 - subscriber20130304110011459 - od_part20140429113327995 - dimension20130807094904783 - od_meter_reference20140304165835390 - od_subscriber_reference20131206105928067 - printmap20130304110011400 - od_crossing20141023083754327 - node20130304110005126 + valve20130304110011497 + od_meter20131120073630165 + od_annotationpoint20131203095020392 + hydrant20130304110004848 + conduites_copy20130709141244955 + od_annotationline20131203095020365 + od_dimension_orientation20131202111155806 + od_remote20150116100522170 + subscriber20130304110011459 + od_part20140429113327995 + dimension20130807094904783 + od_meter_reference20140304165835390 + od_subscriber_reference20131206105928067 + printmap20130304110011400 + od_crossing20141023083754327 + node20130304110005126 - - + + - + - + - + - + - + @@ -79203,237 +79217,237 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - + - - + + @@ -79463,8 +79477,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79494,8 +79508,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79525,8 +79539,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79556,8 +79570,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79587,8 +79601,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79618,8 +79632,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79649,8 +79663,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79680,8 +79694,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79711,8 +79725,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79742,8 +79756,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79773,8 +79787,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79804,8 +79818,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79835,8 +79849,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79866,8 +79880,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79901,7 +79915,7 @@ def my_form_open(dialog, layer, feature): - + @@ -79936,8 +79950,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79967,8 +79981,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -79998,8 +80012,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -80029,8 +80043,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -80060,8 +80074,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -80091,8 +80105,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -80298,31 +80312,31 @@ def my_form_open(dialog, layer, feature): - - + + - + ./ui_forms/pipe.ui 0 @@ -80331,8 +80345,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -80340,26 +80354,26 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - - + + @@ -80524,20 +80538,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -80925,20 +80939,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + @@ -81024,8 +81038,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -81056,8 +81070,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -81088,8 +81102,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -81120,8 +81134,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -81154,8 +81168,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -81353,20 +81367,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - - + + @@ -81578,20 +81592,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - - + + @@ -81805,20 +81819,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -81921,7 +81935,7 @@ def my_form_open(dialog, layer, feature): - + @@ -81966,8 +81980,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -82155,20 +82169,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - - + + @@ -82368,20 +82382,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -82681,20 +82695,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - - + + @@ -82941,20 +82955,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + @@ -83137,8 +83151,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -83169,8 +83183,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -83197,8 +83211,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -83228,8 +83242,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -83419,31 +83433,31 @@ def my_form_open(dialog, layer, feature): - - + + - + . 0 @@ -83452,7 +83466,7 @@ def my_form_open(dialog, layer, feature): - + @@ -83460,80 +83474,80 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -83721,20 +83735,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - - + + @@ -83968,20 +83982,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -84307,46 +84321,46 @@ def my_form_open(dialog, layer, feature): - - + + - + . 0 . generatedlayout - - - - + + + + - + @@ -84354,99 +84368,99 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + @@ -84474,8 +84488,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -84503,8 +84517,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -84532,8 +84546,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -84561,8 +84575,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -84590,8 +84604,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -84790,20 +84804,20 @@ def my_form_open(dialog, layer, feature): - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - + + @@ -85089,8 +85103,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85118,8 +85132,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85147,8 +85161,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85176,8 +85190,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85208,8 +85222,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85237,8 +85251,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85266,8 +85280,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85295,8 +85309,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85324,8 +85338,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -85526,60 +85540,60 @@ def my_form_open(dialog, layer, feature): - - + + - + ./ui_forms/valve.ui 0 . uifilelayout - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + @@ -85588,9 +85602,9 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - - - + + + - + - + - + @@ -85910,7 +85924,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -85971,7 +85985,7 @@ def my_form_open(dialog, layer, feature): - + @@ -85987,7 +86001,7 @@ def my_form_open(dialog, layer, feature): - + @@ -86002,10 +86016,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86020,10 +86034,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86038,10 +86052,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86056,12 +86070,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -86459,12 +86473,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -86862,10 +86876,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86880,10 +86894,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86898,10 +86912,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86916,10 +86930,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86934,10 +86948,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -86952,7 +86966,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -87024,7 +87038,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -87096,26 +87110,26 @@ def my_form_open(dialog, layer, feature): - + - hydrant20130304110004848 - valve20130304110011497 - leak20130821111917060 - subscriber20130304110011459 - od_subscriber_reference20131206105928067 - od_meter20131120073630165 - od_meter_reference20140304165835390 - node20130304110005126 - conduites_copy20130709141244955 - od_annotationline20131203095020365 - od_annotationpoint20131203095020392 - dimension20130807094904783 - od_dimension_orientation20131202111155806 - printmap20130304110011400 + hydrant20130304110004848 + valve20130304110011497 + leak20130821111917060 + subscriber20130304110011459 + od_subscriber_reference20131206105928067 + od_meter20131120073630165 + od_meter_reference20140304165835390 + node20130304110005126 + conduites_copy20130709141244955 + od_annotationline20131203095020365 + od_annotationpoint20131203095020392 + dimension20130807094904783 + od_dimension_orientation20131202111155806 + printmap20130304110011400 - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - - - + + + - + - + - + @@ -87435,7 +87449,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -87495,11 +87509,11 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + @@ -87726,10 +87740,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -87744,10 +87758,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -87762,10 +87776,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -87780,12 +87794,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -88183,10 +88197,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -88201,12 +88215,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -88604,10 +88618,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -88622,10 +88636,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -88641,7 +88655,7 @@ def my_form_open(dialog, layer, feature): - + @@ -88656,10 +88670,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -88674,7 +88688,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -88746,11 +88760,11 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - - - + + + - + - + - + @@ -89070,7 +89084,7 @@ def my_form_open(dialog, layer, feature): - + - + - + @@ -89130,10 +89144,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89148,10 +89162,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89166,10 +89180,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89184,10 +89198,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89202,10 +89216,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89220,10 +89234,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89238,10 +89252,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -89256,12 +89270,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -89659,12 +89673,12 @@ def my_form_open(dialog, layer, feature): - + - - - - + + + + - + - + - + @@ -90062,10 +90076,10 @@ def my_form_open(dialog, layer, feature): - + - + @@ -90081,7 +90095,7 @@ def my_form_open(dialog, layer, feature): - + @@ -90096,11 +90110,11 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + PROJCRS["CH1903 / LV03",BASEGEOGCRS["CH1903",DATUM["CH1903",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4149]],CONVERSION["Swiss Oblique Mercator 1903M",METHOD["Hotine Oblique Mercator (variant B)",ID["EPSG",9815]],PARAMETER["Latitude of projection centre",46.9524055555556,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8811]],PARAMETER["Longitude of projection centre",7.43958333333333,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8812]],PARAMETER["Azimuth of initial line",90,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8813]],PARAMETER["Angle from Rectified to Skew Grid",90,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8814]],PARAMETER["Scale factor on initial line",1,SCALEUNIT["unity",1],ID["EPSG",8815]],PARAMETER["Easting at projection centre",600000,LENGTHUNIT["metre",1],ID["EPSG",8816]],PARAMETER["Northing at projection centre",200000,LENGTHUNIT["metre",1],ID["EPSG",8817]]],CS[Cartesian,2],AXIS["easting (Y)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (X)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Cadastre, engineering survey, topographic mapping (large and medium scale)."],AREA["Liechtenstein; Switzerland."],BBOX[45.82,5.96,47.81,10.49]],ID["EPSG",21781]] +proj=somerc +lat_0=46.9524055555556 +lon_0=7.43958333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs @@ -90368,7 +90382,7 @@ def my_form_open(dialog, layer, feature): - +