This commit is contained in:
Tom LAVEILLE 2026-02-12 11:41:59 +01:00
parent 8c1ee42080
commit ff2e0f22be

View File

@ -1,7 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""
Module Flux Editor pour le plugin CenRA_FLUX
Permet de gérer et charger des couches depuis les bases de données PostGIS (SIG et REF)
"""
from __future__ import absolute_import from __future__ import absolute_import
# Import the PyQt and QGIS libraries # Import des bibliothèques PyQt et QGIS
from builtins import str from builtins import str
from qgis.PyQt import QtCore, QtGui from qgis.PyQt import QtCore, QtGui
@ -9,7 +13,17 @@ from qgis.PyQt.QtCore import QSettings
from qgis.PyQt import QtWidgets from qgis.PyQt import QtWidgets
from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtGui import QIcon
from qgis.core import QgsDataSourceUri, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsSettings, QgsApplication, QgsVectorLayer, QgsRasterLayer, QgsWkbTypes from qgis.core import (
QgsDataSourceUri,
QgsCoordinateReferenceSystem,
QgsCoordinateTransform,
QgsProject,
QgsSettings,
QgsApplication,
QgsVectorLayer,
QgsRasterLayer,
QgsWkbTypes
)
from qgis.PyQt.QtWidgets import ( from qgis.PyQt.QtWidgets import (
QDialog, QDialog,
QPushButton, QPushButton,
@ -31,9 +45,11 @@ from qgis.utils import iface
import psycopg2 import psycopg2
import psycopg2.extras import psycopg2.extras
# Variable globale pour le mode debug
global DeBUG global DeBUG
DeBUG = 0 DeBUG = 0
# Création des icônes pour les couches raster et vecteur
itemIconRaster = QTableWidgetItem() itemIconRaster = QTableWidgetItem()
icon = QIcon() icon = QIcon()
icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconRaster.svg')), QIcon.Mode(0), QIcon.State(1)) icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconRaster.svg')), QIcon.Mode(0), QIcon.State(1))
@ -44,28 +60,36 @@ icon = QIcon()
icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconVecteur.svg')), QIcon.Mode(0), QIcon.State(1)) icon.addPixmap(QtGui.QPixmap(resources_path('icons', 'mIconVecteur.svg')), QIcon.Mode(0), QIcon.State(1))
itemIconVecteur.setIcon(icon) itemIconVecteur.setIcon(icon)
# Récupération des informations de connexion à la base de données
try: try:
account = login_base('account') account = login_base('account')
user = account[0] user = account[0] # Nom d'utilisateur
mdp = account[1] mdp = account[1] # Mot de passe
host = account[2] host = account[2] # Hôte de la base de données
port = account[3] port = account[3] # Port de connexion
dbname = account[4] dbname = account[4] # Nom de la base de données
sigdb = account[5] sigdb = account[5] # Base de données SIG
refdb = account[6] refdb = account[6] # Base de données REF
except NameError: except NameError:
print('Fails to login DB for account') print('Fails to login DB for account')
# Chargement de l'interface utilisateur depuis le fichier .ui
EDITOR_CLASS = load_ui('CenRa_Flux_base.ui') EDITOR_CLASS = load_ui('CenRa_Flux_base.ui')
targetCrs = QgsCoordinateReferenceSystem('EPSG:4326') # Configuration des systèmes de coordonnées de référence (CRS)
layerCrs = QgsCoordinateReferenceSystem('EPSG:2154') targetCrs = QgsCoordinateReferenceSystem('EPSG:4326') # WGS84 (coordonnées géographiques)
layerCrs = QgsCoordinateReferenceSystem('EPSG:2154') # Lambert 93 (projection française)
TranformCRS = QgsCoordinateTransform(layerCrs, targetCrs, QgsProject.instance()) TranformCRS = QgsCoordinateTransform(layerCrs, targetCrs, QgsProject.instance())
class Flux_Editor(QDialog, EDITOR_CLASS): class Flux_Editor(QDialog, EDITOR_CLASS):
"""
Classe principale de l'éditeur de flux
Gère l'interface de sélection et de chargement des couches depuis les bases de données
"""
def __init__(self, parent=None): def __init__(self, parent=None):
"""Initialisation de l'interface et des composants"""
_ = parent _ = parent
super().__init__() super().__init__()
self.setupUi(self) self.setupUi(self)
@ -74,29 +98,34 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.setWindowIcon(QtGui.QIcon(resources_path('icons', 'icon.png'))) self.setWindowIcon(QtGui.QIcon(resources_path('icons', 'icon.png')))
self.first_start = None self.first_start = None
self.iface = iface self.iface = iface
# Configuration des éléments visuels de l'interface
self.label_3.setPixmap(QtGui.QPixmap(resources_path('ui', 'logo.png'))) self.label_3.setPixmap(QtGui.QPixmap(resources_path('ui', 'logo.png')))
self.commandLinkButton.setIcon(QtGui.QIcon(resources_path('ui', 'arrow-bottom.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.commandLinkButton_2.setIcon(QtGui.QIcon(resources_path('ui', 'arrow-up.png')))
# Configuration du tableau des couches disponibles
self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger(0)) self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger(0))
self.toolButton.setIcon(QtGui.QIcon(resources_path('ui', 'find.png'))) self.toolButton.setIcon(QtGui.QIcon(resources_path('ui', 'find.png')))
self.toolButton_2.setIcon(QtGui.QIcon(resources_path('ui', 'star.png'))) self.toolButton_2.setIcon(QtGui.QIcon(resources_path('ui', 'star.png')))
# Ajout des options de base de données (SIG ou REF)
self.comboBox_2.addItem("SIG") self.comboBox_2.addItem("SIG")
self.comboBox_2.addItem('REF') self.comboBox_2.addItem('REF')
self.commandLinkButton.clicked.connect(self.selection_flux) # Connexion des signaux aux slots (événements de l'interface)
self.tableWidget.itemDoubleClicked.connect(self.selection_flux) self.commandLinkButton.clicked.connect(self.selection_flux) # Bouton de sélection de flux
self.pushButton_2.clicked.connect(self.limite_flux) self.tableWidget.itemDoubleClicked.connect(self.selection_flux) # Double-clic sur une couche
self.commandLinkButton_2.clicked.connect(self.suppression_flux) self.pushButton_2.clicked.connect(self.limite_flux) # Bouton de chargement
self.tableWidget_2.itemDoubleClicked.connect(self.suppression_flux) self.commandLinkButton_2.clicked.connect(self.suppression_flux) # Bouton de suppression
self.comboBox_2.currentIndexChanged.connect(self.bd_source) self.tableWidget_2.itemDoubleClicked.connect(self.suppression_flux) # Double-clic pour supprimer
self.comboBox_2.currentIndexChanged.connect(self.bd_source) # Changement de base de données
self.checkBox.hide() self.checkBox.hide()
self.toolButton.clicked.connect(self.getCanevas) self.toolButton.clicked.connect(self.getCanevas) # Filtrer par emprise du canevas
self.toolButton_2.clicked.connect(self.filtre_favorit) self.toolButton_2.clicked.connect(self.filtre_favorit) # Filtrer par favoris
layout = QVBoxLayout() layout = QVBoxLayout()
self.lineEdit.textChanged.connect(self.filtre_dynamique) self.lineEdit.textChanged.connect(self.filtre_dynamique) # Recherche dynamique
layout.addWidget(self.lineEdit) layout.addWidget(self.lineEdit)
self.viewer.hide() self.viewer.hide()
# Configuration du menu de debug (caché par défaut)
self.DeBUG.addItem('') self.DeBUG.addItem('')
self.DeBUG.addItem('Dev') self.DeBUG.addItem('Dev')
self.DeBUG.addItem('01') self.DeBUG.addItem('01')
@ -105,13 +134,14 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.comboBox.currentIndexChanged.connect(self.initialisation_flux) self.comboBox.currentIndexChanged.connect(self.initialisation_flux)
self.DeBUG.currentIndexChanged.connect(self.SwitchDEBUG) self.DeBUG.currentIndexChanged.connect(self.SwitchDEBUG)
self.DeBUG.hide() self.DeBUG.hide() # Menu debug caché par défaut
def raise_(self): def raise_(self):
"""Run method that performs all the real work""" """Run method that performs all the real work"""
self.bd_source() self.bd_source()
def SwitchDEBUG(self): def SwitchDEBUG(self):
"""Change les paramètres de connexion selon le mode debug sélectionné"""
try: try:
global user, mdp, host, port, dbname, sigdb, refdb global user, mdp, host, port, dbname, sigdb, refdb
account = login_base(self.DeBUG.currentText()) account = login_base(self.DeBUG.currentText())
@ -131,10 +161,12 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.DeBUG.show() self.DeBUG.show()
def mousePressEvent(self, event): def mousePressEvent(self, event):
"""Détecte les clics sur le logo pour activer le mode debug (3 clics consécutifs)"""
global DeBUG global DeBUG
# Zone du logo (coordonnées x: 330-560, y: 5-75)
if 330 <= event.pos().x() <= 560 and 5 <= event.pos().y() <= 75: if 330 <= event.pos().x() <= 560 and 5 <= event.pos().y() <= 75:
DeBUG = DeBUG + 1 DeBUG = DeBUG + 1
if DeBUG == 3: if DeBUG == 3: # Activation après 3 clics
DeBUG = 0 DeBUG = 0
self.ModeDeBUG() self.ModeDeBUG()
else: else:
@ -142,20 +174,23 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.DeBUG.hide() self.DeBUG.hide()
def bd_source(self): def bd_source(self):
"""Sélectionne la base de données source (SIG ou REF)"""
self.activateWindow() self.activateWindow()
bd_origine = self.comboBox_2.currentText() bd_origine = self.comboBox_2.currentText()
if bd_origine == 'REF': if bd_origine == 'REF':
self.run_ref() self.run_ref() # Connexion à la base REF
if bd_origine == 'SIG': if bd_origine == 'SIG':
self.run_sig() self.run_sig() # Connexion à la base SIG
def run_ref(self): def run_ref(self):
"""Run method that performs all the real work""" """Initialise la connexion à la base de données REF"""
# Vider le tableau des flux sélectionnés
while self.tableWidget_2.rowCount() > 0: while self.tableWidget_2.rowCount() > 0:
self.tableWidget_2.removeRow(self.tableWidget_2.rowCount() - 1) self.tableWidget_2.removeRow(self.tableWidget_2.rowCount() - 1)
global cur, con, dbtype global cur, con, dbtype
dbtype = refdb dbtype = refdb
# Connexion à la base de données REF
con = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + dbtype + " user=" + user + " password=" + mdp) con = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + dbtype + " user=" + user + " password=" + mdp)
cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor) cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor)
self.combobox_custom() self.combobox_custom()
@ -172,11 +207,13 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
pass pass
def run_sig(self): def run_sig(self):
"""Run method that performs all the real work""" """Initialise la connexion à la base de données SIG"""
# Vider le tableau des flux sélectionnés
while self.tableWidget_2.rowCount() > 0: while self.tableWidget_2.rowCount() > 0:
self.tableWidget_2.removeRow(self.tableWidget_2.rowCount() - 1) self.tableWidget_2.removeRow(self.tableWidget_2.rowCount() - 1)
global cur, con, dbtype global cur, con, dbtype
dbtype = sigdb dbtype = sigdb
# Connexion à la base de données SIG
con = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + dbtype + " user=" + user + " password=" + mdp) con = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + dbtype + " user=" + user + " password=" + mdp)
cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor) cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor)
self.combobox_custom() self.combobox_custom()
@ -189,17 +226,20 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.tableWidget_2.removeRow(self.tableWidget_2.currentRow()) self.tableWidget_2.removeRow(self.tableWidget_2.currentRow())
def AddOrDelToUserFav(self): def AddOrDelToUserFav(self):
"""Ajoute ou supprime une couche des favoris de l'utilisateur"""
selected_items = self.tableWidget.selectedItems() selected_items = self.tableWidget.selectedItems()
favorit_statut = selected_items[4].text() favorit_statut = selected_items[4].text() # 0 = non favori, 1 = favori
selected_items[4].tableWidget().removeCellWidget(selected_items[4].row(), 4) selected_items[4].tableWidget().removeCellWidget(selected_items[4].row(), 4)
schema_name = selected_items[2].text() schema_name = selected_items[2].text()
table_name = selected_items[3].text() table_name = selected_items[3].text()
# Ajout aux favoris
if favorit_statut == "0": if favorit_statut == "0":
FAV = "mStarIconDel.png" FAV = "mStarIconDel.png" # Icône étoile pleine
selected_items[4].setText("1") selected_items[4].setText("1")
# Requête SQL pour ajouter aux favoris
SQLAddFav = """INSERT INTO admin_sig.favtable (utilisateur, schema_name, table_name) VALUES ('""" + user + "','" + schema_name + "','" + table_name + """');""" SQLAddFav = """INSERT INTO admin_sig.favtable (utilisateur, schema_name, table_name) VALUES ('""" + user + "','" + schema_name + "','" + table_name + """');"""
if dbtype == sigdb: if dbtype == sigdb:
cur.execute(SQLAddFav) cur.execute(SQLAddFav)
@ -211,9 +251,11 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
conSIG.commit() conSIG.commit()
conSIG.close() conSIG.close()
# Suppression des favoris
else: else:
FAV = "mStarIconAdd.png" FAV = "mStarIconAdd.png" # Icône étoile vide
selected_items[4].setText("0") selected_items[4].setText("0")
# Requête SQL pour supprimer des favoris
SQLDelFav = """DELETE FROM admin_sig.favtable WHERE utilisateur LIKE '""" + user + """' AND schema_name LIKE '""" + schema_name + """' AND table_name LIKE '""" + table_name + """';""" SQLDelFav = """DELETE FROM admin_sig.favtable WHERE utilisateur LIKE '""" + user + """' AND schema_name LIKE '""" + schema_name + """' AND table_name LIKE '""" + table_name + """';"""
if dbtype == sigdb: if dbtype == sigdb:
cur.execute(SQLDelFav) cur.execute(SQLDelFav)
@ -232,10 +274,11 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.FavButton.clicked.connect(self.AddOrDelToUserFav) self.FavButton.clicked.connect(self.AddOrDelToUserFav)
def initialisation_flux(self): def initialisation_flux(self):
"""Initialise et remplit le tableau des couches disponibles"""
if self.toolButton_2.text() == "1": if self.toolButton_2.text() == "1":
self.filtre_favorit(None) self.filtre_favorit(None)
self.tableWidget.clear() self.tableWidget.clear()
if NoSignals == 0: if NoSignals == 0: # Éviter les boucles infinies lors des mises à jour
if dbtype == sigdb: if dbtype == sigdb:
if self.comboBox.currentText() == 'toutes les catégories': if self.comboBox.currentText() == 'toutes les catégories':
custom_list = schemaname_list custom_list = schemaname_list
@ -253,11 +296,13 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
cur.execute(custom_list) cur.execute(custom_list)
list_schema = cur.fetchall() list_schema = cur.fetchall()
# Vérification de la présence de couches raster dans la base
SQLcountRaster = """SELECT schemaname,viewname FROM pg_catalog.pg_views SQLcountRaster = """SELECT schemaname,viewname FROM pg_catalog.pg_views
WHERE schemaname LIKE 'public' AND viewname LIKE 'raster_columns';""" WHERE schemaname LIKE 'public' AND viewname LIKE 'raster_columns';"""
cur.execute(SQLcountRaster) cur.execute(SQLcountRaster)
RasterIF = len(cur.fetchall()) RasterIF = len(cur.fetchall())
# Récupération de la liste des couches raster si disponibles
if RasterIF == 1: if RasterIF == 1:
SQLloadRaster = """SELECT concat(r_table_schema,'.',r_table_name) from public.raster_columns; """ SQLloadRaster = """SELECT concat(r_table_schema,'.',r_table_name) from public.raster_columns; """
cur.execute(SQLloadRaster) cur.execute(SQLloadRaster)
@ -268,6 +313,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
else: else:
RasterList = [] RasterList = []
# Récupération des projets QGIS stockés dans la base de données
SQLprojects = """SELECT schemaname, tablename FROM pg_catalog.pg_tables WHERE tablename LIKE 'qgis_projects'""" SQLprojects = """SELECT schemaname, tablename FROM pg_catalog.pg_tables WHERE tablename LIKE 'qgis_projects'"""
cur.execute(SQLprojects) cur.execute(SQLprojects)
list_projects = cur.fetchall() list_projects = cur.fetchall()
@ -278,6 +324,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
cur.execute(SQLProjectsQgis) cur.execute(SQLProjectsQgis)
list_projects_qgis.append(cur.fetchall()) list_projects_qgis.append(cur.fetchall())
# Récupération des droits d'accès de l'utilisateur sur les tables
if self.comboBox.currentText() == 'toutes les catégories': if self.comboBox.currentText() == 'toutes les catégories':
SQLGrands = """SELECT concat(table_schema,'.',table_name) FROM information_schema.role_table_grants WHERE grantee in(SELECT rolname FROM pg_catalog.pg_roles WHERE oid in(SELECT roleid FROM pg_auth_members WHERE member = (SELECT usesysid FROM pg_catalog.pg_user WHERE usename = '""" + user + """'))) and privilege_type = 'SELECT';""" SQLGrands = """SELECT concat(table_schema,'.',table_name) FROM information_schema.role_table_grants WHERE grantee in(SELECT rolname FROM pg_catalog.pg_roles WHERE oid in(SELECT roleid FROM pg_auth_members WHERE member = (SELECT usesysid FROM pg_catalog.pg_user WHERE usename = '""" + user + """'))) and privilege_type = 'SELECT';"""
else: else:
@ -291,6 +338,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
for grandsFind in list_grands: for grandsFind in list_grands:
GrandUser.append(grandsFind[0]) GrandUser.append(grandsFind[0])
# Récupération de la liste des favoris de l'utilisateur
SQLFavTable = "SELECT concat(schema_name, '.', table_name) FROM admin_sig.favtable WHERE utilisateur LIKE '" + user + "';" SQLFavTable = "SELECT concat(schema_name, '.', table_name) FROM admin_sig.favtable WHERE utilisateur LIKE '" + user + "';"
if dbtype == refdb: if dbtype == refdb:
conSIG = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + sigdb + " user=" + user + " password=" + mdp) conSIG = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + sigdb + " user=" + user + " password=" + mdp)
@ -306,6 +354,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
for favFind in list_fav: for favFind in list_fav:
FavList.append(favFind[0]) FavList.append(favFind[0])
# Remplissage du tableau avec les couches disponibles
self.tableWidget.setRowCount(len(list_schema)) self.tableWidget.setRowCount(len(list_schema))
self.tableWidget.setColumnCount(5) self.tableWidget.setColumnCount(5)
i = 0 i = 0
@ -371,9 +420,11 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.tableWidget.setItem(i, 4, item) self.tableWidget.setItem(i, 4, item)
self.tableWidget.setCellWidget(i, 4, self.FavButton) self.tableWidget.setCellWidget(i, 4, self.FavButton)
# Coloration des lignes selon les droits d'accès
if (str(value[0]) + '.' + str(value[1])) in GrandUser: if (str(value[0]) + '.' + str(value[1])) in GrandUser:
pass pass # L'utilisateur a les droits
else: else:
# Coloration en violet si droits insuffisants
for j in range(self.tableWidget.columnCount()): for j in range(self.tableWidget.columnCount()):
self.tableWidget.item(i, j).setBackground(QtGui.QColor(187, 134, 192, 50)) self.tableWidget.item(i, j).setBackground(QtGui.QColor(187, 134, 192, 50))
self.tableWidget.item(i, j).setToolTip('Droit insuffisant pour ouvrire la couche !') self.tableWidget.item(i, j).setToolTip('Droit insuffisant pour ouvrire la couche !')
@ -441,6 +492,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.filtre_dynamique(self.lineEdit.text()) self.filtre_dynamique(self.lineEdit.text())
def selection_flux(self): def selection_flux(self):
"""Ajoute une couche sélectionnée à la liste des flux à charger"""
selected_row = 0 selected_row = 0
selected_items = self.tableWidget.selectedItems() selected_items = self.tableWidget.selectedItems()
@ -469,7 +521,8 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
return len(existing_items) > 0 return len(existing_items) > 0
def limite_flux(self): def limite_flux(self):
"""Vérifie le nombre de flux à charger et affiche un avertissement si > 5"""
# Avertissement si plus de 5 couches sélectionnées (risque de performance)
if self.tableWidget_2.rowCount() > 5: if self.tableWidget_2.rowCount() > 5:
self.QMBquestion = QMessageBox.question(iface.mainWindow(), u"Attention !", 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( "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(
@ -485,6 +538,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.chargement_flux() self.chargement_flux()
def chargement_flux(self): def chargement_flux(self):
"""Charge les couches sélectionnées dans QGIS"""
managerAU = QgsApplication.authManager() managerAU = QgsApplication.authManager()
managerAU.availableAuthMethodConfigs().keys() managerAU.availableAuthMethodConfigs().keys()
@ -498,6 +552,7 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
} }
return switcher.get(type, "nothing") return switcher.get(type, "nothing")
# Vérification de la présence de l'extension PostGIS Raster
SQLloadRaster = """SELECT concat(r_table_schema,'.',r_table_name) from public.raster_columns; """ SQLloadRaster = """SELECT concat(r_table_schema,'.',r_table_name) from public.raster_columns; """
SQLextension = """SELECT count(extname) FROM pg_catalog.pg_extension WHERE extname LIKE 'postgis_raster';""" SQLextension = """SELECT count(extname) FROM pg_catalog.pg_extension WHERE extname LIKE 'postgis_raster';"""
@ -514,9 +569,10 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
for rasterFind in list_raster: for rasterFind in list_raster:
RasterList.append(rasterFind[0]) RasterList.append(rasterFind[0])
# Chargement de chaque couche sélectionnée
for row in range(0, self.tableWidget_2.rowCount()): for row in range(0, self.tableWidget_2.rowCount()):
color_rgba_db = 855030089 color_rgba_db = 855030089 # Code couleur pour couche dans autre BD
color_rgba_droit = 851150528 color_rgba_droit = 851150528 # Code couleur pour droits insuffisants
print(self.tableWidget_2.item(row, 1).background().color().rgba()) print(self.tableWidget_2.item(row, 1).background().color().rgba())
if self.tableWidget_2.item(row, 1).background().color().rgba() == color_rgba_droit: if self.tableWidget_2.item(row, 1).background().color().rgba() == color_rgba_droit:
self.QMBquestion = QMessageBox.question(iface.mainWindow(), u"Attention !", "Vous ne disposez pas des droit pour la couche «" + str(self.tableWidget_2.item(row, 1).text()) + ' ' + str(self.tableWidget_2.item(row, 2).text()) + "» !", QMessageBox.StandardButton(0x00004000)) self.QMBquestion = QMessageBox.question(iface.mainWindow(), u"Attention !", "Vous ne disposez pas des droit pour la couche «" + str(self.tableWidget_2.item(row, 1).text()) + ' ' + str(self.tableWidget_2.item(row, 2).text()) + "» !", QMessageBox.StandardButton(0x00004000))
@ -537,26 +593,31 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
code = self.tableWidget_2.item(row, 1).text() code = self.tableWidget_2.item(row, 1).text()
schema = self.tableWidget_2.item(row, 2).text() schema = self.tableWidget_2.item(row, 2).text()
table = self.tableWidget_2.item(row, 3).text() table = self.tableWidget_2.item(row, 3).text()
# Configuration de l'URI de connexion PostGIS
uri = QgsDataSourceUri() uri = QgsDataSourceUri()
uri.setConnection(host, port, dbtype, user, mdp) 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
# Chargement selon le type de couche (raster, vecteur ou projet QGIS)
if (schema + '.' + table) in RasterList: if (schema + '.' + table) in RasterList:
# Chargement d'une couche raster
uri.setDataSource(schema, table, "rast") uri.setDataSource(schema, table, "rast")
uri.setKeyColumn('rid') uri.setKeyColumn('rid') # Clé primaire pour les rasters
uri.setSrid('2154') uri.setSrid('2154') # Lambert 93
layer = QgsRasterLayer(uri.uri(), table, "postgresraster") layer = QgsRasterLayer(uri.uri(), table, "postgresraster")
QgsProject.instance().addMapLayer(layer) QgsProject.instance().addMapLayer(layer)
elif code == 'qgis': elif code == 'qgis':
# Chargement d'un projet QGIS stocké dans la base de données
schema = self.tableWidget_2.item(row, 2).text() schema = self.tableWidget_2.item(row, 2).text()
print(schema) print(schema)
table = self.tableWidget_2.item(row, 3).text() table = self.tableWidget_2.item(row, 3).text()
uri_project = 'postgresql://' + user + ':' + mdp + '@' + host + ':' + port + '?sslmode=disable&dbname=' + dbtype + "&schema=" + schema + '&project=' + table uri_project = 'postgresql://' + user + ':' + mdp + '@' + host + ':' + port + '?sslmode=disable&dbname=' + dbtype + "&schema=" + schema + '&project=' + table
QgsProject.instance().read(uri_project) QgsProject.instance().read(uri_project)
else: else:
uri.setDataSource(schema, table, "geom") # Chargement d'une couche vecteur
uri.setKeyColumn('gid') uri.setDataSource(schema, table, "geom") # Colonne géométrie
uri.setKeyColumn('gid') # Clé primaire
# Chargement de la couche PostGIS # Détection du type de géométrie
geom_type = 'SELECT right(st_geometrytype(geom),-3) as a FROM ' + schema + '.' + table + ' GROUP BY a' geom_type = 'SELECT right(st_geometrytype(geom),-3) as a FROM ' + schema + '.' + table + ' GROUP BY a'
cur.execute(geom_type) cur.execute(geom_type)
list_typegeom = cur.fetchall() list_typegeom = cur.fetchall()
@ -587,8 +648,9 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
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)) 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): def combobox_custom(self):
"""Remplit la liste déroulante des catégories selon la base de données sélectionnée"""
global NoSignals global NoSignals
NoSignals = 1 NoSignals = 1 # Désactive temporairement les signaux pour éviter les boucles
if dbtype == sigdb: if dbtype == sigdb:
self.toolButton.setEnabled(1) self.toolButton.setEnabled(1)
self.comboBox.clear() self.comboBox.clear()
@ -615,7 +677,8 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
NoSignals = 0 NoSignals = 0
def filtre_favorit(self, filter_fav): def filtre_favorit(self, filter_fav):
if self.toolButton_2.text() == "0": """Active ou désactive le filtre des favoris"""
if self.toolButton_2.text() == "0": # Activation du filtre
self.toolButton_2.setText("1") self.toolButton_2.setText("1")
self.toolButton_2.setDown(True) self.toolButton_2.setDown(True)
if self.lineEdit.text() != 'Recherche par mots-clés': if self.lineEdit.text() != 'Recherche par mots-clés':
@ -635,6 +698,8 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
self.tableWidget.setRowHidden(i, False) self.tableWidget.setRowHidden(i, False)
def filtre_dynamique(self, filter_text): def filtre_dynamique(self, filter_text):
"""Filtre dynamique des couches selon le texte saisi"""
# Remplacement des espaces par des underscores pour la recherche
if filter_text.find(' ') >= 0: if filter_text.find(' ') >= 0:
filter_text = filter_text.replace(" ", "_") filter_text = filter_text.replace(" ", "_")
for i in range(self.tableWidget.rowCount()): for i in range(self.tableWidget.rowCount()):
@ -650,6 +715,8 @@ class Flux_Editor(QDialog, EDITOR_CLASS):
break break
def getCanevas(self): def getCanevas(self):
"""Filtre les couches selon l'emprise du canevas QGIS actuel"""
# Récupération de l'emprise du canevas
poly = iface.mapCanvas().extent() poly = iface.mapCanvas().extent()
geom = (str(poly.xMinimum()) + ',' + str(poly.yMinimum()) + ',' + str(poly.xMaximum()) + ',' + str(poly.yMaximum())) geom = (str(poly.xMinimum()) + ',' + str(poly.yMinimum()) + ',' + str(poly.xMaximum()) + ',' + str(poly.yMaximum()))