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
qgisMinimumVersion=3.0
description=Réaliser des cartes dorientation
version=2.1
version=2.2
author=Association Linux-Alpes
email=caliec@linux-alpes.org

View File

@ -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)
),
)