diff --git a/CenRa_METABASE/CenRa_Metabase.py b/CenRa_METABASE/CenRa_Metabase.py new file mode 100644 index 0000000..d1e265a --- /dev/null +++ b/CenRa_METABASE/CenRa_Metabase.py @@ -0,0 +1,217 @@ +__copyright__ = "Copyright 2021, 3Liz" +__license__ = "GPL version 3" +__email__ = "info@3liz.org" + + +from qgis.core import QgsApplication +from qgis.PyQt.QtCore import Qt, QUrl, QSettings +from qgis.PyQt.QtGui import QDesktopServices, QIcon +from qgis.PyQt.QtWidgets import QAction +from qgis.utils import iface +import qgis + +# include +''' +from pg_metadata.connection_manager import ( + store_connections, + validate_connections_names, +) + + +from pg_metadata.locator import LocatorFilter +from pg_metadata.processing.provider import PgMetadataProvider +from pg_metadata.qgis_plugin_tools.tools.custom_logging import setup_logger +''' +import os +from .about_form import MetabaseAboutDialog +from .tools.resources import ( + # plugin_path, + pyperclip, + resources_path, + maj_verif, +) +pyperclip() +from .dock import CenRa_Metabase +from .editor import Metabase_Editor + +# from CenRa_Metabase.issues import CenRa_Issues + + +class PgMetadata: + def __init__(self): + """ Constructor. """ + self.dock = None + self.editor = None +# self.issues = None + self.provider = None + self.locator_filter = None + self.dock_action = None + self.help_action = None + plugin_dir = os.path.dirname(__file__) + end_find = plugin_dir.rfind('\\') + 1 + global NAME + NAME = plugin_dir[end_find:] + maj_verif(NAME) + + # Display About window on first use + version = qgis.utils.pluginMetadata('CenRa_METABASE', 'version') + s = QSettings() + versionUse = s.value("metadata/version", 1, type=str) + if str(versionUse) != str(version): + s.setValue("metadata/version", str(version)) + print(versionUse, version) + self.open_about_dialog() +# setup_logger('pg_metadata') + + # locale, file_path = setup_translation( + # folder=plugin_path("i18n"), file_pattern="CenRa_Metabase_{}.qm") + # if file_path: + # self.translator = QTranslator() + # self.translator.load(file_path) + # noinspection PyCallByClass,PyArgumentList + # QCoreApplication.installTranslator(self.translator) + + # noinspection PyPep8Naming + # def initProcessing(self): + # """ Add the QGIS Processing provider. """ + # if not self.provider: + # self.provider = PgMetadataProvider() + # QgsApplication.processingRegistry().addProvider(self.provider) + + # noinspection PyPep8Naming + def initGui(self): + """ Build the plugin GUI. """ + # self.initProcessing() + + # self.check_invalid_connection_names() + + self.toolBar = iface.addToolBar("CenRa_Metabase") + self.toolBar.setObjectName("CenRa_Metabase") + + icon = QIcon(resources_path('icons', 'icon.png')) + icon2 = QIcon(resources_path('icons', 'icon_2.png')) + + # Open the online help + self.help_action = QAction(icon, 'CenRa_Metabase', iface.mainWindow()) + iface.pluginHelpMenu().addAction(self.help_action) + self.help_action.triggered.connect(self.open_help) + if not self.editor: + self.editor = Metabase_Editor() + + self.editor_action = QAction(icon2, 'CenRa_Metabase', None) + self.toolBar.addAction(self.editor_action) + self.editor_action.triggered.connect(self.open_editor) + + if not self.dock: + self.dock = CenRa_Metabase() + iface.addDockWidget(Qt.DockWidgetArea(0x2), self.dock) + + # Open/close the dock from plugin menu + self.dock_action = QAction(icon, 'CenRa_Metabase', iface.mainWindow()) + iface.pluginMenu().addAction(self.dock_action) + self.dock_action.triggered.connect(self.open_dock) +# if not self.issues: +# self.issues = CenRa_Issues() + + +# self.issues_action = QAction(icon, 'CenRa_Metabase',None) +# self.toolBar.addAction(self.issues_action) +# self.issues_action.triggered.connect(self.open_issues) + ''' + if not self.locator_filter: + self.locator_filter = LocatorFilter(iface) + iface.registerLocatorFilter(self.locator_filter) + + @staticmethod + def check_invalid_connection_names(): + """ Check for invalid connection names in the QgsSettings. """ + valid, invalid = validate_connections_names() + n_invalid = len(invalid) + + if n_invalid == 0: + return + + invalid_text = ', '.join(invalid) + msg = QMessageBox() + msg.setIcon(QMessageBox.Warning) + msg.setWindowTitle(tr('PgMetadata: Database connection(s) not available')) + msg.setText(tr( + f'{n_invalid} connection(s) listed in PgMetadata’s settings are invalid or ' + f'no longer available: {invalid_text}')) + msg.setInformativeText(tr( + 'Do you want to remove these connection(s) from the PgMetadata settings? ' + '(You can also do this later with the “Set Connections” tool.)')) + msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + clicked = msg.exec() + + if clicked == QMessageBox.Yes: + iface.messageBar().pushSuccess('PgMetadata', tr(f'{n_invalid} invalid connection(s) removed.')) + store_connections(valid) + if clicked == QMessageBox.No: + iface.messageBar().pushInfo('PgMetadata', tr(f'Keeping {n_invalid} invalid connections.')) + ''' + def open_about_dialog(self): + """ + About dialog + """ + dialog = MetabaseAboutDialog(iface) + dialog.exec() + + def open_help(): + """ Open the online help. """ + QDesktopServices.openUrl(QUrl('https://plateformesig.cenra-outils.org/')) + + def open_dock(self): + """ Open the dock. """ + self.dock.show() + self.dock.raise_() + + def open_editor(self): + self.editor.show() + self.editor.raise_() + +# def open_issues(self): +# self.issues.show() +# self.issues.raise_() + + def unload(self): + """ Unload the plugin. """ + # if self.editor: + # iface.removePluginMenu('CenRa_Metabase',self.editor_action) + # self.editor.removeToolBarIcon(self.editor_action) + + if self.dock: + iface.removeDockWidget(self.dock) + self.dock.deleteLater() + + if self.provider: + QgsApplication.processingRegistry().removeProvider(self.provider) + del self.provider + + if self.locator_filter: + iface.deregisterLocatorFilter(self.locator_filter) + del self.locator_filter + + if self.help_action: + iface.pluginHelpMenu().removeAction(self.help_action) + del self.help_action + + if self.dock_action: + iface.pluginMenu().removeAction(self.dock_action) + del self.dock_action + + @staticmethod + def run_tests(pattern='test_*.py', package=None): + """Run the test inside QGIS.""" + try: + from pathlib import Path + + from pg_metadata.qgis_plugin_tools.infrastructure.test_runner import ( + test_package, + ) + if package is None: + package = '{}.__init__'.format(Path(__file__).parent.name) + test_package(package, pattern) + except (AttributeError, ModuleNotFoundError): + message = 'Could not load tests. Are you using a production package?' + print(message) # NOQA diff --git a/CenRa_METABASE/README.md b/CenRa_METABASE/README.md new file mode 100644 index 0000000..86abd18 --- /dev/null +++ b/CenRa_METABASE/README.md @@ -0,0 +1 @@ +# CenRa_Metabase \ No newline at end of file diff --git a/CenRa_METABASE/__init__.py b/CenRa_METABASE/__init__.py new file mode 100644 index 0000000..4eaf7d0 --- /dev/null +++ b/CenRa_METABASE/__init__.py @@ -0,0 +1,10 @@ +__copyright__ = "Copyright 2021, 3Liz" +__license__ = "GPL version 3" +__email__ = "info@3liz.org" + + +# noinspection PyPep8Naming +def classFactory(iface): # pylint: disable=invalid-name + _ = iface + from CenRa_METABASE.CenRa_Metabase import PgMetadata + return PgMetadata() diff --git a/CenRa_METABASE/about_form.py b/CenRa_METABASE/about_form.py new file mode 100644 index 0000000..b9fa5a7 --- /dev/null +++ b/CenRa_METABASE/about_form.py @@ -0,0 +1,46 @@ +import os.path + +from pathlib import Path + +from qgis.PyQt import uic +# from qgis.PyQt.QtGui import QPixmap +from qgis.PyQt.QtWidgets import QDialog + +from .tools.resources import devlog + +ABOUT_FORM_CLASS, _ = uic.loadUiType( + os.path.join( + str(Path(__file__).resolve().parent), + 'tools/ui', + 'CenRa_about_form.ui' + ) +) + + +class MetabaseAboutDialog(QDialog, ABOUT_FORM_CLASS): + + """ About - Let the user display the about dialog. """ + + def __init__(self, iface, parent=None): + super().__init__(parent) + self.iface = iface + self.setupUi(self) + + self.viewer.setHtml(devlog('CenRa_METABASE')) + + self.rejected.connect(self.onReject) + self.buttonBox.rejected.connect(self.onReject) + self.buttonBox.accepted.connect(self.onAccept) + + def onAccept(self): + """ + Save options when pressing OK button + """ + self.accept() + + def onReject(self): + """ + Run some actions when + the user closes the dialog + """ + self.close() diff --git a/CenRa_METABASE/dock.py b/CenRa_METABASE/dock.py new file mode 100644 index 0000000..a2979e2 --- /dev/null +++ b/CenRa_METABASE/dock.py @@ -0,0 +1,453 @@ +"""Dock file.""" + +__copyright__ = 'Copyright 2020, 3Liz' +__license__ = 'GPL version 3' +__email__ = 'info@3liz.org' + +import logging +import os + +from collections import namedtuple +from enum import Enum +from functools import partial +from pathlib import Path +from xml.dom.minidom import parseString + +from qgis.core import ( + QgsApplication, + QgsProviderRegistry, + QgsSettings, +) +from qgis.PyQt.QtCore import QLocale, QUrl +from qgis.PyQt.QtGui import QDesktopServices, QIcon +from qgis.PyQt.QtPrintSupport import QPrinter +# from qgis.PyQt.QtWebKitWidgets import QWebPage +from qgis.PyQt.QtWidgets import ( + QAction, + QDockWidget, + QFileDialog, + QMenu, + QToolButton, +) +from qgis.utils import iface +import qgis +from .tools.resources import ( + load_ui, + resources_path, +) +try: + from .tools.PythonSQL import login_base +except ValueError: + print('Pas de fichier PythonSQL') + +DOCK_CLASS = load_ui('CenRa_Metabase_dockwidget_base.ui') +LOGGER = logging.getLogger('CenRa_Metabase') + + +class Format(namedtuple('Format', ['label', 'ext'])): + """ Format available for exporting metadata. """ + pass + + +class OutputFormats(Format, Enum): + """ Output format for a metadata sheet. """ + PDF = Format(label='PDF', ext='pdf') + HTML = Format(label='HTML', ext='html') + DCAT = Format(label='DCAT', ext='xml') + + +class CenRa_Metabase(QDockWidget, DOCK_CLASS): + + def __init__(self, parent=None): + _ = parent + super().__init__() + self.setupUi(self) + self.settings = QgsSettings() + + self.current_datasource_uri = None + self.current_connection = None + + # self.viewer.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks) + # self.viewer.page().linkClicked.connect(self.open_link) + + # Help button + self.external_help.setText('') + self.external_help.setIcon(QIcon(QgsApplication.iconPath('mActionHelpContents.svg'))) + self.external_help.clicked.connect(self.open_external_help) + + # Flat table button + self.flatten_dataset_table.setText('') + # self.flatten_dataset_table.setToolTip(tr("Add the catalog table")) + self.flatten_dataset_table.setIcon(QgsApplication.getThemeIcon("/mActionAddHtml.svg")) + # self.flatten_dataset_table.clicked.connect(self.add_flatten_dataset_table) + + # Settings menu + self.config.setAutoRaise(True) + # self.config.setToolTip(tr("Settings")) + self.config.setPopupMode(QToolButton.ToolButtonPopupMode(2)) + self.config.setIcon(QgsApplication.getThemeIcon("/mActionOptions.svg")) + + self.auto_open_dock_action = QAction( + ("Dommage, cette option n'existe pas encore."), + iface.mainWindow()) + self.auto_open_dock_action.setCheckable(True) + self.auto_open_dock_action.setChecked( + self.settings.value("pgmetadata/auto_open_dock", True, type=bool) + ) + self.auto_open_dock_action.triggered.connect(self.save_auto_open_dock) + menu = QMenu() + menu.addAction(self.auto_open_dock_action) + self.config.setMenu(menu) + + # Setting PDF/HTML menu + self.save_button.setAutoRaise(True) + # self.save_button.setToolTip(tr("Save metadata")) + self.save_button.setPopupMode(QToolButton.ToolButtonPopupMode(2)) + self.save_button.setIcon(QIcon(QgsApplication.iconPath('mActionFileSave.svg'))) + + self.save_as_pdf = QAction( + ('Enregistrer en PDF') + '…', + iface.mainWindow()) + self.save_as_pdf.triggered.connect(partial(self.export_dock_content, OutputFormats.PDF)) + + self.save_as_html = QAction( + ('Enregistrer en HTML') + '…', + iface.mainWindow()) + self.save_as_html.triggered.connect(partial(self.export_dock_content, OutputFormats.HTML)) + self.save_as_dcat = QAction( + ('Enregistrer en DCAT') + '…', + iface.mainWindow()) + self.save_as_dcat.triggered.connect(partial(self.export_dock_content, OutputFormats.DCAT)) + + self.menu_save = QMenu() + self.menu_save.addAction(self.save_as_pdf) + self.menu_save.addAction(self.save_as_html) + self.menu_save.addAction(self.save_as_dcat) + self.save_button.setMenu(self.menu_save) + self.save_button.setEnabled(False) + + self.metadata = QgsProviderRegistry.instance().providerMetadata('postgres') + + # Display message in the dock + # if not settings_connections_names(): + # self.default_html_content_not_installed() + # else: + self.default_html_content_not_pg_layer() + iface.layerTreeView().currentLayerChanged.connect(self.layer_changed) + try: + login_base() + iface.layerTreeView().currentLayerChanged.connect(self.layer_changed) + except ValueError: + # qgis.utils.plugins['CenRa_METABASE'].initGui() + qgis.utils.plugins['CenRa_METABASE'].unload() + # self.default_html_content_not_pg_layer() + + if iface.activeLayer(): + layer = iface.activeLayer() + iface.layerTreeView().setCurrentLayer(None) + iface.layerTreeView().setCurrentLayer(layer) + + def export_dock_content(self, output_format: OutputFormats): + """ Export the current displayed metadata sheet to the given format. """ + layer_name = iface.activeLayer().name() + + file_path = os.path.join( + os.environ['USERPROFILE'], + 'Desktop\\{name}.{ext}'.format(name=layer_name, ext=output_format.ext) + ) + output_file = QFileDialog.getSaveFileName( + self, + ("Enregistrer en {format}").format(format=output_format.label), + file_path, + "{label} (*.{ext})".format( + label=output_format.label, + ext=output_format.ext, + ) + ) + if output_file[0] == '': + return + + self.settings.setValue("UI/lastFileNameWidgetDir", os.path.dirname(output_file[0])) + + output_file_path = output_file[0] + parent_folder = str(Path(output_file_path).parent) + + if output_format == OutputFormats.PDF: + printer = QPrinter() + printer.setOutputFormat(QPrinter.OutputFormat(1)) + # printer.setPageMargins(20,20,20,20,QPrinter.Unit(0)) + printer.setOutputFileName(output_file_path) + self.viewer.print(printer) + iface.messageBar().pushSuccess( + ("Export PDF"), + ( + "The metadata has been exported as PDF successfully in " + "{}").format(parent_folder, output_file_path) + ) + + elif output_format in [OutputFormats.HTML, OutputFormats.DCAT]: + if output_format == OutputFormats.HTML: + data_str = self.viewer.page().currentFrame().toHtml() + else: + layer = iface.activeLayer() + uri = layer.dataProvider().uri() + dataall = self.sql_info(uri) + data = self.sql_to_xml(dataall) + + with open(resources_path('xml', 'dcat.xml'), encoding='utf8') as xml_file: + xml_template = xml_file.read() + + xml = parseString(xml_template.format(language=data[0][0], content=data[0][1])) + + data_str = xml.toprettyxml() + + with open(output_file[0], "w", encoding='utf8') as file_writer: + file_writer.write(data_str) + iface.messageBar().pushSuccess( + ("Export") + ' ' + output_format.label, + ( + "The metadata has been exported as {format} successfully in " + "{path}").format( + format=output_format.label, folder=parent_folder, path=output_file_path) + ) + + def save_auto_open_dock(self): + """ Save settings about the dock. """ + self.settings.setValue("pgmetadata/auto_open_dock", self.auto_open_dock_action.isChecked()) + + def sql_to_xml(self, dataall): + distribution = '' + for y in dataall[1]: + distribution = distribution + ('' + '' + '{data}'.format(data=y[0]) + '{data}'.format(data=y[1]) + '{data}'.format(data=y[2]) + '{data}'.format(data=y[3]) + '{data}'.format(data=y[4]) + '' + '') + publisher = '' + for z in dataall[2]: + publisher = publisher + ('' + '' + '{data}'.format(data=z[1]) + '{data}'.format(data=z[3]) + '' + '') + data_str = [[dataall[0][26], '{data}'.format(data=dataall[0][1]) + '{data}'.format(data=dataall[0][4]) + '{data}'.format(data=dataall[0][5]) + '{data}'.format(data=dataall[0][26]) + '{data}'.format(data=dataall[0][28]) + '{data}'.format(data=dataall[0][20]) + '{data}'.format(data=dataall[0][11]) + '{data}'.format(data=dataall[0][21]) + '{data}'.format(data=dataall[0][13]) + distribution + publisher + '{data}'.format(data=", ".join(str(x) for x in dataall[0][24])) + '{data}'.format(data=", ".join(str(x) for x in dataall[0][6])) + '{data}'.format(data=dataall[0][12])]] + + return data_str + + @staticmethod + def sql_for_layer(uri, output_format: OutputFormats): + """ Get the SQL query for a given layer and output format. """ + locale = QgsSettings().value("locale/userLocale", QLocale().name()) + locale = locale.split('_')[0].lower() + + if output_format == [OutputFormats.HTML, OutputFormats.DCAT]: + sql = ( + "SELECT pgmetadata.get_dataset_item_html_content('{schema}', '{table}', '{locale}');" + ).format(schema=uri.schema(), table=uri.table(), locale=locale) + else: + raise NotImplementedError('Output format is not yet implemented.') + + return sql + + def layer_changed(self, layer): + """ When the layer has changed in the legend, we must check this new layer. """ + self.current_datasource_uri = None + self.current_connection = None + self.ce_trouve_dans_psql(layer) + + def add_flatten_dataset_table(self): + """ Add a flatten dataset table with all links and contacts. """ + ''' + connections, message = connections_list() + if not connections: + LOGGER.critical(message) + self.set_html_content('PgMetadata', message) + return + + if len(connections) > 1: + dialog = QInputDialog() + dialog.setComboBoxItems(connections) + dialog.setWindowTitle(tr("Database")) + dialog.setLabelText(tr("Choose the database to add the catalog")) + if not dialog.exec_(): + return + connection_name = dialog.textValue() + else: + connection_name = connections[0] + + metadata = QgsProviderRegistry.instance().providerMetadata('postgres') + connection = metadata.findConnection(connection_name) + + locale = QgsSettings().value("locale/userLocale", QLocale().name()) + locale = locale.split('_')[0].lower() + + uri = QgsDataSourceUri(connection.uri()) + uri.setTable(f'(SELECT * FROM pgmetadata.export_datasets_as_flat_table(\'{locale}\'))') + uri.setKeyColumn('uid') + + layer = QgsVectorLayer(uri.uri(), '{} - {}'.format(tr("Catalog"), connection_name), 'postgres') + QgsProject.instance().addMapLayer(layer) + ''' + + @staticmethod + def open_external_help(): + QDesktopServices.openUrl(QUrl('https://plateformesig.cenra-outils.org/')) + + @staticmethod + def open_link(url): + QDesktopServices.openUrl(url) + + def set_html_content(self, title=None, body=None): + """ Set the content in the dock. """ + # ink_logo=resources_path('icons', 'CEN_RA.png') + css_file = resources_path('css', 'dock.css') + with open(css_file, 'r', encoding='utf8') as f: + css = f.read() + + html = '' + # html += '' + html += ''.format(css=css) + # html += '' + # html += '' + # html += '' + if title: + html += '

{title}

'.format(title=title) + if body: + html += body + + html += '' + + # It must be a file, even if it does not exist on the file system. + # base_url = QUrl.fromLocalFile(resources_path('images', 'must_be_a_file.png')) + self.viewer.setHtml(html) + + def ce_trouve_dans_psql(self, layer): + try: + uri = layer.dataProvider().uri() + except AttributeError: + self.default_html_content_not_pg_layer() + self.save_button.setEnabled(False) + uri = '' + if uri != '': + if not uri.table(): + layertype = layer.providerType().lower() + if layertype == 'wms' or layertype == 'wfs': + self.set_html_to_wms(layer) + else: + self.default_html_content_not_pg_layer() + self.save_button.setEnabled(False) + else: + data_count = self.sql_check(uri) + # print(data_count) + if data_count == 0: + self.default_html_content_not_metadata() + self.save_button.setEnabled(False) + else: + self.build_html_content(layer, uri) + self.save_button.setEnabled(True) + + def build_html_content(self, layer, uri): + body = '' + + dataall = self.sql_info(uri) + data = dataall[0] + data_url = dataall[1] + data_contact = dataall[2] + # print(len(data_url)) + # data_collonne = [field.name() for field in layer.dataProvider().fields()] + + body += '

Identification

' + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=(", ".join(str(x) for x in data[6]))) + body += ''.format(data=(", ".join(str(x) for x in data[24]))) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += '
Titre{data[4]}
Description{data[5]}
Categories{data}
Thèmes{data}
Mots-clés{data[7]}
Dernier mise à jour{data[23]}
Langue{data[26]}
' + + body += '

Properties spatial

' + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += '
Niveau{data[8]}
Echelle minimum{data[9]}
Echelle maximum{data[10]}
Nombre d\'entités {data[15]}
Type de géométrie{data[16]}
Nom de projection{data[17]}
ID de projection{data[18]}
Emprise{data[28]}
' + + # body += '
' + + body += '

Publication

' + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += '
Date{data[11]}
Fréquence de mise à jour{data[12]}
Licence{data[13]}
Licence attribué{data[25]}
Restriction{data[14]}
' + + body += '

Lien

' + body += '' + for value_url in data_url: + body += ''.format(value_url=value_url) + body += '
TypeURLType MIMEFormatTaille
{value_url[0]}{value_url[1]}{value_url[2]}{value_url[3]}{value_url[4]}
' + ''' + body += '

Liste des champs

' + for collonne in data_collonne: + body += ''.format(collonne=collonne,defini='') + body += '
{collonne}{defini}
' + ''' + body += '

Contacts

' + body += '' + for value_contact in data_contact: + body += ''.format(value_contact=value_contact) + body += '
RôleNomOrganisationEmailTélèphone
{value_contact[0]}{value_contact[1]}{value_contact[2]}{value_contact[3]}{value_contact[4]}
' + + body += '

Metadata

' + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += ''.format(data=data) + body += '
Table{data[2]}
Schema{data[3]}
Date de création{data[20]}
Date de modification{data[21]}
Encodage{data[27]}
UUID{data[1]}
' + + self.set_html_content( + layer.name(), body) + + def set_html_to_wms(self, layer): + self.set_html_content( + 'CenRa Metadata', (layer.htmlMetadata())) + + def default_html_content_not_pg_layer(self): + """ When it's not a PostgreSQL layer. """ + self.set_html_content( + 'CenRa Metadata', ('Vous devez cliquer sur une couche dans la légende qui est stockée dans PostgreSQL.')) + + def default_html_content_not_metadata(self): + self.set_html_content( + 'CenRa Metadata', ('La couche ne contien pas de métadonnée.')) + + def sql_check(self, uri): + cur = login_base() + table = uri.table() + schema = uri.schema() + + sql_count = """SELECT count(uid) FROM metadata.dataset + WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + + cur.execute(sql_count) + data_count = cur.fetchall() + cur.close() + return data_count[0][0] + + def sql_info(self, uri): + cur = login_base() + table = uri.table() + schema = uri.schema() + # [s for s in iface.activeLayer().source().split(" ") if "dbname" in s][0].split("'")[1] + sql_find = """SELECT *,right(left(st_astext(geom,2),-2),-9) FROM metadata.dataset + WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + cur.execute(sql_find) + data_general = cur.fetchall() + sql_findurl = """SELECT type,url,mime,format,taille FROM metadata.dataurl WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + cur.execute(sql_findurl) + data_url = cur.fetchall() + sql_findcontact = """SELECT role,nom,organisation,email,telephone FROM metadata.datacontact WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + cur.execute(sql_findcontact) + data_contact = cur.fetchall() + cur.close() + return data_general[0], data_url, data_contact diff --git a/CenRa_METABASE/editor.py b/CenRa_METABASE/editor.py new file mode 100644 index 0000000..7896e2d --- /dev/null +++ b/CenRa_METABASE/editor.py @@ -0,0 +1,775 @@ +import logging +import os + +# from collections import namedtuple +# from enum import Enum +# from functools import partial +# from pathlib import Path +# from xml.dom.minidom import parseString +# from qgis.gui import * +from qgis.core import ( + QgsApplication, + QgsSettings, + QgsGeometry, + QgsWkbTypes, + Qgis, +) +from qgis.PyQt import QtGui, QtCore +from qgis.PyQt.QtGui import QIcon +# from qgis.PyQt.QtPrintSupport import QPrinter +# from qgis.PyQt.QtWebKitWidgets import QWebPage +import psycopg2 +from qgis.PyQt.QtWidgets import ( + QDialog, + QFileDialog, + QTableWidgetItem, +) +from qgis.utils import iface + +try: + from .tools.PythonSQL import login_base +except ValueError: + print('Pas de fichier PythonSQL') + +from .tools.resources import ( + load_ui, + resources_path, + # send_issues, +) +# from .issues import CenRa_Issues + +EDITOR_CLASS = load_ui('CenRa_Metabase_editorwidget_base.ui') +LOGGEr = logging.getLogger('CenRa_Metabase') + + +class Metabase_Editor(QDialog, EDITOR_CLASS): + def __init__(self, parent=None): + _ = parent + super().__init__() + self.setupUi(self) + self.settings = QgsSettings() + self.setWindowIcon(QtGui.QIcon(resources_path('icons', 'icon.png'))) + self.import_xml.setAutoRaise(True) + self.import_xml.setText('') + self.import_xml.setIcon(QIcon(QgsApplication.iconPath('mActionAddHtml.svg'))) + self.import_xml.clicked.connect(self.py_import_xml) + self.issues_app.setAutoRaise(True) + self.issues_app.setText('') + self.issues_app.setIcon(QIcon(QgsApplication.iconPath('mIconInfo.svg'))) + self.auto_adding.setIcon(QtGui.QIcon(resources_path('icons', 'auto_add.png'))) + self.auto_adding.hide() + if os.getlogin() == 'tlaveille' or 'lpoulin' or 'rclement': + self.auto_adding.show() + + self.auto_adding.clicked.connect(self.auto_run) + # self.issues_app.clicked.connect(self.issues_open) + self.categories_select_view.itemDoubleClicked.connect(self.add_categories_view) + self.categories_view.itemDoubleClicked.connect(self.deleter_categories_view) + self.themes_select_view.itemDoubleClicked.connect(self.add_themes_view) + self.themes_view.itemDoubleClicked.connect(self.deleter_themes_view) + + self.annuler_button.clicked.connect(self.close) + self.ok_button.clicked.connect(self.add_metadata) + + self.add_lien_button.clicked.connect(self.add_lien) + self.add_contact_button.clicked.connect(self.add_contact) + self.delete_lien_button.clicked.connect(self.delete_lien) + self.delete_contact_button.clicked.connect(self.delete_contact) + + def auto_run(self): + self.role_box.setCurrentIndex(1) + self.nom_line.setText('LAVEILLE') + self.organisation_box.setCurrentIndex(1) + self.email_line.setText('tom.laveille@cen-rhonealpes.fr') + self.telephone_line.setText('0451260811') + self.add_contact() + + self.type_box.setCurrentIndex(16) + self.url_line.setText('www.cen-rhonealpes.fr') + self.mime_box.setCurrentIndex(16) + self.format_box.setCurrentIndex(0) + self.taille_line.setText('45') + self.add_lien() + + def add_metadata(self): + table_name = layer.dataProvider().uri().table() + schema_name = layer.dataProvider().uri().schema() + text_titre = self.titre_line.text() + text_description = self.description_text.toPlainText() + text_mots_cles = self.mots_cles_text.toPlainText() + text_date_maj = str(self.date_maj_date.date().toPyDate()) + text_langue = self.langue_box.currentText() + + row_count_categories = self.categories_view.rowCount() + row_count_themes = self.themes_view.rowCount() + row = 1 + array_categories = '{' + while row_count_categories >= row: + if row_count_categories != row: + array_categories += (self.categories_view.item(row - 1, 0).text()) + ', ' + else: + array_categories += (self.categories_view.item(row - 1, 0).text()) + row = row + 1 + array_categories += '}' + row = 1 + array_themes = '{' + while row_count_themes >= row: + if row_count_themes != row: + array_themes += (self.themes_view.item(row - 1, 0).text()) + ', ' + else: + array_themes += (self.themes_view.item(row - 1, 0).text()) + row = row + 1 + array_themes += '}' + + text_date_creation = str(self.date_creation_date.date().toPyDate()) + text_date_modification = str(self.date_modification_date.date().toPyDate()) + text_encode = self.encodage_box.currentText() + text_extend = self.extend_plaintext.toPlainText() + int_nbr_entites = (self.nbr_layers.toPlainText()) + text_geomtype = self.typegeom_plaintext.toPlainText() + text_crsname = self.crsname_plaintext.toPlainText() + text_crscode = self.crscode_plaintext.toPlainText() + text_niveau = self.niveau_plain.toPlainText() + + text_echelle_min = self.echelle_min_plain.toPlainText() + text_echelle_max = self.echelle_max_plain.toPlainText() + if text_echelle_min == '': + text_echelle_min = 'NULL' + if text_echelle_max == '': + text_echelle_max = 'NULL' + + text_date_publication = str(self.date_publication_date.date().toPyDate()) + + text_frequence = self.frequence_box.currentText() + text_restriction = self.restriction_box.currentText() + text_licence = self.licence_box.currentText() + text_licence_attrib = self.licence_attrib_box.currentText() + + ''' + row_count_link = self.table_lien.rowCount() + row = 1 + array_link = '' + while row_count_link >= row: + if row_count_link != row: + array_link += "('" + table_name + "', '" + schema_name + "', '" + (self.table_lien.item(row - 1,1).text()) + "', '" + (self.table_lien.item(row - 1,2).text()) + "', '" + (self.table_lien.item(row - 1,3).text()) + "', '" + (self.table_lien.item(row - 1,4).text()) + "', '" + (self.table_lien.item(row - 1,5).text()) + "')" + ', ' + else: + array_link += "('" + table_name + "', '" + schema_name + "', '" + (self.table_lien.item(row - 1,1).text()) + "', '" + (self.table_lien.item(row - 1,2).text()) + "', '" + (self.table_lien.item(row - 1,3).text()) + "', '" + (self.table_lien.item(row - 1,4).text()) + "', '" + (self.table_lien.item(row - 1,5).text()) + "')" + row = row + 1 + + row_count_contact = self.table_contact.rowCount() + row = 1 + array_contact = '' + while row_count_contact >= row: + if row_count_contact != row: + array_contact += "('" + table_name + "', '" + schema_name + "', '" + (self.table_contact.item(row - 1,1).text()) + "', '" + (self.table_contact.item(row - 1,2).text()) + "', '" + (self.table_contact.item(row - 1,3).text()) + "', '" + (self.table_contact.item(row - 1,4).text()) + "', '" + (self.table_contact.item(row - 1,5).text()) + "')" + ', ' + else: + array_contact += "('" + table_name + "', '" + schema_name + "', '" + (self.table_contact.item(row - 1,1).text()) + "', '" + (self.table_contact.item(row - 1,2).text()) + "', '" + (self.table_contact.item(row - 1,3).text()) + "', '" + (self.table_contact.item(row - 1,4).text()) + "', '" + (self.table_contact.item(row - 1,5).text()) + "')" + row = row + 1 + ''' + + exist = self.status_metadata(layer) + cur_con = login_base(take=True) + cur = cur_con[0] + con = cur_con[1] + list_champs_sql = '' + values_sql_add = '' + if exist: + SQL_uid = """SELECT uid from metadata.dataset where table_name like '""" + table_name + """' and schema_name like '""" + schema_name + """';""" + cur.execute(SQL_uid) + text_uid = (cur.fetchall())[0][0] + + SQL_delete = """DELETE from metadata.dataset where table_name like '""" + table_name + """' and schema_name like '""" + schema_name + """';""" + cur.execute(SQL_delete) + values_sql_add += "'" + text_uid + "'," + + list_champs_sql += 'uid,' + global uid_delete_list_link, uid_delete_list_contact + if len(uid_delete_list_link) >= 35: + SQL_delete_link = """DELETE FROM metadata.dataurl WHERE uid IN (""" + uid_delete_list_link[:- 1] + """);""" + cur.execute(SQL_delete_link) + uid_delete_list_link = '' + if len(uid_delete_list_contact) >= 35: + SQL_delete_contact = """DELETE FROM metadata.datacontact WHERE uid IN (""" + uid_delete_list_contact[:- 1] + """);""" + cur.execute(SQL_delete_contact) + uid_delete_list_contact = '' + + list_champs_sql += 'table_name, schema_name, title, abstract, keywords, data_last_update, langue, categories, themes, creation_date, update_date, encode, geom, spatial_extent, feature_count, geometry_type, projection_name, projection_authid, spatial_level, minimum_optimal_scale, maximum_optimal_scale, publication_date, publication_frequency, confidentiality, license, license_attribution' + values_sql_add += "'" + table_name + "', '" + schema_name + "', '" + text_titre + "', '" + text_description + "', '" + text_mots_cles + "', '" + text_date_maj + "', '" + text_langue + "', '" + array_categories + "', '" + array_themes + "', '" + text_date_creation + "', '" + text_date_modification + "', '" + text_encode + "', '" + text_extend + "', '" + text_extend + "', '" + int_nbr_entites + "', '" + text_geomtype + "', '" + text_crsname + "', '" + text_crscode + "', '" + text_niveau + "'," + text_echelle_min + "," + text_echelle_max + ",'" + text_date_publication + "', '" + text_frequence + "', '" + text_restriction + "', '" + text_licence + "', '" + text_licence_attrib + "'" + + SQL_add = """INSERT INTO metadata.dataset (""" + list_champs_sql + """) VALUES (""" + values_sql_add + """);""" + + cur.execute(SQL_add) + + global array_link, array_contact + if len(array_link) >= 25: + array_link = array_link[:- 1] + SQL_add_link = """INSERT INTO metadata.dataurl (table_name, schema_name, type, url, mime, format, taille) VALUES """ + array_link + """;""" + cur.execute(SQL_add_link) + array_link = '' + + if len(array_contact) >= 25: + array_contact = array_contact[0:- 1] + SQL_add_contact = """INSERT INTO metadata.datacontact (table_name, schema_name, role, nom, organisation, email, telephone) VALUES """ + array_contact + """;""" + cur.execute(SQL_add_contact) + array_contact = '' + + con.commit() + cur.close() + self.close() + + iface.layerTreeView().setCurrentLayer(None) + iface.layerTreeView().setCurrentLayer(layer) + + def raise_(self): + self.activateWindow() + global layer + layer = iface.activeLayer() + global uid_delete_list_link, uid_delete_list_contact, array_link, array_contact + uid_delete_list_link = '' + uid_delete_list_contact = '' + array_link = '' + array_contact = '' + + is_ok = self.is_in_psql(layer) + if is_ok: + exist = self.status_metadata(layer) + if exist: + self.reload_data(layer) + else: + self.new_data(layer) + else: + self.close() + iface.messageBar().pushMessage("Information:", "Cette couche n'est pas stockée dans PostgreSQL", level=Qgis.Warning, duration=30) + + def is_in_psql(self, layer): + try: + uri = layer.dataProvider().uri() + except AttributeError: + uri = '' + return False + if uri != '': + if not uri.table(): + return False + else: + return True + + def status_metadata(self, layer): + uri = layer.dataProvider().uri() + table = uri.table() + schema = uri.schema() + + cur = login_base() + count_sql = """ SELECT count(uid) FROM metadata.dataset WHERE table_name LIKE '""" + table + """' AND schema_name LIKE '""" + schema + """';""" + + cur.execute(count_sql) + data_count = (cur.fetchall())[0][0] + if data_count == 1: + return True + else: + return False + cur.close() + + def new_data(self, layer): + # print(layer.name(),'is new data') + reloader = False + self.interface_view(layer, reloader) + + def reload_data(self, layer): + # print(layer.name(),'reload data') + reloader = True + self.interface_view(layer, reloader) + + def interface_view(self, layer, reloader): + + self.description_text.setText(None) + self.mots_cles_text.setText(None) + self.uuid_ligne.setText(None) + self.niveau_plain.setPlainText(None) + self.echelle_min_plain.setPlainText(None) + self.echelle_max_plain.setPlainText(None) + self.url_line.setText(None) + self.taille_line.setText(None) + self.nom_line.setText(None) + self.email_line.setText(None) + self.telephone_line.setText(None) + self.encodage_box.clear() + self.frequence_box.clear() + self.licence_box.clear() + self.licence_attrib_box.clear() + self.restriction_box.clear() + + all_list = self.fletch_ref() + + categories_list = all_list[0] + themes_list = all_list[1] + langue_list = all_list[2] + encodage_list = all_list[3] + frequency_list = all_list[4] + confidentiality_list = all_list[5] + license_list = all_list[6] + type_list = all_list[7] + mime_list = all_list[8] + format_list = all_list[9] + role_list = all_list[10] + organisation_list = all_list[11] + + # langue_box + self.langue_box.clear() + self.langue_box.addItem('') + # self.langue_box.addItem('Fr') + # self.langue_box.addItem('En') + for langue_list_data in langue_list: + self.langue_box.addItem(langue_list_data[0]) + + for encodage_list_data in encodage_list: + self.encodage_box.addItem(encodage_list_data[0]) + + self.table_ligne.setText(layer.dataProvider().uri().table()) + self.schema_ligne.setText(layer.dataProvider().uri().schema()) + + # categories_select_view + self.categories_select_view.setColumnCount(1) + self.categories_select_view.setColumnWidth(0, 230) + self.categories_select_view.setHorizontalHeaderLabels(['List des categories']) + # categories_view + self.categories_view.setRowCount(0) + self.categories_view.setColumnCount(1) + self.categories_view.setColumnWidth(0, 230) + self.categories_view.setHorizontalHeaderLabels(['Categories']) + + # themes_select_view + self.themes_select_view.setColumnCount(1) + self.themes_select_view.setColumnWidth(0, 230) + self.themes_select_view.setHorizontalHeaderLabels(['List des thèmes']) + # themes_view + self.themes_view.setRowCount(0) + self.themes_view.setColumnCount(1) + self.themes_view.setColumnWidth(0, 230) + self.themes_view.setHorizontalHeaderLabels(['Thèmes']) + + # lien_view + self.table_lien.setRowCount(0) + self.table_lien.setColumnCount(6) + self.table_lien.setColumnWidth(0, 0) + self.table_lien.setHorizontalHeaderLabels(['', 'Type', 'URL', 'MIME', 'Format', 'Taille']) + + # contact_view + self.table_contact.setRowCount(0) + self.table_contact.setColumnCount(6) + self.table_contact.setColumnWidth(0, 0) + self.table_contact.setHorizontalHeaderLabels(['', 'Rôle', 'Nom', 'Organisation', 'Email', 'Telephone']) + + # print(self.date_maj_date.date().toPyDate()) + vector_extend = layer.extent() + polygone_extend = QgsGeometry.fromRect(vector_extend).asWkt() + self.extend_plaintext.setPlainText(str(polygone_extend)) + + qgstype = str(layer.type())[10:] + + if qgstype != 'Raster': + count_layers = str(layer.featureCount()) + geomtype = QgsWkbTypes.displayString(layer.wkbType()) + elif qgstype == 'Raster': + count_layers = str(layer.dataProvider().bandCount()) + geomtype = qgstype + + self.nbr_layers.setPlainText(count_layers) + self.typegeom_plaintext.setPlainText(geomtype) + crs_name = str(layer.crs().description()) + self.crsname_plaintext.setPlainText(crs_name) + crs_code = str(layer.crs().authid()) + self.crscode_plaintext.setPlainText(crs_code) + + self.frequence_box.addItem('') + self.restriction_box.addItem('') + self.licence_box.addItem('') + self.licence_attrib_box.addItem('') + for frequency_list_data in frequency_list: + self.frequence_box.addItem(frequency_list_data[0]) + for confidentiality_list_data in confidentiality_list: + self.restriction_box.addItem(confidentiality_list_data[0]) + for license_list_data in license_list: + self.licence_box.addItem(license_list_data[0]) + + self.type_box.clear() + self.mime_box.clear() + self.format_box.clear() + self.role_box.clear() + self.organisation_box.clear() + + self.type_box.addItem('') + self.mime_box.addItem('') + self.format_box.addItem('') + self.role_box.addItem('') + self.organisation_box.addItem('') + + for type_list_data in type_list: + self.type_box.addItem(type_list_data[0]) + for mime_list_data in mime_list: + self.mime_box.addItem(mime_list_data[0]) + for format_list_data in format_list: + self.format_box.addItem(format_list_data[0]) + for role_list_data in role_list: + self.role_box.addItem(role_list_data[0]) + for organisation_list_data in organisation_list: + self.organisation_box.addItem(organisation_list_data[0]) + + if reloader: + sql_dataload = self.sql_info(layer.dataProvider().uri()) + sql_contactlink = self.sql_infoother(layer.dataProvider().uri()) + sql_datalink = sql_contactlink[0] + sql_datacontact = sql_contactlink[1] + + # print(sql_dataload) + self.titre_line.setText(sql_dataload[4]) + self.date_maj_date.setDateTime(sql_dataload[23]) + self.date_publication_date.setDateTime(sql_dataload[11]) + self.description_text.setText(sql_dataload[5]) + self.mots_cles_text.setText(sql_dataload[7]) + array_langue_box = [self.langue_box.itemText(i) for i in range(self.langue_box.count())] + self.langue_box.setCurrentIndex(array_langue_box.index(sql_dataload[26])) + self.uuid_ligne.setText(sql_dataload[1]) + + self.categories_view.setRowCount(len(sql_dataload[6])) + i = 0 + for categorie_data in sql_dataload[6]: + self.categories_view.setItem(i, 0, QTableWidgetItem(categorie_data)) + i = i + 1 + self.themes_view.setRowCount(len(sql_dataload[24])) + i = 0 + for themes_data in sql_dataload[24]: + self.themes_view.setItem(i, 0, QTableWidgetItem(themes_data)) + i = i + 1 + + self.categories_select_view.setRowCount(len(categories_list) - len(sql_dataload[6])) + self.themes_select_view.setRowCount(len(themes_list) - len(sql_dataload[24])) + i = 0 + for categorie_select_data in categories_list: + try: + in_index = sql_dataload[6].index(categorie_select_data[0]) + in_index = False + except ValueError: + in_index = True + if in_index: + self.categories_select_view.setItem(i, 0, QTableWidgetItem(categorie_select_data[0])) + i = i + 1 + i = 0 + for themes_select_data in themes_list: + try: + in_index = sql_dataload[24].index(themes_select_data[0]) + in_index = False + except ValueError: + in_index = True + if in_index: + self.themes_select_view.setItem(i, 0, QTableWidgetItem(themes_select_data[0])) + i = i + 1 + + array_encodage_box = [self.encodage_box.itemText(i) for i in range(self.encodage_box.count())] + self.encodage_box.setCurrentIndex(array_encodage_box.index(sql_dataload[27])) + + self.niveau_plain.setPlainText(sql_dataload[8]) + + if str(sql_dataload[9]) == 'None': + value_echelle_min = '' + else: + value_echelle_min = str(sql_dataload[9]) + + if str(sql_dataload[10]) == 'None': + value_echelle_max = '' + else: + value_echelle_max = str(sql_dataload[10]) + + self.echelle_min_plain.setPlainText(value_echelle_min) + self.echelle_max_plain.setPlainText(value_echelle_max) + + array_frequence_box = [self.frequence_box.itemText(i) for i in range(self.frequence_box.count())] + self.frequence_box.setCurrentIndex(array_frequence_box.index(sql_dataload[12])) + array_licence_box = [self.licence_box.itemText(i) for i in range(self.licence_box.count())] + self.licence_box.setCurrentIndex(array_licence_box.index(sql_dataload[13])) + array_confidentiality_box = [self.restriction_box.itemText(i) for i in range(self.restriction_box.count())] + self.restriction_box.setCurrentIndex(array_confidentiality_box.index(sql_dataload[14])) + array_licence_attrib_box = [self.licence_attrib_box.itemText(i) for i in range(self.licence_attrib_box.count())] + self.licence_attrib_box.setCurrentIndex(array_licence_attrib_box.index(sql_dataload[25])) + + c = 0 + # self.table_lien.setRowCount(len(sql_datalink)) + for lien_data in sql_datalink: + self.table_lien.insertRow(c) + self.table_lien.setItem(c, 0, QTableWidgetItem(lien_data[1])) + self.table_lien.setItem(c, 1, QTableWidgetItem(lien_data[4])) + self.table_lien.setItem(c, 2, QTableWidgetItem(lien_data[5])) + self.table_lien.setItem(c, 3, QTableWidgetItem(lien_data[6])) + self.table_lien.setItem(c, 4, QTableWidgetItem(lien_data[7])) + self.table_lien.setItem(c, 5, QTableWidgetItem(lien_data[8])) + c = c + 1 + c = 0 + # self.table_contact.setRowCount(len(sql_datacontact)) + for contact_data in sql_datacontact: + self.table_contact.insertRow(c) + self.table_contact.setItem(c, 0, QTableWidgetItem(contact_data[1])) + self.table_contact.setItem(c, 1, QTableWidgetItem(contact_data[4])) + self.table_contact.setItem(c, 2, QTableWidgetItem(contact_data[5])) + self.table_contact.setItem(c, 3, QTableWidgetItem(contact_data[6])) + self.table_contact.setItem(c, 4, QTableWidgetItem(contact_data[7])) + self.table_contact.setItem(c, 5, QTableWidgetItem(contact_data[8])) + c = c + 1 + + else: + + # titre_line + self.titre_line.setText(layer.name()) + self.langue_box.setCurrentIndex(1) + # date_maj_date + now = QtCore.QDateTime.currentDateTime() + self.date_maj_date.setDateTime(now) + self.date_creation_date.setDateTime(now) + self.date_modification_date.setDateTime(now) + self.date_publication_date.setDateTime(now) + self.categories_select_view.setRowCount(len(categories_list)) + self.themes_select_view.setRowCount(len(themes_list)) + i = 0 + for categorie_select_data in categories_list: + self.categories_select_view.setItem(i, 0, QTableWidgetItem(categorie_select_data[0])) + i = i + 1 + i = 0 + for themes_select_data in themes_list: + self.themes_select_view.setItem(i, 0, QTableWidgetItem(themes_select_data[0])) + i = i + 1 + + # print(self.langue_box.currentText()) + + def sql_info(self, uri): + cur = login_base() + table = uri.table() + schema = uri.schema() + # [s for s in iface.activeLayer().source().split(" ") if "dbname" in s][0].split("'")[1] + sql_find = """SELECT *, right(left(st_astext(geom,2),-2),-9) FROM metadata.dataset + WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + cur.execute(sql_find) + data_general = cur.fetchall() + cur.close() + return data_general[0] + + def sql_infoother(self, uri): + cur = login_base() + table = uri.table() + schema = uri.schema() + + sql_findlink = """SELECT * FROM metadata.dataurl + WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + cur.execute(sql_findlink) + data_link = cur.fetchall() + + sql_findcontact = """SELECT * FROM metadata.datacontact + WHERE schema_name LIKE '""" + schema + """' AND table_name LIKE '""" + table + """';""" + cur.execute(sql_findcontact) + data_contact = cur.fetchall() + + cur.close() + return data_link, data_contact + + def add_categories_view(self): + values_add_categories = self.categories_select_view.selectedItems()[0].text() + self.categories_select_view.removeRow(self.categories_select_view.currentRow()) + self.categories_view.insertRow(0) + self.categories_view.setItem(0, 0, QTableWidgetItem(values_add_categories)) + + def deleter_categories_view(self): + values_deleter_categories = self.categories_view.selectedItems()[0].text() + self.categories_view.removeRow(self.categories_view.currentRow()) + self.categories_select_view.insertRow(0) + self.categories_select_view.setItem(0, 0, QTableWidgetItem(values_deleter_categories)) + + def add_themes_view(self): + values_add_themes = self.themes_select_view.selectedItems()[0].text() + self.themes_select_view.removeRow(self.themes_select_view.currentRow()) + self.themes_view.insertRow(0) + self.themes_view.setItem(0, 0, QTableWidgetItem(values_add_themes)) + + def deleter_themes_view(self): + values_deleter_themes = self.themes_view.selectedItems()[0].text() + self.themes_view.removeRow(self.themes_view.currentRow()) + self.themes_select_view.insertRow(0) + self.themes_select_view.setItem(0, 0, QTableWidgetItem(values_deleter_themes)) + + def add_lien(self): + cur = login_base() + maxrow = self.table_lien.rowCount() + self.table_lien.insertRow(maxrow) + + table = layer.dataProvider().uri().table() + schema = layer.dataProvider().uri().schema() + + if self.taille_line.text() == '': + sql_sizefile = """SELECT pg_size_pretty(pg_total_relation_size('""" + schema + '.' + table + """'));""" + try: + cur.execute(sql_sizefile) + boolean = True + + except psycopg2.errors.UndefinedTable: + boolean = False + + if boolean is True: + size_file = (cur.fetchall())[0][0] + else: + size_file = '' + + else: + size_file = self.taille_line.text() + + self.table_lien.setItem(maxrow, 0, QTableWidgetItem('new_value')) + self.table_lien.setItem(maxrow, 1, QTableWidgetItem(self.type_box.currentText())) + self.table_lien.setItem(maxrow, 2, QTableWidgetItem(self.url_line.text())) + self.table_lien.setItem(maxrow, 3, QTableWidgetItem(self.mime_box.currentText())) + self.table_lien.setItem(maxrow, 4, QTableWidgetItem(self.format_box.currentText())) + self.table_lien.setItem(maxrow, 5, QTableWidgetItem(str(size_file))) + + global array_link + array_link += "('" + table + "', '" + schema + "', '" + self.type_box.currentText() + "', '" + self.url_line.text() + "', '" + self.mime_box.currentText() + "', '" + self.format_box.currentText() + "', '" + size_file + "')," + + cur.close() + + def add_contact(self): + maxrow = self.table_contact.rowCount() + self.table_contact.insertRow(maxrow) + + self.table_contact.setItem(maxrow, 0, QTableWidgetItem('new_value')) + self.table_contact.setItem(maxrow, 1, QTableWidgetItem(self.role_box.currentText())) + self.table_contact.setItem(maxrow, 2, QTableWidgetItem(self.nom_line.text())) + self.table_contact.setItem(maxrow, 3, QTableWidgetItem(self.organisation_box.currentText())) + self.table_contact.setItem(maxrow, 4, QTableWidgetItem(self.email_line.text())) + self.table_contact.setItem(maxrow, 5, QTableWidgetItem(self.telephone_line.text())) + + table = layer.dataProvider().uri().table() + schema = layer.dataProvider().uri().schema() + + global array_contact + array_contact += "('" + table + "', '" + schema + "', '" + self.role_box.currentText() + "', '" + self.nom_line.text() + "', '" + self.organisation_box.currentText() + "', '" + self.email_line.text() + "', '" + self.telephone_line.text() + "')," + + def delete_lien(self): + fin = '' + global uid_delete_list_link, array_link + try: + lien_uid = self.table_lien.item(self.table_lien.currentRow(), 0).text() + except AttributeError: + lien_uid = True + self.table_lien.removeRow(self.table_lien.currentRow()) + if lien_uid == 'new_value': + position = self.table_lien.currentRow() + if position < 0: + position = position + 1 + run_x = 0 + while position >= run_x: + # print(position, run_x) + if run_x == 0: + debut = array_link.find("(") + else: + debut = array_link.find("(", fin + 1) + fin = array_link.find(")", debut) + # print(debut, fin) + if run_x == 50: + break + run_x += 1 + # print(array_link[fin + 1:]) + if debut <= 0: + debut = 1 + fin += 1 + array_link = array_link[:debut - 1] + array_link[fin + 1:] + # print('a:', array_link) + elif lien_uid is True: + print('Pas de ligne "Lien"') + else: + uid_delete_list_link += "'" + lien_uid + "'," + + def delete_contact(self): + fin = '' + global uid_delete_list_contact, array_contact + try: + contact_uid = self.table_contact.item(self.table_contact.currentRow(), 0).text() + except AttributeError: + contact_uid = True + self.table_contact.removeRow(self.table_contact.currentRow()) + if contact_uid == 'new_value': + position = self.table_contact.currentRow() + if position < 0: + position = position + 1 + # print('p:', position) + run_x = 0 + while position >= run_x: + if run_x == 0: + debut = array_contact.find("(") + else: + debut = array_contact.find("(", fin + 1) + fin = array_contact.find(")", debut) + # print(debut, fin) + if run_x == 50: + break + run_x += 1 + # print(array_contact[fin + 1:]) + if debut <= 0: + debut = 1 + fin += 1 + array_contact = array_contact[:debut - 1] + array_contact[fin + 1:] + # print('a:', array_contact) + elif contact_uid is True: + print('Pas de ligne "Contact"') + else: + uid_delete_list_contact += "'" + contact_uid + "'," + + def fletch_ref(self): + cur = login_base() + + SQL_categories = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.categories' ORDER BY code, item_order;""" + SQL_themes = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.themes' ORDER BY label_fr;""" + SQL_langue = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.langue';""" + SQL_encodage = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.encodage';""" + SQL_frequency = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.publication_frequency' ORDER BY label_fr;""" + SQL_confidentiality = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.confidentiality' ORDER BY label_fr;""" + SQL_license = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'dataset.license' ORDER BY label_fr;""" + SQL_type = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'link.type' ORDER BY label_fr;""" + SQL_mime = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'link.mime' ORDER BY label_fr;""" + SQL_format = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'link.format' ORDER BY label_fr;""" + SQL_role = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'contact.contact_role' ORDER BY label_fr;""" + SQL_organisation = """SELECT label_fr FROM metadata.glossary WHERE field LIKE 'contact.organisation' ORDER BY label_fr;""" + + cur.execute(SQL_categories) + categories_list = cur.fetchall() + cur.execute(SQL_themes) + themes_list = cur.fetchall() + cur.execute(SQL_langue) + langue_list = cur.fetchall() + cur.execute(SQL_encodage) + encodage_list = cur.fetchall() + + cur.execute(SQL_frequency) + frequency_list = cur.fetchall() + cur.execute(SQL_confidentiality) + confidentiality_list = cur.fetchall() + cur.execute(SQL_license) + license_list = cur.fetchall() + + cur.execute(SQL_type) + type_list = cur.fetchall() + cur.execute(SQL_mime) + mime_list = cur.fetchall() + cur.execute(SQL_format) + format_list = cur.fetchall() + cur.execute(SQL_role) + role_list = cur.fetchall() + cur.execute(SQL_organisation) + organisation_list = cur.fetchall() + + return categories_list, themes_list, langue_list, encodage_list, frequency_list, confidentiality_list, license_list, type_list, mime_list, format_list, role_list, organisation_list + + cur.close() + + def py_import_xml(self): + folder = QFileDialog.getOpenFileName() + if folder: + folder = folder[0] + if folder[len(folder) - 4:] == '.xml': + print('is .xml') + + # def issues_open(self): + # self.issues = CenRa_Issues() + # self.issues.show() diff --git a/CenRa_METABASE/icon.png b/CenRa_METABASE/icon.png new file mode 100644 index 0000000..d53a910 Binary files /dev/null and b/CenRa_METABASE/icon.png differ diff --git a/CenRa_METABASE/issues.py b/CenRa_METABASE/issues.py new file mode 100644 index 0000000..0d6416a --- /dev/null +++ b/CenRa_METABASE/issues.py @@ -0,0 +1,89 @@ +import os +plugin_dir = os.path.dirname(__file__) +end_find = plugin_dir.rfind('\\')+1 + +NAME = plugin_dir[end_find:] +#print(NAME) + +from qgis.gui import * + +from qgis.core import ( + NULL, + QgsApplication, + QgsDataSourceUri, + QgsProject, + QgsProviderConnectionException, + QgsProviderRegistry, + QgsRasterLayer, + QgsSettings, + QgsVectorLayer, + QgsGeometry, +) +from qgis.PyQt.QtWidgets import ( + QDialog, + QAction, + QDockWidget, + QFileDialog, + QInputDialog, + QMenu, + QToolButton, + QTableWidget, + QTableWidgetItem, +) +from qgis.utils import iface + + +from .tools.resources import ( + load_ui, + resources_path, + send_issues, +) + +EDITOR_CLASS = load_ui('CenRa_IssuesSend.ui') + +class CenRa_Issues(QDialog, EDITOR_CLASS): + + def __init__(self, parent=None): + _ = parent + super().__init__() + self.setupUi(self) + self.settings = QgsSettings() + + #place connect here + self.annuler_button.clicked.connect(self.close) + self.ok_button.clicked.connect(self.run_sendissues) + + def run_sendissues(self): + text_titre = self.titre_line.text() + text_message = self.messages_plain.toPlainText() + statu_bug = self.check_bug.isChecked() + statu_aide = self.check_aide.isChecked() + statu_question = self.check_question.isChecked() + statu_amelioration = self.check_amelioration.isChecked() + statu_autre = self.check_autre.isChecked() + + statu = [] + if statu_bug == True : statu = statu + [1] + if statu_aide == True : statu = statu + [3] + if statu_question == True : statu = statu + [5] + if statu_amelioration == True : statu = statu + [2] + if statu_autre == True : statu = statu + [6] + + if len(statu) >= 1: + import qgis + url = qgis.utils.pluginMetadata(NAME,'tracker') + print(text_message) + send_info = send_issues(url,text_titre,text_message,statu) + code = send_info.status_code + print(code) + else: + code = 423 + if code == 201: + iface.messageBar().pushMessage("Envoyer :", "Votre messages à bien été envoyer.", level=Qgis.Success, duration=20) + self.close() + elif code == 422: + iface.messageBar().pushMessage("Erreur :", "Erreur dans le contenu du messages.", level=Qgis.Critical, duration=20) + elif code == 423: + iface.messageBar().pushMessage("Erreur :", "Pas de sujet sélectionné.", level=Qgis.Critical, duration=20) + elif code == 404: + iface.messageBar().pushMessage("Missing :", "Le serveur de messagerie est injoignable.", level=Qgis.Warning, duration=20) diff --git a/CenRa_METABASE/metadata.txt b/CenRa_METABASE/metadata.txt new file mode 100644 index 0000000..8c689d1 --- /dev/null +++ b/CenRa_METABASE/metadata.txt @@ -0,0 +1,49 @@ +# This file contains metadata for your plugin. + +# This file should be included when you package your plugin.# Mandatory items: + +[general] +name=CenRa_Metabase +qgisMinimumVersion=3.0 +supportsQt6=True +description=CenRa_METABASE +version=0.3.1 +author=Conservatoire d'Espaces Naturels de Rhône-Alpes +email=si_besoin@cen-rhonealpes.fr + +about=Permet de saisire et de visualisé les information lier à la metadonné d'une couche ce trouvent sur PostgreSQL + +repository=https://gitea.cenra-outils.org/CEN-RA/Plugin_QGIS +homepage=https://plateformesig.cenra-outils.org/ +tracker=https://gitea.cenra-outils.org/api/v1/repos/CEN-RA/Plugin_QGIS/issues +# End of mandatory metadata + +# Recommended items: + +hasProcessingProvider=no +# Uncomment the following line and add your changelog: +changelog=

CenRa_METABASE:


30/07/2025 - Version 0.3.1:

- Correctife de bug.


19/05/2025 - Version 0.3.0:

- Compatible PyQt5 et PyQt6


09/04/2025 - Version 0.2.3:

- Correctif bug en TT.


09/04/2025 - Version 0.2.2:

- Optimisation pour le TT.


03/04/2025 - Version 0.2.1:

- Mise a jour de securite.


07/01/2025 - Version 0.2.0:

- Deployment sur serveur SIG.


07/01/2025 - Version 0.1.6:

- ByPass du certif ssl ci erreur


19/12/2024 - Version 0.1.5:

- Fix les problem de lenteur qu'en la base est down.


12/12/2024 - Version 0.1.4:

- Crash Fix .


08/10/2024 - Version 0.1.3:

- Lecture de métadonnée des flux WMS/WFS.


07/10/2024 - Version 0.1.2:

- Correctif de bug.


03/10/2024 - Version 0.1.1:

- Remonte la fênetre dans la pille.


26/08/2024 - Version 0.1.0:

- Lancement du plugin CenRa_Metabase

+ +# Tags are comma separated with spaces allowed +tags=python + + +category=Plugins +icon=icon.png +# experimental flag +experimental=True + +# deprecated flag (applies to the whole plugin, not just a single version) +deprecated=False + +# Since QGIS 3.8, a comma separated list of plugins to be installed +# (or upgraded) can be specified. +# Check the documentation for more information. +# plugin_dependencies= + +Category of the plugin: Raster, Vector, Database or Web +# category=cenra,database,metadata + +# If the plugin can run on QGIS Server. +server=False + diff --git a/CenRa_METABASE/tools/css/dock.css b/CenRa_METABASE/tools/css/dock.css new file mode 100644 index 0000000..f05b850 --- /dev/null +++ b/CenRa_METABASE/tools/css/dock.css @@ -0,0 +1,61 @@ +body { + font-family: Ubuntu, Lucida Grande, Segoe UI, Arial, sans-serif; + margin-left: 0px; + margin-right: 0px; + margin-top: 0px; + font-size: 14px; +} +img { + max-width: 100%; +} +img.logo{ + display: inline-block; + margin-left:0px; + margin-right: 0px; + margin-top: 10px; + margin-bottom: 10px; + vertical-align: top; + width:25% +} +h2, h3 { + color: #fff; + background-color: #8cb63c; + line-height: 2; + padding-left:5px; +} + +table { + border-collapse: collapse; + width: 100%; + font-size: 13px; +} +th{ + color: #2c4491 +} +table tr th, table tr td { + text-align: left; + padding: 5px; +} + +table.table-striped { + border: 1px solid #BBB; +} +table.table-striped tr td { + border: 1px solid #BBB; +} +table.table-striped tr th { + border: 1px solid #BBB; +} +table.table-striped tr:nth-child(even) { + background: #EEE; +} +table.table-striped tr:nth-child(odd) { + background: #FFF; +} + +#map { + padding: 5px; + width: 400px; + height: 400px; + box-shadow: 0 0 10px #999; +} diff --git a/CenRa_METABASE/tools/html/contact.html b/CenRa_METABASE/tools/html/contact.html new file mode 100644 index 0000000..a6cda01 --- /dev/null +++ b/CenRa_METABASE/tools/html/contact.html @@ -0,0 +1,7 @@ + + [% contact_role %] + [% name %] + [% organisation_name %] ([% organisation_unit %]) + [% email %] + [% phone %] + diff --git a/CenRa_METABASE/tools/html/link.html b/CenRa_METABASE/tools/html/link.html new file mode 100644 index 0000000..cdcdabe --- /dev/null +++ b/CenRa_METABASE/tools/html/link.html @@ -0,0 +1,7 @@ + + [% type %] + [% name %] + [% mime %] + [% format %] + [% size %] + diff --git a/CenRa_METABASE/tools/html/main.html b/CenRa_METABASE/tools/html/main.html new file mode 100644 index 0000000..f7ff4a0 --- /dev/null +++ b/CenRa_METABASE/tools/html/main.html @@ -0,0 +1,123 @@ +
+

Identification

+ + + + + + + + + + + + + + + + + + + +
Title[% title %]
Abstract[% abstract %]
Categories[% categories %]
Themes[% themes %]
Keywords[% keywords %]
Data last update[% data_last_update %]
+
+ +
+

Spatial properties

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Level[% spatial_level %]
Minimum scale[% minimum_optimal_scale %]
Maximum scale[% maximum_optimal_scale %]
Feature count[% feature_count %]
Geometry[% geometry_type %]
Extent[% spatial_extent %]
Projection name[% projection_name %]
Projection ID[% projection_authid %]
+
+ +
+

Publication

+ + + + + + + + + + + + + + + + +
Date[% publication_date %]
Frequency[% publication_frequency %]
License[% license %]
License attribution / number[% license_attribution %]
Confidentiality[% confidentiality %]
+
+ +
+

Links

+ + + + + + + + + [% meta_links %] +
TypeNameMIMEFormatSize
+
+ +
+

Contacts

+ + + + + + + + + [% meta_contacts %] +
RoleNameOrganisationEmailPhone
+
+ +
+

Metadata

+ + + + + + + + + + + + + + + + +
Table[% table_name %]
Schema[% schema_name %]
Creation[% creation_date %]
Update[% update_date %]
UUID[% uid %]
+
diff --git a/CenRa_METABASE/tools/icons/CEN_RA.png b/CenRa_METABASE/tools/icons/CEN_RA.png new file mode 100644 index 0000000..95ead1c Binary files /dev/null and b/CenRa_METABASE/tools/icons/CEN_RA.png differ diff --git a/CenRa_METABASE/tools/icons/auto_add.png b/CenRa_METABASE/tools/icons/auto_add.png new file mode 100644 index 0000000..021f85b Binary files /dev/null and b/CenRa_METABASE/tools/icons/auto_add.png differ diff --git a/CenRa_METABASE/tools/icons/icon.png b/CenRa_METABASE/tools/icons/icon.png new file mode 100644 index 0000000..96a568e Binary files /dev/null and b/CenRa_METABASE/tools/icons/icon.png differ diff --git a/CenRa_METABASE/tools/icons/icon_2.png b/CenRa_METABASE/tools/icons/icon_2.png new file mode 100644 index 0000000..5e21f30 Binary files /dev/null and b/CenRa_METABASE/tools/icons/icon_2.png differ diff --git a/CenRa_METABASE/tools/images/must_be_a_file.png b/CenRa_METABASE/tools/images/must_be_a_file.png new file mode 100644 index 0000000..7062995 Binary files /dev/null and b/CenRa_METABASE/tools/images/must_be_a_file.png differ diff --git a/CenRa_METABASE/tools/resources.py b/CenRa_METABASE/tools/resources.py new file mode 100644 index 0000000..a37d55b --- /dev/null +++ b/CenRa_METABASE/tools/resources.py @@ -0,0 +1,184 @@ +"""Tools to work with resource files.""" + +import configparser +import shutil +import tempfile +# import base64 +# import psycopg2 +# import psycopg2.extras +import os +from os.path import abspath, join, pardir, dirname + +from qgis.PyQt import uic + +__copyright__ = "Copyright 2019, 3Liz" +__license__ = "GPL version 3" +__email__ = "info@3liz.org" +__revision__ = "$Format:%H$" + + +def plugin_path(*args): + """Get the path to plugin root folder. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :return: Absolute path to the plugin path. + :rtype: str + """ + path = dirname(dirname(__file__)) + path = abspath(abspath(join(path, pardir))) + for item in args: + path = abspath(join(path, item)) + + return path + + +def plugin_name(): + """Return the plugin name according to metadata.txt. + + :return: The plugin name. + :rtype: basestring + """ + metadata = metadata_config() + name = metadata["general"]["name"] + return name + + +def metadata_config() -> configparser: + """Get the INI config parser for the metadata file. + + :return: The config parser object. + :rtype: ConfigParser + """ + path = plugin_path("metadata.txt") + config = configparser.ConfigParser() + config.read(path, encoding='utf8') + return config + + +def plugin_test_data_path(*args, copy=False): + """Get the path to the plugin test data path. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :param copy: If the file must be copied into a temporary directory first. + :type copy: bool + + :return: Absolute path to the resources folder. + :rtype: str + """ + path = abspath(abspath(join(plugin_path(), "test", "data"))) + for item in args: + path = abspath(join(path, item)) + + if copy: + temp = tempfile.mkdtemp() + shutil.copy(path, temp) + return join(temp, args[-1]) + else: + return path + + +def resources_path(*args): + """Get the path to our resources folder. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :return: Absolute path to the resources folder. + :rtype: str + """ + path = abspath(abspath(join(plugin_path(), "CenRa_METABASE\\tools"))) + for item in args: + path = abspath(join(path, item)) + return path + + +def load_ui(*args): + """Get compile UI file. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :return: Compiled UI file. + """ + ui_class, _ = uic.loadUiType(resources_path("ui", *args)) + + return ui_class + + +def pyperclip(): + dst = dirname(dirname(__file__)) + "\\tools\\" + if os.access('N:/', os.R_OK): + src = 'N:/SI_Systeme d information/Z_QGIS/PLUGIN/PythonSQL.py' + try: + shutil.copy(src, dst) + except FileNotFoundError: + print('404') + except UnboundLocalError: + print('404') + + +def send_issues(url, titre, body, labels): + import requests + import urllib.request + import json + # import os + # import qgis + + # usr = os.environ['USERNAME'] + token = '9d0a4e0bea561710e0728f161f7edf4e5201e112' + url = url + '?token=' + token + + headers = {'Authorization': 'token ' + token, 'accept': 'application/json', 'Content-Type': 'application/json'} + + payload = {'title': titre, 'body': body, 'labels': labels} + try: + urllib.request.urlopen('https://google.com') + binar = True + except ValueError: + binar = False + r = '' + if binar: + r = requests.post(url, data=json.dumps(payload), headers=headers) + return r + + +def maj_verif(NAME): + import qgis + import urllib.request + iface = qgis.utils.iface + from qgis.core import Qgis + + # url = qgis.utils.pluginMetadata(NAME, 'repository') + # URL = url+'/raw/branch/main/plugins.xml' + URL = 'https://gitea.cenra-outils.org/CEN-RA/Plugin_QGIS/releases/download/latest/plugins.xml' + # print(URL) + version = qgis.utils.pluginMetadata(NAME, 'version') + len_version = len(version) + try: + urllib.request.urlopen('https://google.com') + binar = True + except urllib.error.URLError: + binar = False + if binar: + try: + version_web = str(urllib.request.urlopen(URL).read()) + plugin_num = version_web.find(NAME) + valeur_version_web = version_web.find('', plugin_num) + 9 + version_plugin = version_web[valeur_version_web:valeur_version_web + len_version] + if version_plugin != version: + iface.messageBar().pushMessage("MAJ :", "Des mise à jour de plugin sont disponibles.", level=Qgis.Info, duration=30) + except urllib.error.URLError: + print("error gitea version ssl") + else: + iface.messageBar().pushMessage("WiFi :", "Pas de connection à internet.", level=Qgis.Warning, duration=30) + + +def devlog(NAME): + import qgis + devmaj = '' + devmaj = devmaj + qgis.utils.pluginMetadata(NAME, 'changelog') + return devmaj diff --git a/CenRa_METABASE/tools/ui/CenRa_IssuesSend.ui b/CenRa_METABASE/tools/ui/CenRa_IssuesSend.ui new file mode 100644 index 0000000..14d923e --- /dev/null +++ b/CenRa_METABASE/tools/ui/CenRa_IssuesSend.ui @@ -0,0 +1,332 @@ + + + CenRa_IssuesSend + + + + 0 + 0 + 810 + 587 + + + + CEN-RA Metabase + + + + icon.svgicon.svg + + + + + 0 + 550 + 811 + 31 + + + + + + + Annuler + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Envoyer + + + + + + + + + 10 + 10 + 791 + 531 + + + + Issues + + + + + 240 + 40 + 321 + 41 + + + + Qt::AlignCenter + + + + + + 10 + 101 + 571 + 421 + + + + + + + 589 + 100 + 191 + 431 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 9 + 9 + 341 + 411 + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Bug + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Aide + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Question + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Amélioration + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Autre + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 250 + 20 + 51 + 21 + + + + + Arial + 14 + + + + Titre: + + + + + + 20 + 70 + 91 + 31 + + + + + Arial + 12 + + + + Messages: + + + + + + 600 + 70 + 91 + 31 + + + + + Arial + 12 + + + + Sujet: + + + + + + ok_button + annuler_button + + + + diff --git a/CenRa_METABASE/tools/ui/CenRa_Metabase_dockwidget_base.ui b/CenRa_METABASE/tools/ui/CenRa_Metabase_dockwidget_base.ui new file mode 100644 index 0000000..78010ec --- /dev/null +++ b/CenRa_METABASE/tools/ui/CenRa_Metabase_dockwidget_base.ui @@ -0,0 +1,74 @@ + + + CenRa_MetabaseDockWidgetBase + + + + 0 + 0 + 329 + 515 + + + + CenRa MetaBase + + + + + + + + + ... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + Qt::NoArrow + + + + + + + ... + + + + + + + help + + + + + + + + + + + + + + diff --git a/CenRa_METABASE/tools/ui/CenRa_Metabase_editorwidget_base.ui b/CenRa_METABASE/tools/ui/CenRa_Metabase_editorwidget_base.ui new file mode 100644 index 0000000..ac91920 --- /dev/null +++ b/CenRa_METABASE/tools/ui/CenRa_Metabase_editorwidget_base.ui @@ -0,0 +1,1946 @@ + + + CenRa_Metabase_editorwidget_base + + + + 0 + 0 + 818 + 741 + + + + CEN-RA Metabase + + + + icon.svgicon.svg + + + + + 0 + 0 + 821 + 711 + + + + + Myriad Pro Black + 10 + 75 + false + true + + + + Qt::DefaultContextMenu + + + Qt::LeftToRight + + + false + + + QTabWidget::North + + + QTabWidget::Rounded + + + 0 + + + + 40 + 40 + + + + true + + + false + + + false + + + false + + + false + + + + Identification + + + + + 30 + 110 + 751 + 99 + + + + + + + Description + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Myriad Pro Black'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400;"><br /></p></body></html> + + + + + + + + + 30 + 220 + 751 + 101 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + Categories : + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + true + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectItems + + + + + + + + + 30 + 330 + 751 + 101 + + + + + + + Thèmes : + + + + + + + Qt::Horizontal + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + 30 + 440 + 751 + 101 + + + + + + + + + + Mots-clés : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 30 + 550 + 751 + 51 + + + + + + + Dernier mise à jour : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + QAbstractSpinBox::NoButtons + + + + 2024 + 12 + 24 + + + + QDateTimeEdit::MonthSection + + + dd/MM/yyyy + + + true + + + 1 + + + Qt::UTC + + + + + + + + + 30 + 30 + 751 + 61 + + + + + + + + + + Titre : + + + + + + + + + 30 + 620 + 751 + 51 + + + + + + + Langue : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Spatial properties + + + + + 220 + 20 + 540 + 39 + + + + + + + 34 + 20 + 170 + 39 + + + + Niveau : + + + + + + 34 + 70 + 170 + 39 + + + + Echelle minimum : + + + + + + 220 + 70 + 540 + 39 + + + + + + + 34 + 120 + 170 + 39 + + + + Echelle maximum : + + + + + + 220 + 120 + 540 + 39 + + + + + + + 34 + 170 + 170 + 39 + + + + Nombre d'entités : + + + + + false + + + + 220 + 170 + 540 + 39 + + + + + + + 34 + 220 + 170 + 39 + + + + Type de géométrie : + + + + + false + + + + 220 + 220 + 540 + 39 + + + + + + false + + + + 220 + 320 + 540 + 39 + + + + + + + 34 + 270 + 170 + 39 + + + + Nom de projection : + + + + + + 34 + 370 + 170 + 39 + + + + Emprise : + + + + + + 34 + 320 + 170 + 39 + + + + ID de projection : + + + + + false + + + + 220 + 270 + 540 + 39 + + + + + + false + + + + 221 + 370 + 540 + 39 + + + + + + + Publication + + + + + 30 + 390 + 751 + 61 + + + + + + + Restriction : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 30 + 210 + 751 + 61 + + + + + + + Licence : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 30 + 30 + 751 + 61 + + + + + + + Date : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + QAbstractSpinBox::NoButtons + + + + 2024 + 12 + 22 + + + + QDateTimeEdit::MonthSection + + + dd/MM/yyyy + + + true + + + 1 + + + Qt::UTC + + + + + + + + + 30 + 300 + 751 + 61 + + + + + + + Licence attribué : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 30 + 120 + 751 + 61 + + + + + + + Fréquence de mise à jour : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Lien + + + + + 10 + 120 + 791 + 511 + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + 20 + 20 + 771 + 61 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + + + Taille : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Type : + + + + + + + + + + + + + URL : + + + + + + + Type MIME : + + + + + + + Format : + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Ajouter + + + + + + + + + + + + + + + 10 + 640 + 791 + 31 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Delete + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 10 + 90 + 790 + 3 + + + + Qt::Horizontal + + + + + + 10 + 20 + 790 + 3 + + + + Qt::Horizontal + + + + + + 10 + 20 + 3 + 70 + + + + Qt::Vertical + + + + + + 800 + 20 + 3 + 70 + + + + Qt::Vertical + + + + + + Contacts + + + + + 20 + 20 + 771 + 61 + + + + + + + Nom : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Ajouter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Email : + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Organisation : + + + + + + + Telephone + + + + + + + Rôle : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + 10 + 120 + 791 + 511 + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + 10 + 640 + 791 + 31 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Delete + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 800 + 20 + 3 + 70 + + + + Qt::Vertical + + + + + + 10 + 20 + 790 + 3 + + + + Qt::Horizontal + + + + + + 10 + 90 + 790 + 3 + + + + Qt::Horizontal + + + + + + 10 + 20 + 3 + 70 + + + + Qt::Vertical + + + + + + Metadata + + + + + 30 + 30 + 751 + 61 + + + + + + + Table : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + + + + + + 30 + 300 + 751 + 61 + + + + + + + Date de modification : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + QAbstractSpinBox::NoButtons + + + + 2024 + 12 + 23 + + + + QDateTimeEdit::MonthSection + + + dd/MM/yyyy + + + true + + + 1 + + + Qt::UTC + + + + + + + + + 30 + 390 + 751 + 61 + + + + + + + Encodage : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 30 + 210 + 751 + 61 + + + + + + + Date de création : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + QAbstractSpinBox::NoButtons + + + + 2024 + 12 + 23 + + + + QDateTimeEdit::MonthSection + + + dd/MM/yyyy + + + true + + + 1 + + + Qt::UTC + + + + + + + + + 30 + 120 + 751 + 61 + + + + + + + Schema : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + + + + + + 30 + 480 + 751 + 61 + + + + + + + UUID : + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + + + + + + + + 0 + 710 + 821 + 31 + + + + + + + Annuler + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + + + 780 + 20 + 25 + 19 + + + + ... + + + + 32 + 32 + + + + Qt::NoArrow + + + + + + 780 + 2 + 25 + 19 + + + + ... + + + + 32 + 32 + + + + Qt::NoArrow + + + + + true + + + + 550 + 10 + 41 + 41 + + + + ... + + + + 32 + 32 + + + + Qt::NoArrow + + + + + titre_line + description_text + ok_button + annuler_button + tabWidget + langue_box + niveau_plain + echelle_min_plain + echelle_max_plain + nbr_layers + typegeom_plaintext + crscode_plaintext + crsname_plaintext + extend_plaintext + restriction_box + licence_box + licence_attrib_box + frequence_box + table_lien + add_lien_button + format_box + mime_box + type_box + delete_lien_button + organisation_box + add_contact_button + role_box + table_contact + delete_contact_button + table_ligne + encodage_box + schema_ligne + uuid_ligne + mots_cles_text + + + + diff --git a/CenRa_METABASE/tools/ui/CenRa_about_form.ui b/CenRa_METABASE/tools/ui/CenRa_about_form.ui new file mode 100644 index 0000000..6ec4843 --- /dev/null +++ b/CenRa_METABASE/tools/ui/CenRa_about_form.ui @@ -0,0 +1,81 @@ + + + CenRa_Metabase_editorwidget_base + + + + 0 + 0 + 471 + 594 + + + + Journal des modifications + + + + ../../CenRa_Metabase/tools/ui/icon.svg../../CenRa_Metabase/tools/ui/icon.svg + + + + + + true + + + Qt::NoFocus + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 453 + 570 + + + + + + 0 + 0 + 451 + 541 + + + + DevLog + + + + + 10 + 20 + 431 + 511 + + + + + + + + + + + QDialogButtonBox::NoButton + + + + + + + + diff --git a/CenRa_METABASE/tools/xml/dcat.xml b/CenRa_METABASE/tools/xml/dcat.xml new file mode 100644 index 0000000..852508d --- /dev/null +++ b/CenRa_METABASE/tools/xml/dcat.xml @@ -0,0 +1,26 @@ + + + + + CEN-RA DCAT RDF catalog + {language} + CEN-RA Metadata + + + + {content} + + + + + + diff --git a/CenRa_METABASE/tools/xml/distribution.xml b/CenRa_METABASE/tools/xml/distribution.xml new file mode 100644 index 0000000..2ff86b0 --- /dev/null +++ b/CenRa_METABASE/tools/xml/distribution.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/CenRa_METABASE/tools/xml/publisher.xml b/CenRa_METABASE/tools/xml/publisher.xml new file mode 100644 index 0000000..1cda931 --- /dev/null +++ b/CenRa_METABASE/tools/xml/publisher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CenRa_PAGERENDER/CenRa_PageRender.py b/CenRa_PAGERENDER/CenRa_PageRender.py new file mode 100644 index 0000000..46e9d24 --- /dev/null +++ b/CenRa_PAGERENDER/CenRa_PageRender.py @@ -0,0 +1,141 @@ +__copyright__ = "Copyright 2021, 3Liz" +__license__ = "GPL version 3" +__email__ = "info@3liz.org" + + +from qgis.core import QgsApplication +from qgis.PyQt.QtCore import QUrl, QSettings +from qgis.PyQt.QtGui import QDesktopServices, QIcon +from qgis.PyQt.QtWidgets import QAction +from qgis.utils import iface +import qgis + + +# include +''' +from pg_metadata.connection_manager import ( + store_connections, + validate_connections_names, +) + + +from pg_metadata.locator import LocatorFilter +from pg_metadata.processing.provider import PgMetadataProvider +from pg_metadata.qgis_plugin_tools.tools.custom_logging import setup_logger +''' +import os +from .tools.resources import ( + # plugin_path, + resources_path, + maj_verif, +) +from .canvas_editor import PageRender_Editor +from .about_form import AboutDialog + + +class PgPageRender: + def __init__(self): + """ Constructor. """ + self.canvas_editor = None +# self.issues = None + self.provider = None + self.locator_filter = None + self.dock_action = None + self.help_action = None + plugin_dir = os.path.dirname(__file__) + end_find = plugin_dir.rfind('\\') + 1 + global NAME + NAME = plugin_dir[end_find:] + maj_verif(NAME) + + # Display About window on first use + version = qgis.utils.pluginMetadata('CenRa_PAGERENDER', 'version') + s = QSettings() + versionUse = s.value("pagerender/version", 1, type=str) + if str(versionUse) != str(version): + s.setValue("pagerender/version", str(version)) + print(versionUse, version) + self.open_about_dialog() + + def initGui(self): + """ Build the plugin GUI. """ + + self.toolBar = iface.addToolBar("CenRa_PAGERENDER") + self.toolBar.setObjectName("CenRa_PAGERENDER") + + icon = QIcon(resources_path('icons', 'icon.png')) + + # Open the online help + self.help_action = QAction(icon, 'CenRa_PAGERENDER', iface.mainWindow()) + iface.pluginHelpMenu().addAction(self.help_action) + self.help_action.triggered.connect(self.open_help) + if not self.canvas_editor: + self.canvas_editor = PageRender_Editor() + + self.pagerender_action = QAction(icon, 'CenRa_PAGERENDER', None) + self.toolBar.addAction(self.pagerender_action) + self.pagerender_action.triggered.connect(self.open_editor) + ''' + if not self.locator_filter: + self.locator_filter = LocatorFilter(iface) + iface.registerLocatorFilter(self.locator_filter) + + @staticmethod + def check_invalid_connection_names(): + """ Check for invalid connection names in the QgsSettings. """ + valid, invalid = validate_connections_names() + n_invalid = len(invalid) + + if n_invalid == 0: + return + + invalid_text = ', '.join(invalid) + msg = QMessageBox() + msg.setIcon(QMessageBox.Warning) + msg.setWindowTitle(tr('PgMetadata: Database connection(s) not available')) + msg.setText(tr( + f'{n_invalid} connection(s) listed in PgMetadata’s settings are invalid or ' + f'no longer available: {invalid_text}')) + msg.setInformativeText(tr( + 'Do you want to remove these connection(s) from the PgMetadata settings? ' + '(You can also do this later with the “Set Connections” tool.)')) + msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + clicked = msg.exec() + + if clicked == QMessageBox.Yes: + iface.messageBar().pushSuccess('PgMetadata', tr(f'{n_invalid} invalid connection(s) removed.')) + store_connections(valid) + if clicked == QMessageBox.No: + iface.messageBar().pushInfo('PgMetadata', tr(f'Keeping {n_invalid} invalid connections.')) + ''' + def open_about_dialog(self): + """ + About dialog + """ + dialog = AboutDialog(iface) + dialog.exec() + + def open_help(): + """ Open the online help. """ + QDesktopServices.openUrl(QUrl('https://plateformesig.cenra-outils.org/')) + + def open_editor(self): + self.canvas_editor.show() + self.canvas_editor.raise_() + + def unload(self): + """ Unload the plugin. """ + if self.canvas_editor: + iface.removePluginMenu('CenRa_PAGERENDER', self.pagerender_action) + + if self.provider: + QgsApplication.processingRegistry().removeProvider(self.provider) + del self.provider + + if self.locator_filter: + iface.deregisterLocatorFilter(self.locator_filter) + del self.locator_filter + + if self.help_action: + iface.pluginHelpMenu().removeAction(self.help_action) + del self.help_action diff --git a/CenRa_PAGERENDER/README.md b/CenRa_PAGERENDER/README.md new file mode 100644 index 0000000..80ccffe --- /dev/null +++ b/CenRa_PAGERENDER/README.md @@ -0,0 +1 @@ +# CenRa_AutoMap \ No newline at end of file diff --git a/CenRa_PAGERENDER/__init__.py b/CenRa_PAGERENDER/__init__.py new file mode 100644 index 0000000..365e090 --- /dev/null +++ b/CenRa_PAGERENDER/__init__.py @@ -0,0 +1,10 @@ +__copyright__ = "Copyright 2021, 3Liz" +__license__ = "GPL version 3" +__email__ = "info@3liz.org" + + +# noinspection PyPep8Naming +def classFactory(iface): # pylint: disable=invalid-name + _ = iface + from CenRa_PAGERENDER.CenRa_PageRender import PgPageRender + return PgPageRender() diff --git a/CenRa_PAGERENDER/about_form.py b/CenRa_PAGERENDER/about_form.py new file mode 100644 index 0000000..8828a44 --- /dev/null +++ b/CenRa_PAGERENDER/about_form.py @@ -0,0 +1,46 @@ +import os.path + +from pathlib import Path + +from qgis.PyQt import uic +# from qgis.PyQt.QtGui import QPixmap +from qgis.PyQt.QtWidgets import QDialog + +from .tools.resources import devlog + +ABOUT_FORM_CLASS, _ = uic.loadUiType( + os.path.join( + str(Path(__file__).resolve().parent), + 'tools/ui', + 'CenRa_about_form.ui' + ) +) + + +class AboutDialog(QDialog, ABOUT_FORM_CLASS): + + """ About - Let the user display the about dialog. """ + + def __init__(self, iface, parent=None): + super().__init__(parent) + self.iface = iface + self.setupUi(self) + + self.viewer.setHtml(devlog('CenRa_PAGERENDER')) + + self.rejected.connect(self.onReject) + self.buttonBox.rejected.connect(self.onReject) + self.buttonBox.accepted.connect(self.onAccept) + + def onAccept(self): + """ + Save options when pressing OK button + """ + self.accept() + + def onReject(self): + """ + Run some actions when + the user closes the dialog + """ + self.close() diff --git a/CenRa_PAGERENDER/canvas_editor.py b/CenRa_PAGERENDER/canvas_editor.py index 01fb22e..66bba0e 100644 --- a/CenRa_PAGERENDER/canvas_editor.py +++ b/CenRa_PAGERENDER/canvas_editor.py @@ -11,7 +11,6 @@ from qgis.core import QgsSettings from qgis.PyQt.QtCore import Qt # from qgis.PyQt.QtPrintSupport import QPrinter # from qgis.PyQt.QtWebKitWidgets import QWebPage -# test de push from qgis.PyQt.QtWidgets import ( QDialog, QFileDialog, diff --git a/CenRa_PAGERENDER/demoV2.py b/CenRa_PAGERENDER/demoV2.py new file mode 100644 index 0000000..df678af --- /dev/null +++ b/CenRa_PAGERENDER/demoV2.py @@ -0,0 +1,169 @@ + +from qgis.core import ( + QgsLayoutSize, + QgsUnitTypes, + QgsLayoutPoint, +) + + +def fletch_canvas(self): + if self.radioButton_6.isChecked(): + values_page = 'A4' + else: + values_page = 'A3' + if self.radioButton_7.isChecked(): + page_rotate = 'Portrait' + else: + page_rotate = 'Landscape' + + if page_rotate == 'Portrait': + if values_page == 'A4': + self.template_parameters['Carte_size'] = QgsLayoutSize(200.0, 200, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_locals'] = QgsLayoutPoint(6, 6, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_rotate'] = 0 + self.template_parameters['Carte_2_size'] = QgsLayoutSize(85.71428571428571, 69, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_locals'] = QgsLayoutPoint(209, 3, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_rotate'] = 0 + self.template_parameters['Legande_size'] = QgsLayoutSize(85.71428571428571, 131, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_locals'] = QgsLayoutPoint(209, 74, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_rotate'] = 0 + self.template_parameters['Arrow_size'] = QgsLayoutSize(14.285714285714286, 14, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_locals'] = QgsLayoutPoint(189, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_rotate'] = 0 + self.template_parameters['Echelle_size'] = QgsLayoutSize(51.42857142857143, 7, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_locals'] = QgsLayoutPoint(9, 197, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_rotate'] = 0 + self.template_parameters['Logo_size'] = QgsLayoutSize(45.714285714285715, 11, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_locals'] = QgsLayoutPoint(3, 3, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_rotate'] = 0 + self.template_parameters['Titre_size'] = QgsLayoutSize(154.28571428571428, 11, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_locals'] = QgsLayoutPoint(51, 3, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_rotate'] = 0 + self.template_parameters['Credit_size'] = QgsLayoutSize(51.42857142857143, 6, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_locals'] = QgsLayoutPoint(151, 197, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_rotate'] = 0 + self.template_parameters['Source_size'] = QgsLayoutSize(51.42857142857143, 6, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_locals'] = QgsLayoutPoint(229, 197, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_rotate'] = 0 + self.template_parameters['Sous_titre_size'] = QgsLayoutSize(125.71428571428571, 14, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_locals'] = QgsLayoutPoint(60, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_rotate'] = 0 + self.template_parameters['Echelle_2_size'] = QgsLayoutSize(51.42857142857143, 13, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_locals'] = QgsLayoutPoint(9, 184, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_rotate'] = 0 + self.template_parameters['Logo_2_size'] = QgsLayoutSize(28.571428571428573, 29, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_locals'] = QgsLayoutPoint(9, 151, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_rotate'] = 0 + if values_page == 'A3': + self.template_parameters['Carte_size'] = QgsLayoutSize(282, 282, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_locals'] = QgsLayoutPoint(8, 8, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_rotate'] = 0 + self.template_parameters['Carte_2_size'] = QgsLayoutSize(121, 97, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_locals'] = QgsLayoutPoint(294, 4, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_rotate'] = 0 + self.template_parameters['Legande_size'] = QgsLayoutSize(121, 185, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_locals'] = QgsLayoutPoint(294, 105, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_rotate'] = 0 + self.template_parameters['Arrow_size'] = QgsLayoutSize(20, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_locals'] = QgsLayoutPoint(266, 28, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_rotate'] = 0 + self.template_parameters['Echelle_size'] = QgsLayoutSize(73, 10, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_locals'] = QgsLayoutPoint(12, 278, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_rotate'] = 0 + self.template_parameters['Logo_size'] = QgsLayoutSize(64, 16, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_locals'] = QgsLayoutPoint(4, 4, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_rotate'] = 0 + self.template_parameters['Titre_size'] = QgsLayoutSize(218, 16, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_locals'] = QgsLayoutPoint(73, 4, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_rotate'] = 0 + self.template_parameters['Credit_size'] = QgsLayoutSize(73, 8, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_locals'] = QgsLayoutPoint(214, 278, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_rotate'] = 0 + self.template_parameters['Source_size'] = QgsLayoutSize(73, 8, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_locals'] = QgsLayoutPoint(322, 278, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_rotate'] = 0 + self.template_parameters['Sous_titre_size'] = QgsLayoutSize(177, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_locals'] = QgsLayoutPoint(85, 28, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_rotate'] = 0 + self.template_parameters['Echelle_2_size'] = QgsLayoutSize(73, 18, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_locals'] = QgsLayoutPoint(12, 260, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_rotate'] = 0 + self.template_parameters['Logo_2_size'] = QgsLayoutSize(40, 40, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_locals'] = QgsLayoutPoint(12, 214, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_rotate'] = 0 + if page_rotate == 'Landscape': + if values_page == 'A4': + self.template_parameters['Carte_size'] = QgsLayoutSize(200.0, 200, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_locals'] = QgsLayoutPoint(6, 6, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_rotate'] = 0 + self.template_parameters['Carte_2_size'] = QgsLayoutSize(85.71428571428571, 69, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_locals'] = QgsLayoutPoint(209, 3, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_rotate'] = 0 + self.template_parameters['Legande_size'] = QgsLayoutSize(85.71428571428571, 131, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_locals'] = QgsLayoutPoint(209, 74, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_rotate'] = 0 + self.template_parameters['Arrow_size'] = QgsLayoutSize(14.285714285714286, 14, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_locals'] = QgsLayoutPoint(189, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_rotate'] = 0 + self.template_parameters['Echelle_size'] = QgsLayoutSize(51.42857142857143, 7, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_locals'] = QgsLayoutPoint(9, 197, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_rotate'] = 0 + self.template_parameters['Logo_size'] = QgsLayoutSize(45.714285714285715, 11, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_locals'] = QgsLayoutPoint(3, 3, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_rotate'] = 0 + self.template_parameters['Titre_size'] = QgsLayoutSize(154.28571428571428, 11, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_locals'] = QgsLayoutPoint(51, 3, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_rotate'] = 0 + self.template_parameters['Credit_size'] = QgsLayoutSize(51.42857142857143, 6, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_locals'] = QgsLayoutPoint(151, 197, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_rotate'] = 0 + self.template_parameters['Source_size'] = QgsLayoutSize(51.42857142857143, 6, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_locals'] = QgsLayoutPoint(229, 197, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_rotate'] = 0 + self.template_parameters['Sous_titre_size'] = QgsLayoutSize(125.71428571428571, 14, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_locals'] = QgsLayoutPoint(60, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_rotate'] = 0 + self.template_parameters['Echelle_2_size'] = QgsLayoutSize(51.42857142857143, 13, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_locals'] = QgsLayoutPoint(9, 184, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_rotate'] = 0 + self.template_parameters['Logo_2_size'] = QgsLayoutSize(28.571428571428573, 29, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_locals'] = QgsLayoutPoint(9, 151, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_rotate'] = 0 + if values_page == 'A3': + self.template_parameters['Carte_size'] = QgsLayoutSize(282, 282, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_locals'] = QgsLayoutPoint(8, 8, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_rotate'] = 0 + self.template_parameters['Carte_2_size'] = QgsLayoutSize(121, 97, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_locals'] = QgsLayoutPoint(294, 4, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Carte_2_rotate'] = 0 + self.template_parameters['Legande_size'] = QgsLayoutSize(121, 185, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_locals'] = QgsLayoutPoint(294, 105, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Legande_rotate'] = 0 + self.template_parameters['Arrow_size'] = QgsLayoutSize(20, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_locals'] = QgsLayoutPoint(266, 28, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Arrow_rotate'] = 0 + self.template_parameters['Echelle_size'] = QgsLayoutSize(73, 10, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_locals'] = QgsLayoutPoint(12, 278, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_rotate'] = 0 + self.template_parameters['Logo_size'] = QgsLayoutSize(64, 16, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_locals'] = QgsLayoutPoint(4, 4, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_rotate'] = 0 + self.template_parameters['Titre_size'] = QgsLayoutSize(218, 16, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_locals'] = QgsLayoutPoint(73, 4, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Titre_rotate'] = 0 + self.template_parameters['Credit_size'] = QgsLayoutSize(73, 8, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_locals'] = QgsLayoutPoint(214, 278, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Credit_rotate'] = 0 + self.template_parameters['Source_size'] = QgsLayoutSize(73, 8, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_locals'] = QgsLayoutPoint(322, 278, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Source_rotate'] = 0 + self.template_parameters['Sous_titre_size'] = QgsLayoutSize(177, 20, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_locals'] = QgsLayoutPoint(85, 28, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Sous_titre_rotate'] = 0 + self.template_parameters['Echelle_2_size'] = QgsLayoutSize(73, 18, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_locals'] = QgsLayoutPoint(12, 260, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Echelle_2_rotate'] = 0 + self.template_parameters['Logo_2_size'] = QgsLayoutSize(40, 40, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_locals'] = QgsLayoutPoint(12, 214, QgsUnitTypes.LayoutMillimeters) + self.template_parameters['Logo_2_rotate'] = 0 + return self.template_parameters diff --git a/CenRa_PAGERENDER/icon.png b/CenRa_PAGERENDER/icon.png new file mode 100644 index 0000000..d53a910 Binary files /dev/null and b/CenRa_PAGERENDER/icon.png differ diff --git a/CenRa_PAGERENDER/issues.py b/CenRa_PAGERENDER/issues.py new file mode 100644 index 0000000..0d6416a --- /dev/null +++ b/CenRa_PAGERENDER/issues.py @@ -0,0 +1,89 @@ +import os +plugin_dir = os.path.dirname(__file__) +end_find = plugin_dir.rfind('\\')+1 + +NAME = plugin_dir[end_find:] +#print(NAME) + +from qgis.gui import * + +from qgis.core import ( + NULL, + QgsApplication, + QgsDataSourceUri, + QgsProject, + QgsProviderConnectionException, + QgsProviderRegistry, + QgsRasterLayer, + QgsSettings, + QgsVectorLayer, + QgsGeometry, +) +from qgis.PyQt.QtWidgets import ( + QDialog, + QAction, + QDockWidget, + QFileDialog, + QInputDialog, + QMenu, + QToolButton, + QTableWidget, + QTableWidgetItem, +) +from qgis.utils import iface + + +from .tools.resources import ( + load_ui, + resources_path, + send_issues, +) + +EDITOR_CLASS = load_ui('CenRa_IssuesSend.ui') + +class CenRa_Issues(QDialog, EDITOR_CLASS): + + def __init__(self, parent=None): + _ = parent + super().__init__() + self.setupUi(self) + self.settings = QgsSettings() + + #place connect here + self.annuler_button.clicked.connect(self.close) + self.ok_button.clicked.connect(self.run_sendissues) + + def run_sendissues(self): + text_titre = self.titre_line.text() + text_message = self.messages_plain.toPlainText() + statu_bug = self.check_bug.isChecked() + statu_aide = self.check_aide.isChecked() + statu_question = self.check_question.isChecked() + statu_amelioration = self.check_amelioration.isChecked() + statu_autre = self.check_autre.isChecked() + + statu = [] + if statu_bug == True : statu = statu + [1] + if statu_aide == True : statu = statu + [3] + if statu_question == True : statu = statu + [5] + if statu_amelioration == True : statu = statu + [2] + if statu_autre == True : statu = statu + [6] + + if len(statu) >= 1: + import qgis + url = qgis.utils.pluginMetadata(NAME,'tracker') + print(text_message) + send_info = send_issues(url,text_titre,text_message,statu) + code = send_info.status_code + print(code) + else: + code = 423 + if code == 201: + iface.messageBar().pushMessage("Envoyer :", "Votre messages à bien été envoyer.", level=Qgis.Success, duration=20) + self.close() + elif code == 422: + iface.messageBar().pushMessage("Erreur :", "Erreur dans le contenu du messages.", level=Qgis.Critical, duration=20) + elif code == 423: + iface.messageBar().pushMessage("Erreur :", "Pas de sujet sélectionné.", level=Qgis.Critical, duration=20) + elif code == 404: + iface.messageBar().pushMessage("Missing :", "Le serveur de messagerie est injoignable.", level=Qgis.Warning, duration=20) diff --git a/CenRa_PAGERENDER/tools/icons/CEN_RA.png b/CenRa_PAGERENDER/tools/icons/CEN_RA.png new file mode 100644 index 0000000..95ead1c Binary files /dev/null and b/CenRa_PAGERENDER/tools/icons/CEN_RA.png differ diff --git a/CenRa_PAGERENDER/tools/icons/icon.png b/CenRa_PAGERENDER/tools/icons/icon.png new file mode 100644 index 0000000..63569ff Binary files /dev/null and b/CenRa_PAGERENDER/tools/icons/icon.png differ diff --git a/CenRa_PAGERENDER/tools/resources.py b/CenRa_PAGERENDER/tools/resources.py new file mode 100644 index 0000000..bdd8c41 --- /dev/null +++ b/CenRa_PAGERENDER/tools/resources.py @@ -0,0 +1,174 @@ +"""Tools to work with resource files.""" + +import configparser +import shutil +import tempfile +# import base64 +# import psycopg2 +# import psycopg2.extras +from os.path import abspath, join, pardir, dirname +from qgis.PyQt.QtWidgets import QApplication +from qgis.PyQt import uic + +__copyright__ = "Copyright 2019, 3Liz" +__license__ = "GPL version 3" +__email__ = "info@3liz.org" +__revision__ = "$Format:%H$" + + +def plugin_path(*args): + """Get the path to plugin root folder. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :return: Absolute path to the plugin path. + :rtype: str + """ + path = dirname(dirname(__file__)) + path = abspath(abspath(join(path, pardir))) + for item in args: + path = abspath(join(path, item)) + + return path + + +def plugin_name(): + """Return the plugin name according to metadata.txt. + + :return: The plugin name. + :rtype: basestring + """ + metadata = metadata_config() + name = metadata["general"]["name"] + return name + + +def metadata_config() -> configparser: + """Get the INI config parser for the metadata file. + + :return: The config parser object. + :rtype: ConfigParser + """ + path = plugin_path("metadata.txt") + config = configparser.ConfigParser() + config.read(path, encoding='utf8') + return config + + +def plugin_test_data_path(*args, copy=False): + """Get the path to the plugin test data path. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :param copy: If the file must be copied into a temporary directory first. + :type copy: bool + + :return: Absolute path to the resources folder. + :rtype: str + """ + path = abspath(abspath(join(plugin_path(), "test", "data"))) + for item in args: + path = abspath(join(path, item)) + + if copy: + temp = tempfile.mkdtemp() + shutil.copy(path, temp) + return join(temp, args[-1]) + else: + return path + + +def resources_path(*args): + """Get the path to our resources folder. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :return: Absolute path to the resources folder. + :rtype: str + """ + path = abspath(abspath(join(plugin_path(), "CenRa_PAGERENDER\\tools"))) + for item in args: + path = abspath(join(path, item)) + return path + + +def load_ui(*args): + """Get compile UI file. + + :param args List of path elements e.g. ['img', 'logos', 'image.png'] + :type args: str + + :return: Compiled UI file. + """ + ui_class, _ = uic.loadUiType(resources_path("ui", *args)) + + return ui_class + + +def send_issues(url, titre, body, labels): + import requests + import urllib.request + import json + # import os + + # usr = os.environ['USERNAME'] + token = '9d0a4e0bea561710e0728f161f7edf4e5201e112' + url = url + '?token=' + token + + headers = {'Authorization': 'token ' + token, 'accept': 'application/json', 'Content-Type': 'application/json'} + + payload = {'title': titre, 'body': body, 'labels': labels} + try: + urllib.request.urlopen('https://google.com') + binar = True + except urllib.requests.URLError: + binar = False + r = '' + if binar: + r = requests.post(url, data=json.dumps(payload), headers=headers) + return r + + +def maj_verif(NAME): + import qgis + import urllib.request + iface = qgis.utils.iface + from qgis.core import Qgis + + # url = qgis.utils.pluginMetadata(NAME, 'repository') + # URL = url+'/raw/branch/main/plugins.xml' + URL = 'https://gitea.cenra-outils.org/CEN-RA/Plugin_QGIS/releases/download/latest/plugins.xml' +# print(URL) + version = qgis.utils.pluginMetadata(NAME, 'version') + len_version = len(version) + try: + urllib.request.urlopen('https://google.com') + binar = True + except urllib.requests.URLError: + binar = False + if binar: + try: + version_web = str(urllib.request.urlopen(URL).read()) + plugin_num = version_web.find(NAME) + valeur_version_web = version_web.find('', plugin_num) + 9 + version_plugin = version_web[valeur_version_web:valeur_version_web + len_version] + if version_plugin != version: + iface.messageBar().pushMessage("MAJ :", "Des mise à jour de plugin sont disponibles.", level=Qgis.Info, duration=30) + except urllib.requests.URLError: + print("error gitea version ssl") + else: + iface.messageBar().pushMessage("WiFi :", "Pas de connection à internet.", level=Qgis.Warning, duration=30) + + +def tr(text, context="@default"): + return QApplication.translate(context, text) + + +def devlog(NAME): + import qgis + devmaj = '' + devmaj = devmaj + qgis.utils.pluginMetadata(NAME, 'changelog') + return devmaj diff --git a/CenRa_PAGERENDER/tools/ui/CenRa_IssuesSend.ui b/CenRa_PAGERENDER/tools/ui/CenRa_IssuesSend.ui new file mode 100644 index 0000000..14d923e --- /dev/null +++ b/CenRa_PAGERENDER/tools/ui/CenRa_IssuesSend.ui @@ -0,0 +1,332 @@ + + + CenRa_IssuesSend + + + + 0 + 0 + 810 + 587 + + + + CEN-RA Metabase + + + + icon.svgicon.svg + + + + + 0 + 550 + 811 + 31 + + + + + + + Annuler + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Envoyer + + + + + + + + + 10 + 10 + 791 + 531 + + + + Issues + + + + + 240 + 40 + 321 + 41 + + + + Qt::AlignCenter + + + + + + 10 + 101 + 571 + 421 + + + + + + + 589 + 100 + 191 + 431 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 9 + 9 + 341 + 411 + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Bug + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Aide + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Question + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Amélioration + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Autre + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 250 + 20 + 51 + 21 + + + + + Arial + 14 + + + + Titre: + + + + + + 20 + 70 + 91 + 31 + + + + + Arial + 12 + + + + Messages: + + + + + + 600 + 70 + 91 + 31 + + + + + Arial + 12 + + + + Sujet: + + + + + + ok_button + annuler_button + + + + diff --git a/CenRa_PAGERENDER/tools/ui/CenRa_PageRender_base.ui b/CenRa_PAGERENDER/tools/ui/CenRa_PageRender_base.ui index 3c96170..884a749 100644 --- a/CenRa_PAGERENDER/tools/ui/CenRa_PageRender_base.ui +++ b/CenRa_PAGERENDER/tools/ui/CenRa_PageRender_base.ui @@ -78,7 +78,7 @@ 296 - Qt::Orientation::Horizontal + Qt::Horizontal @@ -100,7 +100,7 @@ 0 - Qt::Orientation::Vertical + Qt::Vertical true @@ -118,12 +118,6 @@ QFrame#frame{background-color: rgb(255, 255, 255, 170);} - - QFrame::Shape::StyledPanel - - - QFrame::Shadow::Raised - @@ -139,24 +133,9 @@ background-color: rgba(10, 10, 10, 50) - - QFrame::Shape::NoFrame - - - QFrame::Shadow::Plain - - - 5 - - - 2 - - - Qt::AlignmentFlag::AlignCenter - 5 @@ -176,9 +155,6 @@ background-color: rgba(10, 10, 10, 50) - - QFrame::Shadow::Plain - @@ -277,27 +253,12 @@ background-color: rgba(10, 10, 10, 50) - - QFrame::Shape::NoFrame - - - QFrame::Shadow::Raised - - - -1 - - - 0 - false - - Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTop|Qt::AlignmentFlag::AlignTrailing - false @@ -364,27 +325,12 @@ background-color: rgba(10, 10, 10, 50) - - QFrame::Shape::NoFrame - - - QFrame::Shadow::Raised - - - -1 - - - 0 - false - - Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTop|Qt::AlignmentFlag::AlignTrailing - false @@ -446,12 +392,6 @@ QFrame#frame_2{background-color: rgb(255, 255, 255, 170);} - - QFrame::Shape::StyledPanel - - - QFrame::Shadow::Raised - @@ -465,13 +405,13 @@ 1 - Qt::ScrollBarPolicy::ScrollBarAlwaysOff + Qt::ScrollBarAsNeeded - QAbstractScrollArea::SizeAdjustPolicy::AdjustToContentsOnFirstShow + QAbstractScrollArea::AdjustIgnored - QAbstractItemView::EditTrigger::NoEditTriggers + QAbstractItemView::NoEditTriggers false @@ -483,19 +423,19 @@ false - QAbstractItemView::DragDropMode::NoDragDrop + QAbstractItemView::NoDragDrop - Qt::DropAction::IgnoreAction + Qt::IgnoreAction true - QAbstractItemView::SelectionMode::SingleSelection + QAbstractItemView::NoSelection - QAbstractItemView::SelectionBehavior::SelectRows + QAbstractItemView::SelectItems @@ -504,7 +444,7 @@ - Qt::TextElideMode::ElideMiddle + Qt::ElideLeft true @@ -590,13 +530,13 @@ 1 - Qt::ScrollBarPolicy::ScrollBarAlwaysOff + Qt::ScrollBarAsNeeded - QAbstractScrollArea::SizeAdjustPolicy::AdjustToContentsOnFirstShow + QAbstractScrollArea::AdjustIgnored - QAbstractItemView::EditTrigger::DoubleClicked + QAbstractItemView::NoEditTriggers false @@ -608,19 +548,19 @@ false - QAbstractItemView::DragDropMode::NoDragDrop + QAbstractItemView::NoDragDrop - Qt::DropAction::IgnoreAction + Qt::IgnoreAction true - QAbstractItemView::SelectionMode::SingleSelection + QAbstractItemView::NoSelection - QAbstractItemView::SelectionBehavior::SelectRows + QAbstractItemView::SelectItems @@ -629,7 +569,7 @@ - Qt::TextElideMode::ElideMiddle + Qt::ElideLeft true @@ -707,16 +647,16 @@ - Qt::FocusPolicy::NoFocus + Qt::NoFocus - Qt::LayoutDirection::LeftToRight + Qt::LeftToRight false - Qt::InputMethodHint::ImhNone + Qt::ImhNone @@ -741,7 +681,7 @@ - QAbstractSpinBox::ButtonSymbols::NoButtons + QAbstractSpinBox::UpDownArrows @@ -763,7 +703,7 @@ - QAbstractSpinBox::ButtonSymbols::NoButtons + QAbstractSpinBox::UpDownArrows @@ -812,9 +752,6 @@ 40 - - Qt::Orientation::Vertical - true diff --git a/CenRa_PAGERENDER/tools/ui/CenRa_about_form.ui b/CenRa_PAGERENDER/tools/ui/CenRa_about_form.ui new file mode 100644 index 0000000..6ec4843 --- /dev/null +++ b/CenRa_PAGERENDER/tools/ui/CenRa_about_form.ui @@ -0,0 +1,81 @@ + + + CenRa_Metabase_editorwidget_base + + + + 0 + 0 + 471 + 594 + + + + Journal des modifications + + + + ../../CenRa_Metabase/tools/ui/icon.svg../../CenRa_Metabase/tools/ui/icon.svg + + + + + + true + + + Qt::NoFocus + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 453 + 570 + + + + + + 0 + 0 + 451 + 541 + + + + DevLog + + + + + 10 + 20 + 431 + 511 + + + + + + + + + + + QDialogButtonBox::NoButton + + + + + + + + diff --git a/CenRa_PAGERENDER/tools/ui/rotate.png b/CenRa_PAGERENDER/tools/ui/rotate.png new file mode 100644 index 0000000..85826ed Binary files /dev/null and b/CenRa_PAGERENDER/tools/ui/rotate.png differ diff --git a/CenRa_PAGERENDER/tools/ui/size.png b/CenRa_PAGERENDER/tools/ui/size.png new file mode 100644 index 0000000..7cd2a08 Binary files /dev/null and b/CenRa_PAGERENDER/tools/ui/size.png differ diff --git a/CenRa_PAGERENDER/tools/ui/size_0.png b/CenRa_PAGERENDER/tools/ui/size_0.png new file mode 100644 index 0000000..571076b Binary files /dev/null and b/CenRa_PAGERENDER/tools/ui/size_0.png differ