Commit 8de02395 authored by Benjamin Jakimow's avatar Benjamin Jakimow
Browse files

Added EOTSVVectorLayerTools


refactoring of next/previous labeling options
Signed-off-by: Benjamin Jakimow's avatarBenjamin Jakimow benjamin.jakimow@geo.hu-berlin.de <benjamin.jakimow@geo.hu-berlin.de>
parent 2a26e275
Pipeline #15914 failed with stage
in 6 seconds
......@@ -14,26 +14,23 @@ class SpectralLibraryDockWidget(SpectralLibraryPanel):
assert isinstance(self.SLW, SpectralLibraryWidget)
self.mActionNextFeature = QAction('Next Feature', parent=self)
self.mActionNextFeature.setIcon(QIcon(':/images/themes/default/mActionAtlasNext.svg'))
self.mActionNextFeature.triggered.connect(
lambda *args,
lyr=self.speclib(),
vlt=self.SLW.vectorLayerTools():
gotoNextFeature(lyr, vlt)
)
self.mActionNextFeature.triggered.connect(self.onGotoNextFeature)
self.mActionPreviousFeature = QAction('Previous Feature', parent=self)
self.mActionPreviousFeature.setIcon(QIcon(':/images/themes/default/mActionAtlasPrev.svg'))
self.mActionPreviousFeature.triggered.connect(
lambda *args,
lyr=self.speclib(),
vlt=self.SLW.vectorLayerTools():
gotoPreviousFeature(lyr, vlt))
self.mActionPreviousFeature.triggered.connect(self.onGotoPreviousFeature)
self.SLW.mToolbar: QToolBar
self.SLW.mToolbar.insertActions(self.SLW.mActionToggleEditing,
[self.mActionPreviousFeature, self.mActionNextFeature])
self.SLW.mToolbar.insertSeparator(self.SLW.mActionToggleEditing)
def onGotoNextFeature(self, *arg):
gotoNextFeature(self.SLW)
def onGotoPreviousFeature(self, *args):
gotoPreviousFeature(self.SLW)
def setVectorLayerTools(self, tools: QgsVectorLayerTools):
self.SLW.setVectorLayerTools(tools)
......
......@@ -12,6 +12,7 @@ from qgis.gui import QgsDockWidget, QgsSpinBox, QgsDoubleSpinBox, \
from eotimeseriesviewer.externals.qps.layerproperties import showLayerPropertiesDialog, AttributeTableWidget
from eotimeseriesviewer.timeseries import TimeSeriesDate, TimeSeriesSource
from eotimeseriesviewer.vectorlayertools import EOTSVVectorLayerTools
from eotimeseriesviewer import DIR_UI
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
......@@ -19,6 +20,7 @@ from qgis.PyQt.QtWidgets import *
from .externals.qps.utils import datetime64, loadUi, SpatialPoint, SpatialExtent
from .externals.qps.classification.classificationscheme import ClassInfo, ClassificationScheme
from .externals.qps.layerproperties import showLayerPropertiesDialog
from .externals.qps.vectorlayertools import VectorLayerTools
from .externals.qps.models import Option, OptionListModel
from .externals.qps.classification.classificationscheme import EDITOR_WIDGET_REGISTRY_KEY as CS_KEY
......@@ -639,9 +641,33 @@ class LabelAttributeTypeWidgetDelegate(QStyledItemDelegate):
model.setData(index, w.currentData(Qt.UserRole), Qt.EditRole)
def gotoNextFeature(layer: QgsVectorLayer,
tools: QgsVectorLayerTools,
visible_features: typing.List[int] = None) -> int:
class GotoFeatureOptions(enum.IntFlag):
SelectFeature = 1
PanToFeature = 2
ZoomToFeature = 4
FocusVisibility=8
def gotoFeature(fid: int, layer: QgsVectorLayer, tools: EOTSVVectorLayerTools, options: GotoFeatureOptions):
if GotoFeatureOptions.SelectFeature in options:
layer.selectByIds([fid])
if GotoFeatureOptions.PanToFeature in options:
tools.panToSelected(layer)
if GotoFeatureOptions.ZoomToFeature in options:
tools.zoomToSelected(layer)
if GotoFeatureOptions.FocusVisibility in options:
tools.focusVisibility()
def gotoNextFeature(layer: typing.Union[QgsVectorLayer, AttributeTableWidget],
tools: EOTSVVectorLayerTools = None,
visible_features: typing.List[int] = None,
options: GotoFeatureOptions = GotoFeatureOptions.SelectFeature
) -> int:
if isinstance(layer, AttributeTableWidget):
return gotoNextFeature(layer.mLayer, layer.vectorLayerTools(), layer.mMainView.filteredFeatures(), options)
assert isinstance(tools, QgsVectorLayerTools)
if isinstance(layer, QgsVectorLayer) and layer.hasFeatures():
if not isinstance(visible_features, list):
......@@ -663,15 +689,29 @@ def gotoNextFeature(layer: QgsVectorLayer,
else:
nextFID = visible_features[next_index]
layer.selectByIds([nextFID])
tools.panToSelected(layer)
gotoFeature(nextFID, layer, tools, options)
return nextFID
return None
def gotoPreviousFeature(layer: QgsVectorLayer,
tools: QgsVectorLayerTools,
visible_features: typing.List[int] = None):
def gotoPreviousFeature(layer: typing.Union[QgsVectorLayer, AttributeTableWidget],
tools: EOTSVVectorLayerTools = None,
visible_features: typing.List[int] = None,
options: GotoFeatureOptions = GotoFeatureOptions.SelectFeature):
"""
Selects the next feature
:param layer:
:type layer:
:param tools:
:type tools:
:param visible_features:
:type visible_features:
:return:
:rtype:
"""
if isinstance(layer, AttributeTableWidget):
return gotoPreviousFeature(layer.mLayer, layer.vectorLayerTools(), layer.mMainView.filteredFeatures(), options)
assert isinstance(tools, QgsVectorLayerTools)
if isinstance(layer, QgsVectorLayer) and layer.hasFeatures():
if not isinstance(visible_features, list):
......@@ -693,8 +733,7 @@ def gotoPreviousFeature(layer: QgsVectorLayer,
else:
nextFID = visible_features[next_index]
layer.selectByIds([nextFID])
tools.panToSelected(layer)
gotoFeature(nextFID, layer, tools, options)
class LabelWidget(AttributeTableWidget):
......@@ -705,31 +744,41 @@ class LabelWidget(AttributeTableWidget):
super().__init__(*args, *kwds)
self.mActionNextFeature = QAction('Next Feature', parent=self)
self.mActionNextFeature: QAction = QAction('Next Feature', parent=self)
self.mActionNextFeature.setIcon(QIcon(':/images/themes/default/mActionAtlasNext.svg'))
self.mActionNextFeature.triggered.connect(
lambda *args,
lyr=self.mLayer,
vlt=self.vectorLayerTools(),
mv=self.mMainView
: gotoNextFeature(lyr, vlt, visible_features=mv.filteredFeatures())
)
self.mActionNextFeature.triggered.connect(self.onGotoNextFeature)
self.mActionPreviousFeature = QAction('Previous Feature', parent=self)
self.mActionPreviousFeature: QAction = QAction('Previous Feature', parent=self)
self.mActionPreviousFeature.setIcon(QIcon(':/images/themes/default/mActionAtlasPrev.svg'))
self.mActionPreviousFeature.triggered.connect(
lambda *args,
lyr=self.mLayer,
vlt=self.vectorLayerTools(),
mv=self.mMainView
: gotoPreviousFeature(lyr, vlt, visible_features=mv.filteredFeatures()))
self.mOptionSelectBehaviour = QAction('Selection behaviour')
self.mOptionSelectBehaviour.setCheckable(True)
self.mOptionSelectBehaviour.setChecked(True)
self.mActionPreviousFeature.triggered.connect(self.onGotoPreviousFeature)
m = QMenu()
m.setToolTipsVisible(True)
self.mOptionAutoSelectNextFeature = m.addAction('Auto select')
self.mOptionAutoSelectNextFeature.setToolTip('Automatically selects the next / previous feature')
self.mOptionAutoSelectNextFeature.setCheckable(True)
self.mOptionAutoSelectNextFeature.setIcon(QIcon(':/images/themes/default/mIconSelected.svg'))
self.mOptionAutoPan = m.addAction('Auto pan')
self.mOptionAutoPan.setToolTip('Automatically pans the the next / previous feature')
self.mOptionAutoPan.setIcon(QIcon(':/images/themes/default/mActionPanToSelected.svg'))
self.mOptionAutoPan.setCheckable(True)
self.mOptionAutoUpdateImageVisibility = m.addAction('Auto visibility update')
self.mOptionAutoUpdateImageVisibility.setToolTip(
'Automatically updates the date visibility according to the displayed spatial extent.')
self.mOptionAutoUpdateImageVisibility.setCheckable(True)
self.mOptionAutoUpdateImageVisibility.setIcon(QIcon(':/eotimeseriesviewer/icons/mapview.svg'))
self.mActionNextFeature.setMenu(m)
m = QMenu()
m.setToolTipsVisible(True)
self.mOptionSelectBehaviour: QAction = m.addAction('Selection behaviour')
self.mOptionSelectBehaviour.setCheckable(True)
self.mOptionSelectBehaviour.setChecked(True)
self.mOptionSelectionSetSelection = m.addAction('Set Selection')
self.mOptionSelectionSetSelection.setIcon(QIcon(':/images/themes/default/mIconSelected.svg'))
self.mOptionSelectionSetSelection.setToolTip('Selects a feature.')
......@@ -781,6 +830,28 @@ class LabelWidget(AttributeTableWidget):
self.mLayer.featureAdded.connect(self.onLabelFeatureAdded)
self.mMainView.tableView().willShowContextMenu.connect(self.onShowContextMenu)
def onGotoNextFeature(self, *arg):
# todo: allow to got to unselected features. needs VectorLayerTools support panToFids / zoomToFids
gotoNextFeature(self, options=self.gotoFeatureOptions())
def gotoFeatureOptions(self) -> GotoFeatureOptions:
"""
Returns the GoTo-Feature options
:return:
:rtype:
"""
options = GotoFeatureOptions(0)
if self.mOptionAutoSelectNextFeature.isChecked():
options = options | GotoFeatureOptions.SelectFeature
if self.mOptionAutoPan.isChecked():
options = options | GotoFeatureOptions.PanToFeature
if self.mOptionAutoUpdateImageVisibility.isChecked():
options = options | GotoFeatureOptions.FocusVisibility
return options
def onGotoPreviousFeature(self, *args):
gotoPreviousFeature(self)
def onShowContextMenu(self, menu: QMenu, idx: QModelIndex):
fid = idx.data(QgsAttributeTableModel.FeatureIdRole)
......
......@@ -52,6 +52,7 @@ from eotimeseriesviewer.docks import LabelDockWidget, SpectralLibraryDockWidget
from eotimeseriesviewer.profilevisualization import ProfileViewDock
from eotimeseriesviewer.temporalprofiles import TemporalProfileLayer
from eotimeseriesviewer.mapvisualization import MapView, MapWidget
from eotimeseriesviewer.vectorlayertools import EOTSVVectorLayerTools
import eotimeseriesviewer.settings as eotsvSettings
from .externals.qps.speclib.core import SpectralProfile, SpectralLibrary
from .externals.qps.speclib.gui import SpectralLibraryPanel, SpectralLibraryWidget
......@@ -487,12 +488,12 @@ class EOTimeSeriesViewer(QgisInterface, QObject):
self.mPostDataLoadingArgs: dict = dict()
self.mVectorLayerTools: VectorLayerTools = VectorLayerTools()
self.mVectorLayerTools: EOTSVVectorLayerTools = EOTSVVectorLayerTools()
self.mVectorLayerTools.sigMessage.connect(lambda msg, level: self.logMessage(msg, LOG_MESSAGE_TAG, level))
self.mVectorLayerTools.sigPanRequest.connect(self.setSpatialCenter)
self.mVectorLayerTools.sigZoomRequest.connect(self.setSpatialExtent)
self.mVectorLayerTools.sigEditingStarted.connect(self.updateCurrentLayerActions)
self.mVectorLayerTools.sigFocusVisibility.connect(self.focusTimeSeriesDateVisibility)
# Save reference to the QGIS interface
# init empty time series
......@@ -1577,6 +1578,27 @@ class EOTimeSeriesViewer(QgisInterface, QObject):
"""Removes the plugin menu item and icon """
self.iface.removeToolBarIcon(self.action)
def focusTimeSeriesDateVisibility(self, *args, extent:SpatialExtent = None, date: TimeSeriesDate = None):
"""
Adjusts the visibility of TimeSeriesDates to the presence of data in a spatial extent.
:param args:
:type args:
:param extent:
:type extent:
:param date:
:type date:
:return:
:rtype:
"""
if extent is None:
extent = self.mapWidget().spatialExtent()
if date is None:
date = self.mapWidget().currentDate()
self.timeSeries().focusVisibility(extent, date_of_interest=date)
def updateCurrentLayerActions(self, *args):
"""
Enables/disables actions and buttons that relate to the current layer and its current state
......@@ -1617,7 +1639,7 @@ class EOTimeSeriesViewer(QgisInterface, QObject):
if isinstance(layer, (QgsRasterLayer, QgsVectorLayer)):
self.currentLayerChanged.emit(layer)
def vectorLayerTools(self) -> VectorLayerTools:
def vectorLayerTools(self) -> EOTSVVectorLayerTools:
return self.mVectorLayerTools
def show(self):
......
......@@ -1193,20 +1193,20 @@ class MapCanvas(QgsMapCanvas):
'with this map extent.')
action.triggered.connect(lambda *args,
ext=self.spatialExtent():
ts.focusVisibilityToExtent(ext=ext,
date_of_interest=date,
max_after=n_max,
max_before=n_max
))
ts.focusVisibility(ext=ext,
date_of_interest=date,
max_after=n_max,
max_before=n_max
))
action = menu.addAction('Update source visibility (all)')
action.setToolTip('Updates observation source visibility according their spatial intersection '
'with this map extent.<br/>'
'<span style="color:red">This can take some time for longe time series</span>')
'<span style="color:red">This can take some time for long time series</span>')
action.triggered.connect(lambda *args,
ext=self.spatialExtent():
ts.focusVisibilityToExtent(ext=ext, date_of_interest=date))
ts.focusVisibility(ext=ext, date_of_interest=date))
menu.addSeparator()
......
......@@ -1276,9 +1276,19 @@ class TimeSeriesFindOverlapTask(QgsTask):
gt = ds.GetGeoTransform()
ul = geo2px(targetExtent2.upperLeftPt(), gt)
lr = geo2px(targetExtent2.lowerRightPt(), gt)
xsize = lr.x() - ul.x() - 1
ysize = lr.y() - ul.y() - 1
data = band1.ReadAsArray(ul.x(), ul.y(), xsize, ysize, self.mSampleSize, self.mSampleSize)
x0 = max(ul.x(), 0)
y0 = max(ul.y(), 0)
x1 = min(lr.x(), ds.RasterXSize-1)
y1 = min(lr.y(), ds.RasterYSize-1)
xsize = x1-y0+1
ysize = y1-y0+1
if xsize <= 0 or ysize <= 0:
return False
data = band1.ReadAsArray(x0, y0, xsize, ysize, min(self.mSampleSize, xsize), min(self.mSampleSize, ysize))
return bool(np.any(data != nodata))
else:
......@@ -1504,12 +1514,20 @@ class TimeSeries(QAbstractItemModel):
if isinstance(spatialExtent, SpatialExtent) and self.mCurrentSpatialExtent != spatialExtent:
self.mCurrentSpatialExtent = spatialExtent
def focusVisibilityToExtent(self, ext: SpatialExtent = None, runAsync: bool = None,
date_of_interest: np.datetime64 = None,
max_before: int = -1,
max_after: int = -1):
def focusVisibility(self,
ext: SpatialExtent = None,
runAsync: bool = None,
date_of_interest: np.datetime64 = None,
max_before: int = -1,
max_after: int = -1):
"""
Changes TSDs visibility according to its intersection with a SpatialExtent
:param date_of_interest:
:type date_of_interest:
:param max_after:
:type max_after:
:param max_before:
:type max_before:
:param runAsync: if True (default), the visibility check is run in a parallel task
:param ext: SpatialExtent
"""
......
......@@ -144,7 +144,7 @@ QToolBox::tab:selected { /* italicize selected tabs */
</size>
</property>
<attribute name="icon">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<iconset resource="../../../QGIS/images/images.qrc">
<normaloff>:/images/themes/default/mLayoutItemMap.svg</normaloff>:/images/themes/default/mLayoutItemMap.svg</iconset>
</attribute>
<attribute name="label">
......@@ -656,7 +656,7 @@ QToolBox::tab:selected { /* italicize selected tabs */
</customwidgets>
<resources>
<include location="eotsv_resources.qrc"/>
<include location="../../../QGIS_Images/images/images.qrc"/>
<include location="../../../QGIS/images/images.qrc"/>
</resources>
<connections>
<connection>
......
from qgis.PyQt.QtCore import pyqtSignal
from .externals.qps.vectorlayertools import VectorLayerTools
class EOTSVVectorLayerTools(VectorLayerTools):
sigFocusVisibility = pyqtSignal()
def __init__(self, *args, **kwds):
super(EOTSVVectorLayerTools, self).__init__(*args, **kwds)
def focusVisibility(self):
self.sigFocusVisibility.emit()
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment