Ajout des traductions anglaises, formattage du code

This commit is contained in:
Jacky Volpes 2021-09-01 15:49:57 +02:00
parent b8ffd46a70
commit b823b462b0
5 changed files with 246 additions and 100 deletions

53
orientation/i18n/en.ts Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US" sourcelanguage="fr_FR">
<context>
<name>Orientation</name>
<message>
<source>Zone étendue</source>
<translation>Large area</translation>
</message>
<message>
<source>La zone est vraiment trop étendue, descendre en-dessous de 1:20000</source>
<translation>The area is too large, lower the scale below 1:20000</translation>
</message>
<message>
<source>La zone est étendue et le téléchargement risque de prendre longtemps.
Continuer ?</source>
<translation>The area is large and the downloading might take time.
Continue?</translation>
</message>
<message>
<source>Sélectionnez un dossier de travail pour enregistrer le projet QGIS</source>
<translation>Select a working directory to save the QGIS project</translation>
</message>
<message>
<source>Attention</source>
<translation>Warning</translation>
</message>
<message>
<source>Vous n&apos;avez pas installé l&apos;extension QuickOSM</source>
<translation>You haven&apos;t installed QuickOSM extension</translation>
</message>
<message>
<source>Chargement</source>
<translation>Loading</translation>
</message>
<message>
<source>Récupération des data en ligne</source>
<translation>Gettin gonline data</translation>
</message>
<message>
<source>Erreur</source>
<translation>Error</translation>
</message>
<message>
<source>Les champs suivants sont en doublons et ont é supprimés au profit de leur doublon en minuscule :
-
- </source>
<translation>The following fields were duplicated and have been deleted using the lower-case field in priority:
-
- </translation>
</message>
</context>
</TS>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0" language="fr" sourcelanguage="en">
<context>
<name>@default</name>
<message>
<location filename="test_translations.py" line="48"/>
<source>Good morning</source>
<translation>Bonjour</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,2 @@
TRANSLATIONS = en.ts
SOURCES = ../orientation.py

View File

@ -6,7 +6,7 @@
name=CaLiÉc name=CaLiÉc
qgisMinimumVersion=3.0 qgisMinimumVersion=3.0
description=Réaliser des cartes dorientation description=Réaliser des cartes dorientation
version=2.1 version=2.2
author=Association Linux-Alpes author=Association Linux-Alpes
email=caliec@linux-alpes.org email=caliec@linux-alpes.org

View File

@ -20,27 +20,38 @@
* * * *
***************************************************************************/ ***************************************************************************/
""" """
from qgis.PyQt.QtCore import Qt, QSettings, QTranslator, QCoreApplication import os.path
from qgis.PyQt.QtGui import QIcon import shutil
from qgis.PyQt.QtWidgets import QAction, qApp, QFileDialog, QProgressBar, QMessageBox, QMenu, QToolButton import tempfile
from pathlib import Path
from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransformContext, QgsProject, QgsVectorFileWriter, QgsVectorLayer, QgsFeatureRequest
from qgis.utils import OverrideCursor
import processing
from processing import QgsProcessingException 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 # Initialize Qt resources from file resources.py
from .resources import * from .resources import *
import processing
import os.path
import shutil
import tempfile
from pathlib import Path
from processing.tools import dataobjects
class Orientation: class Orientation:
"""QGIS Plugin Implementation.""" """QGIS Plugin Implementation."""
@ -58,11 +69,10 @@ class Orientation:
# initialize plugin directory # initialize plugin directory
self.plugin_dir = os.path.dirname(__file__) self.plugin_dir = os.path.dirname(__file__)
# initialize locale # initialize locale
locale = QSettings().value('locale/userLocale')[0:2] locale = QSettings().value("locale/userLocale")[0:2]
locale_path = os.path.join( locale_path = os.path.join(
self.plugin_dir, self.plugin_dir, "i18n", "Orientation_{}.qm".format(locale)
'i18n', )
'Orientation_{}.qm'.format(locale))
if os.path.exists(locale_path): if os.path.exists(locale_path):
self.translator = QTranslator() self.translator = QTranslator()
@ -71,7 +81,7 @@ class Orientation:
# Declare instance attributes # Declare instance attributes
self.actions = [] self.actions = []
self.menu = self.tr('CaLiEc') self.menu = "CaLiÉc"
# Check if plugin was started the first time in current QGIS session # Check if plugin was started the first time in current QGIS session
# Must be set in initGui() to survive plugin reloads # Must be set in initGui() to survive plugin reloads
@ -90,8 +100,7 @@ class Orientation:
:rtype: QString :rtype: QString
""" """
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
return QCoreApplication.translate('Orientation', message) return QCoreApplication.translate("Orientation", message)
def add_action( def add_action(
self, self,
@ -103,7 +112,8 @@ class Orientation:
add_to_toolbar=True, add_to_toolbar=True,
status_tip=None, status_tip=None,
whats_this=None, whats_this=None,
parent=None): parent=None,
):
"""Add a toolbar icon to the toolbar. """Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource :param icon_path: Path to the icon for this action. Can be a resource
@ -159,9 +169,7 @@ class Orientation:
self.iface.addToolBarIcon(action) self.iface.addToolBarIcon(action)
if add_to_menu: if add_to_menu:
self.iface.addPluginToMenu( self.iface.addPluginToMenu(self.menu, action)
self.menu,
action)
self.actions.append(action) self.actions.append(action)
@ -170,38 +178,68 @@ class Orientation:
def initGui(self): def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI.""" """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 = QMenu()
my_menu.addActions([self.add_action(icon_path=":/plugins/caliec/vignette_caliec", text=self.tr("Style CaLiÉc"), parent=my_menu, my_menu.addActions(
add_to_toolbar=False, add_to_menu=False, [
callback=lambda: self.run("style_caliec")), self.add_action(
self.add_action(icon_path=":/plugins/caliec/vignette_kid", text=self.tr("Style kid"), parent=my_menu, icon_path=":/plugins/caliec/vignette_caliec",
add_to_toolbar=False, add_to_menu=False, text=self.tr("Style CaLiÉc"),
callback=lambda: self.run("style_kid")), parent=my_menu,
self.add_action(icon_path=":/plugins/caliec/vignette_jardin", text=self.tr("Style jardin"), parent=my_menu, add_to_toolbar=False,
add_to_toolbar=False, add_to_menu=False, add_to_menu=False,
callback=lambda: self.run("style_jardin"))]) 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( menu_action = self.add_action(
icon_path, icon_path,
text=self.tr('DEV - Créer le projet'), text=self.tr("Créer le projet"),
callback=lambda: None, callback=lambda: None,
parent=self.iface.mainWindow()) parent=self.iface.mainWindow(),
)
menu_action.setMenu(my_menu) 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() # will be set False in run()
self.first_start = True 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): def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI.""" """Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions: for action in self.actions:
self.iface.removePluginMenu( self.iface.removePluginMenu("CaLiÉc", action)
self.tr('CaLiÉc'),
action)
self.iface.removeToolBarIcon(action) self.iface.removeToolBarIcon(action)
self.iface.pluginHelpMenu().removeAction(self.help_action)
del self.help_action
def run(self, main_style): def run(self, main_style):
try: try:
@ -213,7 +251,7 @@ class Orientation:
def main(self, main_style): def main(self, main_style):
# Paramètres du projet # Paramètres du projet
tempdir = tempfile.TemporaryDirectory() 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") lambert93 = QgsCoordinateReferenceSystem("EPSG:2154")
wgspm = QgsCoordinateReferenceSystem("EPSG:3857") wgspm = QgsCoordinateReferenceSystem("EPSG:3857")
scr = wgspm scr = wgspm
@ -226,7 +264,13 @@ class Orientation:
context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)
if len(project.mapLayersByName("OpenStreetMap")) == 0: 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 return
# Correspondances des noms des couches et des styles: # Correspondances des noms des couches et des styles:
@ -234,9 +278,9 @@ class Orientation:
# Commenter les couches non désirées # Commenter les couches non désirées
# L'ordre impacte directement l'ordre final des couches # L'ordre impacte directement l'ordre final des couches
names = { names = {
#"OUTPUT_OTHER_RELATIONS": (None, "Autres"), # "OUTPUT_OTHER_RELATIONS": (None, "Autres"),
"OUTPUT_MULTIPOLYGONS": ("multipolygon", "Surfaces"), "OUTPUT_MULTIPOLYGONS": ("multipolygon", "Surfaces"),
#"OUTPUT_MULTILINESTRINGS": (None, "Multilignes"), # "OUTPUT_MULTILINESTRINGS": (None, "Multilignes"),
"OUTPUT_LINES": ("linestring", "Lignes"), "OUTPUT_LINES": ("linestring", "Lignes"),
"OUTPUT_POINTS": ("point", "Points"), "OUTPUT_POINTS": ("point", "Points"),
} }
@ -244,21 +288,38 @@ class Orientation:
# Vérif de l'échelle # Vérif de l'échelle
if self.iface.mapCanvas().scale() > 10000: if self.iface.mapCanvas().scale() > 10000:
if self.iface.mapCanvas().scale() > 20000: if self.iface.mapCanvas().scale() > 20000:
QMessageBox.warning(self.iface.mainWindow(), "Zone étendue", QMessageBox.warning(
"La zone est vraiment trop étendue, descendre en-dessous de 1:20000", self.iface.mainWindow(),
QMessageBox.Ok) self.tr("Zone étendue"),
self.tr(
"La zone est vraiment trop étendue, descendre en-dessous de 1:20000"
),
QMessageBox.Ok,
)
return return
if QMessageBox.warning(self.iface.mainWindow(), "Zone étendue", 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" "La zone est étendue et le téléchargement risque de prendre longtemps.\n"
"Continuer ?", "Continuer ?"
QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: ),
QMessageBox.Yes | QMessageBox.No,
)
== QMessageBox.No
):
return return
# Paramétrage du dossier de travail # Paramétrage du dossier de travail
settings = QSettings() settings = QSettings()
dir = QFileDialog.getExistingDirectory(self.iface.mainWindow(), dir = QFileDialog.getExistingDirectory(
"Sélectionnez un dossier de travail", self.iface.mainWindow(),
settings.value("caliec/workingDir")) self.tr(
"Sélectionnez un dossier de travail pour enregistrer le projet QGIS"
),
settings.value("caliec/workingDir"),
)
if dir == "": if dir == "":
return return
settings.setValue("caliec/workingDir", dir) settings.setValue("caliec/workingDir", dir)
@ -266,10 +327,16 @@ class Orientation:
# Construction de la requête overpass # Construction de la requête overpass
try: try:
url = processing.run("quickosm:buildqueryextent", url = processing.run(
parameters={"EXTENT": self.iface.mapCanvas().extent()})["OUTPUT_URL"] "quickosm:buildqueryextent",
parameters={"EXTENT": self.iface.mapCanvas().extent()},
)["OUTPUT_URL"]
except QgsProcessingException: 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 return
# Barre de chargement animée # Barre de chargement animée
@ -277,7 +344,9 @@ class Orientation:
message_bar = self.iface.messageBar() message_bar = self.iface.messageBar()
progress_bar = QProgressBar() progress_bar = QProgressBar()
progress_bar.setMaximum(0) 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) widget.layout().addWidget(progress_bar)
message_bar.pushWidget(widget) message_bar.pushWidget(widget)
@ -290,18 +359,25 @@ class Orientation:
style_name, layer_name = style_layer_names style_name, layer_name = style_layer_names
# On explose les champs # On explose les champs
layer = processing.run("native:explodehstorefield", layer = processing.run(
parameters={"INPUT": layers[osm_name], "native:explodehstorefield",
parameters={
"INPUT": layers[osm_name],
"FIELD": "other_tags", "FIELD": "other_tags",
"OUTPUT": "memory:"}, "OUTPUT": "memory:",
context=context)["OUTPUT"] },
context=context,
)["OUTPUT"]
# On enlève les champs en doublons en gardant celui des doublons qui est écrit tout en minuscule # 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 = [a.name() for a in layer.fields()]
field_names_lower = [a.lower() for a in field_names] field_names_lower = [a.lower() for a in field_names]
expected_fields, deleted_fields = [], [] expected_fields, deleted_fields = [], []
for field_name, field_name_lower in zip(field_names, field_names_lower): 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) expected_fields.append(field_name)
else: else:
deleted_fields.append(field_name) deleted_fields.append(field_name)
@ -309,30 +385,52 @@ class Orientation:
# S'il y a des doublons # S'il y a des doublons
if len(deleted_fields) > 0: if len(deleted_fields) > 0:
# On réexplose les champs sans doublons # On réexplose les champs sans doublons
layer = processing.run("native:explodehstorefield", layer = processing.run(
parameters={"INPUT": layers[osm_name], "native:explodehstorefield",
parameters={
"INPUT": layers[osm_name],
"FIELD": "other_tags", "FIELD": "other_tags",
"OUTPUT": "memory:", "OUTPUT": "memory:",
"EXPECTED_FIELDS": ",".join(expected_fields)}, "EXPECTED_FIELDS": ",".join(expected_fields),
context=context)["OUTPUT"] },
context=context,
)["OUTPUT"]
# On enregistre le layer dans le gpkg # On enregistre le layer dans le gpkg
options.layerName = layer_name 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: if code != 0:
with OverrideCursor(Qt.ArrowCursor): 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 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 # Les layers suivants seront enregistrés dans le gpkg déjà existant
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
# On charge le style # On charge le style
if style_name is not None: if style_name is not None:
stylefile = str((Path(tempdir.name) / style_name).with_suffix('.qml')) stylefile = str((Path(tempdir.name) / style_name).with_suffix(".qml"))
processing.run("native:filedownloader", processing.run(
parameters={"URL": styles_url + f"{style_name}.qml", "OUTPUT": stylefile}) "native:filedownloader",
parameters={
"URL": styles_url + f"{style_name}.qml",
"OUTPUT": stylefile,
},
)
new_layer.loadNamedStyle(stylefile) new_layer.loadNamedStyle(stylefile)
# On charge le nouveau layer # On charge le nouveau layer
@ -343,11 +441,15 @@ class Orientation:
except IndexError: except IndexError:
pass pass
self.iface.mapCanvas().refreshAllLayers() self.iface.mapCanvas().refreshAllLayers()
project.write(str(workDir / 'orient.qgs')) project.write(str(workDir / "orient.qgs"))
if len(deleted_fields) > 0: if len(deleted_fields) > 0:
with OverrideCursor(Qt.ArrowCursor): with OverrideCursor(Qt.ArrowCursor):
QMessageBox.warning(self.iface.mainWindow(), "Attention", QMessageBox.warning(
"Les champs suivants sont en doublons et ont été supprimés au profit de leur doublon en minuscule :\n- " + self.iface.mainWindow(),
"\n - ".join(deleted_fields)) 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)
),
)