From 3cc814c037a6c5257c3186ce924552cd43b0d8ed Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Fri, 4 Oct 2024 21:49:52 +0200 Subject: [PATCH 1/8] move settings to QGIS API --- .../core/filters/swiss_locator_filter.py | 30 +++-- .../filters/swiss_locator_filter_feature.py | 5 +- .../filters/swiss_locator_filter_layer.py | 5 +- .../filters/swiss_locator_filter_location.py | 5 +- .../swiss_locator_filter_vector_tiles.py | 33 +++-- .../core/filters/swiss_locator_filter_wmts.py | 20 ++- swiss_locator/core/language.py | 11 +- swiss_locator/core/settings.py | 120 +++++++++--------- swiss_locator/gui/config_dialog.py | 38 +++--- swiss_locator/map_geo_admin/layers.py | 4 +- swiss_locator/metadata.txt | 3 + swiss_locator/swiss_locator_plugin.py | 19 ++- 12 files changed, 170 insertions(+), 123 deletions(-) diff --git a/swiss_locator/core/filters/swiss_locator_filter.py b/swiss_locator/core/filters/swiss_locator_filter.py index 85a0899..eed53de 100644 --- a/swiss_locator/core/filters/swiss_locator_filter.py +++ b/swiss_locator/core/filters/swiss_locator_filter.py @@ -120,7 +120,9 @@ def __init__( self.minimum_search_length = 2 self.nam = QNetworkAccessManager() - self.nam.setRedirectPolicy(QNetworkRequest.RedirectPolicy.NoLessSafeRedirectPolicy) + self.nam.setRedirectPolicy( + QNetworkRequest.RedirectPolicy.NoLessSafeRedirectPolicy + ) self.network_replies = dict() if crs: @@ -133,7 +135,9 @@ def __init__( self.map_canvas = iface.mapCanvas() self.map_canvas.destinationCrsChanged.connect(self.create_transforms) - self.rubber_band = QgsRubberBand(self.map_canvas, QgsWkbTypes.GeometryType.PointGeometry) + self.rubber_band = QgsRubberBand( + self.map_canvas, QgsWkbTypes.GeometryType.PointGeometry + ) self.rubber_band.setColor(QColor(255, 255, 50, 200)) self.rubber_band.setIcon(self.rubber_band.ICON_CIRCLE) self.rubber_band.setIconSize(15) @@ -155,7 +159,7 @@ def name(self): return self.__class__.__name__ def priority(self): - return self.settings.value(f"{self.type.value}_priority") + return QgsLocatorFilter.Priority.Medium def displayName(self): # this should be re-implemented @@ -185,20 +189,20 @@ def hasConfigWidget(self): def openConfigWidget(self, parent=None): dlg = ConfigDialog(parent) - wid = dlg.findChild(QTabWidget, "tabWidget", Qt.FindChildOption.FindDirectChildrenOnly) + wid = dlg.findChild( + QTabWidget, "tabWidget", Qt.FindChildOption.FindDirectChildrenOnly + ) tab = wid.findChild(QWidget, self.type.value) wid.setCurrentWidget(tab) dlg.exec() def create_transforms(self): # this should happen in the main thread - self.crs = self.settings.value("crs") - if self.crs == "project": - map_crs = self.map_canvas.mapSettings().destinationCrs() - if map_crs.isValid() and ":" in map_crs.authid(): - self.crs = map_crs.authid().split(":")[1] - if self.crs not in AVAILABLE_CRS: - self.crs = "2056" + map_crs = self.map_canvas.mapSettings().destinationCrs() + if map_crs.isValid() and ":" in map_crs.authid(): + self.crs = map_crs.authid().split(":")[1] + if self.crs not in AVAILABLE_CRS: + self.crs = "2056" assert self.crs in AVAILABLE_CRS src_crs_ch = QgsCoordinateReferenceSystem("EPSG:{}".format(self.crs)) assert src_crs_ch.isValid() @@ -421,7 +425,7 @@ def triggerResult(self, result: QgsLocatorResult): point = QgsGeometry.fromPointXY(swiss_result.point) point.transform(self.transform_4326) self.highlight(point) - if self.settings.value("show_map_tip") and with_qt_web_kit(): + if self.settings.show_map_tip.value() and with_qt_web_kit(): self.show_map_tip(swiss_result.layer, swiss_result.feature_id, point) # Vector tiles @@ -519,7 +523,7 @@ def triggerResult(self, result: QgsLocatorResult): if layer and feature_id: self.fetch_feature(layer, feature_id) - if self.settings.value("show_map_tip") and with_qt_web_kit(): + if self.settings.show_map_tip.value() and with_qt_web_kit(): self.show_map_tip(layer, feature_id, point) else: self.current_timer = QTimer() diff --git a/swiss_locator/core/filters/swiss_locator_filter_feature.py b/swiss_locator/core/filters/swiss_locator_filter_feature.py index fd1085c..b3772fe 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_feature.py +++ b/swiss_locator/core/filters/swiss_locator_filter_feature.py @@ -53,12 +53,15 @@ def displayName(self): def prefix(self): return "chf" + def priority(self): + return self.settings.filter_feature_priority.value() + def perform_fetch_results(self, search: str, feedback: QgsFeedback): # Feature search is split in several requests # otherwise URL is too long requests = [] try: - limit = self.settings.value(f"{FilterType.Feature.value}_limit") + limit = self.settings.filter_feature_limit.value() layers = list(self.searchable_layers.keys()) assert len(layers) > 0 step = 20 diff --git a/swiss_locator/core/filters/swiss_locator_filter_layer.py b/swiss_locator/core/filters/swiss_locator_filter_layer.py index 524b789..6dd2e6f 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_layer.py +++ b/swiss_locator/core/filters/swiss_locator_filter_layer.py @@ -52,8 +52,11 @@ def displayName(self): def prefix(self): return "chl" + def priority(self): + return self.settings.filter_layers_priority.value() + def perform_fetch_results(self, search: str, feedback: QgsFeedback): - limit = self.settings.value(f"{FilterType.Location.value}_limit") + limit = self.settings.filter_layers_limit.value() urls = [ map_geo_admin_url(search, self.type.value, self.crs, self.lang, limit), opendata_swiss_url(search), diff --git a/swiss_locator/core/filters/swiss_locator_filter_location.py b/swiss_locator/core/filters/swiss_locator_filter_location.py index 7d24e61..8fbfb88 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_location.py +++ b/swiss_locator/core/filters/swiss_locator_filter_location.py @@ -57,8 +57,11 @@ def displayName(self): def prefix(self): return "chs" + def priority(self): + return self.settings.filter_location_priority.value() + def perform_fetch_results(self, search: str, feedback: QgsFeedback): - limit = self.settings.value(f"{FilterType.Location.value}_limit") + limit = self.settings.filter_location_limit.value() url, params = map_geo_admin_url( search, self.type.value, self.crs, self.lang, limit ) diff --git a/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py b/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py index cc8b937..5b0dd86 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py +++ b/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py @@ -1,8 +1,6 @@ from qgis.gui import QgisInterface from qgis.core import ( QgsApplication, - QgsBlockingNetworkRequest, - QgsFetchedContent, QgsLocatorResult, QgsFeedback, ) @@ -29,6 +27,9 @@ def displayName(self): def prefix(self): return "chb" + def priority(self): + return self.settings.filter_vt_priority.value() + def hasConfigWidget(self): return False @@ -38,27 +39,31 @@ def perform_fetch_results(self, search: str, feedback: QgsFeedback): "title": "Base map", "description": "", "url": "https://vectortiles.geo.admin.ch/tiles/ch.swisstopo.base.vt/v1.0.0/{z}/{x}/{y}.pbf", - "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.basemap.vt/style.json" + "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.basemap.vt/style.json", }, "light base map": { - "title": "Light base map", "description": "", + "title": "Light base map", + "description": "", "url": "https://vectortiles.geo.admin.ch/tiles/ch.swisstopo.base.vt/v1.0.0/{z}/{x}/{y}.pbf", - "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.lightbasemap.vt/style.json" + "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.lightbasemap.vt/style.json", }, "imagery base map": { - "title": "Imagery base map", "description": "", + "title": "Imagery base map", + "description": "", "url": "https://vectortiles.geo.admin.ch/tiles/ch.swisstopo.base.vt/v1.0.0/{z}/{x}/{y}.pbf", - "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.imagerybasemap.vt/style.json" + "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.imagerybasemap.vt/style.json", }, "leichte-basiskarte": { - "title": "leichte-basiskarte", "description": "", + "title": "leichte-basiskarte", + "description": "", "url": "https://vectortiles.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v3.0.1/{z}/{x}/{y}.pbf", - "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte.vt/style.json" + "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte.vt/style.json", }, "leichte-basiskarte-imagery": { - "title": "leichte-basiskarte-imagery", "description": "", + "title": "leichte-basiskarte-imagery", + "description": "", "url": "https://vectortiles.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v3.0.1/{z}/{x}/{y}.pbf", - "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte-imagery.vt/style.json" + "style": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte-imagery.vt/style.json", }, } @@ -68,7 +73,9 @@ def perform_fetch_results(self, search: str, feedback: QgsFeedback): if not search or search.lower() in keyword: result = QgsLocatorResult() result.filter = self - result.icon = QgsApplication.getThemeIcon("/mActionAddVectorTileLayer.svg") + result.icon = QgsApplication.getThemeIcon( + "/mActionAddVectorTileLayer.svg" + ) result.displayString = data[keyword]["title"] result.description = data[keyword]["description"] @@ -82,7 +89,7 @@ def perform_fetch_results(self, search: str, feedback: QgsFeedback): results[result] = score # sort the results with score - #results = sorted([result for (result, score) in results.items()]) + # results = sorted([result for (result, score) in results.items()]) for result in results: self.resultFetched.emit(result) diff --git a/swiss_locator/core/filters/swiss_locator_filter_wmts.py b/swiss_locator/core/filters/swiss_locator_filter_wmts.py index 5ebd014..a125601 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_wmts.py +++ b/swiss_locator/core/filters/swiss_locator_filter_wmts.py @@ -56,7 +56,10 @@ def __init__(self, iface: QgisInterface = None, crs: str = None, capabilities=No self.info(self.content.status()) - if self.content.status() == QgsFetchedContent.ContentStatus.Finished and self.content.filePath(): + if ( + self.content.status() == QgsFetchedContent.ContentStatus.Finished + and self.content.filePath() + ): file_path = self.content.filePath() self.info( f"Swisstopo capabilities already downloaded. Reading from {file_path}" @@ -73,7 +76,8 @@ def clone(self): nam.get(request, forceRefresh=True) reply = nam.reply() if ( - reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute) == 200 + reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute) + == 200 ): # other codes are handled by NetworkAccessManager self.capabilities = ET.fromstring(reply.content().data().decode("utf8")) else: @@ -91,8 +95,14 @@ def displayName(self): def prefix(self): return "chw" + def priority(self): + return self.settings.filter_wmts_priority.value() + def handle_capabilities_response(self): - if self.content.status() == QgsFetchedContent.ContentStatus.Finished and self.content.filePath(): + if ( + self.content.status() == QgsFetchedContent.ContentStatus.Finished + and self.content.filePath() + ): self.info( f"Swisstopo capabilities has been downloaded. Reading from {self.content.filePath()}" ) @@ -100,7 +110,7 @@ def handle_capabilities_response(self): else: self.info( "The Swiss Locator filter for WMTS layers could not fetch capabilities", - Qgis.MessageLevel.Critical + Qgis.MessageLevel.Critical, ) def perform_fetch_results(self, search: str, feedback: QgsFeedback): @@ -170,6 +180,6 @@ def perform_fetch_results(self, search: str, feedback: QgsFeedback): # sort the results with score results = sorted([result for (result, score) in results.items()]) - for result in results[0 : self.settings.value("wmts_limit")]: + for result in results[0 : self.settings.filter_wmts_limit.value()]: self.resultFetched.emit(result) self.result_found = True diff --git a/swiss_locator/core/language.py b/swiss_locator/core/language.py index ad3712a..e1d24a3 100644 --- a/swiss_locator/core/language.py +++ b/swiss_locator/core/language.py @@ -27,6 +27,7 @@ from qgis.PyQt.QtCore import QLocale, QSettings from .settings import Settings from qgis.core import NULL +from .parameters import AVAILABLE_LANGUAGES def get_language() -> str: @@ -36,17 +37,13 @@ def get_language() -> str: :return: 2 chars long string representing the language to be used """ # get lang from settings - lang = Settings().value("lang") + lang = Settings().lang.value() if not lang: - # if None, try to use the locale one - from .parameters import AVAILABLE_LANGUAGES - locale = str(QSettings().value("locale/userLocale")).replace(str(NULL), "en_CH") locale_lang = QLocale.languageToString(QLocale(locale).language()) if locale_lang in AVAILABLE_LANGUAGES: lang = AVAILABLE_LANGUAGES[locale_lang] - else: - # defaults to English - lang = "en" + if lang not in AVAILABLE_LANGUAGES: + lang = "en" return lang diff --git a/swiss_locator/core/settings.py b/swiss_locator/core/settings.py index d67e0d1..3443076 100644 --- a/swiss_locator/core/settings.py +++ b/swiss_locator/core/settings.py @@ -24,82 +24,86 @@ # # --------------------------------------------------------------------- - -from qgis.core import QgsLocatorFilter -from swiss_locator.qgissettingmanager import ( - SettingManager, - Scope, - Bool, - String, - Stringlist, - Integer, - Enum, +from qgis.core import ( + QgsLocatorFilter, + QgsSettingsTree, + QgsSettingsEntryBool, + QgsSettingsEntryString, + QgsSettingsEntryEnumFlag, + QgsSettingsEntryInteger, + QgsSettingsEntryStringList, ) from swiss_locator.core.filters.filter_type import FilterType -pluginName = "swiss_locator_plugin" +PLUGIN_NAME = "swiss_locator_plugin" + + +class Settings(object): + instance = None + def __new__(cls): + if cls.instance is None: + cls.instance = super(Settings, cls).__new__(cls) -class Settings(SettingManager): - def __init__(self): - SettingManager.__init__(self, pluginName) + settings_node = QgsSettingsTree.createPluginTreeNode(pluginName=PLUGIN_NAME) - # lang of the service - # possible values are de, fr, it , rm, en - # if left empty or NULL, try to use locale and defaults to en - self.add_setting(String("lang", Scope.Global, "")) - self.add_setting( - String( - "crs", - Scope.Global, - "project", - allowed_values=("2056", "21781", "project"), + cls.lang = QgsSettingsEntryString("lang", settings_node, "lang") + cls.show_map_tip = QgsSettingsEntryBool( + "show_map_tip", settings_node, False + ) + cls.feature_search_restrict = QgsSettingsEntryBool( + "feature_search_restrict", settings_node, False + ) + cls.layers_include_opendataswiss = QgsSettingsEntryBool( + "layers_include_opendataswiss", settings_node, True + ) + cls.feature_search_layers_list = QgsSettingsEntryStringList( + "feature_search_layers_list", settings_node, [] ) - ) - self.add_setting(Bool("show_map_tip", Scope.Global, False)) - self.add_setting( - Enum( + cls.filter_location_priority = QgsSettingsEntryEnumFlag( f"{FilterType.Location.value}_priority", - Scope.Global, + settings_node, QgsLocatorFilter.Priority.Highest, ) - ) - self.add_setting(Integer(f"{FilterType.Location.value}_limit", Scope.Global, 8)) - self.add_setting( - Enum( + cls.filter_location_limit = QgsSettingsEntryInteger( + f"{FilterType.Location.value}_limit", settings_node, 8 + ) + + cls.filter_wmts_priority = QgsSettingsEntryEnumFlag( f"{FilterType.WMTS.value}_priority", - Scope.Global, - QgsLocatorFilter.Priority.Highest, + settings_node, + QgsLocatorFilter.Priority.Medium, + ) + cls.filter_wmts_limit = QgsSettingsEntryInteger( + f"{FilterType.WMTS.value}_limit", settings_node, 8 ) - ) - self.add_setting(Integer(f"{FilterType.WMTS.value}_limit", Scope.Global, 8)) - self.add_setting( - Enum( + + cls.filter_vt_priority = QgsSettingsEntryEnumFlag( f"{FilterType.VectorTiles.value}_priority", - Scope.Global, - QgsLocatorFilter.Priority.Medium, + settings_node, + QgsLocatorFilter.Priority.Highest, ) - ) - self.add_setting(Integer(f"{FilterType.VectorTiles.value}_limit", Scope.Global, 8)) - self.add_setting( - Enum( + cls.filter_vt_limit = QgsSettingsEntryInteger( + f"{FilterType.VectorTiles.value}_limit", settings_node, 8 + ) + + cls.filter_feature_priority = QgsSettingsEntryEnumFlag( f"{FilterType.Feature.value}_priority", - Scope.Global, - QgsLocatorFilter.Priority.Highest, + settings_node, + QgsLocatorFilter.Priority.High, + ) + cls.filter_feature_limit = QgsSettingsEntryInteger( + f"{FilterType.Feature.value}_limit", settings_node, 8 ) - ) - self.add_setting(Integer(f"{FilterType.Feature.value}_limit", Scope.Global, 8)) - self.add_setting( - Enum( + + cls.filter_layers_priority = QgsSettingsEntryEnumFlag( f"{FilterType.Layers.value}_priority", - Scope.Global, + settings_node, QgsLocatorFilter.Priority.High, ) - ) - self.add_setting(Integer(f"{FilterType.Layers.value}_limit", Scope.Global, 5)) - - self.add_setting(Bool("feature_search_restrict", Scope.Global, False)) - self.add_setting(Stringlist("feature_search_layers_list", Scope.Global, None)) + cls.filter_layers_limit = QgsSettingsEntryInteger( + f"{FilterType.Layers.value}_limit", settings_node, 5 + ) - self.add_setting(Bool("layers_include_opendataswiss", Scope.Global, True)) + return cls.instance diff --git a/swiss_locator/gui/config_dialog.py b/swiss_locator/gui/config_dialog.py index cab1315..4cb84ac 100644 --- a/swiss_locator/gui/config_dialog.py +++ b/swiss_locator/gui/config_dialog.py @@ -26,33 +26,35 @@ from qgis.PyQt.QtWidgets import QDialog, QTableWidgetItem, QAbstractItemView, QComboBox from qgis.PyQt.uic import loadUiType from qgis.core import QgsLocatorFilter +from qgis.gui import QgsSettingsStringComboBoxWrapper -from ..qgissettingmanager.setting_dialog import SettingDialog, UpdateMode from ..core.settings import Settings from ..core.language import get_language from ..map_geo_admin.layers import searchable_layers from .qtwebkit_conf import with_qt_web_kit +from ..core.filters.filter_type import FilterType +from ..core.parameters import AVAILABLE_LANGUAGES DialogUi, _ = loadUiType(os.path.join(os.path.dirname(__file__), "../ui/config.ui")) -class ConfigDialog(QDialog, DialogUi, SettingDialog): +class ConfigDialog(QDialog, DialogUi): def __init__(self, parent=None): - settings = Settings() + self.settings = Settings() QDialog.__init__(self, parent) - SettingDialog.__init__( - self, setting_manager=settings, mode=UpdateMode.DialogAccept - ) + self.setupUi(self) self.lang.addItem( self.tr("use the application locale, defaults to English"), "" ) - from ..core.filters.filter_type import FilterType - from ..core.parameters import AVAILABLE_LANGUAGES - for key, val in AVAILABLE_LANGUAGES.items(): self.lang.addItem(key, val) + + self.lang_wrapper = QgsSettingsStringComboBoxWrapper( + self.lang, self.settings.lang + ) + for filter_type in FilterType: cb = self.findChild(QComboBox, "{}_priority".format(filter_type.value)) if cb is not None: # Some filters might not have a config dialog @@ -96,23 +98,25 @@ def __init__(self, parent=None): self.feature_search_layers_list.horizontalHeader().setStretchLastSection(True) self.feature_search_layers_list.resizeColumnsToContents() - self.settings = settings - self.init_widgets() - if not with_qt_web_kit(): - map_tip = self.setting_widget("show_map_tip") - map_tip.widget.setEnabled(False) - map_tip.widget.setToolTip(self.tr("You need to install QtWebKit to use map tips.")) + self.show_map_tip.setEnabled(False) + self.show_map_tip.setToolTip( + self.tr("You need to install QtWebKit to use map tips.") + ) def select_all(self, select: bool = True): for r in range(self.feature_search_layers_list.rowCount()): item = self.feature_search_layers_list.item(r, 0) - item.setCheckState(Qt.CheckState.Checked if select else Qt.CheckState.Unchecked) + item.setCheckState( + Qt.CheckState.Checked if select else Qt.CheckState.Unchecked + ) @pyqtSlot(str) def filter_rows(self, text: str): if text: - items = self.feature_search_layers_list.findItems(text, Qt.MatchFlag.MatchContains) + items = self.feature_search_layers_list.findItems( + text, Qt.MatchFlag.MatchContains + ) print(text) print(len(items)) shown_rows = [] diff --git a/swiss_locator/map_geo_admin/layers.py b/swiss_locator/map_geo_admin/layers.py index df25e11..f1ea1ea 100644 --- a/swiss_locator/map_geo_admin/layers.py +++ b/swiss_locator/map_geo_admin/layers.py @@ -43,8 +43,8 @@ def searchable_layers(lang: str, restrict: bool = False) -> dict: assert lang in AVAILABLE_LANGUAGES.values() settings = Settings() - restrict_enabled_by_user = settings.value("feature_search_restrict") - restrict_layer_list = settings.value("feature_search_layers_list") + restrict_enabled_by_user = settings.feature_search_restrict.value() + restrict_layer_list = settings.feature_search_layers_list.value() layers = {} diff --git a/swiss_locator/metadata.txt b/swiss_locator/metadata.txt index a42aaa7..eef59cb 100644 --- a/swiss_locator/metadata.txt +++ b/swiss_locator/metadata.txt @@ -8,6 +8,9 @@ version=dev author=OPENGIS.ch email=info@opengis.ch +supportsQt6=yes + + # Tags are comma separated with spaces allowed tags=swiss, suisse, schweiz, locator, geoadmin, geoportal, opendata.swiss diff --git a/swiss_locator/swiss_locator_plugin.py b/swiss_locator/swiss_locator_plugin.py index 6771926..1d365fd 100644 --- a/swiss_locator/swiss_locator_plugin.py +++ b/swiss_locator/swiss_locator_plugin.py @@ -20,7 +20,7 @@ import os from qgis.PyQt.QtCore import QCoreApplication, QLocale, QSettings, QTranslator from qgis.PyQt.QtWidgets import QWidget -from qgis.core import Qgis, QgsApplication, QgsMessageLog, NULL +from qgis.core import Qgis, QgsApplication, QgsMessageLog, NULL, QgsSettingsTree from qgis.gui import QgisInterface, QgsMessageBarItem from swiss_locator.core.filters.swiss_locator_filter_feature import ( @@ -36,12 +36,15 @@ from swiss_locator.core.filters.swiss_locator_filter_vector_tiles import ( SwissLocatorFilterVectorTiles, ) + try: from swiss_locator.core.profiles.profile_generator import SwissProfileSource except ImportError: # Should fail only for QGIS < 3.26, where profiles weren't available SwissProfileSource = None +from swiss_locator.core.settings import PLUGIN_NAME + class SwissLocatorPlugin: def __init__(self, iface: QgisInterface): @@ -75,11 +78,13 @@ def initGui(self): self.locator_filters[-1].message_emitted.connect(self.show_message) if Qgis.QGIS_VERSION_INT >= 33700: - QgsApplication.profileSourceRegistry().registerProfileSource(self.profile_source) + QgsApplication.profileSourceRegistry().registerProfileSource( + self.profile_source + ) QgsMessageLog.logMessage( "Swiss profile source has been registered!", "Swiss locator", - Qgis.MessageLevel.Info + Qgis.MessageLevel.Info, ) def unload(self): @@ -88,13 +93,17 @@ def unload(self): self.iface.deregisterLocatorFilter(locator_filter) if Qgis.QGIS_VERSION_INT >= 33700: - QgsApplication.profileSourceRegistry().unregisterProfileSource(self.profile_source) + QgsApplication.profileSourceRegistry().unregisterProfileSource( + self.profile_source + ) QgsMessageLog.logMessage( "Swiss profile source has been unregistered!", "Swiss locator", - Qgis.MessageLevel.Info + Qgis.MessageLevel.Info, ) + QgsSettingsTree.unregisterPluginTreeNode(PLUGIN_NAME) + def show_message( self, title: str, msg: str, level: Qgis.MessageLevel, widget: QWidget = None ): From 9935acab89554d920e4fb1d50b43a9ba47a9a7cc Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Mon, 7 Oct 2024 14:29:15 +0200 Subject: [PATCH 2/8] raise QGIS minimum to 3.34, config available for 3.40+ --- .../core/filters/swiss_locator_filter.py | 6 +- swiss_locator/core/settings.py | 98 ++++++++++--------- swiss_locator/gui/config_dialog.py | 87 ++++++++++++---- swiss_locator/metadata.txt | 2 +- swiss_locator/ui/config.ui | 74 ++++++-------- 5 files changed, 161 insertions(+), 106 deletions(-) diff --git a/swiss_locator/core/filters/swiss_locator_filter.py b/swiss_locator/core/filters/swiss_locator_filter.py index eed53de..440b45f 100644 --- a/swiss_locator/core/filters/swiss_locator_filter.py +++ b/swiss_locator/core/filters/swiss_locator_filter.py @@ -59,7 +59,9 @@ ) from swiss_locator.core.settings import Settings from swiss_locator.core.language import get_language -from swiss_locator.gui.config_dialog import ConfigDialog + +if Qgis.QGIS_VERSION_INT >= 33900: + from swiss_locator.gui.config_dialog import ConfigDialog from swiss_locator.gui.maptip import MapTip from swiss_locator.gui.qtwebkit_conf import with_qt_web_kit from swiss_locator.utils.utils import url_with_param @@ -185,7 +187,7 @@ def clearPreviousResults(self): self.current_timer = None def hasConfigWidget(self): - return True + return Qgis.QGIS_VERSION_INT >= 33900 def openConfigWidget(self, parent=None): dlg = ConfigDialog(parent) diff --git a/swiss_locator/core/settings.py b/swiss_locator/core/settings.py index 3443076..c4db3fa 100644 --- a/swiss_locator/core/settings.py +++ b/swiss_locator/core/settings.py @@ -25,11 +25,11 @@ # --------------------------------------------------------------------- from qgis.core import ( + metaEnumFromType, QgsLocatorFilter, QgsSettingsTree, QgsSettingsEntryBool, QgsSettingsEntryString, - QgsSettingsEntryEnumFlag, QgsSettingsEntryInteger, QgsSettingsEntryStringList, ) @@ -61,49 +61,59 @@ def __new__(cls): "feature_search_layers_list", settings_node, [] ) - cls.filter_location_priority = QgsSettingsEntryEnumFlag( - f"{FilterType.Location.value}_priority", - settings_node, - QgsLocatorFilter.Priority.Highest, - ) - cls.filter_location_limit = QgsSettingsEntryInteger( - f"{FilterType.Location.value}_limit", settings_node, 8 - ) + me = metaEnumFromType(QgsLocatorFilter.Priority) - cls.filter_wmts_priority = QgsSettingsEntryEnumFlag( - f"{FilterType.WMTS.value}_priority", - settings_node, - QgsLocatorFilter.Priority.Medium, - ) - cls.filter_wmts_limit = QgsSettingsEntryInteger( - f"{FilterType.WMTS.value}_limit", settings_node, 8 - ) - - cls.filter_vt_priority = QgsSettingsEntryEnumFlag( - f"{FilterType.VectorTiles.value}_priority", - settings_node, - QgsLocatorFilter.Priority.Highest, - ) - cls.filter_vt_limit = QgsSettingsEntryInteger( - f"{FilterType.VectorTiles.value}_limit", settings_node, 8 - ) - - cls.filter_feature_priority = QgsSettingsEntryEnumFlag( - f"{FilterType.Feature.value}_priority", - settings_node, - QgsLocatorFilter.Priority.High, - ) - cls.filter_feature_limit = QgsSettingsEntryInteger( - f"{FilterType.Feature.value}_limit", settings_node, 8 - ) - - cls.filter_layers_priority = QgsSettingsEntryEnumFlag( - f"{FilterType.Layers.value}_priority", - settings_node, - QgsLocatorFilter.Priority.High, - ) - cls.filter_layers_limit = QgsSettingsEntryInteger( - f"{FilterType.Layers.value}_limit", settings_node, 5 - ) + cls.filters = { + FilterType.Location.value: { + "priority": QgsSettingsEntryString( + f"{FilterType.Location.value}_priority", + settings_node, + me.valueToKey(QgsLocatorFilter.Priority.Highest), + ), + "limit": QgsSettingsEntryInteger( + f"{FilterType.Location.value}_limit", settings_node, 8 + ), + }, + FilterType.WMTS.value: { + "priority": QgsSettingsEntryString( + f"{FilterType.WMTS.value}_priority", + settings_node, + me.valueToKey(QgsLocatorFilter.Priority.Medium), + ), + "limit": QgsSettingsEntryInteger( + f"{FilterType.WMTS.value}_limit", settings_node, 8 + ), + }, + FilterType.VectorTiles.value: { + "priority": QgsSettingsEntryString( + f"{FilterType.VectorTiles.value}_priority", + settings_node, + me.valueToKey(QgsLocatorFilter.Priority.Highest), + ), + "limit": QgsSettingsEntryInteger( + f"{FilterType.VectorTiles.value}_limit", settings_node, 8 + ), + }, + FilterType.Feature.value: { + "priority": QgsSettingsEntryString( + f"{FilterType.Feature.value}_priority", + settings_node, + me.valueToKey(QgsLocatorFilter.Priority.High), + ), + "limit": QgsSettingsEntryInteger( + f"{FilterType.Feature.value}_limit", settings_node, 8 + ), + }, + FilterType.Layers.value: { + "priority": QgsSettingsEntryString( + f"{FilterType.Layers.value}_priority", + settings_node, + me.valueToKey(QgsLocatorFilter.Priority.High), + ), + "limit": QgsSettingsEntryInteger( + f"{FilterType.Layers.value}_limit", settings_node, 5 + ), + }, + } return cls.instance diff --git a/swiss_locator/gui/config_dialog.py b/swiss_locator/gui/config_dialog.py index 4cb84ac..8396452 100644 --- a/swiss_locator/gui/config_dialog.py +++ b/swiss_locator/gui/config_dialog.py @@ -25,8 +25,12 @@ from qgis.PyQt.QtCore import Qt, pyqtSlot from qgis.PyQt.QtWidgets import QDialog, QTableWidgetItem, QAbstractItemView, QComboBox from qgis.PyQt.uic import loadUiType -from qgis.core import QgsLocatorFilter -from qgis.gui import QgsSettingsStringComboBoxWrapper +from qgis.core import QgsLocatorFilter, metaEnumFromType +from qgis.gui import ( + QgsSettingsEditorWidgetWrapper, + QgsSettingsStringComboBoxWrapper, + QgsSettingsBoolCheckBoxWrapper, +) from ..core.settings import Settings from ..core.language import get_language @@ -39,11 +43,23 @@ class ConfigDialog(QDialog, DialogUi): + def accept(self): + for wrapper in self.wrappers: + wrapper.setSettingFromWidget() + + layers_list = [] + for r in range(self.feature_search_layers_list.rowCount()): + item = self.feature_search_layers_list.item(r, 0) + if item.checkState() == Qt.CheckState.Checked: + layers_list.append(item.text()) + self.settings.feature_search_layers_list.setValue(layers_list) + super().accept() + def __init__(self, parent=None): self.settings = Settings() QDialog.__init__(self, parent) - self.setupUi(self) + self.wrappers: [QgsSettingsEditorWidgetWrapper] = [] self.lang.addItem( self.tr("use the application locale, defaults to English"), "" @@ -51,24 +67,51 @@ def __init__(self, parent=None): for key, val in AVAILABLE_LANGUAGES.items(): self.lang.addItem(key, val) - self.lang_wrapper = QgsSettingsStringComboBoxWrapper( - self.lang, self.settings.lang + self.wrappers.append( + QgsSettingsStringComboBoxWrapper( + self.lang, + self.settings.lang, + QgsSettingsStringComboBoxWrapper.Mode.Data, + ) + ) + + self.wrappers.append( + QgsSettingsBoolCheckBoxWrapper( + self.layers_include_opendataswiss, + self.settings.layers_include_opendataswiss, + ) + ) + self.wrappers.append( + QgsSettingsBoolCheckBoxWrapper( + self.feature_search_restrict, self.settings.feature_search_restrict + ) ) + me = metaEnumFromType(QgsLocatorFilter.Priority) for filter_type in FilterType: cb = self.findChild(QComboBox, "{}_priority".format(filter_type.value)) if cb is not None: # Some filters might not have a config dialog - cb.addItem(self.tr("Highest"), QgsLocatorFilter.Priority.Highest) - cb.addItem(self.tr("High"), QgsLocatorFilter.Priority.High) - cb.addItem(self.tr("Medium"), QgsLocatorFilter.Priority.Medium) - cb.addItem(self.tr("Low"), QgsLocatorFilter.Priority.Low) - cb.addItem(self.tr("Lowest"), QgsLocatorFilter.Priority.Lowest) - - self.crs.addItem( - self.tr("Use map CRS if possible, defaults to CH1903+"), "project" - ) - self.crs.addItem("CH 1903+ (EPSG:2056)", "2056") - self.crs.addItem("CH 1903 (EPSG:21781)", "21781") + cb.addItem( + self.tr("Highest"), me.valueToKey(QgsLocatorFilter.Priority.Highest) + ) + cb.addItem( + self.tr("High"), me.valueToKey(QgsLocatorFilter.Priority.High) + ) + cb.addItem( + self.tr("Medium"), me.valueToKey(QgsLocatorFilter.Priority.Medium) + ) + cb.addItem(self.tr("Low"), me.valueToKey(QgsLocatorFilter.Priority.Low)) + cb.addItem( + self.tr("Lowest"), me.valueToKey(QgsLocatorFilter.Priority.Lowest) + ) + + self.wrappers.append( + QgsSettingsStringComboBoxWrapper( + cb, + self.settings.filters[filter_type.value]["priority"], + QgsSettingsStringComboBoxWrapper.Mode.Data, + ) + ) self.search_line_edit.textChanged.connect(self.filter_rows) self.select_all_button.pressed.connect(self.select_all) @@ -88,10 +131,14 @@ def __init__(self, parent=None): QAbstractItemView.SelectionMode.SingleSelection ) r = 0 + layers_list = self.settings.feature_search_layers_list.value() for layer, description in layers.items(): item = QTableWidgetItem(layer) item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsUserCheckable) - # item.setCheckState(Qt.Unchecked) + checked = layer in layers_list + item.setCheckState( + Qt.CheckState.Checked if checked else Qt.CheckState.Unchecked + ) self.feature_search_layers_list.setItem(r, 0, item) self.feature_search_layers_list.setItem(r, 1, QTableWidgetItem(description)) r += 1 @@ -103,6 +150,12 @@ def __init__(self, parent=None): self.show_map_tip.setToolTip( self.tr("You need to install QtWebKit to use map tips.") ) + else: + self.wrappers.append( + QgsSettingsBoolCheckBoxWrapper( + self.show_map_tip, self.settings.show_map_tip + ) + ) def select_all(self, select: bool = True): for r in range(self.feature_search_layers_list.rowCount()): diff --git a/swiss_locator/metadata.txt b/swiss_locator/metadata.txt index eef59cb..72a612b 100644 --- a/swiss_locator/metadata.txt +++ b/swiss_locator/metadata.txt @@ -1,7 +1,7 @@ [general] name=Swiss Locator -qgisMinimumVersion=3.16 +qgisMinimumVersion=3.34 description=A locator filter for Swiss Geoportal (geo.admin.ch) and opendata.swiss resources about=Search for locations, WMS layers of features in the whole Swiss Geoportal catalog as well as in opendata.swiss version=dev diff --git a/swiss_locator/ui/config.ui b/swiss_locator/ui/config.ui index db61569..b901441 100644 --- a/swiss_locator/ui/config.ui +++ b/swiss_locator/ui/config.ui @@ -14,50 +14,17 @@ Swiss locator filter configuration - - - - Language - - - - - - - Coordinates system - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + Show map tip on the map whenever possible - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + 0 @@ -273,7 +240,7 @@ true - + true @@ -328,13 +295,36 @@ - - + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + - Show map tip on the map whenever possible + Language + + + + Qt::Horizontal + + + + 40 + 20 + + + + From 7224377f7b773de0e9e719e58f319531cfbf8fd6 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Mon, 7 Oct 2024 14:46:03 +0200 Subject: [PATCH 3/8] remmoved submodule --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 6dbbcef..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "swiss_locator/qgissettingmanager"] - path = swiss_locator/qgissettingmanager - url = git@github.com:opengisch/qgis_setting_manager.git From 835c28aebef544b27cf62871e15bda7e27f2f2a5 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Mon, 7 Oct 2024 14:58:50 +0200 Subject: [PATCH 4/8] follow up --- .github/workflows/test.yml | 2 +- swiss_locator/qgissettingmanager | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 160000 swiss_locator/qgissettingmanager diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3162396..0bd5f7c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,4 +22,4 @@ jobs: - name: docker test run: | - docker run -v $(pwd):/usr/src -w /usr/src opengisch/qgis:${QGIS_TEST_VERSION} sh -c 'xvfb-run pytest-3 --ignore-glob=**/qgissettingmanager/*' + docker run -v $(pwd):/usr/src -w /usr/src opengisch/qgis:${QGIS_TEST_VERSION} sh -c 'xvfb-run pytest-3' diff --git a/swiss_locator/qgissettingmanager b/swiss_locator/qgissettingmanager deleted file mode 160000 index 565a0bc..0000000 --- a/swiss_locator/qgissettingmanager +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 565a0bcd496ec3e42b3e39e06abb7cd24b8af48d From 8380a917e1b43f64b5eccfc699ca61afa026b99b Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Mon, 7 Oct 2024 15:00:56 +0200 Subject: [PATCH 5/8] fix docker image --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0bd5f7c..ef47a86 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,4 +22,4 @@ jobs: - name: docker test run: | - docker run -v $(pwd):/usr/src -w /usr/src opengisch/qgis:${QGIS_TEST_VERSION} sh -c 'xvfb-run pytest-3' + docker run -v $(pwd):/usr/src -w /usr/src qgis/qgis:${QGIS_TEST_VERSION} sh -c 'xvfb-run pytest-3' From 9520e33130c76da51d73c7c1d816e024bb2cb8a7 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Tue, 8 Oct 2024 08:36:25 +0200 Subject: [PATCH 6/8] fix settings --- swiss_locator/core/filters/swiss_locator_filter.py | 10 +++++++++- .../core/filters/swiss_locator_filter_feature.py | 3 --- .../core/filters/swiss_locator_filter_layer.py | 3 --- .../core/filters/swiss_locator_filter_location.py | 3 --- .../core/filters/swiss_locator_filter_vector_tiles.py | 3 --- .../core/filters/swiss_locator_filter_wmts.py | 3 --- swiss_locator/core/settings.py | 2 +- 7 files changed, 10 insertions(+), 17 deletions(-) diff --git a/swiss_locator/core/filters/swiss_locator_filter.py b/swiss_locator/core/filters/swiss_locator_filter.py index 440b45f..297ca26 100644 --- a/swiss_locator/core/filters/swiss_locator_filter.py +++ b/swiss_locator/core/filters/swiss_locator_filter.py @@ -31,6 +31,7 @@ from qgis.PyQt.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager from qgis.core import ( + metaEnumFromType, Qgis, QgsLocatorFilter, QgsLocatorResult, @@ -120,6 +121,7 @@ def __init__( self.result_found = False self.access_managers = {} self.minimum_search_length = 2 + self.me = metaEnumFromType(QgsLocatorFilter.Priority) self.nam = QNetworkAccessManager() self.nam.setRedirectPolicy( @@ -161,7 +163,13 @@ def name(self): return self.__class__.__name__ def priority(self): - return QgsLocatorFilter.Priority.Medium + (value, ok) = self.me.keyToValue( + self.settings.filters[self.type.value]["priority"].value() + ) + if ok: + return QgsLocatorFilter.Priority(value) + else: + return QgsLocatorFilter.Priority.Medium def displayName(self): # this should be re-implemented diff --git a/swiss_locator/core/filters/swiss_locator_filter_feature.py b/swiss_locator/core/filters/swiss_locator_filter_feature.py index b3772fe..fd83ab7 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_feature.py +++ b/swiss_locator/core/filters/swiss_locator_filter_feature.py @@ -53,9 +53,6 @@ def displayName(self): def prefix(self): return "chf" - def priority(self): - return self.settings.filter_feature_priority.value() - def perform_fetch_results(self, search: str, feedback: QgsFeedback): # Feature search is split in several requests # otherwise URL is too long diff --git a/swiss_locator/core/filters/swiss_locator_filter_layer.py b/swiss_locator/core/filters/swiss_locator_filter_layer.py index 6dd2e6f..c8d4385 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_layer.py +++ b/swiss_locator/core/filters/swiss_locator_filter_layer.py @@ -52,9 +52,6 @@ def displayName(self): def prefix(self): return "chl" - def priority(self): - return self.settings.filter_layers_priority.value() - def perform_fetch_results(self, search: str, feedback: QgsFeedback): limit = self.settings.filter_layers_limit.value() urls = [ diff --git a/swiss_locator/core/filters/swiss_locator_filter_location.py b/swiss_locator/core/filters/swiss_locator_filter_location.py index 8fbfb88..daca5d0 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_location.py +++ b/swiss_locator/core/filters/swiss_locator_filter_location.py @@ -57,9 +57,6 @@ def displayName(self): def prefix(self): return "chs" - def priority(self): - return self.settings.filter_location_priority.value() - def perform_fetch_results(self, search: str, feedback: QgsFeedback): limit = self.settings.filter_location_limit.value() url, params = map_geo_admin_url( diff --git a/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py b/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py index 5b0dd86..8a2a6bd 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py +++ b/swiss_locator/core/filters/swiss_locator_filter_vector_tiles.py @@ -27,9 +27,6 @@ def displayName(self): def prefix(self): return "chb" - def priority(self): - return self.settings.filter_vt_priority.value() - def hasConfigWidget(self): return False diff --git a/swiss_locator/core/filters/swiss_locator_filter_wmts.py b/swiss_locator/core/filters/swiss_locator_filter_wmts.py index a125601..6b36b93 100644 --- a/swiss_locator/core/filters/swiss_locator_filter_wmts.py +++ b/swiss_locator/core/filters/swiss_locator_filter_wmts.py @@ -95,9 +95,6 @@ def displayName(self): def prefix(self): return "chw" - def priority(self): - return self.settings.filter_wmts_priority.value() - def handle_capabilities_response(self): if ( self.content.status() == QgsFetchedContent.ContentStatus.Finished diff --git a/swiss_locator/core/settings.py b/swiss_locator/core/settings.py index c4db3fa..c3cd400 100644 --- a/swiss_locator/core/settings.py +++ b/swiss_locator/core/settings.py @@ -38,7 +38,7 @@ PLUGIN_NAME = "swiss_locator_plugin" -class Settings(object): +class Settings: instance = None def __new__(cls): From f78f72ba1d840402026de86379f3a3071d2f408e Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Tue, 8 Oct 2024 08:37:04 +0200 Subject: [PATCH 7/8] fix ui --- swiss_locator/ui/config.ui | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/swiss_locator/ui/config.ui b/swiss_locator/ui/config.ui index b901441..e5b5e96 100644 --- a/swiss_locator/ui/config.ui +++ b/swiss_locator/ui/config.ui @@ -27,7 +27,7 @@ - 0 + 1 @@ -94,8 +94,18 @@ - - + + + + Qt::Vertical + + + + 20 + 40 + + + @@ -107,15 +117,18 @@ - - + + + + + - Qt::Vertical + Qt::Horizontal - 20 - 40 + 40 + 20 From d695d76383b60dfcca8686f0da8c31e21f95076a Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Tue, 8 Oct 2024 08:40:23 +0200 Subject: [PATCH 8/8] bump to 3.40 --- swiss_locator/core/filters/swiss_locator_filter.py | 5 ++--- swiss_locator/metadata.txt | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/swiss_locator/core/filters/swiss_locator_filter.py b/swiss_locator/core/filters/swiss_locator_filter.py index 297ca26..26fec1a 100644 --- a/swiss_locator/core/filters/swiss_locator_filter.py +++ b/swiss_locator/core/filters/swiss_locator_filter.py @@ -61,8 +61,7 @@ from swiss_locator.core.settings import Settings from swiss_locator.core.language import get_language -if Qgis.QGIS_VERSION_INT >= 33900: - from swiss_locator.gui.config_dialog import ConfigDialog +from swiss_locator.gui.config_dialog import ConfigDialog from swiss_locator.gui.maptip import MapTip from swiss_locator.gui.qtwebkit_conf import with_qt_web_kit from swiss_locator.utils.utils import url_with_param @@ -195,7 +194,7 @@ def clearPreviousResults(self): self.current_timer = None def hasConfigWidget(self): - return Qgis.QGIS_VERSION_INT >= 33900 + return True def openConfigWidget(self, parent=None): dlg = ConfigDialog(parent) diff --git a/swiss_locator/metadata.txt b/swiss_locator/metadata.txt index 72a612b..e64469e 100644 --- a/swiss_locator/metadata.txt +++ b/swiss_locator/metadata.txt @@ -1,7 +1,7 @@ [general] name=Swiss Locator -qgisMinimumVersion=3.34 +qgisMinimumVersion=3.40 description=A locator filter for Swiss Geoportal (geo.admin.ch) and opendata.swiss resources about=Search for locations, WMS layers of features in the whole Swiss Geoportal catalog as well as in opendata.swiss version=dev