From 1ab8ea8731ae168e691d15058510327986281925 Mon Sep 17 00:00:00 2001 From: Taku Fukada Date: Sun, 29 Oct 2023 10:57:37 +0900 Subject: [PATCH] Labeling in post-processing (#21) --- .../algorithms/create_grid_square.py | 72 +++++++++++------- .../algorithms/create_legacy_grid.py | 74 ++++++++++++------- 2 files changed, 93 insertions(+), 53 deletions(-) diff --git a/japanese_grids/algorithms/create_grid_square.py b/japanese_grids/algorithms/create_grid_square.py index f0d7ec1..6b27a07 100644 --- a/japanese_grids/algorithms/create_grid_square.py +++ b/japanese_grids/algorithms/create_grid_square.py @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from typing import Any, Optional, cast +from typing import Any from PyQt5.QtCore import QCoreApplication, QVariant from qgis.core import ( @@ -34,10 +34,12 @@ QgsProcessingContext, QgsProcessingException, # pyright: ignore QgsProcessingFeedback, + QgsProcessingLayerPostProcessorInterface, QgsProcessingParameterEnum, QgsProcessingParameterExtent, QgsProcessingParameterFeatureSink, - QgsVectorLayer, + QgsTextBufferSettings, + QgsTextFormat, QgsVectorLayerSimpleLabeling, QgsWkbTypes, ) @@ -126,6 +128,10 @@ class CreateGridSquareAlgorithm(QgsProcessingAlgorithm): EXTENT = "EXTENT" GEOGRAPHIC_CRS = "GEOGRAPHIC_CRS" + def __init__(self) -> None: + super().__init__() + self.post_processors = {key: LayerStyler(key) for key in _LAYERS} + def initAlgorithm(self, config=None): for layer_kind in _LAYERS.values(): self.addParameter( @@ -143,7 +149,7 @@ def initAlgorithm(self, config=None): self.GEOGRAPHIC_CRS, _tr("地理座標系"), options=[v["label"] for v in _CRS_SELECTION], - defaultValue=0, + defaultValue=1, ) ) @@ -173,7 +179,7 @@ def displayName(self): def shortHelpString(self) -> str: return _tr(_DESCRIPTION) - def processAlgorithm( # noqa: C901 + def processAlgorithm( self, parameters: dict[str, Any], context: QgsProcessingContext, @@ -228,6 +234,11 @@ def processAlgorithm( # noqa: C901 "1/4メッシュ、1/8メッシュを出力する場合は、思わぬ大量の地物生成を防ぐため、メッシュの作成範囲を指定する必要があります。" ) + # Set post-processor + if context.willLoadLayerOnCompletion(dest_id): + comp = context.layerToLoadOnCompletionDetails(dest_id) + comp.setPostProcessor(self.post_processors[layer_kind_name]) + if not sinks: raise QgsProcessingException( "地域メッシュの出力先が1つも選択されていません。\n利用したい地域メッシュの出力先を一時ファイルやファイルに切り替えて実行してください。" @@ -279,26 +290,35 @@ def processAlgorithm( # noqa: C901 feedback.setProgress(100) - # Label settings - for kind, dest_id in dest_ids.items(): - layer = cast( - Optional[QgsVectorLayer], - context.temporaryLayerStore().mapLayer(dest_id), - ) - if layer is None: - continue - layer_kind = _LAYERS[kind] - settings = QgsPalLayerSettings() - settings.fieldName = "code" - settings.placement = Qgis.LabelPlacement.OverPoint # type: ignore - settings.centroidInside = False - settings.centroidWhole = True - settings.scaleVisibility = True - settings.maximumScale = layer_kind["max_scale"] - settings.minimumScale = layer_kind["min_scale"] - labeling = QgsVectorLayerSimpleLabeling(settings) - layer.setOpacity(0.5) - layer.setLabeling(labeling) - layer.setLabelsEnabled(True) - return result + + +class LayerStyler(QgsProcessingLayerPostProcessorInterface): + def __init__(self, kind: str): + self._kind = kind + super().__init__() + + def postProcessLayer(self, layer, context, feedback): + if not layer.isValid(): + return + + layer_kind = _LAYERS[self._kind] + settings = QgsPalLayerSettings() + settings.fieldName = "code" + settings.placement = Qgis.LabelPlacement.OverPoint # type: ignore + settings.centroidInside = False + settings.centroidWhole = True + settings.scaleVisibility = True + format = QgsTextFormat() + buffer = QgsTextBufferSettings() + buffer.setEnabled(True) + buffer.setSize(1) + buffer.setOpacity(0.75) + format.setBuffer(buffer) + settings.setFormat(format) + settings.maximumScale = layer_kind["max_scale"] + settings.minimumScale = layer_kind["min_scale"] + labeling = QgsVectorLayerSimpleLabeling(settings) + layer.setOpacity(0.5) + layer.setLabeling(labeling) + layer.setLabelsEnabled(True) diff --git a/japanese_grids/algorithms/create_legacy_grid.py b/japanese_grids/algorithms/create_legacy_grid.py index cd65900..87c4a5f 100644 --- a/japanese_grids/algorithms/create_legacy_grid.py +++ b/japanese_grids/algorithms/create_legacy_grid.py @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from typing import Any, List, Optional, TypedDict, cast +from typing import Any, List, TypedDict from PyQt5.QtCore import QCoreApplication, QVariant from qgis.core import ( @@ -32,12 +32,14 @@ QgsProcessing, QgsProcessingAlgorithm, QgsProcessingContext, - QgsProcessingException, # pyright: ignore + QgsProcessingException, # pyright: ignore # pyright: ignore QgsProcessingFeedback, + QgsProcessingLayerPostProcessorInterface, QgsProcessingParameterEnum, QgsProcessingParameterExtent, QgsProcessingParameterFeatureSink, - QgsVectorLayer, + QgsTextBufferSettings, + QgsTextFormat, QgsVectorLayerSimpleLabeling, QgsWkbTypes, ) @@ -261,6 +263,10 @@ class CreateLegacyGridAlgorithm(QgsProcessingAlgorithm): DATUM_NO = "DATUM" PLANE_RECTANGULAR_NO = "PLANE_RECTANGULAR_NO" + def __init__(self) -> None: + super().__init__() + self.post_processors = {key: LayerStyler(key) for key in _LAYERS} + def initAlgorithm(self, config=None): for layer_kind in _LAYERS.values(): self.addParameter( @@ -287,7 +293,7 @@ def initAlgorithm(self, config=None): self.DATUM_NO, _tr("測地系"), options=[v["label"] for v in _DATUM_SELECTION], - defaultValue=0, + defaultValue=1, ) ) @@ -317,7 +323,7 @@ def displayName(self): def shortHelpString(self) -> str: return _tr(_DESCRIPTION) - def processAlgorithm( # noqa: C901 + def processAlgorithm( self, parameters: dict[str, Any], context: QgsProcessingContext, @@ -379,6 +385,11 @@ def processAlgorithm( # noqa: C901 "地図情報レベル 1000, 500 を出力する場合は、思わぬ大量の地物生成を防ぐため、メッシュの作成範囲を指定する必要があります。" ) + # Set post-processor + if context.willLoadLayerOnCompletion(dest_id): + comp = context.layerToLoadOnCompletionDetails(dest_id) + comp.setPostProcessor(self.post_processors[layer_kind_name]) + if not sinks: raise QgsProcessingException( "地図情報レベルの出力先が1つも選択されていません。\n利用したい地図情報レベルの出力先を一時ファイルやファイルに切り替えて実行してください。" @@ -429,26 +440,35 @@ def processAlgorithm( # noqa: C901 feedback.setProgress(100) - # Label settings - for kind, dest_id in dest_ids.items(): - layer = cast( - Optional[QgsVectorLayer], - context.temporaryLayerStore().mapLayer(dest_id), - ) - if layer is None: - continue - layer_kind = _LAYERS[kind] - settings = QgsPalLayerSettings() - settings.fieldName = "code" - settings.placement = Qgis.LabelPlacement.OverPoint # type: ignore - settings.centroidInside = False - settings.centroidWhole = True - settings.scaleVisibility = True - settings.maximumScale = layer_kind["max_scale"] - settings.minimumScale = layer_kind["min_scale"] - labeling = QgsVectorLayerSimpleLabeling(settings) - layer.setOpacity(0.5) - layer.setLabeling(labeling) - layer.setLabelsEnabled(True) - return result + + +class LayerStyler(QgsProcessingLayerPostProcessorInterface): + def __init__(self, kind: str): + self._kind = kind + super().__init__() + + def postProcessLayer(self, layer, context, feedback): + if not layer.isValid(): + return + + layer_kind = _LAYERS[self._kind] + settings = QgsPalLayerSettings() + settings.fieldName = "code" + settings.placement = Qgis.LabelPlacement.OverPoint # type: ignore + settings.centroidInside = False + settings.centroidWhole = True + settings.scaleVisibility = True + format = QgsTextFormat() + buffer = QgsTextBufferSettings() + buffer.setEnabled(True) + buffer.setSize(1) + buffer.setOpacity(0.75) + format.setBuffer(buffer) + settings.setFormat(format) + settings.maximumScale = layer_kind["max_scale"] + settings.minimumScale = layer_kind["min_scale"] + labeling = QgsVectorLayerSimpleLabeling(settings) + layer.setOpacity(0.5) + layer.setLabeling(labeling) + layer.setLabelsEnabled(True)