# -*- coding: utf-8 -*- from __future__ import absolute_import # Import the PyQt and QGIS libraries # from builtins import next from builtins import str # from builtins import object from qgis.PyQt import QtCore, QtGui from qgis.PyQt.QtCore import QSettings from qgis.PyQt import QtWidgets # from qgis.PyQt.QtWidgets import QDialog from qgis.PyQt.QtGui import QIcon # from qgis.PyQt.QtCore import * # from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsSettings from qgis.core import QgsDataSourceUri, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsSettings, QgsApplication, QgsVectorLayer, QgsRasterLayer, QgsWkbTypes from qgis.PyQt.QtWidgets import ( QDialog, # QAction, # QDockWidget, # QFileDialog, # QInputDialog, # QMenu, # QToolButton, # QTableWidget, QTableWidgetItem, QMessageBox, QVBoxLayout, ) from .tools.SQLRequet import schemaname_list, schemaname_list_ref, schemaname_distinct from .tools.resources import ( load_ui, resources_path, # send_issues, ) try: from .tools.PythonSQL import login_base except NameError: print('Pas de fichier PythonSQL') # from .issues import CenRa_Issues # from ast import literal_eval from qgis.utils import iface # import os.path # import os # import webbrowser import psycopg2 import psycopg2.extras # import base64 global DeBUG DeBUG = 0 itemIconRaster = QTableWidgetItem() icon = QIcon() icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconRaster.svg')), QIcon.Mode(0), QIcon.State(1)) itemIconRaster.setIcon(icon) itemIconVecteur = QTableWidgetItem() icon = QIcon() icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconVecteur.svg')), QIcon.Mode(0), QIcon.State(1)) itemIconVecteur.setIcon(icon) try: account = login_base('account') user = account[0] mdp = account[1] host = account[2] port = account[3] dbname = account[4] sigdb = account[5] refdb = account[6] except NameError: print('Fails to login DB for account') EDITOR_CLASS = load_ui('CenRa_Flux_base.ui') targetCrs = QgsCoordinateReferenceSystem('EPSG:4326') layerCrs = QgsCoordinateReferenceSystem('EPSG:2154') TranformCRS = QgsCoordinateTransform(layerCrs, targetCrs, QgsProject.instance()) class Flux_Editor(QDialog, EDITOR_CLASS): def __init__(self, parent=None): _ = parent super().__init__() self.setupUi(self) self.settings = QgsSettings() self.s = QSettings() self.setWindowIcon(QtGui.QIcon(resources_path('icons', 'icon.png'))) self.first_start = None self.iface = iface self.label_3.setPixmap(QtGui.QPixmap(resources_path('ui', 'logo.png'))) self.commandLinkButton.setIcon(QtGui.QIcon(resources_path('ui', 'arrow-bottom.png'))) self.commandLinkButton_2.setIcon(QtGui.QIcon(resources_path('ui', 'arrow-up.png'))) self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger(0)) self.toolButton.setIcon(QtGui.QIcon(resources_path('ui', 'find.png'))) self.comboBox_2.addItem("SIG") self.comboBox_2.addItem('REF') self.comboBox.currentIndexChanged.connect(self.initialisation_flux) self.commandLinkButton.clicked.connect(self.selection_flux) self.tableWidget.itemDoubleClicked.connect(self.selection_flux) self.pushButton_2.clicked.connect(self.limite_flux) self.commandLinkButton_2.clicked.connect(self.suppression_flux) self.tableWidget_2.itemDoubleClicked.connect(self.suppression_flux) self.comboBox_2.currentIndexChanged.connect(self.bd_source) self.checkBox.hide() # self.checkBox.stateChanged.connect(self.modeCarte) self.toolButton.clicked.connect(self.getCanevas) layout = QVBoxLayout() self.lineEdit.textChanged.connect(self.filtre_dynamique) # self.viewer.textChanged.connect(self.NewTitle) layout.addWidget(self.lineEdit) self.viewer.hide() self.DeBUG.addItem('') self.DeBUG.addItem('01') self.DeBUG.addItem('0726') self.DeBUG.addItem('4269') self.DeBUG.hide() def raise_(self): """Run method that performs all the real work""" self.bd_source() def ModeDeBUG(self): self.DeBUG.show() def mousePressEvent(self, event): global DeBUG if 330 <= event.pos().x() <= 560 and 5 <= event.pos().y() <= 75: DeBUG = DeBUG + 1 if DeBUG == 3: DeBUG = 0 self.ModeDeBUG() else: DeBUG = 0 self.DeBUG.hide() """ def NewTitle(self): if self.viewer.title() != '': Tsplit = ((self.viewer.title()).split('.')) print(Tsplit[0], Tsplit[1]) self.openPostGIS(Tsplit[0], Tsplit[1]) """ def bd_source(self): self.activateWindow() bd_origine = self.comboBox_2.currentText() if bd_origine == 'REF': self.run_ref() if bd_origine == 'SIG': self.run_sig() def run_ref(self): """Run method that performs all the real work""" while self.tableWidget_2.rowCount() > 0: self.tableWidget_2.removeRow(self.tableWidget_2.rowCount() - 1) # print(self.tableWidget_2.rowCount()) global cur, con, dbtype dbtype = refdb con = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + dbtype + " user=" + user + " password=" + mdp) cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor) self.initialisation_flux() self.combobox_custom() # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start is True: self.first_start = False # show the dialog self.show() # Run the dialog event loop result = self.exec() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass def run_sig(self): """Run method that performs all the real work""" while self.tableWidget_2.rowCount() > 0: self.tableWidget_2.removeRow(self.tableWidget_2.rowCount() - 1) global cur, con, dbtype dbtype = sigdb con = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + dbtype + " user=" + user + " password=" + mdp) cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor) self.initialisation_flux() self.combobox_custom() # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start is True: self.first_start = False # show the dialog self.show() # Run the dialog event loop result = self.exec() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass def suppression_flux(self): self.tableWidget_2.removeRow(self.tableWidget_2.currentRow()) def initialisation_flux(self): if dbtype == sigdb: # self.toolButton.setEnabled(1) if self.comboBox.currentText() == 'toutes les catégories': custom_list = schemaname_list elif self.comboBox.currentText() == 'travaux': custom_list = """(SELECT schemaname,tablename from pg_catalog.pg_tables where schemaname like '""" + str(self.comboBox.currentText()) + """%' order by schemaname,tablename) UNION (SELECT schemaname,matviewname AS tablename FROM pg_catalog.pg_matviews where schemaname like '""" + str(self.comboBox.currentText()) + """%' order by schemaname,tablename) order by schemaname,tablename;""" else: custom_list = """(SELECT schemaname,tablename from pg_catalog.pg_tables where schemaname like '\\_""" + str(self.comboBox.currentText()) + """%' order by schemaname,tablename) UNION (SELECT schemaname,matviewname AS tablename FROM pg_catalog.pg_matviews where schemaname like '\\_""" + str(self.comboBox.currentText()) + """%' order by schemaname,tablename) order by schemaname,tablename;""" else: if self.comboBox.currentText() == 'toutes les catégories': custom_list = schemaname_list_ref else: custom_list = """SELECT schemaname,tablename from pg_catalog.pg_tables where schemaname like '""" + str(self.comboBox.currentText()) + """' order by schemaname,tablename;""" cur.execute(custom_list) list_schema = cur.fetchall() SQLcountRaster = """SELECT schemaname,viewname FROM pg_catalog.pg_views WHERE schemaname LIKE 'public' AND viewname LIKE 'raster_columns';""" cur.execute(SQLcountRaster) RasterIF = len(cur.fetchall()) if RasterIF == 1: SQLloadRaster = """SELECT concat(r_table_schema,'.',r_table_name) from public.raster_columns; """ cur.execute(SQLloadRaster) list_raster = cur.fetchall() RasterList = [] for rasterFind in list_raster: RasterList.append(rasterFind[0]) else: RasterList = [] self.tableWidget.setRowCount(len(list_schema)) self.tableWidget.setColumnCount(4) i = 0 for value in list_schema: if dbtype == sigdb: type_val = str(value[0])[1:3] schema_name = str(value[0])[4:] table_name = str(value[1][len(value[0]) + 1:]) if value[0] == value[1][:len(value[0])]: table_name = str(value[1][len(value[0]) + 1:]) else: table_name = str(value[1]) else: type_val = '' schema_name = str(value[0]) table_name = str(value[1]) if type_val == 'fo': type_val = str(value[0])[1:5] schema_name = str(value[0])[6:] if value[0] == value[1][:len(value[0])]: table_name = str(value[1][len(value[0]) + 1:]) else: table_name = str(value[1]) elif type_val == 'ra': type_val = 'travaux' schema_name = str(value[0]) table_name = str(value[1]) elif type_val != '00' and type_val != '01' and type_val != '07' and type_val != '26' and type_val != '42' and type_val != '69' and type_val != 'ra': type_val = 'agregation' schema_name = str(value[0]) table_name = str(value[1]) if (str(value[0]) + '.' + str(value[1])) in RasterList: SVG = 'mIconRaster.svg' else: SVG = 'mIconVecteur.svg' itemIcon = QTableWidgetItem() icon = QIcon() icon.addPixmap(QtGui.QPixmap(resources_path('icons', SVG)), QIcon.Mode(0), QIcon.State(1)) itemIcon.setIcon(icon) self.tableWidget.setItem(i, 0, itemIcon) item = QTableWidgetItem(type_val) self.tableWidget.setItem(i, 1, item) item = QTableWidgetItem(schema_name) self.tableWidget.setItem(i, 2, item) item = QTableWidgetItem(table_name) self.tableWidget.setItem(i, 3, item) i = i + 1 self.tableWidget.setColumnWidth(0, 20) self.tableWidget.setColumnWidth(1, 70) self.tableWidget.setColumnWidth(2, 300) self.tableWidget.setColumnWidth(3, 300) self.tableWidget.setHorizontalHeaderLabels(["Type", "Code", "Schema", "Table"]) def selection_flux(self): selected_row = 0 selected_items = self.tableWidget.selectedItems() # Assuming you want to compare items in the first column for uniqueness # svgTake = (selected_items[2].tableWidget().cellWidget(0,0)) new_item_text = selected_items[3].text() if not self.item_already_exists(new_item_text): self.tableWidget_2.insertRow(selected_row) for column in range(self.tableWidget.columnCount()): cloned_item = selected_items[column].clone() self.tableWidget_2.setHorizontalHeaderLabels(["Type", "Code", "Schema", "Table"]) self.tableWidget_2.setColumnCount(4) self.tableWidget_2.setItem(selected_row, column, cloned_item) self.tableWidget_2.setColumnWidth(0, 20) self.tableWidget_2.setColumnWidth(1, 70) self.tableWidget_2.setColumnWidth(2, 300) self.tableWidget_2.setColumnWidth(3, 300) def item_already_exists(self, new_item_text): # Assuming you want to compare items in the first column for uniqueness existing_items = self.tableWidget_2.findItems(new_item_text, QtCore.Qt.MatchFlag(0)) # Check if there are any existing items with the same text in the first column return len(existing_items) > 0 def limite_flux(self): if self.tableWidget_2.rowCount() > 5: self.QMBquestion = QMessageBox.question(iface.mainWindow(), u"Attention !", "Le nombre de flux à charger en une seule fois est limité à 5 pour des questions de performances. Souhaitez vous tout de même charger les " + str( self.tableWidget_2.rowCount()) + " flux sélectionnés ? (risque de plantage de QGIS)", QMessageBox.StandardButton(0x00004000) | QMessageBox.StandardButton(0x00010000)) if self.QMBquestion == QMessageBox.StandardButton(0x00004000): self.chargement_flux() if self.QMBquestion == QMessageBox.StandardButton(0x00001000): print("Annulation du chargement des couches") if self.tableWidget_2.rowCount() <= 5: self.chargement_flux() """ def openPostGIS(self, schema, table): uri = QgsDataSourceUri() uri.setConnection(host, port, sigdb, user, mdp) if (schema + '.' + table) in LRasterList: uri.setDataSource(schema, table, "rast") uri.setKeyColumn('rid') uri.setSrid('2154') layer = QgsRasterLayer(uri.uri(), table, "postgresraster") else: uri.setDataSource(schema, table, "geom") uri.setKeyColumn('gid') uri.setSrid('2154') layer = QgsVectorLayer(uri.uri(), table, "postgres") # Ajout de la couche au canevas QGIS QgsProject.instance().addMapLayer(layer) """ def chargement_flux(self): managerAU = QgsApplication.authManager() managerAU.availableAuthMethodConfigs().keys() def REQUEST(type): switcher = { 'WFS': "GetFeature", 'WMS': "GetMap", 'WMS+Vecteur': "GetMap", 'WMS+Raster': "GetMap", 'WMTS': "GetMap" } return switcher.get(type, "nothing") # def displayOnWindows(type, uri, name): # p = [] SQLloadRaster = """SELECT concat(r_table_schema,'.',r_table_name) from public.raster_columns; """ cur.execute(SQLloadRaster) list_raster = cur.fetchall() RasterList = [] for rasterFind in list_raster: RasterList.append(rasterFind[0]) for row in range(0, self.tableWidget_2.rowCount()): color_rgba = 855030089 if self.tableWidget_2.item(row, 1).background().color().rgba() != color_rgba: # supression de la partie de l'url après le point d'interrogation if dbtype == sigdb: code = self.tableWidget_2.item(row, 1).text() schema = '_' + code + '_' + self.tableWidget_2.item(row, 2).text() if code == 'travaux' or code == 'agregation': schema = self.tableWidget_2.item(row, 2).text() table = self.tableWidget_2.item(row, 3).text() else: table = self.tableWidget_2.item(row, 3).text() table = schema + '_' + table elif dbtype == refdb: # code = self.tableWidget_2.item(row,1).text() schema = self.tableWidget_2.item(row, 2).text() table = self.tableWidget_2.item(row, 3).text() # .split("?", 1)[0] uri = QgsDataSourceUri() uri.setConnection(host, port, dbtype, user, mdp) # nom du schéma à remplacer: "hydrographie" à supprimer et mettre "couches_collaboratives" lorsqu'on aura regroupé les couches à modifier dans un même schéma if (schema + '.' + table) in RasterList: uri.setDataSource(schema, table, "rast") uri.setKeyColumn('rid') uri.setSrid('2154') layer = QgsRasterLayer(uri.uri(), table, "postgresraster") QgsProject.instance().addMapLayer(layer) else: uri.setDataSource(schema, table, "geom") uri.setKeyColumn('gid') # Chargement de la couche PostGIS geom_type = 'SELECT right(st_geometrytype(geom),-3) as a FROM ' + schema + '.' + table + ' GROUP BY a' cur.execute(geom_type) list_typegeom = cur.fetchall() if len(list_typegeom) > 1: for typegeom in list_typegeom: if typegeom[0] == 'MultiPolygon': uri.setWkbType(QgsWkbTypes.MultiPolygon) elif typegeom[0] == 'MultiLineString': uri.setWkbType(QgsWkbTypes.MultiLineString) elif typegeom[0] == 'Point': uri.setWkbType(QgsWkbTypes.Point) if typegeom[0] == 'Polygon': uri.setWkbType(QgsWkbTypes.Polygon) elif typegeom[0] == 'LineString': uri.setWkbType(QgsWkbTypes.LineString) elif typegeom[0] == 'MultiPoint': uri.setWkbType(QgsWkbTypes.MultiPoint) if (typegeom[0] is not None and typegeom[0] != 'Polygon'): uri.setSrid('2154') layer = QgsVectorLayer(uri.uri(), table, "postgres") # Ajout de la couche au canevas QGIS QgsProject.instance().addMapLayer(layer) else: layer = QgsVectorLayer(uri.uri(), table, "postgres") # Ajout de la couche au canevas QGIS QgsProject.instance().addMapLayer(layer) else: self.QMBquestion = QMessageBox.question(iface.mainWindow(), u"Attention !", "La couche «" + str(self.tableWidget_2.item(row, 1).text()) + ' ' + str(self.tableWidget_2.item(row, 2).text()) + "» ne ce trouve pas dans cette BD !", QMessageBox.StandardButton(0x00004000)) def combobox_custom(self): if dbtype == sigdb: self.toolButton.setEnabled(1) self.comboBox.clear() self.comboBox.addItem("toutes les catégories") self.comboBox.addItem('00') self.comboBox.addItem('01') self.comboBox.addItem('07') self.comboBox.addItem('26') self.comboBox.addItem('42') self.comboBox.addItem('69') self.comboBox.addItem('agregation') self.comboBox.addItem('travaux') self.comboBox.addItem('form') if dbtype == refdb: self.toolButton.setEnabled(0) custom_list = schemaname_distinct cur.execute(custom_list) list_schema = cur.fetchall() self.comboBox.clear() self.comboBox.addItem("toutes les catégories") for baxval in list_schema: self.comboBox.addItem(baxval[0]) def filtre_dynamique(self, filter_text): if filter_text.find(' ') >= 0: filter_text = filter_text.replace(" ", "_") for i in range(self.tableWidget.rowCount()): for j in range(self.tableWidget.columnCount()): item = self.tableWidget.item(i, j) match = filter_text.lower() not in item.text().lower() self.tableWidget.setRowHidden(i, match) if not match: break def getCanevas(self): poly = iface.mapCanvas().extent() geom = (str(poly.xMinimum()) + ',' + str(poly.yMinimum()) + ',' + str(poly.xMaximum()) + ',' + str(poly.yMaximum())) SQL_GEOM_CONTOUR = """SELECT DISTINCT tschema,tname FROM "_agregation_ra"."_agreg_contour" WHERE st_intersects(geom,ST_MakeEnvelope(""" + geom + ",2154)) ORDER BY tname" SQL_GEOM_HABITAT = """SELECT DISTINCT tschema,tname FROM "_agregation_ra"."_agreg_habitat" WHERE st_intersects(geom,ST_MakeEnvelope(""" + geom + ",2154)) ORDER BY tname" SQL_GEOM_EU_HABITAT = """SELECT DISTINCT tschema,tname FROM "_agregation_ra"."_agreg_eu_habitat" WHERE st_intersects(geom,ST_MakeEnvelope(""" + geom + ",2154)) ORDER BY tname" SQL_GEOM_TRAVAUX_PREVUS_LIGNE = """SELECT DISTINCT tschema,tname FROM "_agregation_ra"."_agreg_travaux_prevus_ligne" WHERE st_intersects(geom,ST_MakeEnvelope(""" + geom + ",2154)) ORDER BY tname" SQL_GEOM_TRAVAUX_PREVUS_POINT = """SELECT DISTINCT tschema,tname FROM "_agregation_ra"."_agreg_travaux_prevus_point" WHERE st_intersects(geom,ST_MakeEnvelope(""" + geom + ",2154)) ORDER BY tname" SQL_GEOM_TRAVAUX_PREVUS_POLY = """SELECT DISTINCT tschema,tname FROM "_agregation_ra"."_agreg_travaux_prevus_poly" WHERE st_intersects(geom,ST_MakeEnvelope(""" + geom + ",2154)) ORDER BY tname" cur.execute(SQL_GEOM_CONTOUR) TableContour = cur.fetchall() cur.execute(SQL_GEOM_HABITAT) TableHabitat = cur.fetchall() cur.execute(SQL_GEOM_EU_HABITAT) TableEuHabitat = cur.fetchall() cur.execute(SQL_GEOM_TRAVAUX_PREVUS_LIGNE) TableTravauxLigne = cur.fetchall() cur.execute(SQL_GEOM_TRAVAUX_PREVUS_POINT) TableTravauxPoint = cur.fetchall() cur.execute(SQL_GEOM_TRAVAUX_PREVUS_POLY) TableTravauxPoly = cur.fetchall() TableHaveGeom = sorted(TableContour + TableHabitat + TableEuHabitat + TableTravauxLigne + TableTravauxPoint + TableTravauxPoly) row_count = 0 self.tableWidget.setRowCount(0) for e in TableHaveGeom: cur.execute("""SELECT DISTINCT count(*) FROM pg_catalog.pg_tables WHERE schemaname LIKE '""" + e[0] + """' AND tablename LIKE '""" + e[1] + """';""") TableSomme = cur.fetchall()[0][0] if e[0][1:3] != 'fo': DepName = QTableWidgetItem(e[0][1:3]) SchemaName = QTableWidgetItem(e[0][4:]) else: DepName = QTableWidgetItem('form') SchemaName = QTableWidgetItem(e[0][6:]) TableName = QTableWidgetItem(e[1][len(e[0]) + 1:]) self.tableWidget.insertRow(row_count) itemIcon = QTableWidgetItem() icon = QIcon() icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconVecteur.svg')), QIcon.Mode(0), QIcon.State(1)) itemIcon.setIcon(icon) self.tableWidget.setItem(row_count, 0, itemIcon) self.tableWidget.setItem(row_count, 1, DepName) self.tableWidget.setItem(row_count, 2, SchemaName) self.tableWidget.setItem(row_count, 3, TableName) if TableSomme == 0: for j in range(self.tableWidget.columnCount()): self.tableWidget.item(row_count, j).setBackground(QtGui.QColor(246, 185, 73, 50)) self.tableWidget.item(row_count, j).setToolTip('Couche dans une autre BD !') row_count = row_count + 1 if self.lineEdit.text() != 'Recherche par mots-clés': self.filtre_dynamique(self.lineEdit.text()) def SwitchGeom(self, vargeom): new_object = '[' obj = vargeom['coordinates'][0][0] for obj_X in obj: new_object = new_object + '[' + str(obj_X[1]) + ',' + str(obj_X[0]) + '],' new_object = new_object[:-1] + ']' return (new_object) # def popup(self): # self.dialog = Popup() # +++ - self # self.dialog.text_edit.show()