forked from CEN-RA/Plugin_QGIS
Téléverser les fichiers vers "CenRa_Metabase"
This commit is contained in:
parent
839eb525e4
commit
f831f2e5a3
@ -1,481 +1,488 @@
|
|||||||
"""Dock file."""
|
"""Dock file."""
|
||||||
|
|
||||||
__copyright__ = 'Copyright 2020, 3Liz'
|
__copyright__ = 'Copyright 2020, 3Liz'
|
||||||
__license__ = 'GPL version 3'
|
__license__ = 'GPL version 3'
|
||||||
__email__ = 'info@3liz.org'
|
__email__ = 'info@3liz.org'
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from xml.dom.minidom import parseString
|
from xml.dom.minidom import parseString
|
||||||
|
|
||||||
from qgis.core import (
|
from qgis.core import (
|
||||||
NULL,
|
NULL,
|
||||||
QgsApplication,
|
QgsApplication,
|
||||||
QgsDataSourceUri,
|
QgsDataSourceUri,
|
||||||
QgsProject,
|
QgsProject,
|
||||||
QgsProviderConnectionException,
|
QgsProviderConnectionException,
|
||||||
QgsProviderRegistry,
|
QgsProviderRegistry,
|
||||||
QgsRasterLayer,
|
QgsRasterLayer,
|
||||||
QgsSettings,
|
QgsSettings,
|
||||||
QgsVectorLayer,
|
QgsVectorLayer,
|
||||||
)
|
)
|
||||||
from qgis.PyQt.QtCore import QLocale, QUrl
|
from qgis.PyQt.QtCore import QLocale, QUrl
|
||||||
from qgis.PyQt.QtGui import QDesktopServices, QIcon
|
from qgis.PyQt.QtGui import QDesktopServices, QIcon
|
||||||
from qgis.PyQt.QtPrintSupport import QPrinter
|
from qgis.PyQt.QtPrintSupport import QPrinter
|
||||||
from qgis.PyQt.QtWebKitWidgets import QWebPage
|
from qgis.PyQt.QtWebKitWidgets import QWebPage
|
||||||
from qgis.PyQt.QtWidgets import (
|
from qgis.PyQt.QtWidgets import (
|
||||||
QDialog,
|
QDialog,
|
||||||
QAction,
|
QAction,
|
||||||
QDockWidget,
|
QDockWidget,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
QInputDialog,
|
QInputDialog,
|
||||||
QMenu,
|
QMenu,
|
||||||
QToolButton,
|
QToolButton,
|
||||||
)
|
)
|
||||||
from qgis.gui import *
|
from qgis.gui import *
|
||||||
from qgis.utils import iface
|
from qgis.utils import iface
|
||||||
'''
|
'''
|
||||||
from pg_metadata.connection_manager import (
|
from pg_metadata.connection_manager import (
|
||||||
check_pgmetadata_is_installed,
|
check_pgmetadata_is_installed,
|
||||||
connections_list,
|
connections_list,
|
||||||
settings_connections_names,
|
settings_connections_names,
|
||||||
)
|
)
|
||||||
'''
|
'''
|
||||||
from CenRa_Metabase.resources.i18n import tr
|
|
||||||
|
from .tools.resources import (
|
||||||
from CenRa_Metabase.resources.resources import (
|
load_ui,
|
||||||
load_ui,
|
resources_path,
|
||||||
resources_path,
|
login_base,
|
||||||
login_base,
|
)
|
||||||
)
|
|
||||||
|
DOCK_CLASS = load_ui('CenRa_Metabase_dockwidget_base.ui')
|
||||||
DOCK_CLASS = load_ui('CenRa_Metabase_dockwidget_base.ui')
|
LOGGER = logging.getLogger('CenRa_Metabase')
|
||||||
LOGGER = logging.getLogger('CenRa_Metabase')
|
|
||||||
|
|
||||||
|
class Format(namedtuple('Format', ['label', 'ext'])):
|
||||||
class Format(namedtuple('Format', ['label', 'ext'])):
|
""" Format available for exporting metadata. """
|
||||||
""" Format available for exporting metadata. """
|
pass
|
||||||
pass
|
|
||||||
|
|
||||||
|
class OutputFormats(Format, Enum):
|
||||||
class OutputFormats(Format, Enum):
|
""" Output format for a metadata sheet. """
|
||||||
""" Output format for a metadata sheet. """
|
PDF = Format(label='PDF', ext='pdf')
|
||||||
PDF = Format(label='PDF', ext='pdf')
|
HTML = Format(label='HTML', ext='html')
|
||||||
HTML = Format(label='HTML', ext='html')
|
DCAT = Format(label='DCAT', ext='xml')
|
||||||
DCAT = Format(label='DCAT', ext='xml')
|
|
||||||
|
|
||||||
|
class CenRa_Metabase(QDockWidget, DOCK_CLASS):
|
||||||
class CenRa_Metabase(QDockWidget, DOCK_CLASS):
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
def __init__(self, parent=None):
|
_ = parent
|
||||||
_ = parent
|
super().__init__()
|
||||||
super().__init__()
|
self.setupUi(self)
|
||||||
self.setupUi(self)
|
self.settings = QgsSettings()
|
||||||
self.settings = QgsSettings()
|
|
||||||
|
self.current_datasource_uri = None
|
||||||
self.current_datasource_uri = None
|
self.current_connection = None
|
||||||
self.current_connection = None
|
|
||||||
|
self.viewer.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
|
||||||
self.viewer.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
|
self.viewer.page().linkClicked.connect(self.open_link)
|
||||||
self.viewer.page().linkClicked.connect(self.open_link)
|
|
||||||
|
# Help button
|
||||||
# Help button
|
self.external_help.setText('')
|
||||||
self.external_help.setText('')
|
self.external_help.setIcon(QIcon(QgsApplication.iconPath('mActionHelpContents.svg')))
|
||||||
self.external_help.setIcon(QIcon(QgsApplication.iconPath('mActionHelpContents.svg')))
|
self.external_help.clicked.connect(self.open_external_help)
|
||||||
self.external_help.clicked.connect(self.open_external_help)
|
|
||||||
|
# Flat table button
|
||||||
# Flat table button
|
self.flatten_dataset_table.setText('')
|
||||||
self.flatten_dataset_table.setText('')
|
#self.flatten_dataset_table.setToolTip(tr("Add the catalog table"))
|
||||||
self.flatten_dataset_table.setToolTip(tr("Add the catalog table"))
|
self.flatten_dataset_table.setIcon(QgsApplication.getThemeIcon("/mActionAddHtml.svg"))
|
||||||
self.flatten_dataset_table.setIcon(QgsApplication.getThemeIcon("/mActionAddHtml.svg"))
|
#self.flatten_dataset_table.clicked.connect(self.add_flatten_dataset_table)
|
||||||
#self.flatten_dataset_table.clicked.connect(self.add_flatten_dataset_table)
|
|
||||||
|
# Settings menu
|
||||||
# Settings menu
|
self.config.setAutoRaise(True)
|
||||||
self.config.setAutoRaise(True)
|
#self.config.setToolTip(tr("Settings"))
|
||||||
self.config.setToolTip(tr("Settings"))
|
self.config.setPopupMode(QToolButton.InstantPopup)
|
||||||
self.config.setPopupMode(QToolButton.InstantPopup)
|
self.config.setIcon(QgsApplication.getThemeIcon("/mActionOptions.svg"))
|
||||||
self.config.setIcon(QgsApplication.getThemeIcon("/mActionOptions.svg"))
|
|
||||||
|
self.auto_open_dock_action = QAction(
|
||||||
self.auto_open_dock_action = QAction(
|
("Dommage, cette option n'existe pas encore."),
|
||||||
tr('Auto open dock from locator'),
|
iface.mainWindow())
|
||||||
iface.mainWindow())
|
self.auto_open_dock_action.setCheckable(True)
|
||||||
self.auto_open_dock_action.setCheckable(True)
|
self.auto_open_dock_action.setChecked(
|
||||||
self.auto_open_dock_action.setChecked(
|
self.settings.value("pgmetadata/auto_open_dock", True, type=bool)
|
||||||
self.settings.value("pgmetadata/auto_open_dock", True, type=bool)
|
)
|
||||||
)
|
self.auto_open_dock_action.triggered.connect(self.save_auto_open_dock)
|
||||||
self.auto_open_dock_action.triggered.connect(self.save_auto_open_dock)
|
menu = QMenu()
|
||||||
menu = QMenu()
|
menu.addAction(self.auto_open_dock_action)
|
||||||
menu.addAction(self.auto_open_dock_action)
|
self.config.setMenu(menu)
|
||||||
self.config.setMenu(menu)
|
|
||||||
|
# Setting PDF/HTML menu
|
||||||
# Setting PDF/HTML menu
|
self.save_button.setAutoRaise(True)
|
||||||
self.save_button.setAutoRaise(True)
|
#self.save_button.setToolTip(tr("Save metadata"))
|
||||||
self.save_button.setToolTip(tr("Save metadata"))
|
self.save_button.setPopupMode(QToolButton.InstantPopup)
|
||||||
self.save_button.setPopupMode(QToolButton.InstantPopup)
|
self.save_button.setIcon(QIcon(QgsApplication.iconPath('mActionFileSave.svg')))
|
||||||
self.save_button.setIcon(QIcon(QgsApplication.iconPath('mActionFileSave.svg')))
|
|
||||||
|
self.save_as_pdf = QAction(
|
||||||
self.save_as_pdf = QAction(
|
('Enregistrer en PDF') + '…',
|
||||||
tr('Enregistrer en PDF') + '…',
|
iface.mainWindow())
|
||||||
iface.mainWindow())
|
self.save_as_pdf.triggered.connect(partial(self.export_dock_content, OutputFormats.PDF))
|
||||||
self.save_as_pdf.triggered.connect(partial(self.export_dock_content, OutputFormats.PDF))
|
|
||||||
|
self.save_as_html = QAction(
|
||||||
self.save_as_html = QAction(
|
('Enregistrer en HTML') + '…',
|
||||||
tr('Enregistrer en HTML') + '…',
|
iface.mainWindow())
|
||||||
iface.mainWindow())
|
self.save_as_html.triggered.connect(partial(self.export_dock_content, OutputFormats.HTML))
|
||||||
self.save_as_html.triggered.connect(partial(self.export_dock_content, OutputFormats.HTML))
|
self.save_as_dcat = QAction(
|
||||||
self.save_as_dcat = QAction(
|
('Enregistrer en DCAT') + '…',
|
||||||
tr('Enregistrer en DCAT') + '…',
|
iface.mainWindow())
|
||||||
iface.mainWindow())
|
self.save_as_dcat.triggered.connect(partial(self.export_dock_content, OutputFormats.DCAT))
|
||||||
self.save_as_dcat.triggered.connect(partial(self.export_dock_content, OutputFormats.DCAT))
|
|
||||||
|
self.menu_save = QMenu()
|
||||||
self.menu_save = QMenu()
|
self.menu_save.addAction(self.save_as_pdf)
|
||||||
self.menu_save.addAction(self.save_as_pdf)
|
self.menu_save.addAction(self.save_as_html)
|
||||||
self.menu_save.addAction(self.save_as_html)
|
self.menu_save.addAction(self.save_as_dcat)
|
||||||
self.menu_save.addAction(self.save_as_dcat)
|
self.save_button.setMenu(self.menu_save)
|
||||||
self.save_button.setMenu(self.menu_save)
|
self.save_button.setEnabled(False)
|
||||||
self.save_button.setEnabled(False)
|
|
||||||
|
self.metadata = QgsProviderRegistry.instance().providerMetadata('postgres')
|
||||||
self.metadata = QgsProviderRegistry.instance().providerMetadata('postgres')
|
|
||||||
|
# Display message in the dock
|
||||||
# Display message in the dock
|
#if not settings_connections_names():
|
||||||
#if not settings_connections_names():
|
#self.default_html_content_not_installed()
|
||||||
#self.default_html_content_not_installed()
|
#else:
|
||||||
#else:
|
self.default_html_content_not_pg_layer()
|
||||||
self.default_html_content_not_pg_layer()
|
|
||||||
|
iface.layerTreeView().currentLayerChanged.connect(self.layer_changed)
|
||||||
iface.layerTreeView().currentLayerChanged.connect(self.layer_changed)
|
|
||||||
|
if iface.activeLayer():
|
||||||
if iface.activeLayer():
|
layer=iface.activeLayer()
|
||||||
layer=iface.activeLayer()
|
iface.layerTreeView().setCurrentLayer(None)
|
||||||
iface.layerTreeView().setCurrentLayer(None)
|
iface.layerTreeView().setCurrentLayer(layer)
|
||||||
iface.layerTreeView().setCurrentLayer(layer)
|
|
||||||
|
def export_dock_content(self, output_format: OutputFormats):
|
||||||
def export_dock_content(self, output_format: OutputFormats):
|
""" Export the current displayed metadata sheet to the given format. """
|
||||||
""" Export the current displayed metadata sheet to the given format. """
|
layer_name = iface.activeLayer().name()
|
||||||
layer_name = iface.activeLayer().name()
|
|
||||||
|
file_path = os.path.join(
|
||||||
file_path = os.path.join(
|
os.environ['USERPROFILE'],
|
||||||
self.settings.value("UI/lastFileNameWidgetDir"),
|
'Desktop\\{name}.{ext}'.format(name=layer_name, ext=output_format.ext)
|
||||||
'{name}.{ext}'.format(name=layer_name, ext=output_format.ext)
|
)
|
||||||
)
|
output_file = QFileDialog.getSaveFileName(
|
||||||
output_file = QFileDialog.getSaveFileName(
|
self,
|
||||||
self,
|
("Enregistrer en {format}").format(format=output_format.label),
|
||||||
tr("Enregistrer en {format}").format(format=output_format.label),
|
file_path,
|
||||||
file_path,
|
"{label} (*.{ext})".format(
|
||||||
"{label} (*.{ext})".format(
|
label=output_format.label,
|
||||||
label=output_format.label,
|
ext=output_format.ext,
|
||||||
ext=output_format.ext,
|
)
|
||||||
)
|
)
|
||||||
)
|
if output_file[0] == '':
|
||||||
if output_file[0] == '':
|
return
|
||||||
return
|
|
||||||
|
self.settings.setValue("UI/lastFileNameWidgetDir", os.path.dirname(output_file[0]))
|
||||||
self.settings.setValue("UI/lastFileNameWidgetDir", os.path.dirname(output_file[0]))
|
|
||||||
|
output_file_path = output_file[0]
|
||||||
output_file_path = output_file[0]
|
parent_folder = str(Path(output_file_path).parent)
|
||||||
parent_folder = str(Path(output_file_path).parent)
|
|
||||||
|
if output_format == OutputFormats.PDF:
|
||||||
if output_format == OutputFormats.PDF:
|
printer = QPrinter()
|
||||||
printer = QPrinter()
|
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
printer.setPageMargins(20, 20, 20, 20, QPrinter.Millimeter)
|
||||||
printer.setPageMargins(20, 20, 20, 20, QPrinter.Millimeter)
|
printer.setOutputFileName(output_file_path)
|
||||||
printer.setOutputFileName(output_file_path)
|
self.viewer.print(printer)
|
||||||
self.viewer.print(printer)
|
iface.messageBar().pushSuccess(
|
||||||
iface.messageBar().pushSuccess(
|
("Export PDF"),
|
||||||
tr("Export PDF"),
|
(
|
||||||
tr(
|
"The metadata has been exported as PDF successfully in "
|
||||||
"The metadata has been exported as PDF successfully in "
|
"<a href=\"{}\">{}</a>").format(parent_folder, output_file_path)
|
||||||
"<a href=\"{}\">{}</a>").format(parent_folder, output_file_path)
|
)
|
||||||
)
|
|
||||||
|
elif output_format in [OutputFormats.HTML,OutputFormats.DCAT]:
|
||||||
elif output_format in [OutputFormats.HTML,OutputFormats.DCAT]:
|
if output_format == OutputFormats.HTML:
|
||||||
if output_format == OutputFormats.HTML:
|
data_str = self.viewer.page().currentFrame().toHtml()
|
||||||
data_str = self.viewer.page().currentFrame().toHtml()
|
else:
|
||||||
else:
|
layer = iface.activeLayer()
|
||||||
layer = iface.activeLayer()
|
uri = layer.dataProvider().uri()
|
||||||
uri = layer.dataProvider().uri()
|
dataall = self.sql_info(uri)
|
||||||
dataall = self.sql_info(uri)
|
data = self.sql_to_xml(dataall)
|
||||||
data = self.sql_to_xml(dataall)
|
|
||||||
|
with open(resources_path('xml', 'dcat.xml'), encoding='utf8') as xml_file:
|
||||||
with open(resources_path('xml', 'dcat.xml'), encoding='utf8') as xml_file:
|
xml_template = xml_file.read()
|
||||||
xml_template = xml_file.read()
|
|
||||||
|
xml = parseString(xml_template.format(language=data[0][0], content=data[0][1]))
|
||||||
xml = parseString(xml_template.format(language=data[0][0], content=data[0][1]))
|
|
||||||
|
data_str = xml.toprettyxml()
|
||||||
data_str = xml.toprettyxml()
|
|
||||||
|
with open(output_file[0], "w", encoding='utf8') as file_writer:
|
||||||
with open(output_file[0], "w", encoding='utf8') as file_writer:
|
file_writer.write(data_str)
|
||||||
file_writer.write(data_str)
|
iface.messageBar().pushSuccess(
|
||||||
iface.messageBar().pushSuccess(
|
("Export") + ' ' + output_format.label,
|
||||||
tr("Export") + ' ' + output_format.label,
|
(
|
||||||
tr(
|
"The metadata has been exported as {format} successfully in "
|
||||||
"The metadata has been exported as {format} successfully in "
|
"<a href=\"{folder}\">{path}</a>").format(
|
||||||
"<a href=\"{folder}\">{path}</a>").format(
|
format=output_format.label, folder=parent_folder, path=output_file_path)
|
||||||
format=output_format.label, folder=parent_folder, path=output_file_path)
|
)
|
||||||
)
|
|
||||||
|
def save_auto_open_dock(self):
|
||||||
def save_auto_open_dock(self):
|
""" Save settings about the dock. """
|
||||||
""" Save settings about the dock. """
|
self.settings.setValue("pgmetadata/auto_open_dock", self.auto_open_dock_action.isChecked())
|
||||||
self.settings.setValue("pgmetadata/auto_open_dock", self.auto_open_dock_action.isChecked())
|
def sql_to_xml(self,dataall):
|
||||||
def sql_to_xml(self,dataall):
|
distribution=''
|
||||||
distribution=''
|
for y in dataall[1]:
|
||||||
for y in dataall[1]:
|
distribution = distribution + (
|
||||||
distribution = distribution + (
|
'<dcat:distribution>'+
|
||||||
'<dcat:distribution>'+
|
'<dcat:Distribution>'+
|
||||||
'<dcat:Distribution>'+
|
'<dct:title>{data}</dct:title>'.format(data=y[0])+
|
||||||
'<dct:title>{data}</dct:title>'.format(data=y[0])+
|
'<dcat:downloadURL>{data}</dcat:downloadURL>'.format(data=y[1])+
|
||||||
'<dcat:downloadURL>{data}</dcat:downloadURL>'.format(data=y[1])+
|
'<dcat:mediaType>{data}</dcat:mediaType>'.format(data=y[2])+
|
||||||
'<dcat:mediaType>{data}</dcat:mediaType>'.format(data=y[2])+
|
'<dct:format>{data}</dct:format>'.format(data=y[3])+
|
||||||
'<dct:format>{data}</dct:format>'.format(data=y[3])+
|
'<dct:bytesize>{data}</dct:bytesize>'.format(data=y[4])+
|
||||||
'<dct:bytesize>{data}</dct:bytesize>'.format(data=y[4])+
|
'</dcat:Distribution>'+
|
||||||
'</dcat:Distribution>'+
|
'</dcat:distribution>')
|
||||||
'</dcat:distribution>')
|
publisher=''
|
||||||
publisher=''
|
for z in dataall[2]:
|
||||||
for z in dataall[2]:
|
publisher = publisher + (
|
||||||
publisher = publisher + (
|
'<dct:publisher>'+
|
||||||
'<dct:publisher>'+
|
'<foaf:Organization>'+
|
||||||
'<foaf:Organization>'+
|
'<foaf:name>{data}</foaf:name>'.format(data=z[1])+
|
||||||
'<foaf:name>{data}</foaf:name>'.format(data=z[1])+
|
'<foaf:mbox>{data}</foaf:mbox>'.format(data=z[3])+
|
||||||
'<foaf:mbox>{data}</foaf:mbox>'.format(data=z[3])+
|
'</foaf:Organization>'+
|
||||||
'</foaf:Organization>'+
|
'</dct:publisher>')
|
||||||
'</dct:publisher>')
|
data_str = [[dataall[0][26],
|
||||||
data_str = [[dataall[0][26],
|
'<dct:identifier>{data}</dct:identifier>'.format(data=dataall[0][1])+
|
||||||
'<dct:identifier>{data}</dct:identifier>'.format(data=dataall[0][1])+
|
'<dct:title>{data}</dct:title>'.format(data=dataall[0][4])+
|
||||||
'<dct:title>{data}</dct:title>'.format(data=dataall[0][4])+
|
'<dct:description>{data}</dct:description>'.format(data=dataall[0][5])+
|
||||||
'<dct:description>{data}</dct:description>'.format(data=dataall[0][5])+
|
'<dct:language>{data}</dct:language>'.format(data=dataall[0][26])+
|
||||||
'<dct:language>{data}</dct:language>'.format(data=dataall[0][26])+
|
'<dct:spatial>{data}</dct:spatial>'.format(data=dataall[0][28])+
|
||||||
'<dct:spatial>{data}</dct:spatial>'.format(data=dataall[0][28])+
|
'<dct:created rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">{data}</dct:created>'.format(data=dataall[0][20])+
|
||||||
'<dct:created rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">{data}</dct:created>'.format(data=dataall[0][20])+
|
'<dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">{data}</dct:issued>'.format(data=dataall[0][11])+
|
||||||
'<dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">{data}</dct:issued>'.format(data=dataall[0][11])+
|
'<dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">{data}</dct:modified>'.format(data=dataall[0][21])+
|
||||||
'<dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">{data}</dct:modified>'.format(data=dataall[0][21])+
|
'<dct:license>{data}</dct:license>'.format(data=dataall[0][13])+
|
||||||
'<dct:license>{data}</dct:license>'.format(data=dataall[0][13])+
|
distribution+
|
||||||
distribution+
|
publisher+
|
||||||
publisher+
|
'<dcat:theme>{data}</dcat:theme>'.format(data=", ".join(str(x) for x in dataall[0][24]))+
|
||||||
'<dcat:theme>{data}</dcat:theme>'.format(data=", ".join(str(x) for x in dataall[0][24]))+
|
'<dcat:keyword>{data}</dcat:keyword>'.format(data=", ".join(str(x) for x in dataall[0][6]))+
|
||||||
'<dcat:keyword>{data}</dcat:keyword>'.format(data=", ".join(str(x) for x in dataall[0][6]))+
|
'<dct:accrualPeriodicity>{data}</dct:accrualPeriodicity>'.format(data=dataall[0][12])]]
|
||||||
'<dct:accrualPeriodicity>{data}</dct:accrualPeriodicity>'.format(data=dataall[0][12])]]
|
|
||||||
|
return data_str
|
||||||
return data_str
|
|
||||||
|
@staticmethod
|
||||||
@staticmethod
|
def sql_for_layer(uri, output_format: OutputFormats):
|
||||||
def sql_for_layer(uri, output_format: OutputFormats):
|
""" Get the SQL query for a given layer and output format. """
|
||||||
""" Get the SQL query for a given layer and output format. """
|
locale = QgsSettings().value("locale/userLocale", QLocale().name())
|
||||||
locale = QgsSettings().value("locale/userLocale", QLocale().name())
|
locale = locale.split('_')[0].lower()
|
||||||
locale = locale.split('_')[0].lower()
|
|
||||||
|
if output_format == [OutputFormats.HTML,OutputFormats.DCAT]:
|
||||||
if output_format == [OutputFormats.HTML,OutputFormats.DCAT]:
|
sql = (
|
||||||
sql = (
|
"SELECT pgmetadata.get_dataset_item_html_content('{schema}', '{table}', '{locale}');"
|
||||||
"SELECT pgmetadata.get_dataset_item_html_content('{schema}', '{table}', '{locale}');"
|
).format(schema=uri.schema(), table=uri.table(), locale=locale)
|
||||||
).format(schema=uri.schema(), table=uri.table(), locale=locale)
|
else:
|
||||||
else:
|
raise NotImplementedError('Output format is not yet implemented.')
|
||||||
raise NotImplementedError('Output format is not yet implemented.')
|
|
||||||
|
return sql
|
||||||
return sql
|
|
||||||
|
def layer_changed(self, layer):
|
||||||
def layer_changed(self, layer):
|
""" When the layer has changed in the legend, we must check this new layer. """
|
||||||
""" When the layer has changed in the legend, we must check this new layer. """
|
self.current_datasource_uri = None
|
||||||
self.current_datasource_uri = None
|
self.current_connection = None
|
||||||
self.current_connection = None
|
self.ce_trouve_dans_psql(layer)
|
||||||
self.ce_trouve_dans_psql(layer)
|
|
||||||
|
|
||||||
|
def add_flatten_dataset_table(self):
|
||||||
def add_flatten_dataset_table(self):
|
""" Add a flatten dataset table with all links and contacts. """
|
||||||
""" Add a flatten dataset table with all links and contacts. """
|
'''
|
||||||
'''
|
connections, message = connections_list()
|
||||||
connections, message = connections_list()
|
if not connections:
|
||||||
if not connections:
|
LOGGER.critical(message)
|
||||||
LOGGER.critical(message)
|
self.set_html_content('PgMetadata', message)
|
||||||
self.set_html_content('PgMetadata', message)
|
return
|
||||||
return
|
|
||||||
|
if len(connections) > 1:
|
||||||
if len(connections) > 1:
|
dialog = QInputDialog()
|
||||||
dialog = QInputDialog()
|
dialog.setComboBoxItems(connections)
|
||||||
dialog.setComboBoxItems(connections)
|
dialog.setWindowTitle(tr("Database"))
|
||||||
dialog.setWindowTitle(tr("Database"))
|
dialog.setLabelText(tr("Choose the database to add the catalog"))
|
||||||
dialog.setLabelText(tr("Choose the database to add the catalog"))
|
if not dialog.exec_():
|
||||||
if not dialog.exec_():
|
return
|
||||||
return
|
connection_name = dialog.textValue()
|
||||||
connection_name = dialog.textValue()
|
else:
|
||||||
else:
|
connection_name = connections[0]
|
||||||
connection_name = connections[0]
|
|
||||||
|
metadata = QgsProviderRegistry.instance().providerMetadata('postgres')
|
||||||
metadata = QgsProviderRegistry.instance().providerMetadata('postgres')
|
connection = metadata.findConnection(connection_name)
|
||||||
connection = metadata.findConnection(connection_name)
|
|
||||||
|
locale = QgsSettings().value("locale/userLocale", QLocale().name())
|
||||||
locale = QgsSettings().value("locale/userLocale", QLocale().name())
|
locale = locale.split('_')[0].lower()
|
||||||
locale = locale.split('_')[0].lower()
|
|
||||||
|
uri = QgsDataSourceUri(connection.uri())
|
||||||
uri = QgsDataSourceUri(connection.uri())
|
uri.setTable(f'(SELECT * FROM pgmetadata.export_datasets_as_flat_table(\'{locale}\'))')
|
||||||
uri.setTable(f'(SELECT * FROM pgmetadata.export_datasets_as_flat_table(\'{locale}\'))')
|
uri.setKeyColumn('uid')
|
||||||
uri.setKeyColumn('uid')
|
|
||||||
|
layer = QgsVectorLayer(uri.uri(), '{} - {}'.format(tr("Catalog"), connection_name), 'postgres')
|
||||||
layer = QgsVectorLayer(uri.uri(), '{} - {}'.format(tr("Catalog"), connection_name), 'postgres')
|
QgsProject.instance().addMapLayer(layer)
|
||||||
QgsProject.instance().addMapLayer(layer)
|
'''
|
||||||
'''
|
|
||||||
|
@staticmethod
|
||||||
@staticmethod
|
def open_external_help():
|
||||||
def open_external_help():
|
QDesktopServices.openUrl(QUrl('https://plateformesig.cenra-outils.org/'))
|
||||||
QDesktopServices.openUrl(QUrl('https://plateformesig.cenra-outils.org/'))
|
|
||||||
|
@staticmethod
|
||||||
@staticmethod
|
def open_link(url):
|
||||||
def open_link(url):
|
QDesktopServices.openUrl(url)
|
||||||
QDesktopServices.openUrl(url)
|
|
||||||
|
def set_html_content(self, title=None, body=None):
|
||||||
def set_html_content(self, title=None, body=None):
|
""" Set the content in the dock. """
|
||||||
""" Set the content in the dock. """
|
#link_logo=resources_path('icons', 'CEN_RA.png')
|
||||||
#link_logo=resources_path('icons', 'CEN_RA.png')
|
css_file = resources_path('css', 'dock.css')
|
||||||
css_file = resources_path('css', 'dock.css')
|
with open(css_file, 'r', encoding='utf8') as f:
|
||||||
with open(css_file, 'r', encoding='utf8') as f:
|
css = f.read()
|
||||||
css = f.read()
|
|
||||||
|
html = '<html><head>'
|
||||||
html = '<html><head>'
|
#html += '<script src="http://ignf.github.io/geoportal-sdk/latest/dist/2d/GpSDK2D.js" defer ></script>'
|
||||||
#html += '<script src="http://ignf.github.io/geoportal-sdk/latest/dist/2d/GpSDK2D.js" defer ></script>'
|
html += '<style>{css}</style></head><body>'.format(css=css)
|
||||||
html += '<style>{css}</style></head><body>'.format(css=css)
|
#html += '<link rel="stylesheet" href="http://ignf.github.io/geoportal-sdk/latest/dist/2d/GpSDK2D.css" >'
|
||||||
#html += '<link rel="stylesheet" href="http://ignf.github.io/geoportal-sdk/latest/dist/2d/GpSDK2D.css" >'
|
#html += '<script src="file:///C:/Users/tlaveille/Desktop/maps.js" defer></script>'
|
||||||
#html += '<script src="file:///C:/Users/tlaveille/Desktop/maps.js" defer></script>'
|
#html += '<noscript>Your browser does not support JavaScript!</noscript>'
|
||||||
#html += '<noscript>Your browser does not support JavaScript!</noscript>'
|
if title:
|
||||||
if title:
|
html += '<h2>{title} <img class=logo src=https://i2.wp.com/www.cen-rhonealpes.fr/wp-content/uploads/2013/04/cen-rhonealpes-couleurs1.jpg?w=340&ssl=1></h2>'.format(title=title)
|
||||||
html += '<h2>{title} <img class=logo src=https://i2.wp.com/www.cen-rhonealpes.fr/wp-content/uploads/2013/04/cen-rhonealpes-couleurs1.jpg?w=340&ssl=1></h2>'.format(title=title)
|
if body:
|
||||||
if body:
|
html += body
|
||||||
html += body
|
|
||||||
|
html += '</body></html>'
|
||||||
html += '</body></html>'
|
|
||||||
|
# It must be a file, even if it does not exist on the file system.
|
||||||
# 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'))
|
||||||
base_url = QUrl.fromLocalFile(resources_path('images', 'must_be_a_file.png'))
|
self.viewer.setHtml(html, base_url)
|
||||||
self.viewer.setHtml(html, base_url)
|
|
||||||
|
def ce_trouve_dans_psql(self,layer):
|
||||||
def ce_trouve_dans_psql(self,layer):
|
try:
|
||||||
try:
|
uri = layer.dataProvider().uri()
|
||||||
uri = layer.dataProvider().uri()
|
except:
|
||||||
except:
|
self.default_html_content_not_pg_layer()
|
||||||
self.default_html_content_not_pg_layer()
|
self.save_button.setEnabled(False)
|
||||||
self.save_button.setEnabled(False)
|
uri=''
|
||||||
uri=''
|
if uri != '':
|
||||||
if uri != '':
|
if not uri.table():
|
||||||
if not uri.table():
|
layertype = layer.providerType().lower()
|
||||||
self.default_html_content_not_pg_layer()
|
if layertype == 'wms' or layertype == 'wfs':
|
||||||
self.save_button.setEnabled(False)
|
self.set_html_to_wms(layer)
|
||||||
else:
|
else:
|
||||||
data_count = self.sql_check(uri)
|
self.default_html_content_not_pg_layer()
|
||||||
#print(data_count)
|
self.save_button.setEnabled(False)
|
||||||
if data_count == 0:
|
else:
|
||||||
self.default_html_content_not_metadata()
|
data_count = self.sql_check(uri)
|
||||||
self.save_button.setEnabled(False)
|
#print(data_count)
|
||||||
else:
|
if data_count == 0:
|
||||||
self.build_html_content(layer,uri)
|
self.default_html_content_not_metadata()
|
||||||
self.save_button.setEnabled(True)
|
self.save_button.setEnabled(False)
|
||||||
|
else:
|
||||||
def build_html_content(self,layer,uri):
|
self.build_html_content(layer,uri)
|
||||||
body = ''
|
self.save_button.setEnabled(True)
|
||||||
|
|
||||||
dataall=self.sql_info(uri)
|
def build_html_content(self,layer,uri):
|
||||||
data=dataall[0]
|
body = ''
|
||||||
data_url=dataall[1]
|
|
||||||
data_contact=dataall[2]
|
dataall=self.sql_info(uri)
|
||||||
#print(len(data_url))
|
data=dataall[0]
|
||||||
data_collonne=[field.name() for field in layer.dataProvider().fields()]
|
data_url=dataall[1]
|
||||||
|
data_contact=dataall[2]
|
||||||
body += '<div><h3>Identification</h3><table class="table table-condensed">'
|
#print(len(data_url))
|
||||||
body += '<tr><th>Titre</th><td>{data[4]}</td></tr>'.format(data=data)
|
data_collonne=[field.name() for field in layer.dataProvider().fields()]
|
||||||
body += '<tr><th>Description</th><td>{data[5]}</td></tr>'.format(data=data)
|
|
||||||
body += '<tr><th>Categories</th><td>{data}</td></tr>'.format(data=(", ".join(str(x) for x in data[6])))
|
body += '<div><h3>Identification</h3><table class="table table-condensed">'
|
||||||
body += '<tr><th>Thèmes</th><td>{data}</td></tr>'.format(data=(", ".join(str(x) for x in data[24])))
|
body += '<tr><th>Titre</th><td>{data[4]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Mots-clés</th><td>{data[7]}</td></tr>'.format(data=data)
|
body += '<tr><th>Description</th><td>{data[5]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Dernier mise à jour</th><td>{data[23]}</td></tr>'.format(data=data)
|
body += '<tr><th>Categories</th><td>{data}</td></tr>'.format(data=(", ".join(str(x) for x in data[6])))
|
||||||
body += '<tr><th>Langue</th><td>{data[26]}</td></tr>'.format(data=data)
|
body += '<tr><th>Thèmes</th><td>{data}</td></tr>'.format(data=(", ".join(str(x) for x in data[24])))
|
||||||
body += '</table></div>'
|
body += '<tr><th>Mots-clés</th><td>{data[7]}</td></tr>'.format(data=data)
|
||||||
|
body += '<tr><th>Dernier mise à jour</th><td>{data[23]}</td></tr>'.format(data=data)
|
||||||
body += '<div><h3>Properties spatial</h3><table class="table table-condensed">'
|
body += '<tr><th>Langue</th><td>{data[26]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Niveau</th><td>{data[8]}</td></tr>'.format(data=data)
|
body += '</table></div>'
|
||||||
body += '<tr><th>Echelle minimum</th><td>{data[9]}</td></tr>'.format(data=data)
|
|
||||||
body += '<tr><th>Echelle maximum</th><td>{data[10]}</td></tr>'.format(data=data)
|
body += '<div><h3>Properties spatial</h3><table class="table table-condensed">'
|
||||||
body += '<tr><th>Nombre d\'entités </th><td>{data[15]}</td></tr>'.format(data=data)
|
body += '<tr><th>Niveau</th><td>{data[8]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Type de géométrie</th><td>{data[16]}</td></tr>'.format(data=data)
|
body += '<tr><th>Echelle minimum</th><td>{data[9]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Nom de projection</th><td>{data[17]}</td></tr>'.format(data=data)
|
body += '<tr><th>Echelle maximum</th><td>{data[10]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>ID de projection</th><td>{data[18]}</td></tr>'.format(data=data)
|
body += '<tr><th>Nombre d\'entités </th><td>{data[15]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Emprise</th><td>{data[28]}</td></tr>'.format(data=data)
|
body += '<tr><th>Type de géométrie</th><td>{data[16]}</td></tr>'.format(data=data)
|
||||||
body += '</table></div>'
|
body += '<tr><th>Nom de projection</th><td>{data[17]}</td></tr>'.format(data=data)
|
||||||
|
body += '<tr><th>ID de projection</th><td>{data[18]}</td></tr>'.format(data=data)
|
||||||
#body += '<div id="map"></div>'
|
body += '<tr><th>Emprise</th><td>{data[28]}</td></tr>'.format(data=data)
|
||||||
|
body += '</table></div>'
|
||||||
body += '<div><h3>Publication</h3><table class="table table-condensed">'
|
|
||||||
body += '<tr><th>Date</th><td>{data[11]}</td></tr>'.format(data=data)
|
#body += '<div id="map"></div>'
|
||||||
body += '<tr><th>Fréquence de mise à jour</th><td>{data[12]}</td></tr>'.format(data=data)
|
|
||||||
body += '<tr><th>Licence</th><td>{data[13]}</td></tr>'.format(data=data)
|
body += '<div><h3>Publication</h3><table class="table table-condensed">'
|
||||||
body += '<tr><th>Licence attribué</th><td>{data[25]}</td></tr>'.format(data=data)
|
body += '<tr><th>Date</th><td>{data[11]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Restriction</th><td>{data[14]}</td></tr>'.format(data=data)
|
body += '<tr><th>Fréquence de mise à jour</th><td>{data[12]}</td></tr>'.format(data=data)
|
||||||
body += '</table></div>'
|
body += '<tr><th>Licence</th><td>{data[13]}</td></tr>'.format(data=data)
|
||||||
|
body += '<tr><th>Licence attribué</th><td>{data[25]}</td></tr>'.format(data=data)
|
||||||
body += '<div><h3>Lien</h3><table class="table table-condensed table-striped table-bordered">'
|
body += '<tr><th>Restriction</th><td>{data[14]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Type</th><th>URL</th><th>Type MIME</th><th>Format</th><th>Taille</th></tr>'
|
body += '</table></div>'
|
||||||
for value_url in data_url:
|
|
||||||
body += '<tr><td>{value_url[0]}</td><td>{value_url[1]}</td><td>{value_url[2]}</td><td>{value_url[3]}</td><td>{value_url[4]}</td></tr>'.format(value_url=value_url)
|
body += '<div><h3>Lien</h3><table class="table table-condensed table-striped table-bordered">'
|
||||||
body += '</table></div>'
|
body += '<tr><th>Type</th><th>URL</th><th>Type MIME</th><th>Format</th><th>Taille</th></tr>'
|
||||||
'''
|
for value_url in data_url:
|
||||||
body += '<div><h3>Liste des champs</h3><table class="table table-condensed table-striped table-bordered">'
|
body += '<tr><td>{value_url[0]}</td><td>{value_url[1]}</td><td>{value_url[2]}</td><td>{value_url[3]}</td><td>{value_url[4]}</td></tr>'.format(value_url=value_url)
|
||||||
for collonne in data_collonne:
|
body += '</table></div>'
|
||||||
body += '<tr><th>{collonne}</th><td>{defini}</td></tr>'.format(collonne=collonne,defini='')
|
'''
|
||||||
body += '</table></div>'
|
body += '<div><h3>Liste des champs</h3><table class="table table-condensed table-striped table-bordered">'
|
||||||
'''
|
for collonne in data_collonne:
|
||||||
body += '<div><h3>Contacts</h3><table class="table table-condensed table-striped table-bordered">'
|
body += '<tr><th>{collonne}</th><td>{defini}</td></tr>'.format(collonne=collonne,defini='')
|
||||||
body += '<tr><th>Rôle</th><th>Nom</th><th>Organisation</th><th>Email</th><th>Télèphone</th></tr>'
|
body += '</table></div>'
|
||||||
for value_contact in data_contact:
|
'''
|
||||||
body += '<tr><td>{value_contact[0]}</td><td>{value_contact[1]}</td><td>{value_contact[2]}</td><td>{value_contact[3]}</td><td>{value_contact[4]}</td></tr>'.format(value_contact=value_contact)
|
body += '<div><h3>Contacts</h3><table class="table table-condensed table-striped table-bordered">'
|
||||||
body += '</table></div>'
|
body += '<tr><th>Rôle</th><th>Nom</th><th>Organisation</th><th>Email</th><th>Télèphone</th></tr>'
|
||||||
|
for value_contact in data_contact:
|
||||||
body += '<div><h3>Metadata</h3><table class="table table-condensed">'
|
body += '<tr><td>{value_contact[0]}</td><td>{value_contact[1]}</td><td>{value_contact[2]}</td><td>{value_contact[3]}</td><td>{value_contact[4]}</td></tr>'.format(value_contact=value_contact)
|
||||||
body += '<tr><th>Table</th><td>{data[2]}</td></tr>'.format(data=data)
|
body += '</table></div>'
|
||||||
body += '<tr><th>Schema</th><td>{data[3]}</td></tr>'.format(data=data)
|
|
||||||
body += '<tr><th>Date de création</th><td>{data[20]}</td></tr>'.format(data=data)
|
body += '<div><h3>Metadata</h3><table class="table table-condensed">'
|
||||||
body += '<tr><th>Date de modification</th><td>{data[21]}</td></tr>'.format(data=data)
|
body += '<tr><th>Table</th><td>{data[2]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>Encodage</th><td>{data[27]}</td></tr>'.format(data=data)
|
body += '<tr><th>Schema</th><td>{data[3]}</td></tr>'.format(data=data)
|
||||||
body += '<tr><th>UUID</th><td>{data[1]}</td></tr>'.format(data=data)
|
body += '<tr><th>Date de création</th><td>{data[20]}</td></tr>'.format(data=data)
|
||||||
body += '</table></div>'
|
body += '<tr><th>Date de modification</th><td>{data[21]}</td></tr>'.format(data=data)
|
||||||
|
body += '<tr><th>Encodage</th><td>{data[27]}</td></tr>'.format(data=data)
|
||||||
self.set_html_content(
|
body += '<tr><th>UUID</th><td>{data[1]}</td></tr>'.format(data=data)
|
||||||
layer.name(), body)
|
body += '</table></div>'
|
||||||
|
|
||||||
def default_html_content_not_pg_layer(self):
|
self.set_html_content(
|
||||||
""" When it's not a PostgreSQL layer. """
|
layer.name(), body)
|
||||||
self.set_html_content(
|
|
||||||
'CenRa Metadata', tr('Vous devez cliquer sur une couche dans la légende qui est stockée dans PostgreSQL.'))
|
def set_html_to_wms(self,layer):
|
||||||
def default_html_content_not_metadata(self):
|
self.set_html_content(
|
||||||
self.set_html_content(
|
'CenRa Metadata',(layer.htmlMetadata()))
|
||||||
'CenRa Metadata', tr('La couche ne contien pas de métadonnée.'))
|
def default_html_content_not_pg_layer(self):
|
||||||
|
""" When it's not a PostgreSQL layer. """
|
||||||
def sql_check(self,uri):
|
self.set_html_content(
|
||||||
cur=login_base()
|
'CenRa Metadata', ('Vous devez cliquer sur une couche dans la légende qui est stockée dans PostgreSQL.'))
|
||||||
table = uri.table()
|
def default_html_content_not_metadata(self):
|
||||||
schema = uri.schema()
|
self.set_html_content(
|
||||||
|
'CenRa Metadata', ('La couche ne contien pas de métadonnée.'))
|
||||||
sql_count = """SELECT count(uid) FROM metadata.dataset
|
|
||||||
WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
def sql_check(self,uri):
|
||||||
|
cur=login_base()
|
||||||
cur.execute(sql_count)
|
table = uri.table()
|
||||||
data_count = cur.fetchall()
|
schema = uri.schema()
|
||||||
cur.close()
|
|
||||||
return data_count[0][0]
|
sql_count = """SELECT count(uid) FROM metadata.dataset
|
||||||
|
WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
||||||
def sql_info(self,uri):
|
|
||||||
cur=login_base()
|
cur.execute(sql_count)
|
||||||
table = uri.table()
|
data_count = cur.fetchall()
|
||||||
schema = uri.schema()
|
cur.close()
|
||||||
#[s for s in iface.activeLayer().source().split(" ") if "dbname" in s][0].split("'")[1]
|
return data_count[0][0]
|
||||||
sql_find = """SELECT *,right(left(st_astext(geom,2),-2),-9) FROM metadata.dataset
|
|
||||||
WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
def sql_info(self,uri):
|
||||||
cur.execute(sql_find)
|
cur=login_base()
|
||||||
data_general = cur.fetchall()
|
table = uri.table()
|
||||||
sql_findurl = """SELECT type,url,mime,format,taille FROM metadata.dataurl WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
schema = uri.schema()
|
||||||
cur.execute(sql_findurl)
|
#[s for s in iface.activeLayer().source().split(" ") if "dbname" in s][0].split("'")[1]
|
||||||
data_url = cur.fetchall()
|
sql_find = """SELECT *,right(left(st_astext(geom,2),-2),-9) FROM metadata.dataset
|
||||||
sql_findcontact = """SELECT role,nom,organisation,email,telephone FROM metadata.datacontact WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
||||||
cur.execute(sql_findcontact)
|
cur.execute(sql_find)
|
||||||
data_contact = cur.fetchall()
|
data_general = cur.fetchall()
|
||||||
cur.close()
|
sql_findurl = """SELECT type,url,mime,format,taille FROM metadata.dataurl WHERE schema_name LIKE '"""+schema+"""' AND table_name LIKE '"""+table+"""';"""
|
||||||
return data_general[0],data_url,data_contact
|
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
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
name=CenRa_Metabase
|
name=CenRa_Metabase
|
||||||
qgisMinimumVersion=3.0
|
qgisMinimumVersion=3.0
|
||||||
description=CenRa_METABASE
|
description=CenRa_METABASE
|
||||||
version=1.2
|
version=1.3
|
||||||
author=Conservatoire d'Espaces Naturels de Rhône-Alpes
|
author=Conservatoire d'Espaces Naturels de Rhône-Alpes
|
||||||
email=si_besoin@cen-rhonealpes.fr
|
email=si_besoin@cen-rhonealpes.fr
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ tracker=https://gitea.cenra-outils.org/api/v1/repos/CEN-RA/Plugin_QGIS/issues
|
|||||||
|
|
||||||
hasProcessingProvider=no
|
hasProcessingProvider=no
|
||||||
# Uncomment the following line and add your changelog:
|
# Uncomment the following line and add your changelog:
|
||||||
changelog=<h2>CenRa_Metabase:</h2></br><p><h3>07/10/2024 - Version 1.2: </h3> - Correctif de bug.</p></br><p><h3>03/10/2024 - Version 1.1: </h3> - Remonte la fênetre dans la pille.</p></br><p><h3>26/08/2024 - Version 1.0: </h3> - Lancement du plugin CenRa_Metabase </p></br>
|
changelog=<h2>CenRa_Metabase:</h2></br><p><h3>08/10/2024 - Version 1.3: </h3> - Lecture de métadonnée des flux WMS/WFS.</p></br><p><h3>07/10/2024 - Version 1.2: </h3> - Correctif de bug.</p></br><p><h3>03/10/2024 - Version 1.1: </h3> - Remonte la fênetre dans la pille.</p></br><p><h3>26/08/2024 - Version 1.0: </h3> - Lancement du plugin CenRa_Metabase </p></br>
|
||||||
|
|
||||||
# Tags are comma separated with spaces allowed
|
# Tags are comma separated with spaces allowed
|
||||||
tags=python
|
tags=python
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user