### Dataforsyningen API Endpoints (Bash) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt Demonstrates how to interact with the Dataforsyningen API using cURL commands. It shows examples for fetching user permissions with a provided token and retrieving QLR configuration files. These endpoints are crucial for plugin functionality and configuration. ```bash # Hent brugerens tilladte services # Token indsættes direkte i URL curl "https://api.dataforsyningen.dk/userpermissions/DIT_TOKEN_HER" # Eksempel respons: # [ # {"name": "skaermkort"}, # {"name": "forvaltning"}, # {"name": "dhm"}, # {"name": "orto_foraar"}, # {"name": "matriklen"} # ] # Hent QLR konfigurationsfil curl "https://qgisplugin.dataforsyningen.dk/qgis_plugin_dataforsyningen_udentoken.qlr" # Eksempel på QLR struktur: # # # # # ... # # # # skaermkort_layer_id # url=https://api.dataforsyningen.dk/skaermkort_daempet_wmts_DAF?token={{df_token}}&... # # ``` -------------------------------- ### Dataforsyningen API Endpoints Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The plugin communicates with the Dataforsyningen API to retrieve user permissions and configuration. This section provides examples of the API calls made by the plugin. ```APIDOC ## Dataforsyningen API Endpoints Pluginet kommunikerer med Dataforsyningens API for at hente brugertilladelser og konfiguration. Her er eksempler på de API-kald der foretages. ### Get User Permissions Retrieves the user's allowed services. ### Method GET ### Endpoint `https://api.dataforsyningen.dk/userpermissions/DIT_TOKEN_HER` ### Parameters #### Query Parameters - **DIT_TOKEN_HER** (string) - Required - The user's authentication token. ### Response Example ```json [ {"name": "skaermkort"}, {"name": "forvaltning"}, {"name": "dhm"}, {"name": "orto_foraar"}, {"name": "matriklen"} ] ``` ### Get QLR Configuration File Fetches the QLR configuration file for QGIS. ### Method GET ### Endpoint `https://qgisplugin.dataforsyningen.dk/qgis_plugin_dataforsyningen_udentoken.qlr` ### Response Example ```xml ... skaermkort_layer_id url=https://api.dataforsyningen.dk/skaermkort_daempet_wmts_DAF?token={{df_token}}&... ``` ``` -------------------------------- ### Plugin Initialization Entry Point (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The `classFactory` function serves as the entry point for the Dataforsyningen plugin when loaded by QGIS. It initializes and returns an instance of the main plugin class, Dataforsyningen. ```python def classFactory(iface): """Indlæs Dataforsyningen klassen. :param iface: QGIS interface instans :type iface: QgsInterface :return: Plugin instans """ from .dataforsyningen import Dataforsyningen return Dataforsyningen(iface) ``` -------------------------------- ### SettingManager Class Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Demonstrates how to define and add settings using the SettingManager class. ```APIDOC ## SettingManager Class ### Description This class is the core for managing settings in your QGIS plugin. You subclass it to define your plugin's settings. ### Method ```python from qgissettingmanager import * class MySettings(SettingManager): def __init__(self): SettingManager.__init__(self, my_plugin_name) self.add_setting( Bool("my_setting", Scope.Global, True) ) ``` ### Adding Settings Use the `add_setting` method to include various types of settings. ### Parameters - `SettingClass`: The type of setting (e.g., `Bool`, `String`, `Color`, `Integer`, `Double`, `Stringlist`). - `name` (string): The unique name of the setting. - `scope` (`Scope.Global` or `Scope.Project`): Where the setting is stored. - `default_value`: The initial value of the setting (type must match `SettingClass`). - `options` (dict, optional): Additional options for widget integration. ``` -------------------------------- ### Manage Configuration with Config Class (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The Config class integrates data from Dataforsyningen and local QLR files, handling asynchronous loading and emitting signals for errors or success. It combines categories from both sources and provides methods to retrieve specific map layer nodes. Dependencies include custom DfConfig and LocalConfig classes. ```Python from qgis.PyQt import QtCore from .df_config import DfConfig from .local_config import LocalConfig class Config(QtCore.QObject): # Signals df_con_error = QtCore.pyqtSignal() # Netværksfejl df_settings_warning = QtCore.pyqtSignal() # Token mangler loaded = QtCore.pyqtSignal() # Data indlæst def __init__(self, settings): super(Config, self).__init__() self.settings = settings self.categories = [] self.categories_list = [] # Dataforsyningen konfiguration self.df_config = DfConfig(settings) self.df_config.df_con_error.connect(self.propagate_df_con_error) self.df_config.loaded.connect(self._handle_df_config_loaded) # Lokal QLR konfiguration self.local_config = LocalConfig(settings) def begin_load(self): """Start asynkron indlæsning af konfiguration.""" self.df_config.begin_load() def _handle_df_config_loaded(self): """Håndter når Dataforsyningen data er indlæst.""" self.df_categories = self.df_config.get_categories() self.local_categories = self.local_config.get_categories() # Kombiner kategorier self.categories = self.df_categories + self.local_categories self.categories_list = [self.df_categories, self.local_categories] self.loaded.emit() def get_categories(self): """Hent alle kategorier (Dataforsyningen + lokale).""" return self.categories def get_category_lists(self): """Hent kategorier som separate lister.""" return self.categories_list def get_df_maplayer_node(self, layer_id): """Hent maplayer node fra Dataforsyningen QLR.""" return self.df_config.get_maplayer_node(layer_id) def get_local_maplayer_node(self, layer_id): """Hent maplayer node fra lokal QLR.""" return self.local_config.get_maplayer_node(layer_id) ``` -------------------------------- ### Plugin Initialization Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The `classFactory` function serves as the entry point for the Dataforsyningen plugin when loaded by QGIS. It initializes the plugin by creating an instance of the main Dataforsyningen class. ```APIDOC ## Plugin Initialisering ### Description `classFactory` is the entry point function that initializes the plugin when QGIS loads it. The function receives the QGIS interface object and returns an instance of the main class. ### Method Python ### Endpoint N/A (Plugin Entry Point) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python # __init__.py - Plugin entry point def classFactory(iface): """Loads the Dataforsyningen class. :param iface: QGIS interface instance :type iface: QgsInterface :return: Plugin instance """ from .dataforsyningen import Dataforsyningen return Dataforsyningen(iface) ``` ### Response #### Success Response (200) An instance of the `Dataforsyningen` class. #### Response Example N/A ``` -------------------------------- ### Dataforsyningen Main Class Implementation (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The `Dataforsyningen` class manages the plugin's lifecycle, GUI elements, and data loading. It handles settings registration, locator filter integration, menu construction, and error reporting. Dependencies include QGIS core modules and custom modules like `mysettings`, `config`, and `layerlocatorfilter`. ```python from qgis.core import QgsProject, QgsMessageLog from qgis.PyQt.QtWidgets import QAction, QMenu from .mysettings import Settings, OptionsFactory from .config import Config from .layerlocatorfilter import LayerLocatorFilter class Dataforsyningen: """QGIS Plugin Implementation.""" def __init__(self, iface): # Gem reference til QGIS interface self.iface = iface # Initialiser indstillinger self.settings = Settings() self.settings.settings_updated.connect(self.reloadMenu) # Registrer indstillingspanel self.options_factory = OptionsFactory(self.settings) self.options_factory.setTitle("Dataforsyningen") iface.registerOptionsWidgetFactory(self.options_factory) # Konfiguration med signals self.config = Config(self.settings) self.config.df_con_error.connect(self.show_df_error) self.config.df_settings_warning.connect(self.show_df_settings_warning) self.config.loaded.connect(self.fillMenu) # Lokator filter til søgning self.layer_locator_filter = LayerLocatorFilter() self.iface.registerLocatorFilter(self.layer_locator_filter) self.menu = None self.category_menus = [] def initGui(self): """Opret GUI elementer - kaldes af QGIS.""" self.createMenu() def createMenu(self): """Opret menu i QGIS menubar.""" menu_bar = self.iface.mainWindow().menuBar() self.menu = QMenu(menu_bar) self.menu.setObjectName("Dataforsyningen") self.menu.setTitle("Dataforsyningen") menu_bar.insertMenu( self.iface.firstRightStandardMenu().menuAction(), self.menu ) self.config.begin_load() def open_df_node(self, layer_id): """Åbn et lag fra Dataforsyningen.""" node = self.config.get_df_maplayer_node(layer_id) QgsProject.instance().readLayer(node) def unload(self): """Fjern plugin fra QGIS.""" self.iface.unregisterOptionsWidgetFactory(self.options_factory) self.iface.deregisterLocatorFilter(self.layer_locator_filter) self.clearMenu() ``` -------------------------------- ### SettingDialog Integration Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Explains how to link UI widgets to settings using the SettingDialog class for seamless UI management. ```APIDOC ## SettingDialog Integration ### Description Integrate your dialogs with the `SettingDialog` class to automatically populate widgets from settings and save widget changes back to settings. ### Quick Start 1. **Name your widgets** the same as your setting names. 2. **Subclass `SettingDialog`** in your dialog class: ```python class MyDialog(QDialog, Ui_myDialog, SettingDialog): def __init__(self): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings) ``` When the dialog is shown, widgets matching setting names will be updated. Upon acceptance, settings will be updated from the widgets. ### Widget List To check which settings are associated with widgets, print `self.widget_list()`. ``` -------------------------------- ### Dataforsyningen Main Class Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The main `Dataforsyningen` class manages the plugin's lifecycle, menu construction, and layer loading. It handles settings registration, locator filtering, and builds the menu structure based on user permissions. ```APIDOC ## Dataforsyningen Hovedklasse ### Description The main class handles the plugin lifecycle, menu building, and layer loading. It registers settings, locator filters, and constructs the menu structure based on user permissions. ### Method Python ### Endpoint N/A (Class Definition) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from qgis.core import QgsProject, QgsMessageLog from qgis.PyQt.QtWidgets import QAction, QMenu from .mysettings import Settings, OptionsFactory from .config import Config from .layerlocatorfilter import LayerLocatorFilter class Dataforsyningen: """QGIS Plugin Implementation.""" def __init__(self, iface): # Store reference to QGIS interface self.iface = iface # Initialize settings self.settings = Settings() self.settings.settings_updated.connect(self.reloadMenu) # Register settings panel self.options_factory = OptionsFactory(self.settings) self.options_factory.setTitle("Dataforsyningen") iface.registerOptionsWidgetFactory(self.options_factory) # Configuration with signals self.config = Config(self.settings) self.config.df_con_error.connect(self.show_df_error) self.config.df_settings_warning.connect(self.show_df_settings_warning) self.config.loaded.connect(self.fillMenu) # Locator filter for searching self.layer_locator_filter = LayerLocatorFilter() self.iface.registerLocatorFilter(self.layer_locator_filter) self.menu = None self.category_menus = [] def initGui(self): """Create GUI elements - called by QGIS.""" self.createMenu() def createMenu(self): """Create menu in QGIS menubar.""" menu_bar = self.iface.mainWindow().menuBar() self.menu = QMenu(menu_bar) self.menu.setObjectName("Dataforsyningen") self.menu.setTitle("Dataforsyningen") menu_bar.insertMenu( self.iface.firstRightStandardMenu().menuAction(), self.menu ) self.config.begin_load() def open_df_node(self, layer_id): """Open a layer from Dataforsyningen.""" node = self.config.get_df_maplayer_node(layer_id) QgsProject.instance().readLayer(node) def unload(self): """Remove plugin from QGIS.""" self.iface.unregisterOptionsWidgetFactory(self.options_factory) self.iface.deregisterLocatorFilter(self.layer_locator_filter) self.clearMenu() def log_message(message): """Log message to QGIS message log.""" QgsMessageLog.logMessage(message, "Dataforsyningen plugin") ``` ### Response #### Success Response (200) Initializes the plugin's GUI elements and loads configuration. #### Response Example N/A ``` -------------------------------- ### Python DfConfig Class for Dataforsyningen API Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The DfConfig class manages API interactions, including fetching user permissions and QLR configuration files. It implements local caching for QLR files for up to 12 hours and uses QgsNetworkContentFetcher for asynchronous network requests. Dependencies include datetime, hashlib, json, QGIS core and PyQt modules, and a local qlr_file module. ```python import datetime import hashlib import json from qgis.core import QgsNetworkContentFetcher from qgis.PyQt import QtCore from qgis.PyQt.QtCore import QUrl from .qlr_file import QlrFile FILE_MAX_AGE = datetime.timedelta(hours=12) DF_SERVICES_URL = "https://api.dataforsyningen.dk/userpermissions/{{df_token}}" class DfConfig(QtCore.QObject): df_con_error = QtCore.pyqtSignal() df_settings_warning = QtCore.pyqtSignal() loaded = QtCore.pyqtSignal() def __init__(self, settings): super(DfConfig, self).__init__() self.settings = settings self.allowed_df_services = {} self.df_qlr_file = None # Netværk fetchers self._services_network_fetcher = QgsNetworkContentFetcher() self._qlr_network_fetcher = QgsNetworkContentFetcher() self._services_network_fetcher.finished.connect(self._handle_services_response) self._qlr_network_fetcher.finished.connect(self._handle_qlr_response) def begin_load(self): """Start indlæsning af konfiguration.""" # Generer cached filnavn baseret på token hash token_hash = hashlib.md5(self.settings.value("token").encode()).hexdigest() self.cached_df_qlr_filename = self.settings.value("cache_path") + token_hash + "_dataforsyning_data.qlr" if self.settings.is_set(): self._request_services() else: self.df_settings_warning.emit() def _request_services(self): """Hent brugerens tilladte services fra API.""" url = self.insert_token(DF_SERVICES_URL) self._services_network_fetcher.fetchContent(QUrl(url)) def _handle_services_response(self): """Håndter svar fra services API.""" reply = self._services_network_fetcher.reply() if reply.error(): self.df_con_error.emit() return response = str(reply.readAll(), "utf-8") doc = json.loads(response) # Gem tilladte services self.allowed_df_services = {"any_type": {"services": []}} for service in doc: self.allowed_df_services["any_type"]["services"].append(service["name"]) # Fortsæt med at hente QLR self._get_qlr_file() def _get_qlr_file(self): """Hent QLR konfigurationsfil (fra cache eller netværk).""" import os if os.path.exists(self.cached_df_qlr_filename): file_time = datetime.datetime.fromtimestamp( os.path.getmtime(self.cached_df_qlr_filename) ) if file_time > datetime.datetime.now() - FILE_MAX_AGE: self._load_config_from_cached_df_qlr() return # Hent fra netværk url = self.settings.value("df_qlr_url") self._qlr_network_fetcher.fetchContent(QUrl(url)) def user_has_access(self, service_name): """Check om bruger har adgang til en service.""" return service_name in self.allowed_df_services["any_type"]["services"] def insert_token(self, text): """Indsæt token i tekst med {{df_token}} placeholder.""" return text.replace("{{df_token}}", self.settings.value("token")) def get_categories(self): """Hent kategorier filtreret efter brugerens adgang.""" return self.categories def get_maplayer_node(self, layer_id): """Hent XML node for et lag.""" return self.df_qlr_file.get_maplayer_node(layer_id) ``` -------------------------------- ### Manage Plugin Settings with Settings Class (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The Settings class manages all plugin configurations, including API tokens, cache paths, and custom QLR files. It utilizes QGIS's settings system for persistent storage and provides methods to add, retrieve, and update settings. Dependencies include QGIS PyQt modules and custom setting types. ```Python from qgis.PyQt import QtCore from PyQt5.QtCore import QFileInfo from .qgissettingmanager import SettingManager, String, Bool, Scope CONFIG_FILE_URL = 'https://qgisplugin.dataforsyningen.dk/qgis_plugin_dataforsyningen_udentoken.qlr' class Settings(SettingManager): settings_updated = QtCore.pyqtSignal() def __init__(self): SettingManager.__init__(self, 'Dataforsyningen') # Dataforsyningen token (påkrævet) self.add_setting(String('token', Scope.Global, '')) # Brug brugerdefineret QLR-fil self.add_setting(Bool('use_custom_file', Scope.Global, False)) self.add_setting(String('custom_qlr_file', Scope.Global, '')) # Vis kun baggrundskort fra Dataforsyningen self.add_setting(Bool('only_background', Scope.Global, False)) # Cache mappe til QLR-filer path = QFileInfo(__file__).path() df_path = path + '/df/' self.add_setting(String('cache_path', Scope.Global, df_path)) # URL til QLR konfigurationsfil self.add_setting(String('df_qlr_url', Scope.Global, CONFIG_FILE_URL)) def is_set(self): """Check om token er konfigureret.""" return bool(self.value('token')) def emit_updated(self): """Signal at indstillinger er opdateret.""" self.settings_updated.emit() # Eksempel på brug af indstillinger settings = Settings() # Hent token token = settings.value('token') # Sæt token settings.set_value('token', 'dit-dataforsyningen-token') # Check om konfigureret if settings.is_set(): print("Token er konfigureret") ``` -------------------------------- ### Supported Widget Types Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Lists the types of Qt/QGIS widgets that are automatically supported for setting management. ```APIDOC ## Supported Widget Types ### Description The `SettingManager` automatically detects and handles various widget types for different setting data types. If a widget type is not supported, an error will be raised. ### Strings - `QLineEdit` - `QComboBox` (Options: `comboMode` as `data` or `text`) - `QButtonGroup` (Uses checked widget text) - `QgsMapLayerComboBox` (Uses layer ID) ### Booleans - `QCheckBox` - Any checkable widget (e.g., `QGroupBox`) ### Colors - `QgsColorButton` (Native QGIS widget) - Other widgets (label, pushbutton recommended). Options: `allowAlpha` (boolean), `dialogTitle` (string). ### Integers - `QLineEdit` - `QSpinBox` - `QSlider` - `QComboBox` (Uses combo box index) ### Doubles - `QLineEdit` - `QDoubleSpinBox` ### Stringlist - `QListWidget` (Checks items whose text is in the list) - `QButtonGroup` (Checks items whose name is in the list) ### Extending Support New widget types can be easily added. If you encounter an unsupported widget, consider contributing or opening an issue on the project's GitHub repository. ``` -------------------------------- ### QlrFile Class Methods Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt Methods for parsing QLR XML structures to retrieve layer groups and service information. ```APIDOC ## GET /QlrFile/groups ### Description Parses the provided QLR XML content to extract a hierarchical list of layer groups and their associated layers. ### Method GET (Class Method: get_groups_with_layers) ### Parameters #### Request Body - **xml** (string) - Required - The raw XML content of the QLR file. ### Response #### Success Response (200) - **result** (list) - A list of objects containing 'name' (group name) and 'layers' (list of layer objects). #### Response Example [ { "name": "Topographic Maps", "layers": [ { "name": "Roads", "id": "roads_123", "service": "wms_service_name" } ] } ] ## GET /QlrFile/maplayer-service ### Description Extracts the service name from a specific maplayer node by parsing the datasource URL string. ### Method GET (Class Method: get_maplayer_service) ### Parameters #### Request Body - **maplayer_node** (XMLNode) - Required - The DOM node representing the maplayer. ### Response #### Success Response (200) - **service** (string) - The extracted service name from the datasource URL path. ``` -------------------------------- ### Define a Setting Manager Class Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Create a custom class inheriting from SettingManager to define and initialize plugin settings. Settings are added using the add_setting method with specified types, scopes, and default values. ```python from qgissettingmanager import * class MySettings(SettingManager): def __init__(self): SettingManager.__init__(self, my_plugin_name) self.add_setting( Bool("my_setting", Scope.Global, True) ) ``` -------------------------------- ### Bind Settings to Dialog Widgets Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Automatically synchronize dialog widgets with settings by subclassing SettingDialog. Widgets must be named identically to their corresponding setting keys for automatic detection. ```python class MyDialog(QDialog, Ui_myDialog, SettingDialog): def __init__(self): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings) ``` -------------------------------- ### Accessing and Modifying Settings Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Shows how to retrieve and update setting values within your plugin. ```APIDOC ## Accessing and Modifying Settings ### Description Once your settings are defined, you can easily access and modify their values using the `value` and `setValue` methods. ### Usage 1. **Instantiate your settings class:** ```python import MySettings self.settings = MySettings() ``` 2. **Get a setting value:** ```python myVariable = self.settings.value("myVariable") ``` 3. **Set a setting value:** ```python self.settings.set_value("myVariable", False) ``` ### Removing Settings Settings can be removed from the registry (local or project-wise) using the `remove` method: ```python MySettings().remove('my_setting') ``` ``` -------------------------------- ### Load and Parse Local QLR Files in Python Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt This Python code defines the LocalConfig class responsible for loading and parsing user-defined QLR files. It handles file existence checks, reading file content, and converting QLR groups into a structured category format for QGIS. Dependencies include os.path and QGIS PyQt modules. ```Python import os.path from qgis.PyQt.QtCore import QFile, QIODevice from .qlr_file import QlrFile class LocalConfig: def __init__(self, settings): self.settings = settings self.settings.settings_updated.connect(self.reload) self.categories = [] self.qlr_file = None self.reload() def reload(self): """Genindlæs lokal konfiguration.""" self.categories = [] if self.settings.value("use_custom_file"): self.local_qlr_filename = self.settings.value("custom_qlr_file") if os.path.exists(self.local_qlr_filename): self.qlr_file = self.get_local_qlr_file() if self.qlr_file: self.categories = self.get_local_categories() def get_local_qlr_file(self): """Læs og parse lokal QLR fil.""" f = QFile(self.local_qlr_filename) f.open(QIODevice.ReadOnly) return QlrFile(f.readAll()) def get_local_categories(self): """Konverter QLR grupper til kategorier.""" local_categories = [] for group in self.qlr_file.get_groups_with_layers(): category = { "name": group["name"], "selectables": [] } for layer in group["layers"]: category["selectables"].append({ "type": "layer", "source": "local", # Markér som lokal kilde "name": layer["name"], "id": layer["id"], }) if category["selectables"]: local_categories.append(category) return local_categories def get_categories(self): """Hent alle lokale kategorier.""" return self.categories def get_maplayer_node(self, layer_id): """Hent maplayer node fra lokal QLR.""" return self.qlr_file.get_maplayer_node(layer_id) ``` -------------------------------- ### SettingDialog Update Modes Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Details the different modes for updating settings when using SettingDialog. ```APIDOC ## SettingDialog Update Modes ### Description Control when settings are updated in relation to dialog interactions using the `mode` parameter in `SettingDialog`. ### Usage ```python SettingDialog(settingManager, mode=UpdateMode.DialogAccept) ``` ### Modes - `UpdateMode.NoUpdate`: Settings are not updated automatically. - `UpdateMode.DialogAccept` (default): Settings are updated only when the dialog is accepted. - `UpdateMode.WidgetUpdate`: Settings are updated immediately as widget values change. ``` -------------------------------- ### QGIS Layer Locator Filter Implementation (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt Implements a custom QGIS locator filter to enable searching and adding layers directly from the QGIS locator bar. It integrates with Dataforsyningen to provide searchable layers, their categories, and actions to add them. Dependencies include QGIS core modules. ```Python from qgis.core import QgsLocatorFilter, QgsLocatorResult class LayerLocatorFilter(QgsLocatorFilter): def __init__(self, data=None): super(LayerLocatorFilter, self).__init__() self.data = data if data else LayerLocatorFilterData() def set_searchable_layers(self, searchable_layers): """Sæt lag der kan søges i.""" self.data.set_searchable_layers(searchable_layers) def clone(self): """Klon filter til threading.""" return LayerLocatorFilter(data=self.data) def name(self): return "dataforsyningen" def displayName(self): return "Dataforsyningen" def prefix(self): """Prefix til direkte søgning (dataforsyningen:søgeord).""" return "dataforsyningen" def priority(self): return QgsLocatorFilter.Low def flags(self): return QgsLocatorFilter.FlagFast def fetchResults(self, query, context, feedback): """Søg efter matchende lag.""" for layer in self.data.get_matching_layers(query): result = QgsLocatorResult() result.filter = self result.displayString = layer["title"] result.userData = layer["actionindex"] result.score = 0 self.resultFetched.emit(result) def triggerResult(self, result): """Aktivér valgt resultat (tilføj lag).""" action = self.data.get_action(result.userData) action.activate(0) class LayerLocatorFilterData: """Delt data for søgefilter.""" def __init__(self): self.actions = [] self.searchable_layers = [] def set_searchable_layers(self, searchable_layers): """Initialiser søgbare lag.""" self.searchable_layers = searchable_layers self.actions = [] for i, layer in enumerate(self.searchable_layers): self.actions.append(layer["action"]) layer["actionindex"] = i layer["searchstring"] = self.create_search_string(layer) layer["title"] += f" ({layer['category']}, Dataforsyningen)" def create_search_string(self, layer): """Opret normaliseret søgestreng.""" search = f"{layer['category']} {layer['title']}" search = search.replace("/", " ").replace("-", " ") return " " + search.lower() def get_matching_layers(self, query): """Find lag der matcher søgeforespørgsel.""" search_terms = query.lower().split() matching = [] for layer in self.searchable_layers: matches = sum( 1 for term in search_terms if f" {term}" in layer["searchstring"] ) if matches == len(search_terms): matching.append(layer) return matching def get_action(self, index): """Hent action for lag-index.""" return self.actions[index] # Eksempel på søgning data = LayerLocatorFilterData() data.set_searchable_layers([ {"title": "Skærmkort", "category": "Baggrundskort", "action": some_action}, {"title": "Kommunegrænser", "category": "Administrative", "action": other_action}, ]) # Søg efter "skærm" results = data.get_matching_layers("skærm") # Returnerer: [{"title": "Skærmkort (Baggrundskort, Dataforsyningen)", ...}] ``` -------------------------------- ### Access and Modify Settings Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Retrieve or update setting values programmatically using the value and set_value methods on an instance of your settings class. ```python import MySettings self.settings = MySettings() myVariable = self.settings.value("myVariable") self.settings.set_value("myVariable", False) ``` -------------------------------- ### Customizing Dialog Behavior Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Provides methods for adding custom logic before dialog acceptance and handling `showEvent`. ```APIDOC ## Customizing Dialog Behavior ### Description Customize the behavior of `SettingDialog` by overriding methods for pre-acceptance checks and handling `showEvent`. ### Before Accept Check Override `SettingDialog.before_accept_dialog()` to perform custom validation. Settings are saved only if this method returns `True`. ```python class MyDialog(QDialog, Ui_myDialog, SettingDialog): # ... (init method as above) def before_accept_dialog(self): # Add your custom checks here if not self.some_condition_is_met(): return False return True ``` ### Handling showEvent If you redefine `showEvent` in your dialog class, ensure you call the parent `showEvent` to maintain `SettingDialog` functionality. ```python class MyDialog(QDialog, Ui_myDialog, SettingDialog): # ... (init method as above) def showEvent(self, e): SettingDialog.showEvent(self, e) # Call parent showEvent first # Add your own stuff after the setting dialog's showEvent logic ``` ``` -------------------------------- ### Configure Setting Update Behavior Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md Control when settings are updated during dialog interaction using the UpdateMode parameter in SettingDialog. ```python SettingDialog(settingManager, mode=UpdateMode.DialogAccept) ``` -------------------------------- ### Logging Utility Function (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt A simple utility function to log messages to the QGIS message log, categorized under 'Dataforsyningen plugin'. This helps in debugging and monitoring plugin operations. ```python def log_message(message): """Log besked til QGIS beskedlog.""" QgsMessageLog.logMessage(message, "Dataforsyningen plugin") ``` -------------------------------- ### Parse QLR XML to Extract Layer Groups and Services (Python) Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The `QlrFile` class parses QLR XML content to extract hierarchical layer information. It identifies layer groups, layers within those groups, and determines the service name from the layer's datasource URL. This is useful for understanding QGIS project layer configurations. ```Python import urllib.parse from qgis.PyQt import QtXml class QlrFile: def __init__(self, xml): """Initialiser med QLR XML indhold.""" self.doc = QtXml.QDomDocument() self.doc.setContent(xml) def get_groups_with_layers(self): """Hent alle grupper med deres lag. Returns: list: [{'name': gruppenavn, 'layers': [{'name': lagnavn, 'id': lagid, 'service': servicenavn}]}] """ result = [] groups = self.doc.elementsByTagName("layer-tree-group") for i in range(groups.count()): group = groups.at(i) group_name = group.toElement().attribute("name") if group_name: layers = self.get_group_layers(group) if layers: result.append({"name": group_name, "layers": layers}) return result def get_group_layers(self, group_node): """Hent lag fra en gruppe. Returns: list: [{'name': lagnavn, 'id': lagid, 'service': servicenavn}] """ result = [] child_nodes = group_node.childNodes() for i in range(child_nodes.count()): node = child_nodes.at(i) if node.nodeName() == "layer-tree-layer": layer_name = node.toElement().attribute("name") layer_id = node.toElement().attribute("id") maplayer_node = self.get_maplayer_node(layer_id) if maplayer_node: service = self.get_maplayer_service(maplayer_node) if service: result.append({ "name": layer_name, "id": layer_id, "service": service }) return result def get_maplayer_node(self, layer_id): """Hent maplayer XML node ud fra lag-id.""" return self.getFirstChildByTagNameValue( self.doc.documentElement(), "maplayer", "id", layer_id ) def get_maplayer_service(self, maplayer_node): """Ekstraher servicenavn fra datasource URL.""" datasource_nodes = maplayer_node.toElement().elementsByTagName("datasource") if datasource_nodes.count() == 1: datasource = datasource_nodes.at(0).toElement().text() # Find URL parameter for part in datasource.split("&") + datasource.split(" "): if part.startswith("url"): url_only = part[part.index("=") + 1:] url_path = urllib.parse.urlparse(url_only).path[1:] url_split = url_path.split("/") # Returner servicenavn return url_split[1] if len(url_split) >= 2 else url_path return None # Eksempel på brug from qgis.PyQt.QtCore import QFile, QIODevice # Læs QLR fil f = QFile("/sti/til/config.qlr") f.open(QIODevice.ReadOnly) xml_content = f.readAll() # Parse QLR qlr = QlrFile(xml_content) # Hent alle grupper med lag groups = qlr.get_groups_with_layers() for group in groups: print(f"Kategori: {group['name']}") for layer in group['layers']: print(f" - {layer['name']} (service: {layer['service']})") ``` -------------------------------- ### LayerLocatorFilter - Search Functionality Source: https://context7.com/sdfidk/qgis-dataforsyningen/llms.txt The LayerLocatorFilter integrates with QGIS's locator search bar, allowing users to search for and add layers directly from the search bar. This section provides the Python code for the filter. ```APIDOC ## LayerLocatorFilter - Søgefunktion `LayerLocatorFilter` integrerer med QGIS' lokator-søgefelt, så brugere kan søge efter og tilføje lag direkte fra søgefeltet. ```python from qgis.core import QgsLocatorFilter, QgsLocatorResult class LayerLocatorFilter(QgsLocatorFilter): def __init__(self, data=None): super(LayerLocatorFilter, self).__init__() self.data = data if data else LayerLocatorFilterData() def set_searchable_layers(self, searchable_layers): """Sæt lag der kan søges i.""" self.data.set_searchable_layers(searchable_layers) def clone(self): """Klon filter til threading.""" return LayerLocatorFilter(data=self.data) def name(self): return "dataforsyningen" def displayName(self): return "Dataforsyningen" def prefix(self): """Prefix til direkte søgning (dataforsyningen:søgeord).""" return "dataforsyningen" def priority(self): return QgsLocatorFilter.Low def flags(self): return QgsLocatorFilter.FlagFast def fetchResults(self, query, context, feedback): """Søg efter matchende lag.""" for layer in self.data.get_matching_layers(query): result = QgsLocatorResult() result.filter = self result.displayString = layer["title"] result.userData = layer["actionindex"] result.score = 0 self.resultFetched.emit(result) def triggerResult(self, result): """Aktivér valgt resultat (tilføj lag).""" action = self.data.get_action(result.userData) action.activate(0) class LayerLocatorFilterData: """Delt data for søgefilter.""" def __init__(self): self.actions = [] self.searchable_layers = [] def set_searchable_layers(self, searchable_layers): """Initialiser søgbare lag.""" self.searchable_layers = searchable_layers self.actions = [] for i, layer in enumerate(self.searchable_layers): self.actions.append(layer["action"]) layer["actionindex"] = i layer["searchstring"] = self.create_search_string(layer) layer["title"] += f" ({layer['category']}, Dataforsyningen)" def create_search_string(self, layer): """Opret normaliseret søgestreng.""" search = f"{layer['category']} {layer['title']}" search = search.replace("/", " ").replace("-", " ") return " " + search.lower() def get_matching_layers(self, query): """Find lag der matcher søgeforespørgsel.""" search_terms = query.lower().split() matching = [] for layer in self.searchable_layers: matches = sum( 1 for term in search_terms if f" {term}" in layer["searchstring"] ) if matches == len(search_terms): matching.append(layer) return matching def get_action(self, index): """Hent action for lag-index.""" return self.actions[index] # Eksempel på søgning data = LayerLocatorFilterData() data.set_searchable_layers([ {"title": "Skærmkort", "category": "Baggrundskort", "action": some_action}, {"title": "Kommunegrænser", "category": "Administrative", "action": other_action}, ]) # Søg efter "skærm" results = data.get_matching_layers("skærm") # Returnerer: [{"title": "Skærmkort (Baggrundskort, Dataforsyningen)", ...}] ``` ``` -------------------------------- ### Override ShowEvent in SettingDialog Source: https://github.com/sdfidk/qgis-dataforsyningen/blob/main/Dataforsyningen/mysettings/qgissettingmanager/README.md When overriding the showEvent method in a SettingDialog subclass, ensure the base class showEvent is called to maintain proper functionality. ```python def showEvent(self, e): settingDialog.showEvent(self, e) # do your own stuff ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.