diff --git a/orientation/i18n/en.ts b/orientation/i18n/en.ts
new file mode 100644
index 0000000..c86209d
--- /dev/null
+++ b/orientation/i18n/en.ts
@@ -0,0 +1,53 @@
+
+
+
+
+ Orientation
+
+
+ Large area
+
+
+
+ The area is too large, lower the scale below 1:20000
+
+
+
+ The area is large and the downloading might take time.
+Continue?
+
+
+
+ Select a working directory to save the QGIS project
+
+
+
+ Warning
+
+
+
+ You haven't installed QuickOSM extension
+
+
+
+ Loading
+
+
+
+ Gettin gonline data
+
+
+
+ Error
+
+
+
+ The following fields were duplicated and have been deleted using the lower-case field in priority:
+-
+ -
+
+
+
diff --git a/orientation/i18n/fr.ts b/orientation/i18n/fr.ts
deleted file mode 100644
index 739632b..0000000
--- a/orientation/i18n/fr.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- @default
-
-
-
- Bonjour
-
-
-
diff --git a/orientation/i18n/orientation.pro b/orientation/i18n/orientation.pro
new file mode 100644
index 0000000..1213997
--- /dev/null
+++ b/orientation/i18n/orientation.pro
@@ -0,0 +1,2 @@
+TRANSLATIONS = en.ts
+SOURCES = ../orientation.py
diff --git a/orientation/metadata.txt b/orientation/metadata.txt
index e8a4459..ac4d257 100644
--- a/orientation/metadata.txt
+++ b/orientation/metadata.txt
@@ -6,7 +6,7 @@
name=CaLiÉc
qgisMinimumVersion=3.0
description=Réaliser des cartes d’orientation
-version=2.1
+version=2.2
author=Association Linux-Alpes
email=caliec@linux-alpes.org
diff --git a/orientation/orientation.py b/orientation/orientation.py
index 4667ce2..9733d4b 100644
--- a/orientation/orientation.py
+++ b/orientation/orientation.py
@@ -20,27 +20,38 @@
* *
***************************************************************************/
"""
-from qgis.PyQt.QtCore import Qt, QSettings, QTranslator, QCoreApplication
-from qgis.PyQt.QtGui import QIcon
-from qgis.PyQt.QtWidgets import QAction, qApp, QFileDialog, QProgressBar, QMessageBox, QMenu, QToolButton
-
-from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransformContext, QgsProject, QgsVectorFileWriter, QgsVectorLayer, QgsFeatureRequest
-from qgis.utils import OverrideCursor
+import os.path
+import shutil
+import tempfile
+from pathlib import Path
+import processing
from processing import QgsProcessingException
-
+from processing.tools import dataobjects
+from qgis.core import (
+ QgsCoordinateReferenceSystem,
+ QgsCoordinateTransformContext,
+ QgsFeatureRequest,
+ QgsProject,
+ QgsVectorFileWriter,
+ QgsVectorLayer,
+)
+from qgis.PyQt.QtCore import QCoreApplication, QSettings, Qt, QTranslator, QUrl
+from qgis.PyQt.QtGui import QDesktopServices, QIcon
+from qgis.PyQt.QtWidgets import (
+ QAction,
+ QFileDialog,
+ QMenu,
+ QMessageBox,
+ QProgressBar,
+ QToolButton,
+ qApp,
+)
+from qgis.utils import OverrideCursor
# Initialize Qt resources from file resources.py
from .resources import *
-import processing
-import os.path
-import shutil
-import tempfile
-
-from pathlib import Path
-
-from processing.tools import dataobjects
class Orientation:
"""QGIS Plugin Implementation."""
@@ -58,11 +69,10 @@ class Orientation:
# initialize plugin directory
self.plugin_dir = os.path.dirname(__file__)
# initialize locale
- locale = QSettings().value('locale/userLocale')[0:2]
+ locale = QSettings().value("locale/userLocale")[0:2]
locale_path = os.path.join(
- self.plugin_dir,
- 'i18n',
- 'Orientation_{}.qm'.format(locale))
+ self.plugin_dir, "i18n", "Orientation_{}.qm".format(locale)
+ )
if os.path.exists(locale_path):
self.translator = QTranslator()
@@ -71,7 +81,7 @@ class Orientation:
# Declare instance attributes
self.actions = []
- self.menu = self.tr('CaLiEc')
+ self.menu = "CaLiÉc"
# Check if plugin was started the first time in current QGIS session
# Must be set in initGui() to survive plugin reloads
@@ -90,8 +100,7 @@ class Orientation:
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass
- return QCoreApplication.translate('Orientation', message)
-
+ return QCoreApplication.translate("Orientation", message)
def add_action(
self,
@@ -103,7 +112,8 @@ class Orientation:
add_to_toolbar=True,
status_tip=None,
whats_this=None,
- parent=None):
+ parent=None,
+ ):
"""Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource
@@ -159,9 +169,7 @@ class Orientation:
self.iface.addToolBarIcon(action)
if add_to_menu:
- self.iface.addPluginToMenu(
- self.menu,
- action)
+ self.iface.addPluginToMenu(self.menu, action)
self.actions.append(action)
@@ -170,38 +178,68 @@ class Orientation:
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI."""
- icon_path = ':/plugins/caliec/icon.png'
+ icon_path = ":/plugins/caliec/icon.png"
my_menu = QMenu()
- my_menu.addActions([self.add_action(icon_path=":/plugins/caliec/vignette_caliec", text=self.tr("Style CaLiÉc"), parent=my_menu,
- add_to_toolbar=False, add_to_menu=False,
- callback=lambda: self.run("style_caliec")),
- self.add_action(icon_path=":/plugins/caliec/vignette_kid", text=self.tr("Style kid"), parent=my_menu,
- add_to_toolbar=False, add_to_menu=False,
- callback=lambda: self.run("style_kid")),
- self.add_action(icon_path=":/plugins/caliec/vignette_jardin", text=self.tr("Style jardin"), parent=my_menu,
- add_to_toolbar=False, add_to_menu=False,
- callback=lambda: self.run("style_jardin"))])
+ my_menu.addActions(
+ [
+ self.add_action(
+ icon_path=":/plugins/caliec/vignette_caliec",
+ text=self.tr("Style CaLiÉc"),
+ parent=my_menu,
+ add_to_toolbar=False,
+ add_to_menu=False,
+ callback=lambda: self.run("style_caliec"),
+ ),
+ self.add_action(
+ icon_path=":/plugins/caliec/vignette_kid",
+ text=self.tr("Style kid"),
+ parent=my_menu,
+ add_to_toolbar=False,
+ add_to_menu=False,
+ callback=lambda: self.run("style_kid"),
+ ),
+ self.add_action(
+ icon_path=":/plugins/caliec/vignette_jardin",
+ text=self.tr("Style jardin"),
+ parent=my_menu,
+ add_to_toolbar=False,
+ add_to_menu=False,
+ callback=lambda: self.run("style_jardin"),
+ ),
+ ]
+ )
menu_action = self.add_action(
icon_path,
- text=self.tr('DEV - Créer le projet'),
+ text=self.tr("Créer le projet"),
callback=lambda: None,
- parent=self.iface.mainWindow())
+ parent=self.iface.mainWindow(),
+ )
menu_action.setMenu(my_menu)
- self.iface.pluginToolBar().widgetForAction(menu_action).setPopupMode(QToolButton.InstantPopup)
+ self.iface.pluginToolBar().widgetForAction(menu_action).setPopupMode(
+ QToolButton.InstantPopup
+ )
+
+ self.help_action = QAction(QIcon(icon_path), "CaLiÉc", self.iface.mainWindow())
+ self.iface.pluginHelpMenu().addAction(self.help_action)
+ self.help_action.triggered.connect(self.show_help)
# will be set False in run()
self.first_start = True
+ @staticmethod
+ def show_help():
+ QDesktopServices.openUrl(
+ QUrl("https://forge.chapril.org/linux_alpes/caliec/wiki/CaLi%C3%89c")
+ )
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions:
- self.iface.removePluginMenu(
- self.tr('CaLiÉc'),
- action)
+ self.iface.removePluginMenu("CaLiÉc", action)
self.iface.removeToolBarIcon(action)
-
+ self.iface.pluginHelpMenu().removeAction(self.help_action)
+ del self.help_action
def run(self, main_style):
try:
@@ -213,7 +251,7 @@ class Orientation:
def main(self, main_style):
# Paramètres du projet
tempdir = tempfile.TemporaryDirectory()
- styles_url = f'https://forge.chapril.org/linux_alpes/caliec/raw/branch/master/{main_style}/styles/'
+ styles_url = f"https://forge.chapril.org/linux_alpes/caliec/raw/branch/master/{main_style}/styles/"
lambert93 = QgsCoordinateReferenceSystem("EPSG:2154")
wgspm = QgsCoordinateReferenceSystem("EPSG:3857")
scr = wgspm
@@ -226,7 +264,13 @@ class Orientation:
context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)
if len(project.mapLayersByName("OpenStreetMap")) == 0:
- QMessageBox.warning(self.iface.mainWindow(), "Attention", "Affichez d'abord un fond Openstreetmap (menu XYZ tiles) et cadrez la zone voulue")
+ QMessageBox.warning(
+ self.iface.mainWindow(),
+ self.tr("Attention"),
+ self.tr(
+ "Affichez d'abord un fond Openstreetmap (menu XYZ tiles) et cadrez la zone voulue"
+ ),
+ )
return
# Correspondances des noms des couches et des styles:
@@ -234,31 +278,48 @@ class Orientation:
# Commenter les couches non désirées
# L'ordre impacte directement l'ordre final des couches
names = {
- #"OUTPUT_OTHER_RELATIONS": (None, "Autres"),
- "OUTPUT_MULTIPOLYGONS": ("multipolygon", "Surfaces"),
- #"OUTPUT_MULTILINESTRINGS": (None, "Multilignes"),
- "OUTPUT_LINES": ("linestring", "Lignes"),
- "OUTPUT_POINTS": ("point", "Points"),
- }
+ # "OUTPUT_OTHER_RELATIONS": (None, "Autres"),
+ "OUTPUT_MULTIPOLYGONS": ("multipolygon", "Surfaces"),
+ # "OUTPUT_MULTILINESTRINGS": (None, "Multilignes"),
+ "OUTPUT_LINES": ("linestring", "Lignes"),
+ "OUTPUT_POINTS": ("point", "Points"),
+ }
# Vérif de l'échelle
if self.iface.mapCanvas().scale() > 10000:
if self.iface.mapCanvas().scale() > 20000:
- QMessageBox.warning(self.iface.mainWindow(), "Zone étendue",
- "La zone est vraiment trop étendue, descendre en-dessous de 1:20000",
- QMessageBox.Ok)
+ QMessageBox.warning(
+ self.iface.mainWindow(),
+ self.tr("Zone étendue"),
+ self.tr(
+ "La zone est vraiment trop étendue, descendre en-dessous de 1:20000"
+ ),
+ QMessageBox.Ok,
+ )
return
- if QMessageBox.warning(self.iface.mainWindow(), "Zone étendue",
- "La zone est étendue et le téléchargement risque de prendre longtemps.\n"
- "Continuer ?",
- QMessageBox.Yes | QMessageBox.No) == QMessageBox.No:
+ if (
+ QMessageBox.warning(
+ self.iface.mainWindow(),
+ self.tr("Zone étendue"),
+ self.tr(
+ "La zone est étendue et le téléchargement risque de prendre longtemps.\n"
+ "Continuer ?"
+ ),
+ QMessageBox.Yes | QMessageBox.No,
+ )
+ == QMessageBox.No
+ ):
return
# Paramétrage du dossier de travail
settings = QSettings()
- dir = QFileDialog.getExistingDirectory(self.iface.mainWindow(),
- "Sélectionnez un dossier de travail",
- settings.value("caliec/workingDir"))
+ dir = QFileDialog.getExistingDirectory(
+ self.iface.mainWindow(),
+ self.tr(
+ "Sélectionnez un dossier de travail pour enregistrer le projet QGIS"
+ ),
+ settings.value("caliec/workingDir"),
+ )
if dir == "":
return
settings.setValue("caliec/workingDir", dir)
@@ -266,10 +327,16 @@ class Orientation:
# Construction de la requête overpass
try:
- url = processing.run("quickosm:buildqueryextent",
- parameters={"EXTENT": self.iface.mapCanvas().extent()})["OUTPUT_URL"]
+ url = processing.run(
+ "quickosm:buildqueryextent",
+ parameters={"EXTENT": self.iface.mapCanvas().extent()},
+ )["OUTPUT_URL"]
except QgsProcessingException:
- QMessageBox.warning(self.iface.mainWindow(), "Attention", "Vous n'avez pas installé l'extension QuickOSM")
+ QMessageBox.warning(
+ self.iface.mainWindow(),
+ self.tr("Attention"),
+ self.tr("Vous n'avez pas installé l'extension QuickOSM"),
+ )
return
# Barre de chargement animée
@@ -277,7 +344,9 @@ class Orientation:
message_bar = self.iface.messageBar()
progress_bar = QProgressBar()
progress_bar.setMaximum(0)
- widget = message_bar.createMessage("Chargement", "Récupération des data en ligne")
+ widget = message_bar.createMessage(
+ self.tr("Chargement"), self.tr("Récupération des data en ligne")
+ )
widget.layout().addWidget(progress_bar)
message_bar.pushWidget(widget)
@@ -290,18 +359,25 @@ class Orientation:
style_name, layer_name = style_layer_names
# On explose les champs
- layer = processing.run("native:explodehstorefield",
- parameters={"INPUT": layers[osm_name],
- "FIELD": "other_tags",
- "OUTPUT": "memory:"},
- context=context)["OUTPUT"]
+ layer = processing.run(
+ "native:explodehstorefield",
+ parameters={
+ "INPUT": layers[osm_name],
+ "FIELD": "other_tags",
+ "OUTPUT": "memory:",
+ },
+ context=context,
+ )["OUTPUT"]
# On enlève les champs en doublons en gardant celui des doublons qui est écrit tout en minuscule
field_names = [a.name() for a in layer.fields()]
field_names_lower = [a.lower() for a in field_names]
expected_fields, deleted_fields = [], []
for field_name, field_name_lower in zip(field_names, field_names_lower):
- if field_names_lower.count(field_name_lower) == 1 or field_name.lower() == field_name:
+ if (
+ field_names_lower.count(field_name_lower) == 1
+ or field_name.lower() == field_name
+ ):
expected_fields.append(field_name)
else:
deleted_fields.append(field_name)
@@ -309,30 +385,52 @@ class Orientation:
# S'il y a des doublons
if len(deleted_fields) > 0:
# On réexplose les champs sans doublons
- layer = processing.run("native:explodehstorefield",
- parameters={"INPUT": layers[osm_name],
- "FIELD": "other_tags",
- "OUTPUT": "memory:",
- "EXPECTED_FIELDS": ",".join(expected_fields)},
- context=context)["OUTPUT"]
+ layer = processing.run(
+ "native:explodehstorefield",
+ parameters={
+ "INPUT": layers[osm_name],
+ "FIELD": "other_tags",
+ "OUTPUT": "memory:",
+ "EXPECTED_FIELDS": ",".join(expected_fields),
+ },
+ context=context,
+ )["OUTPUT"]
# On enregistre le layer dans le gpkg
options.layerName = layer_name
- code, error = QgsVectorFileWriter.writeAsVectorFormatV2(layer, str(workDir / "data.gpkg"), QgsCoordinateTransformContext(), options)
+ code, error = QgsVectorFileWriter.writeAsVectorFormatV2(
+ layer,
+ str(workDir / "data.gpkg"),
+ QgsCoordinateTransformContext(),
+ options,
+ )
if code != 0:
with OverrideCursor(Qt.ArrowCursor):
- QMessageBox.warning(self.iface.mainWindow(), 'Erreur', f"Erreur à l'export de la couche {layer_name} : \n\n{error[:2000]}")
+ QMessageBox.warning(
+ self.iface.mainWindow(),
+ self.tr("Erreur"),
+ self.tr(
+ f"Erreur à l'export de la couche {layer_name} : \n\n{error[:2000]}"
+ ),
+ )
return
- new_layer = QgsVectorLayer(str(workDir / f"data.gpkg|layername={layer_name}"), layer_name)
+ new_layer = QgsVectorLayer(
+ str(workDir / f"data.gpkg|layername={layer_name}"), layer_name
+ )
# Les layers suivants seront enregistrés dans le gpkg déjà existant
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
# On charge le style
if style_name is not None:
- stylefile = str((Path(tempdir.name) / style_name).with_suffix('.qml'))
- processing.run("native:filedownloader",
- parameters={"URL": styles_url + f"{style_name}.qml", "OUTPUT": stylefile})
+ stylefile = str((Path(tempdir.name) / style_name).with_suffix(".qml"))
+ processing.run(
+ "native:filedownloader",
+ parameters={
+ "URL": styles_url + f"{style_name}.qml",
+ "OUTPUT": stylefile,
+ },
+ )
new_layer.loadNamedStyle(stylefile)
# On charge le nouveau layer
@@ -343,11 +441,15 @@ class Orientation:
except IndexError:
pass
self.iface.mapCanvas().refreshAllLayers()
- project.write(str(workDir / 'orient.qgs'))
+ project.write(str(workDir / "orient.qgs"))
if len(deleted_fields) > 0:
with OverrideCursor(Qt.ArrowCursor):
- QMessageBox.warning(self.iface.mainWindow(), "Attention",
- "Les champs suivants sont en doublons et ont été supprimés au profit de leur doublon en minuscule :\n- " +
- "\n - ".join(deleted_fields))
-
+ QMessageBox.warning(
+ self.iface.mainWindow(),
+ self.tr("Attention"),
+ self.tr(
+ "Les champs suivants sont en doublons et ont été supprimés au profit de leur doublon en minuscule :\n- "
+ + "\n - ".join(deleted_fields)
+ ),
+ )