Téléverser les fichiers vers "CenRa_COPIE"

This commit is contained in:
Tom LAVEILLE 2024-08-01 15:17:32 +02:00
parent 6aa35a2620
commit c8966c7316
5 changed files with 544 additions and 0 deletions

35
CenRa_COPIE/__init__.py Normal file
View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
Copie
A QGIS plugin
Permet la copie d'une table dans une base PostGis
-------------------
begin : 2015-04-13
copyright : (C) 2015 by Guillaume COSTES - CEN Rhône-Alpes
email : guillaume.costes@espaces-naturels.fr
git sha : $Format:%H$
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
This script initializes the plugin, making it known to QGIS.
"""
# noinspection PyPep8Naming
def classFactory(iface): # pylint: disable=invalid-name
"""Load Copie class from file Copie.
:param iface: A QGIS interface instance.
:type iface: QgsInterface
"""
#
from .copie import Copie
return Copie(iface)

BIN
CenRa_COPIE/cenra.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

360
CenRa_COPIE/copie.py Normal file
View File

@ -0,0 +1,360 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
Copie
A QGIS plugin
Permet la copie d'une table dans une base PostGis
-------------------
begin : 2015-04-13
git sha : $Format:%H$
copyright : (C) 2015 by Guillaume COSTES - CEN Rhône-Alpes
email : guillaume.costes@espaces-naturels.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from __future__ import absolute_import
#from PyQt4.QtCore import *
#from PyQt4.QtGui import *
from qgis.PyQt.QtCore import QSettings
from qgis.PyQt.QtWidgets import QAction, QMenu, QDialog, QMessageBox
from qgis.PyQt.QtGui import QIcon
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from qgis.core import QgsDataSourceUri
from builtins import str
from builtins import object
from qgis.core import *
from qgis.gui import *
# Initialize Qt resources from file resources.py
from . import resources_rc
# Import the code for the dialog
from .copie_dialog import CopieDialog
import os.path
from .PythonSQL import *
import psycopg2
import psycopg2.extras
import base64
#import socket
import os
#import sys
class Copie(object):
"""QGIS Plugin Implementation."""
def __init__(self, iface):
"""Constructor.
:param iface: An interface instance that will be passed to this class
which provides the hook by which you can manipulate the QGIS
application at run time.
:type iface: QgsInterface
"""
# Save reference to the QGIS interface
self.iface = iface
# initialize plugin directory
self.plugin_dir = os.path.dirname(__file__)
# initialize locale
locale = QSettings().value('locale/userLocale')[0:2]
locale_path = os.path.join(
self.plugin_dir,
'i18n',
'Copie_{}.qm'.format(locale))
if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
if qVersion() > '4.3.3':
QCoreApplication.installTranslator(self.translator)
# Create the dialog (after translation) and keep reference
self.dlg = CopieDialog()
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&Copie')
# TODO: We are going to let the user set this up in a future iteration
self.toolbar = self.iface.addToolBar(u'Copie')
self.toolbar.setObjectName(u'Copie')
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass
return QCoreApplication.translate('Copie', message)
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
"""Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource
path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
:type icon_path: str
:param text: Text that should be shown in menu items for this action.
:type text: str
:param callback: Function to be called when the action is triggered.
:type callback: function
:param enabled_flag: A flag indicating if the action should be enabled
by default. Defaults to True.
:type enabled_flag: bool
:param add_to_menu: Flag indicating whether the action should also
be added to the menu. Defaults to True.
:type add_to_menu: bool
:param add_to_toolbar: Flag indicating whether the action should also
be added to the toolbar. Defaults to True.
:type add_to_toolbar: bool
:param status_tip: Optional text to show in a popup when mouse pointer
hovers over the action.
:type status_tip: str
:param parent: Parent widget for the new action. Defaults None.
:type parent: QWidget
:param whats_this: Optional text to show in the status bar when the
mouse pointer hovers over the action.
:returns: The action that was created. Note that the action is also
added to self.actions list.
:rtype: QAction
"""
icon = QIcon(icon_path)
action = QAction(icon, text, parent)
action.triggered.connect(callback)
action.setEnabled(enabled_flag)
if status_tip is not None:
action.setStatusTip(status_tip)
if whats_this is not None:
action.setWhatsThis(whats_this)
if add_to_toolbar:
self.toolbar.addAction(action)
if add_to_menu:
self.iface.addPluginToMenu(
self.menu,
action)
self.actions.append(action)
return action
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI."""
icon_path = ':/plugins/Copie/table_copie.png'
self.add_action(
icon_path,
text=self.tr(u'Copie'),
callback=self.run,
parent=self.iface.mainWindow())
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions:
self.iface.removePluginMenu(
self.tr(u'&Copie'),
action)
self.iface.removeToolBarIcon(action)
# remove the toolbar
del self.toolbar
def run(self):
"""Run method that performs all the real work"""
layer = self.iface.activeLayer()
if layer == None :
#self.iface.messageBar().pushMessage(u"Vous devez sélectionner une table !", level=QgsMessageBar.WARNING, duration=5)
self.iface.messageBar().pushMessage("Ooops", u"Vous devez sélectionner une table !", level=Qgis.Warning, duration=5)
else :
# Récupération des sources de la couche active
list_sources = layer.source().split(" ")
# dbname
source_db = [s for s in list_sources if "dbname" in s][0].split("'")[1]
# schema
source_schema = [s for s in list_sources if "table" in s][0].split('"')[1]
# tablename
source_tablename = [s for s in list_sources if "table" in s][0].split('"')[3]
if source_db != sigdb:
#self.iface.messageBar().pushMessage(u"Un référentiel ne peut être copié, utilisez les filtres !", level=QgsMessageBar.CRITICAL, duration=10)
self.iface.messageBar().pushMessage("Ooops", u"Vous ne pouvez copier des couches que dans sigXX", level=Qgis.Critical, duration=5)
else :
first_conn = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=first_cnx password=" + password)
first_cur = first_conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
first_cur.execute("SELECT mdp_w, login_w FROM pg_catalog.pg_user t1, admin_sig.vm_users_sig t2 WHERE t2.oid = t1.usesysid AND (login_w = '" + os_user + "' OR login_w = '" + os_user + "')")
res_ident = first_cur.fetchone()
mdp = base64.b64decode(str(res_ident[0])).decode('utf-8')
user = res_ident[1]
con = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=" + user + " password=" + mdp)
cur = con.cursor(cursor_factory = psycopg2.extras.DictCursor)
first_conn.close()
# Creation de la liste des schemas de la base de donnees
SQL = """WITH list_schema AS (
SELECT catalog_name, schema_name
FROM information_schema.schemata
WHERE schema_name <> 'information_schema'
AND schema_name !~ E'^pg_'
ORDER BY schema_name
)
SELECT string_agg(schema_name,',')
FROM list_schema
GROUP BY catalog_name"""
cur.execute(SQL)
list_brut = str(next(cur))
list = list_brut [2:-3]
listItems = list.split(",")
con.close()
self.dlg.schema.clear()
self.dlg.schema.addItems(listItems)
self.dlg.schema.setCurrentIndex(-1) # Pour ne pas commencer la liste au premier schema
self.dlg.table_source.setText(source_schema + "." + source_tablename) # Affiche le nom de la table source
# show the dialog
self.dlg.show()
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result:
#******************************debut script*********************************
first_conn = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=first_cnx password=" + password)
first_cur = first_conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
first_cur.execute("SELECT mdp_w, login_w FROM pg_catalog.pg_user t1, admin_sig.vm_users_sig t2 WHERE t2.oid = t1.usesysid AND (login_w = '" + os_user + "' OR login_w = '" + os_user + "')")
res_ident = first_cur.fetchone()
mdp = base64.b64decode(str(res_ident[0])).decode('utf-8')
user = res_ident[1]
con = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=" + user + " password=" + mdp)
cur = con.cursor(cursor_factory = psycopg2.extras.DictCursor)
first_conn.close()
# Récupération de la couche active
layer = self.iface.activeLayer()
# Récupération des sources de la couche active
list_sources = layer.source().split(" ")
# dbname
source_db = [s for s in list_sources if "dbname" in s][0].split("'")[1]
# schema
source_schema = [s for s in list_sources if "table" in s][0].split('"')[1]
# tablename
source_tablename = [s for s in list_sources if "table" in s][0].split('"')[3]
if self.dlg.schema.currentIndex() == -1 :
QMessageBox.warning(None, "Oups :", "Veuillez choisir un dossier de destination.")
return
schema = self.dlg.schema.currentText()
if self.dlg.table_destination.text() == '' :
QMessageBox.warning(None, "Oups :", "Veuillez choisir un nom de destination.")
return
if self.dlg.annee.text() == 'aaaa' or self.dlg.annee.text() == '':
tablename = schema + "_" + self.dlg.table_destination.text().lower()
else :
tablename = schema + "_" + self.dlg.table_destination.text().lower() + "_" + self.dlg.annee.text()
tablename_qgis = tablename[1:] # Permet d'enlever le "_", ajouter a la premiere etape, dans qgis
if self.dlg.table_vide.isChecked() == 1 :
SQL_table = "CREATE TABLE " + schema + "." + tablename + " AS SELECT * FROM " + source_schema + "." + source_tablename + " LIMIT 0;"
else :
SQL_table = "CREATE TABLE " + schema + "." + tablename + " AS SELECT * FROM " + source_schema + "." + source_tablename
SQL_pkey = "ALTER TABLE " + schema + "." + tablename + " ADD CONSTRAINT " + tablename + "_pkey" + " PRIMARY KEY (gid)"
SQL_sequence_01 = "CREATE SEQUENCE " + schema + "." + tablename + "_gid_seq" + " INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;"
SQL_sequence_02 = "ALTER TABLE " + schema + "." + tablename + " ALTER COLUMN gid SET DEFAULT nextval(\'" + schema + "." + tablename + "_gid_seq\'::regclass);"
SQL_sequence_03 = "SELECT setval(\'" + schema + "." + tablename + "_gid_seq\'::regclass, (SELECT max(gid) AS max_gid FROM " + schema + "." + tablename + "));"
SQL_sequence_04 = "ALTER SEQUENCE " + schema + "." + tablename + "_gid_seq" + " OWNED BY " + schema + "." + tablename + ".gid;"
SQL_trigger_area_m2 = "CREATE TRIGGER area_m2" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.area_m2();"
SQL_trigger_area_ha = "CREATE TRIGGER area_ha" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.area_ha();"
SQL_trigger_length_m = "CREATE TRIGGER length_m" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.length_m();"
SQL_trigger_length_km = "CREATE TRIGGER length_km" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.length_km();"
SQL_trigger_coordonnees = "CREATE TRIGGER coordonnees" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.coordonnees();"
cur.execute(SQL_table)
cur.execute(SQL_pkey)
cur.execute(SQL_sequence_01)
cur.execute(SQL_sequence_02)
cur.execute(SQL_sequence_03)
cur.execute(SQL_sequence_04)
if layer.wkbType() == QgsWkbTypes.PointGeometry :
cur.execute(SQL_trigger_coordonnees)
if layer.wkbType() == QgsWkbTypes.LineGeometry :
cur.execute(SQL_trigger_length_m)
cur.execute(SQL_trigger_length_km)
if layer.wkbType() == QgsWkbTypes.PolygonGeometry :
cur.execute(SQL_trigger_area_m2)
cur.execute(SQL_trigger_area_ha)
con.commit()
### Affichage de la table
uri = QgsDataSourceUri()
# set host name, port, database name, username and password
uri.setConnection(host ,port ,dbname ,user ,mdp)
# set database schema, table name, geometry column and optionaly subset (WHERE clause)
uri.setDataSource(schema, tablename, geom)
layer = self.iface.addVectorLayer(uri.uri(), tablename_qgis, "postgres")
con.commit()
con.close()
#self.iface.messageBar().pushMessage("Table \"" + source_schema + "." + source_tablename + u"\" copiée dans \"" + schema + "." + tablename + "\"." , level=QgsMessageBar.INFO, duration=10)
self.iface.messageBar().pushMessage("Bravo!", "Table \"" + source_schema + "." + source_tablename + u"\" copiée dans \"" + schema + "." + tablename + "\".", level=Qgis.Success, duration=5)
pass

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
CopieDialog
A QGIS plugin
Permet la copie d'une table dans une base PostGis
-------------------
begin : 2015-04-13
git sha : $Format:%H$
copyright : (C) 2015 by Guillaume COSTES - CEN Rhône-Alpes
email : guillaume.costes@espaces-naturels.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
import os
from qgis.PyQt import QtCore, QtGui, QtGui, uic
from qgis.PyQt.QtWidgets import QAction, QMenu, QDialog
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'copie_dialog_base.ui'))
class CopieDialog(QDialog, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(CopieDialog, self).__init__(parent)
# Set up the user interface from Designer.
# After setupUI you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots - see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'copie_dialog_base.ui'
#
# Created: Tue Apr 14 11:48:04 2015
# by: PyQt4 UI code generator 4.10.2
#
# WARNING! All changes made in this file will be lost!
from builtins import object
from qgis.PyQt import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_CopieDialogBase(object):
def setupUi(self, CopieDialogBase):
CopieDialogBase.setObjectName(_fromUtf8("CopieDialogBase"))
CopieDialogBase.resize(386, 290)
self.button_box = QtGui.QDialogButtonBox(CopieDialogBase)
self.button_box.setGeometry(QtCore.QRect(100, 250, 161, 32))
self.button_box.setOrientation(QtCore.Qt.Horizontal)
self.button_box.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.button_box.setObjectName(_fromUtf8("button_box"))
self.schema_label = QtGui.QLabel(CopieDialogBase)
self.schema_label.setGeometry(QtCore.QRect(20, 100, 121, 29))
self.schema_label.setMaximumSize(QtCore.QSize(10000, 16777215))
self.schema_label.setObjectName(_fromUtf8("schema_label"))
self.label_nom_table = QtGui.QLabel(CopieDialogBase)
self.label_nom_table.setGeometry(QtCore.QRect(20, 150, 131, 29))
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.label_nom_table.setFont(font)
self.label_nom_table.setObjectName(_fromUtf8("label_nom_table"))
self.schema = QtGui.QComboBox(CopieDialogBase)
self.schema.setGeometry(QtCore.QRect(20, 130, 351, 20))
self.schema.setObjectName(_fromUtf8("schema"))
self.table_destination = QtGui.QLineEdit(CopieDialogBase)
self.table_destination.setGeometry(QtCore.QRect(20, 180, 291, 20))
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.table_destination.setFont(font)
self.table_destination.setObjectName(_fromUtf8("table_destination"))
self.annee = QtGui.QLineEdit(CopieDialogBase)
self.annee.setGeometry(QtCore.QRect(320, 180, 50, 20))
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.annee.setFont(font)
self.annee.setAlignment(QtCore.Qt.AlignCenter)
self.annee.setObjectName(_fromUtf8("annee"))
self.table_vide = QtGui.QCheckBox(CopieDialogBase)
self.table_vide.setGeometry(QtCore.QRect(60, 220, 271, 20))
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.table_vide.setFont(font)
self.table_vide.setObjectName(_fromUtf8("table_vide"))
self.table_source = QtGui.QLineEdit(CopieDialogBase)
self.table_source.setEnabled(False)
self.table_source.setGeometry(QtCore.QRect(20, 60, 351, 20))
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.table_source.setFont(font)
self.table_source.setObjectName(_fromUtf8("table_source"))
self.Titre = QtGui.QLabel(CopieDialogBase)
self.Titre.setGeometry(QtCore.QRect(0, 0, 381, 31))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.Titre.setFont(font)
self.Titre.setAlignment(QtCore.Qt.AlignCenter)
self.Titre.setObjectName(_fromUtf8("Titre"))
self.table_source_label = QtGui.QLabel(CopieDialogBase)
self.table_source_label.setGeometry(QtCore.QRect(20, 30, 75, 29))
self.table_source_label.setMaximumSize(QtCore.QSize(75, 16777215))
self.table_source_label.setObjectName(_fromUtf8("table_source_label"))
self.retranslateUi(CopieDialogBase)
QtCore.QObject.connect(self.button_box, QtCore.SIGNAL(_fromUtf8("accepted()")), CopieDialogBase.accept)
QtCore.QObject.connect(self.button_box, QtCore.SIGNAL(_fromUtf8("rejected()")), CopieDialogBase.reject)
QtCore.QMetaObject.connectSlotsByName(CopieDialogBase)
def retranslateUi(self, CopieDialogBase):
CopieDialogBase.setWindowTitle(_translate("CopieDialogBase", "Copie", None))
self.schema_label.setText(_translate("CopieDialogBase", "Dossier de destination ", None))
self.label_nom_table.setText(_translate("CopieDialogBase", "Nom de la nouvelle table", None))
self.annee.setText(_translate("CopieDialogBase", "aaaa", None))
self.table_vide.setText(_translate("CopieDialogBase", "Cocher cette case pour vider la table de destination", None))
self.Titre.setText(_translate("CopieDialogBase", "Copie d\'une table", None))
self.table_source_label.setText(_translate("CopieDialogBase", "Table source ", None))