Skip to content

Commit

Permalink
Merge branch 'auto_activate_filter' into 'main'
Browse files Browse the repository at this point in the history
auto_activate_filter

Closes #17, #21, and #22

See merge request qgis/hvbg-filterplugin!12
  • Loading branch information
pgipper committed Nov 16, 2022
2 parents 8da8953 + 8cfe95f commit fb3131f
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 137 deletions.
64 changes: 40 additions & 24 deletions controller.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Iterable, Optional, List

from PyQt5.QtCore import pyqtSignal, QObject
from qgis.core import QgsProject, QgsMapLayer, QgsMapLayerType, QgsWkbTypes, QgsGeometry, QgsCoordinateReferenceSystem
from qgis.core import Qgis, QgsProject, QgsMapLayer, QgsMapLayerType, QgsWkbTypes, QgsGeometry
from qgis.gui import QgsRubberBand
from qgis.utils import iface

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

Expand All @@ -14,25 +15,20 @@ class FilterController(QObject):
currentFilter: Optional[FilterDefinition]
rubberBands: Optional[List[QgsRubberBand]]

filterChanged = pyqtSignal(FilterDefinition)
filterChanged = pyqtSignal(object)

def __init__(self, parent: Optional[QObject] = None) -> None:
super().__init__(parent=parent)
self.currentFilter = FilterDefinition(
self.tr('New Filter'), '', QgsCoordinateReferenceSystem(), Predicate.INTERSECTS, False
)
self.currentFilter = None
self.rubberBands = []
self.toolbarIsActive = False

def onToggled(self, checked: bool) -> None:
self.toolbarIsActive = checked
if checked and not self.currentFilter.isValid:
return
self.updateProjectLayers(checked)
def removeFilter(self) -> None:
self.currentFilter = None
self.refreshFilter()

def updateConnectionProjectLayersAdded(self, checked):
def updateConnectionProjectLayersAdded(self):
self.disconnectProjectLayersAdded()
if checked:
if self.hasValidFilter():
QgsProject.instance().layersAdded.connect(self.onLayersAdded)

def disconnectProjectLayersAdded(self):
Expand All @@ -49,22 +45,21 @@ def onLayersAdded(self, layers: Iterable[QgsMapLayer]):
filterString = f'{FILTER_COMMENT_START}{filterCondition}{FILTER_COMMENT_STOP}'
layer.setSubsetString(filterString)

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

def updateProjectLayers(self, checked):
self.updateConnectionProjectLayersAdded(checked)
self.updateLayerFilters(checked)
def updateProjectLayers(self):
self.updateConnectionProjectLayersAdded()
self.updateLayerFilters()

def refreshFilter(self):
self.filterChanged.emit(self.currentFilter)
if self.currentFilter.isValid:
self.updateProjectLayers(self.toolbarIsActive)
self.updateProjectLayers()

def setFilterFromSelection(self):
layer = iface.activeLayer()
Expand All @@ -79,7 +74,7 @@ def setFilterFromSelection(self):
return
crs = iface.activeLayer().crs()
geom = QgsGeometry().collectGeometry([feature.geometry() for feature in layer.selectedFeatures()])

self.initFilter()
self.currentFilter.crs = crs
self.currentFilter.wkt = geom.asWkt()
self.refreshFilter()
Expand All @@ -92,6 +87,27 @@ def setFilterBbox(self, bbox: bool):
self.currentFilter.bbox = bbox
self.refreshFilter()

def saveCurrentFilter(self):
saveFilterDefinition(self.currentFilter)
def initFilter(self):
self.currentFilter = FilterDefinition.defaultFilter()

def hasValidFilter(self):
return self.currentFilter and self.currentFilter.isValid

def startSketchingTool(self):
self.mapTool = PolygonTool()
self.mapTool.sketchFinished.connect(self.onSketchFinished)
iface.mapCanvas().setMapTool(self.mapTool)

def stopSketchingTool(self):
iface.mapCanvas().unsetMapTool(self.mapTool)
self.mapTool.deactivate()

def onSketchFinished(self, geometry: QgsGeometry):
self.stopSketchingTool()
if not geometry.isGeosValid():
iface.messageBar().pushMessage(self.tr("Geometry is not valid"), level=Qgis.Warning, duration=3)
return
self.initFilter()
self.currentFilter.wkt = geometry.asWkt()
self.currentFilter.crs = QgsProject.instance().crs()
self.refreshFilter()
19 changes: 13 additions & 6 deletions filters.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from dataclasses import dataclass
from dataclasses import dataclass, replace
from enum import Enum, IntEnum
from typing import List, Optional
from typing import List

from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QMessageBox
from qgis.core import QgsVectorLayer, QgsGeometry, QgsCoordinateReferenceSystem
from qgis.utils import iface
Expand Down Expand Up @@ -51,13 +50,11 @@ def filterString(self, layer: QgsVectorLayer) -> str:
if self.predicate == Predicate.DISJOINT:
spatial_predicate = "NOT ST_INTERSECTS"


wkt = self.wkt
if self.bbox:
rect = QgsGeometry.fromWkt(self.wkt).boundingBox()
wkt = QgsGeometry.fromRect(rect).asWkt()


geom_name = getLayerGeomName(layer)
return template.format(
spatial_predicate=spatial_predicate,
Expand All @@ -84,14 +81,21 @@ def fromStorageString(value: str) -> 'FilterDefinition':
bbox = bool(bbox_str == 'True')
return FilterDefinition(name, wkt, crs, predicate, bbox)

@staticmethod
def defaultFilter():
return FilterDefinition(tr('New Filter'), '', QgsCoordinateReferenceSystem(), Predicate.INTERSECTS, False)

@property
def isValid(self) -> bool:
return all([self.wkt, self.crs.isValid(), self.predicate])
return all([self.geometry.isGeosValid(), self.crs.isValid(), self.predicate])

@property
def isSaved(self) -> bool:
return self.storageString == readSettingsValue(self.name)

def copy(self):
return replace(self)


def loadFilterDefinition(name: str) -> FilterDefinition:
return FilterDefinition.fromStorageString(readSettingsValue(name))
Expand All @@ -102,6 +106,9 @@ def loadAllFilterDefinitions() -> List[FilterDefinition]:


def saveFilterDefinition(filterDef: FilterDefinition) -> None:
if not filterDef:
iface.messageBar().pushInfo("", tr("No current filter"))
return
if not filterDef.isValid:
iface.messageBar().pushInfo("", tr("Current filter definition is not valid"))
return
Expand Down
Binary file modified i18n/map_filter_de.qm
Binary file not shown.
Loading

0 comments on commit fb3131f

Please sign in to comment.