Newer
Older
assert isinstance(tsd, TimeSeriesDate)
DV.sigLoadingStarted.connect(self.sigLoadingStarted.emit)
DV.sigLoadingFinished.connect(self.sigLoadingFinished.emit)
DV.sigVisibilityChanged.connect(lambda: self.STV.adjustScrollArea())
bisect.insort(self.mViews, DV)
i = self.mViews.index(DV)
DV.ui.setParent(self.STV.targetLayout.parentWidget())
self.STV.targetLayout.insertWidget(i, DV.ui)
DV.ui.show()

Benjamin Jakimow
committed
def removeDates(self, tsdList):
toRemove = [v for v in self.mViews if v.TSD in tsdList]
removedDates = []
for DV in toRemove:
self.mViews.remove(DV)
for mapCanvas in DV.mMapCanvases.values():
toRemove = mapCanvas.layers()
mapCanvas.setLayers([])
toRemove = [l for l in toRemove if isinstance(l, QgsRasterLayer)]
if len(toRemove) > 0:
QgsProject.instance().removeMapLayers([l.id() for l in toRemove])
DV.ui.parent().layout().removeWidget(DV.ui)
DV.ui.hide()
DV.ui.close()
removedDates.append(DV.TSD)
del DV

Benjamin Jakimow
committed
if len(removedDates) > 0:
self.sigResizeRequired.emit()

Benjamin Jakimow
committed

Benjamin Jakimow
committed

Benjamin Jakimow
committed
def __getitem__(self, slice):
return self.mViews[slice]
def __delitem__(self, slice):
self.removeDates(self.mViews[slice])

benjamin.jakimow@geo.hu-berlin.de
committed
class MapViewListModel(QAbstractListModel):
"""
A model to store a list of map views.

benjamin.jakimow@geo.hu-berlin.de
committed
"""
sigMapViewsAdded = pyqtSignal(list)
sigMapViewsRemoved = pyqtSignal(list)

benjamin.jakimow@geo.hu-berlin.de
committed
def __init__(self, parent=None):
super(MapViewListModel, self).__init__(parent)
self.mMapViewList = []

benjamin.jakimow@geo.hu-berlin.de
committed
def addMapView(self, mapView):
i = len(self.mMapViewList)
self.insertMapView(i, mapView)
def insertMapView(self, i, mapView):
self.insertMapViews(i, [mapView])
def insertMapViews(self, i, mapViews):
assert isinstance(mapViews, list)
assert i >= 0 and i <= len(self.mMapViewList)
self.beginInsertRows(QModelIndex(), i, i + len(mapViews) - 1)

benjamin.jakimow@geo.hu-berlin.de
committed
for j in range(len(mapViews)):
mapView = mapViews[j]
assert isinstance(mapView, MapView)
mapView.sigTitleChanged.connect(
lambda : self.doRefresh([mapView])
)
self.mMapViewList.insert(i + j, mapView)
self.endInsertRows()
self.sigMapViewsAdded.emit(mapViews)

benjamin.jakimow@geo.hu-berlin.de
committed
def doRefresh(self, mapViews):
for mapView in mapViews:
idx = self.mapView2idx(mapView)
self.dataChanged.emit(idx, idx)

benjamin.jakimow@geo.hu-berlin.de
committed
def removeMapView(self, mapView):
self.removeMapViews([mapView])

benjamin.jakimow@geo.hu-berlin.de
committed
def removeMapViews(self, mapViews):
assert isinstance(mapViews, list)
for mv in mapViews:
assert mv in self.mMapViewList
idx = self.mapView2idx(mv)
self.beginRemoveRows(idx.parent(), idx.row(), idx.row())
self.mMapViewList.remove(mv)
self.endRemoveRows()
self.sigMapViewsRemoved.emit(mapViews)

benjamin.jakimow@geo.hu-berlin.de
committed
def rowCount(self, parent=None, *args, **kwargs):
return len(self.mMapViewList)

benjamin.jakimow@geo.hu-berlin.de
committed
def columnCount(self, QModelIndex_parent=None, *args, **kwargs):
return 1
def idx2MapView(self, index):
if isinstance(index, QModelIndex):
if index.isValid():
index = index.row()
else:
return None
assert index >= 0 and index < len(self.mMapViewList)
return self.mMapViewList[index]
def mapView2idx(self, mapView):
assert isinstance(mapView, MapView)
row = self.mMapViewList.index(mapView)
return self.createIndex(row, 0, mapView)

benjamin.jakimow@geo.hu-berlin.de
committed
def __getitem__(self, slice):
return self.mMapViewList[slice]
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
if (index.row() >= len(self.mMapViewList)) or (index.row() < 0):
return None
mapView = self.idx2MapView(index)
assert isinstance(mapView, MapView)
if role == Qt.DisplayRole:
value = '{} {}'.format(index.row() +1 , mapView.title())
#if role == Qt.DecorationRole:
#value = classInfo.icon(QSize(20,20))
if role == Qt.UserRole:
value = mapView
return value
class MapViewDock(QgsDockWidget, loadUI('mapviewdock.ui')):
sigMapViewAdded = pyqtSignal(MapView)
sigMapViewRemoved = pyqtSignal(MapView)
sigShowProfiles = pyqtSignal(SpatialPoint, MapCanvas, str)
sigMapCanvasColorChanged = pyqtSignal(QColor)
sigSpatialExtentChanged = pyqtSignal(SpatialExtent)
sigCrsChanged = pyqtSignal(QgsCoordinateReferenceSystem)
sigMapSizeChanged = pyqtSignal(QSize)
def setTimeSeries(self, timeSeries:TimeSeries):
assert isinstance(timeSeries, TimeSeries)
self.mTimeSeries = timeSeries
self.mTimeSeries.sigSensorAdded.connect(self.addSensor)
self.mTimeSeries.sigSensorRemoved.connect(self.removeSensor)
def __init__(self, parent=None):
super(MapViewDock, self).__init__(parent)
self.setupUi(self)
self.btnAddMapView.setDefaultAction(self.actionAddMapView)
self.btnRemoveMapView.setDefaultAction(self.actionRemoveMapView)
self.btnCrs.crsChanged.connect(self.sigCrsChanged)
self.btnMapCanvasColor.colorChanged.connect(self.onMapCanvasBackgroundColorChanged)
self.btnApplySizeChanges.clicked.connect(lambda : self.sigMapSizeChanged.emit(QSize(self.spinBoxMapSizeX.value(),self.spinBoxMapSizeY.value())))
self.actionAddMapView.triggered.connect(self.createMapView)
self.actionRemoveMapView.triggered.connect(lambda : self.removeMapView(self.currentMapView()) if self.currentMapView() else None)
self.actionApplyStyles.triggered.connect(self.refreshCurrentMapView)
self.toolBox.currentChanged.connect(self.onToolboxIndexChanged)
self.spinBoxMapSizeX.valueChanged.connect(lambda: self.onMapSizeChanged('X'))
self.spinBoxMapSizeY.valueChanged.connect(lambda: self.onMapSizeChanged('Y'))
self.mLastMapSize = self.mapSize()

benjamin.jakimow@geo.hu-berlin.de
committed
"""
Returns the defined MapViews
:return: [list-of-MapViews]
"""
assert isinstance(self.toolBox, QToolBox)
mapViews = []
for i in range(self.toolBox.count()):
item = self.toolBox.widget(i)
if isinstance(item, MapView):
mapViews.append(item)
return mapViews

Benjamin Jakimow
committed
"""
Returns all MapCanvases from all MapViews
:return: [list-of-MapCanvases]

Benjamin Jakimow
committed
"""
maps = []
for mapView in self.mapViews():
assert isinstance(mapView, MapView)
maps.extend(mapView.mapCanvases())
return maps

Benjamin Jakimow
committed
if isinstance(crs, QgsCoordinateReferenceSystem):
old = self.btnCrs.crs()
if old != crs:
self.btnCrs.setCrs(crs)
self.btnCrs.setLayerCrs(crs)
def setMapSize(self, size):
assert isinstance(size, QSize)
ws = [self.spinBoxMapSizeX, self.spinBoxMapSizeY]
oldSize = self.mapSize()
b = oldSize != size
for w in ws:
w.blockSignals(True)
self.spinBoxMapSizeX.setValue(size.width()),
self.spinBoxMapSizeY.setValue(size.height())
self.mLastMapSize = QSize(size)
for w in ws:
w.blockSignals(False)
self.mLastMapSize = QSize(size)
if b:
self.sigMapSizeChanged.emit(size)
def onMapSizeChanged(self, dim):
newSize = self.mapSize()
#1. set size of other dimension accordingly
if dim is not None:
if self.checkBoxKeepSubsetAspectRatio.isChecked():
if dim == 'X':
vOld = self.mLastMapSize.width()
vNew = newSize.width()
targetSpinBox = self.spinBoxMapSizeY
elif dim == 'Y':
vOld = self.mLastMapSize.height()
vNew = newSize.height()
targetSpinBox = self.spinBoxMapSizeX

benjamin.jakimow@geo.hu-berlin.de
committed
oldState = targetSpinBox.blockSignals(True)
targetSpinBox.setValue(int(round(float(vNew) / vOld * targetSpinBox.value())))
targetSpinBox.blockSignals(oldState)
newSize = self.mapSize()
if newSize != self.mLastMapSize:
self.btnApplySizeChanges.setEnabled(True)
else:
self.sigMapSizeChanged.emit(self.mapSize())
self.btnApplySizeChanges.setEnabled(False)
self.setMapSize(newSize)

benjamin.jakimow@geo.hu-berlin.de
committed
def mapSize(self):
return QSize(self.spinBoxMapSizeX.value(),
self.spinBoxMapSizeY.value())

benjamin.jakimow@geo.hu-berlin.de
committed
def refreshCurrentMapView(self, *args):
mv = self.currentMapView()
if isinstance(mv, MapView):
mv.refreshMapView()
else:
s =""

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
for mapView in mapViews:
idx = self.stackedWidget.indexOf(mapView.ui)
if idx >= 0:
self.stackedWidget.removeWidget(mapView.ui)
mapView.ui.close()
else:
s = ""

benjamin.jakimow@geo.hu-berlin.de
committed
self.actionRemoveMapView.setEnabled(len(self.mMapViews) > 0)

benjamin.jakimow@geo.hu-berlin.de
committed
def mapBackgroundColor(self)->QColor:
"""
Returns the map canvas background color
:return: QColor
"""
return self.btnMapCanvasColor.color()

benjamin.jakimow@geo.hu-berlin.de
committed
def setMapBackgroundColor(self, color:QColor):
"""
Sets the MapCanvas background color
:param color: QColor
"""
if color != self.mapBackgroundColor():
self.btnMapCanvasColor.setColor(color)

benjamin.jakimow@geo.hu-berlin.de
committed
def onMapCanvasBackgroundColorChanged(self, color:QColor):
"""
Reacts on a changes map color
:param color: QColor
"""
assert isinstance(color, QColor)
self.mColor = color
for mapCanvas in self.mapCanvases():
assert isinstance(mapCanvas, MapCanvas)
mapCanvas.addToRefreshPipeLine(color)

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
def onMapViewsAdded(self, mapViews):
nextShown = None
for mapView in mapViews:
mapView.sigTitleChanged.connect(self.updateTitle)
self.stackedWidget.addWidget(mapView.ui)
if nextShown is None:
nextShown = mapView

benjamin.jakimow@geo.hu-berlin.de
committed
contents = mapView.ui.scrollAreaWidgetContents
size = contents.size()
hint = contents.sizeHint()
#mapView.ui.scrollArea.update()
s = ""
#setMinimumSize(mapView.ui.scrollAreaWidgetContents.sizeHint())
#hint = contents.sizeHint()
#contents.setMinimumSize(hint)
if isinstance(nextShown, MapView):
self.setCurrentMapView(nextShown)

benjamin.jakimow@geo.hu-berlin.de
committed
for mapView in mapViews:
self.sigMapViewAdded.emit(mapView)

benjamin.jakimow@geo.hu-berlin.de
committed
def updateButtons(self, *args):
b = len(self.mMapViews) > 0
self.actionRemoveMapView.setEnabled(b)
self.actionApplyStyles.setEnabled(b)
self.actionHighlightMapView.setEnabled(b)

benjamin.jakimow@geo.hu-berlin.de
committed

Benjamin Jakimow
committed
def createMapView(self, name:str=None)->MapView:
"""
Create a new MapView
:return: MapView
"""

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed

Benjamin Jakimow
committed
if isinstance(name, str) and len(name) > 0:
title = name
else:

Benjamin Jakimow
committed
while title in [m.title() for m in self.mapViews()]:
n += 1
title = 'Map View {}'.format(n)
mapView.setTitle(title)
mapView.sigShowProfiles.connect(self.sigShowProfiles)

benjamin.jakimow@geo.hu-berlin.de
committed
mapView.setTimeSeries(self.mTimeSeries)
self.addMapView(mapView)
return mapView

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
"""

benjamin.jakimow@geo.hu-berlin.de
committed
"""
assert isinstance(mapView, MapView)
mapView.sigTitleChanged.connect(lambda *args, mv=mapView : self.onMapViewUpdated(mv))
mapView.sigMapViewVisibility.connect(lambda *args, mv=mapView : self.onMapViewUpdated(mv))
i = self.toolBox.addItem(mapView, mapView.windowIcon(), mapView.title())
self.toolBox.setCurrentIndex(i)
self.onMapViewUpdated(mapView)
self.sigMapViewAdded.emit(mapView)

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
b = isinstance(self.toolBox.currentWidget(), MapView)
self.actionRemoveMapView.setEnabled(b)

benjamin.jakimow@geo.hu-berlin.de
committed
def onMapViewUpdated(self, mapView:MapView):
"""
Handles updates that react on MapView changes
:param mapView: MapView to make the update for
"""
numMV = 0
for i in range(self.toolBox.count()):
item = self.toolBox.widget(i)
if mapView.isVisible():
icon = QIcon(":/timeseriesviewer/icons/mapview.svg")
else:
icon = QIcon(":/timeseriesviewer/icons/mapviewHidden.svg")

benjamin.jakimow@geo.hu-berlin.de
committed
self.toolBox.setItemIcon(i, icon)
self.toolBox.setItemText(i, 'Map View {} "{}"'.format(numMV, mapView.title()))
break

benjamin.jakimow@geo.hu-berlin.de
committed
def removeMapView(self, mapView:MapView)->MapView:
"""
Removes a MapView
:param mapView: MapView
:return: MapView
"""
assert mapView in self.mapViews()
for i in range(self.toolBox.count()):
w = self.toolBox.widget(i)
if isinstance(w, MapView) and w == mapView:
self.toolBox.removeItem(i)
mapView.close()
if self.toolBox.count() >= i:
self.toolBox.setCurrentIndex(min(i, self.toolBox.count()-1))

benjamin.jakimow@geo.hu-berlin.de
committed
self.sigMapViewRemoved.emit(mapView)
return mapView

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
def __len__(self)->int:
"""
Returns the number of MapViews
:return: int
"""
return len(self.mapViews())

benjamin.jakimow@geo.hu-berlin.de
committed
def __iter__(self):
"""
Provides an iterator over all MapViews
:return:
"""
return iter(self.mapViews())

benjamin.jakimow@geo.hu-berlin.de
committed
def __getitem__(self, slice):

benjamin.jakimow@geo.hu-berlin.de
committed
def __contains__(self, mapView):
return mapView in self.mapViews()

benjamin.jakimow@geo.hu-berlin.de
committed
def index(self, mapView):
assert isinstance(mapView, MapView)
return self.mapViews().index(mapView)
def addSensor(self, sensor:SensorInstrument):
"""
Adds a new SensorInstrument
:param sensor: SensorInstrument
"""
for mapView in self.mapViews():
mapView.addSensor(sensor)
def removeSensor(self, sensor:SensorInstrument):
"""
Removes a Sensor
:param sensor: SensorInstrument
"""
for mapView in self.mMapViews:
mapView.removeSensor(sensor)
def applyStyles(self):
for mapView in self.mMapViews:
mapView.applyStyles()
def setCrosshairStyle(self, crosshairStyle):
for mapView in self.mMapViews:
mapView.setCrosshairStyle(crosshairStyle)
def setShowCrosshair(self, b):
for mapView in self.mMapViews:
mapView.setCrosshairVisibility(b)
def index(self, mapView):
assert isinstance(mapView, MapView)
return self.mapViewsDefinitions.index(mapView)
assert isinstance(mapView, MapView) and mapView in self.mapViews()
self.toolBox.setCurrentWidget(mapView)
def updateTitle(self, *args):
# self.btnToggleMapViewVisibility.setChecked(mapView)
mapView = self.currentMapView()
if isinstance(mapView, MapView):
title = '{} | {}'.format(self.baseTitle, mapView.title())
else:
title = self.baseTitle
self.setWindowTitle(title)
def currentMapView(self):
w = self.toolBox.currentWidget()
if isinstance(w, MapView):
return w
return None
class MapWidget(QWidget, loadUIFormClass(jp(DIR_UI, 'mapwidget.ui'))):
"""
This widget contains all maps
"""
class ViewMode(enum.Enum):
MapViewByRows = 1,
MapViewByCols = 2
def __init__(self, *args, **kwds):
super(MapWidget, self).__init__(*args, **kwds)
self.setupUi(self)
self.mGrid = self.layout()
self.mViewMode = MapWidget.ViewMode.MapViewByRows
self.mCurrentDate = None
self.mMapSize= QSize(200, 200)
def setMode(self, mode:ViewMode):
self.mViewMode = mode
def setMapsPerMapView(self, n:int):
assert n > 0
if n != self.nMpMV:
self.nMpMV = n
self.updateCanvasWidgets()
def setMapSize(self, size:QSize):
if size != self.mMapSize:
for canvas in self.mapCanvases():
canvas.setFixedSize(size)
self.mMapSize = size
def mapCanvases(self)->list:
return self.mGrid.findChildren(MapCanvas)
def setCurrentDate(self, tsd:TimeSeriesDate):
assert isinstance(tsd, TimeSeriesDate)
self.mCurrentDate = tsd
def currentDate(self)->TimeSeriesDate:
return self.mCurrentDate
def addMapView(self, mapView:MapView):
if mapView not in self.mMapViews:
self.mMapViews.append(mapView)
self.updateCanvasWidgets()
def removeMapView(self, mapView:MapView):
if mapView in self.mMapViews:
self.mMapViews.remove(mapView)
self.updateCanvasWidgets()
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
oldCanvases = self.mGrid.findChildren(MapCanvas)
for c in oldCanvases:
assert isinstance(c, MapCanvas)
c.setParent(None)
c.setLayers([])
c.setTSD(None)
if self.mViewMode == MapWidget.ViewMode.MapViewByRows:
for row, mv in enumerate(self.mMapViews):
assert isinstance(mv, MapView)
self.mCanvases[mv] = []
for col in range(self.nMpMV):
c = MapCanvas()
c.setFixedSize(self.mMapSize)
self.mGrid.addWidget(c, row, col)
self.mCanvases[mv].append(c)
else:
raise NotImplementedError()
self.updateCanvasDates()
def updateCanvasDates(self):
"""
sigLoadingStarted = pyqtSignal(DatumView, MapView)
sigLoadingFinished = pyqtSignal(DatumView, MapView)
sigShowProfiles = pyqtSignal(SpatialPoint, MapCanvas, str)
sigShowMapLayerInfo = pyqtSignal(dict)
sigSpatialExtentChanged = pyqtSignal(SpatialExtent)
sigMapSizeChanged = pyqtSignal(QSize)
sigCRSChanged = pyqtSignal(QgsCoordinateReferenceSystem)
sigActivateMapTool = pyqtSignal(str)
sigMapViewAdded = pyqtSignal(MapView)
sigMapViewRemoved = pyqtSignal(MapView)
sigVisibleDatesChanged = pyqtSignal(list)
def __init__(self, timeSeriesViewer):
super(SpatialTemporalVisualization, self).__init__()
# assert isinstance(timeSeriesViewer, TimeSeriesViewer), timeSeriesViewer
# default map settings
self.mSpatialExtent = SpatialExtent.world()
self.mCRS = self.mSpatialExtent.crs()
self.mSize = QSize(200, 200)
self.mColor = Qt.black
self.mMapCanvases = []
self.ui = timeSeriesViewer.ui
self.mVisibleDates = set()
self.mMapToolKey = MapTools.Pan
self.mMapToolMode = None
self.scrollArea = self.ui.scrollAreaSubsets
assert isinstance(self.scrollArea, MapViewScrollArea)
self.scrollArea.horizontalScrollBar().valueChanged.connect(self.onVisibleMapsChanged)
self.scrollArea.horizontalScrollBar().rangeChanged.connect(self.onVisibleMapsChanged)
# self.scrollArea.sigResized.connect(self.onVisibleMapsChanged)
# self.scrollArea.sigResized.connect(self.refresh())
# self.scrollArea.horizontalScrollBar().valueChanged.connect(self.mRefreshTimer.start)
self.TSV = timeSeriesViewer
self.TS = timeSeriesViewer.timeSeries()
self.ui.dockMapViews.setTimeSeries(self.TS)
self.targetLayout = self.ui.scrollAreaSubsetContent.layout()
self.mMapViewDock = self.ui.dockMapViews
assert isinstance(self.mMapViewDock, MapViewDock)
self.mMapViewDock.sigShowProfiles.connect(self.sigShowProfiles.emit)
self.mMapViewDock.sigMapViewAdded.connect(self.onMapViewAdded)
self.mMapViewDock.sigMapViewAdded.connect(self.sigMapViewAdded.emit)
self.mMapViewDock.sigMapViewRemoved.connect(self.sigMapViewRemoved.emit)
self.DVC = DateViewCollection(self)
self.DVC.sigResizeRequired.connect(self.adjustScrollArea)
self.TS.sigTimeSeriesDatesAdded.connect(self.DVC.addDates)
self.TS.sigTimeSeriesDatesRemoved.connect(self.DVC.removeDates)
self.DVC.addDates(self.TS[:])
if len(self.TS) > 0:
self.setSpatialExtent(self.TS.maxSpatialExtent())
#self.setSubsetSize(QSize(100,50))
self.mMapRefreshTimer = QTimer(self)
self.mMapRefreshTimer.timeout.connect(self.timedCanvasRefresh)
self.mMapRefreshTimer.setInterval(500)
self.mMapRefreshTimer.start()
self.mNumberOfHiddenMapsToRefresh = 2
self.mCurrentLayer = None
self.mAdjustScrollAreaRequest = False
self.mSyncLock = False
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
def setMapTool(self, mapToolKey):
mode = None
if mapToolKey == MapTools.SelectFeature:
if self.ui.optionSelectFeaturesRectangle.isChecked():
mode = QgsMapToolSelectionHandler.SelectionMode.SelectSimple
elif self.ui.optionSelectFeaturesPolygon.isChecked():
mode = QgsMapToolSelectionHandler.SelectionMode.SelectPolygon
elif self.ui.optionSelectFeaturesFreehand.isChecked():
mode = QgsMapToolSelectionHandler.SelectionMode.SelectFreehand
elif self.ui.optionSelectFeaturesRadius.isChecked():
mode = QgsMapToolSelectionHandler.SelectionMode.SelectRadius
else:
mode = QgsMapToolSelectionHandler.SelectionMode.SelectSimple
self.mMapToolKey = mapToolKey
self.mMapToolMode = mode
from .mapcanvas import MapCanvas, MapCanvasMapTools
for canvas in self.mapCanvases():
if isinstance(canvas, MapCanvas):
mapTools = canvas.mapTools()
mapTools.activate(mapToolKey)
mt = canvas.mapTool()
if isinstance(mt, QgsMapToolSelect):
mt.setSelectionMode(mode)
def setCurrentLayer(self, layer:QgsMapLayer):
"""
Sets the current map layer some map tools can operate on
:param layer: QgsMapLayer
"""
assert layer is None or isinstance(layer, QgsMapLayer)
self.mCurrentLayer = layer
for mapView in self.mapViews():
mapView.setCurrentLayer(self.mCurrentLayer)
def syncQGISCanvasCenter(self, qgisChanged:bool):
if self.mSyncLock:
return
iface = qgis.utils.iface
assert isinstance(iface, QgisInterface)
c = iface.mapCanvas()
if not isinstance(c, QgsMapCanvas):
return
tsvCenter = self.spatialExtent().spatialCenter()
qgsCenter = SpatialExtent.fromMapCanvas(c).spatialCenter()
if qgisChanged:
# change EOTSV
if tsvCenter.crs().isValid():
self.mSyncLock = True
qgsCenter = qgsCenter.toCrs(tsvCenter.crs())
if isinstance(qgsCenter, SpatialPoint):
self.setSpatialCenter(qgsCenter)
else:
# change QGIS
if qgsCenter.crs().isValid():
self.mSyncLock = True
tsvCenter = tsvCenter.toCrs(qgsCenter.crs())
if isinstance(tsvCenter, SpatialPoint):
c.setCenter(tsvCenter)
else:
pass

benjamin.jakimow@geo.hu-berlin.de
committed
def visibleMaps(self)->list:
"""
Returns a list of mapcanvas visible to the user
:return: [list-of-MapCanvases
"""
return [m for m in self.mapCanvases() if m.isVisibleToViewport()]
def visibleTSDs(self):
"""
Returns an ordered list of visible time series dates.
:return: [list-of-TimeSeriesDates]
"""
return sorted(list(self.mVisibleDates))
def onVisibleMapsChanged(self, *args):
visibleDates = set([m.tsd() for m in self.visibleMaps()])
if visibleDates != self.mVisibleDates:
self.mVisibleDates.clear()
self.mVisibleDates.update(visibleDates)
self.sigVisibleDatesChanged.emit(list(self.mVisibleDates))
self.mSyncLock = False
if self.mAdjustScrollAreaRequest:
self.doAdjustScrollArea()
self.mAdjustScrollAreaRequest = False
# do refresh maps
visibleMaps = self.visibleMaps()
hiddenMaps = sorted([m for m in self.mapCanvases() if not m.isVisibleToViewport()],
key = lambda c : self.scrollArea.distanceToCenter(c) )
n = 0
# redraw all visible maps
for c in visibleMaps:
assert isinstance(c, MapCanvas)
c.timedRefresh()
n += 1

Benjamin Jakimow
committed
if False and n < 10:
# refresh up to mNumberOfHiddenMapsToRefresh maps which are not visible to the user
i = 0

Benjamin Jakimow
committed
for c in hiddenMaps:
assert isinstance(c, MapCanvas)
c.timedRefresh()
i += 1
if i >= self.mNumberOfHiddenMapsToRefresh and not force:
break
def mapViewFromCanvas(self, mapCanvas:MapCanvas)->MapView:
"""
Returns the MapView a mapCanvas belongs to
:param mapCanvas: MapCanvas
:return: MapView
"""
assert isinstance(mapView, MapView)
if mapCanvas in mapView.mapCanvases():
return mapView
return None
def onMapViewAdded(self, *args):
self.adjustScrollArea()
s = ""

Benjamin Jakimow
committed
def createMapView(self, name:str=None)->MapView:

Benjamin Jakimow
committed
def registerMapCanvas(self, mapCanvas:MapCanvas):
"""
Connects a MapCanvas and its signals
:param mapCanvas: MapCanvas
"""
from eotimeseriesviewer.mapcanvas import MapCanvas
assert isinstance(mapCanvas, MapCanvas)
mapCanvas.setMapLayerStore(self.TSV.mMapLayerStore)
mapCanvas.sigCrosshairPositionChanged.connect(lambda point, canvas=mapCanvas: self.TSV.setCurrentLocation(point, canvas))

Benjamin Jakimow
committed
# set general canvas properties
mapCanvas.setFixedSize(self.mSize)
mapCanvas.setDestinationCrs(self.mCRS)
mapCanvas.setSpatialExtent(self.mSpatialExtent)

Benjamin Jakimow
committed
mapCanvas.sigSpatialExtentChanged.connect(self.setSpatialExtent)
mapCanvas.sigCrosshairPositionChanged.connect(self.onCrosshairChanged)
# activate the current map tool
mapTools = mapCanvas.mapTools()
mapTools.activate(self.mMapToolKey)
mt = mapCanvas.mapTool()
if isinstance(mt, QgsMapToolSelect):
mt.setSelectionMode(self.mMapToolMode)
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
def onCrosshairChanged(self, spatialPoint:SpatialPoint):
"""
Synchronizes all crosshair positions. Takes care of CRS differences.
:param spatialPoint: SpatialPoint of new Crosshair position
"""
from eotimeseriesviewer import CrosshairStyle
srcCanvas = self.sender()
if isinstance(srcCanvas, MapCanvas):
dstCanvases = [c for c in self.mapCanvases() if c != srcCanvas]
else:
dstCanvases = [c for c in self.mapCanvases()]
if isinstance(spatialPoint, SpatialPoint):
for mapCanvas in dstCanvases:
mapCanvas.setCrosshairPosition(spatialPoint, emitSignal=False)
def setCrosshairStyle(self, crosshairStyle:CrosshairStyle):
"""
Sets a crosshair style to all map canvas
:param crosshairStyle: CrosshairStyle
"""
for mapView in self.mapViews():
assert isinstance(mapView, MapView)
mapView.setCrosshairStyle(crosshairStyle)
def setCrosshairVisibility(self, b:bool):
"""
Sets the Crosshair visiblity
:param b: bool
"""
assert isinstance(b, bool)
self.onCrosshairChanged(b)
def setVectorLayer(self, lyr:QgsVectorLayer):
"""
Sets a QgsVectorLaye to be shown on top of raster images
:param lyr: QgsVectorLayer
"""

Benjamin Jakimow
committed

Benjamin Jakimow
committed
def setMapSize(self, size:QSize):
"""
Sets the MapCanvas size.
:param size: QSize
"""

Benjamin Jakimow
committed
assert isinstance(size, QSize)
currentTSD = None
visible = self.visibleTSDs()
if len(visible) > 0:
currentTSD = visible[int(len(visible) / 2)]
from eotimeseriesviewer.mapcanvas import MapCanvas
for mapCanvas in self.mMapCanvases:
assert isinstance(mapCanvas, MapCanvas)
mapCanvas.setFixedSize(size)
self.sigMapSizeChanged.emit(self.mSize)
self.adjustScrollArea()

Benjamin Jakimow
committed
if isinstance(currentTSD, TimeSeriesDate):
self.navigateToTSD(currentTSD)
def mapSize(self)->QSize:
"""
Returns the MapCanvas size
:return: QSize
"""
return QSize(self.mSize)

Benjamin Jakimow
committed
def refresh(self):
"""
Refreshes all visible MapCanvases
"""
for c in self.mapCanvases():
assert isinstance(c, MapCanvas)
c.refresh()

Benjamin Jakimow
committed

Benjamin Jakimow
committed
def adjustScrollArea(self):
"""
Adjusts the scroll area widget to fit all visible widgets
"""
self.mAdjustScrollAreaRequest = True
def doAdjustScrollArea(self):
m = self.targetLayout.contentsMargins()
nX = len(self.DVC)
w = h = 0
s = QSize()
r = None
tsdViews = [v for v in self.DVC if v.ui.isVisible()]
mapViews = [v for v in self.mMapViewDock if v.isVisible()]
nX = len(tsdViews)
nY = len(mapViews)
spacing = self.targetLayout.spacing()
margins = self.targetLayout.contentsMargins()