### 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.