Skip to content

Commit

Permalink
Merge branch 'layer_exceptions' into 'main'
Browse files Browse the repository at this point in the history
Layer exceptions

Closes #6

See merge request qgis/hvbg-filterplugin!8
  • Loading branch information
pgipper committed Nov 12, 2022
2 parents da4f19f + be058c8 commit 2fdf704
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 34 deletions.
8 changes: 4 additions & 4 deletions controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from qgis.utils import iface

from .filters import FilterDefinition, Predicate, FilterManager
from .helpers import getPostgisLayers, removeFilterFromLayer, addFilterToLayer, refreshLayerTree
from .helpers import getPostgisLayers, removeFilterFromLayer, addFilterToLayer, refreshLayerTree, hasLayerException
from .settings import FILTER_COMMENT_START, FILTER_COMMENT_STOP


Expand Down Expand Up @@ -51,10 +51,10 @@ def onLayersAdded(self, layers: Iterable[QgsMapLayer]):

def updateLayerFilters(self, checked: bool):
for layer in getPostgisLayers(QgsProject.instance().mapLayers().values()):
if not checked:
removeFilterFromLayer(layer)
else:
if checked and not hasLayerException(layer):
addFilterToLayer(layer, self.currentFilter)
else:
removeFilterFromLayer(layer)
refreshLayerTree()

def updateProjectLayers(self, checked):
Expand Down
12 changes: 10 additions & 2 deletions helpers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import Any, List, Iterable

from qgis.core import QgsSettings, QgsMapLayer, QgsMapLayerType, QgsVectorLayer, QgsMessageLog, Qgis
from qgis.core import QgsExpressionContextUtils, QgsSettings, QgsMapLayer, QgsMapLayerType, QgsVectorLayer

from .settings import GROUP, FILTER_COMMENT_START, FILTER_COMMENT_STOP
from .settings import GROUP, FILTER_COMMENT_START, FILTER_COMMENT_STOP, LAYER_EXCEPTION_VARIABLE


def saveSettingsValue(key: str, value: Any):
Expand Down Expand Up @@ -72,6 +72,14 @@ def getLayerGeomName(layer: QgsVectorLayer):
return layer.dataProvider().uri().geometryColumn()


def hasLayerException(layer: QgsVectorLayer) -> bool:
return QgsExpressionContextUtils.layerScope(layer).variable(LAYER_EXCEPTION_VARIABLE) == 'true'


def setLayerException(layer: QgsVectorLayer, exception: bool) -> None:
QgsExpressionContextUtils.setLayerVariable(layer, LAYER_EXCEPTION_VARIABLE, exception)


def getTestFilterDefinition():
from .filters import Predicate, FilterDefinition
name = 'museumsinsel'
Expand Down
Binary file modified i18n/map_filter_de.qm
Binary file not shown.
97 changes: 73 additions & 24 deletions i18n/map_filter_de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,79 +109,97 @@
<message>
<location filename="../controller.py" line="70"/>
<source>Select a polygon layer</source>
<translation>Polygonlayer auswählen</translation>
<translation type="obsolete">Polygonlayer auswählen</translation>
</message>
<message>
<location filename="../controller.py" line="73"/>
<source>No features selected</source>
<translation>Keine Features gewählt</translation>
<translation type="obsolete">Keine Features gewählt</translation>
</message>
<message>
<location filename="../controller.py" line="19"/>
<source>New Filter</source>
<translation>Neuer Filter</translation>
<translation type="obsolete">Neuer Filter</translation>
</message>
</context>
<context>
<name>ExtentDialog</name>
<message>
<location filename="../widgets.py" line="34"/>
<location filename="../widgets.py" line="43"/>
<source>Set rectangular filter geometry</source>
<translation>Rechteckige Filtergeometrie setzen</translation>
</message>
</context>
<context>
<name>FilterController</name>
<message>
<location filename="../controller.py" line="21"/>
<source>New Filter</source>
<translation>Neuer Filter</translation>
</message>
<message>
<location filename="../controller.py" line="75"/>
<source>Select a polygon layer</source>
<translation>Polygonlayer auswählen</translation>
</message>
<message>
<location filename="../controller.py" line="78"/>
<source>No features selected</source>
<translation>Keine Features gewählt</translation>
</message>
</context>
<context>
<name>FilterManager</name>
<message>
<location filename="../filters.py" line="84"/>
<location filename="../filters.py" line="102"/>
<source>Current filter definition is not valid</source>
<translation>Aktuelle Filterdefinition ist ungültig</translation>
</message>
<message>
<location filename="../filters.py" line="87"/>
<location filename="../filters.py" line="105"/>
<source>Please provide a name for the filter</source>
<translation>Bitte benennen Sie erst den Filter</translation>
</message>
<message>
<location filename="../filters.py" line="106"/>
<location filename="../filters.py" line="124"/>
<source>Overwrite settings for filter</source>
<translation>Einstellungen überschreiben für Filter</translation>
</message>
<message>
<location filename="../filters.py" line="107"/>
<location filename="../filters.py" line="125"/>
<source>Overwrite?</source>
<translation>Überschreiben?</translation>
</message>
<message>
<location filename="../filters.py" line="111"/>
<location filename="../filters.py" line="129"/>
<source>Delete filter</source>
<translation>Filter löschen</translation>
</message>
<message>
<location filename="../filters.py" line="112"/>
<location filename="../filters.py" line="130"/>
<source>Delete?</source>
<translation>Löschen?</translation>
</message>
<message>
<location filename="../filters.py" line="101"/>
<location filename="../filters.py" line="119"/>
<source>Current settings will be lost. Apply anyway?</source>
<translation>Aktuelle Einstellungen gehen verloren. Trotzdem anwenden?</translation>
</message>
<message>
<location filename="../filters.py" line="102"/>
<location filename="../filters.py" line="120"/>
<source>Continue?</source>
<translation>Fortfahren?</translation>
</message>
</context>
<context>
<name>FilterToolbar</name>
<message>
<location filename="../widgets.py" line="216"/>
<location filename="../widgets.py" line="263"/>
<source>Rectangular filter</source>
<translation>Rechteckiger Filter</translation>
</message>
<message>
<location filename="../widgets.py" line="221"/>
<location filename="../widgets.py" line="268"/>
<source>Filter from selected features</source>
<translation>Filter aus gewählten Features</translation>
</message>
Expand All @@ -191,40 +209,71 @@
<translation type="obsolete">Filter ein/aus</translation>
</message>
<message>
<location filename="../widgets.py" line="230"/>
<location filename="../widgets.py" line="282"/>
<source>Save current filter</source>
<translation>Filter speichern</translation>
</message>
<message>
<location filename="../widgets.py" line="235"/>
<location filename="../widgets.py" line="287"/>
<source>Manage filters</source>
<translation>Filter verwalten</translation>
</message>
<message>
<location filename="../widgets.py" line="178"/>
<location filename="../widgets.py" line="225"/>
<source>Filter Toolbar</source>
<translation>Filterwerkzeugleiste</translation>
</message>
<message>
<location filename="../widgets.py" line="211"/>
<location filename="../widgets.py" line="349"/>
<source>Show filter geometry</source>
<translation>Filtergeometrie anzeigen</translation>
</message>
<message>
<location filename="../widgets.py" line="252"/>
<location filename="../widgets.py" line="306"/>
<source>Activate filter</source>
<translation>Filter aktivieren</translation>
</message>
<message>
<location filename="../widgets.py" line="250"/>
<location filename="../widgets.py" line="304"/>
<source>Deactivate filter</source>
<translation>Filter deaktivieren</translation>
</message>
<message>
<location filename="../widgets.py" line="264"/>
<location filename="../widgets.py" line="319"/>
<source>No filter geometry set</source>
<translation>Keine Filtergeometrie gesetzt</translation>
</message>
<message>
<location filename="../widgets.py" line="277"/>
<source>Exclude layers from filter</source>
<translation>Ausnahmen festlegen</translation>
</message>
<message>
<location filename="../widgets.py" line="344"/>
<source>Hide filter geometry</source>
<translation>Filtergeometrie verstecken</translation>
</message>
</context>
<context>
<name>LayerExceptionsDialog</name>
<message>
<location filename="../widgets.py" line="78"/>
<source>Exclude layers from filter</source>
<translation></translation>
</message>
</context>
<context>
<name>LayerModel</name>
<message>
<location filename="../models.py" line="51"/>
<source>Layer has no spatial index</source>
<translation>Layer hat keinen räumlichen Index</translation>
</message>
<message>
<location filename="../models.py" line="55"/>
<source>Layer type is not supported</source>
<translation>Layertyp wird nicht unterstützt</translation>
</message>
</context>
<context>
<name>ManageFiltersDialog</name>
Expand Down Expand Up @@ -264,12 +313,12 @@
<translation>Schließen</translation>
</message>
<message>
<location filename="../widgets.py" line="125"/>
<location filename="../widgets.py" line="171"/>
<source>Change Name</source>
<translation>Namen ändern</translation>
</message>
<message>
<location filename="../widgets.py" line="125"/>
<location filename="../widgets.py" line="171"/>
<source>New Name:</source>
<translation>Neuer Name:</translation>
</message>
Expand All @@ -285,7 +334,7 @@
<context>
<name>PredicateButton</name>
<message>
<location filename="../widgets.py" line="139"/>
<location filename="../widgets.py" line="185"/>
<source>Geometric predicate</source>
<translation>Räumlicher Operator</translation>
</message>
Expand Down
32 changes: 31 additions & 1 deletion models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from typing import Any

from PyQt5.QtCore import QAbstractListModel, Qt, QModelIndex
from qgis.core import QgsMessageLog, Qgis
from PyQt5.QtGui import QStandardItemModel, QStandardItem

from qgis.core import QgsMessageLog, Qgis, QgsProject, QgsFeatureSource, QgsApplication

from .helpers import hasLayerException
from .settings import SUPPORTED_PROVIDERS
from .filters import FilterManager


Expand Down Expand Up @@ -29,3 +35,27 @@ def removeRows(self, row: int, count: int = 1, parent: QModelIndex = ...) -> boo
self.filters = self.filters[:row] + self.tableData[row + count:]
self.endRemoveRows()
return True


class LayerModel(QStandardItemModel):
def __init__(self, parent=None):
super(LayerModel, self).__init__(parent)

for layer in [layerNode.layer() for layerNode in QgsProject.instance().layerTreeRoot().findLayers()]:
item = QStandardItem(layer.name())
item.setData(layer, role=DataRole)
item.setFlags(Qt.ItemIsUserCheckable)
if layer.providerType() in SUPPORTED_PROVIDERS:
item.setEnabled(True)
if layer.dataProvider().hasSpatialIndex() == QgsFeatureSource.SpatialIndexNotPresent:
item.setToolTip(self.tr('Layer has no spatial index'))
item.setIcon(QgsApplication.getThemeIcon('/mIconWarning.svg'))
else:
item.setEnabled(False)
item.setToolTip(self.tr('Layer type is not supported'))
if hasLayerException(layer):
item.setCheckState(Qt.Checked)
else:
item.setCheckState(Qt.Unchecked)
self.appendRow(item)

4 changes: 4 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
GROUP = 'MapFilter' # The section name for filter definitions stored in QSettings
LAYER_EXCEPTION_VARIABLE = 'MapFilterException'
SPLIT_STRING = '#!#!#' # String used to split filter definition parameters in QSettings

# The filter string might contain user-specific parts so we surround *our* filter
# string with text markers
FILTER_COMMENT_START = '/* MapFilter Plugin Start */'
FILTER_COMMENT_STOP = '/* MapFilter Plugin Stop */'

# The QGIS Provider Types that can be filtered by the plugin
SUPPORTED_PROVIDERS = ['postgres']
Loading

0 comments on commit 2fdf704

Please sign in to comment.