Newer
Older
DV.sigLoadingStarted.connect(self.sigLoadingStarted.emit)
DV.sigLoadingFinished.connect(self.sigLoadingFinished.emit)
DV.sigVisibilityChanged.connect(lambda: self.STV.adjustScrollArea())
for i, mapView in enumerate(self.STV.MVC):
DV.insertMapView(mapView)
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
"""
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.MVC = self.ui.dockMapViews
assert isinstance(self.MVC, MapViewDock)
self.MVC.sigShowProfiles.connect(self.sigShowProfiles.emit)
self.MVC.sigMapViewAdded.connect(self.onMapViewAdded)
self.MVC.sigMapViewAdded.connect(self.sigMapViewAdded.emit)
self.MVC.sigMapViewRemoved.connect(self.sigMapViewRemoved.emit)
self.vectorOverlay = None
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
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
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
"""
for mapView in self.MVC:
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
return self.MVC.createMapView(name=name)

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)
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
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
"""
self.MVC.setVectorLayer(lyr)

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.MVC if v.isVisible()]
nX = len(tsdViews)
nY = len(mapViews)
spacing = self.targetLayout.spacing()
margins = self.targetLayout.contentsMargins()
sizeX = 1
sizeY = 50
if nX > 0:
s = tsdViews[0].ui.sizeHint().width()
s = nX * (s + spacing) + margins.left() + margins.right()
sizeX = s
if nY > 0 and nX > 0:
s = tsdViews[0].ui.sizeHint().height()
s = s + margins.top() + margins.bottom()
sizeY = s
#s = tsdViews[0].ui.sizeHint()
#s = QSize(nX * (s.width() + spacing) + margins.left() + margins.right(),
# s.height() + margins.top() + margins.bottom())
#print(sizeX, sizeY)
self.targetLayout.parentWidget().resize(QSize(sizeX, sizeY))
def onLocationRequest(self, pt:SpatialPoint, canvas:QgsMapCanvas):
def setSpatialCenter(self, center:SpatialPoint, mapCanvas0=None):
Sets the spatial center of all MapCanvases
:param center: SpatialPoint
:param mapCanvas0:
extent = self.spatialExtent()
if isinstance(extent, SpatialExtent):
centerOld = extent.center()
center = center.toCrs(extent.crs())

Benjamin Jakimow
committed
if center != centerOld and isinstance(center, SpatialPoint):
extent = extent.__copy__()
extent.setCenter(center)
self.setSpatialExtent(extent)
def spatialCenter(self)->SpatialPoint:
return self.spatialExtent().spatialCenter()
Sets the spatial extent of all MapCanvases
:param extent: SpatialExtent
:param mapCanvas0:
:return:
lastExtent = self.spatialExtent()
extent = extent.toCrs(self.crs())
if not isinstance(extent, SpatialExtent) \
or extent.isEmpty() or not extent.isFinite() \
or extent.width() <= 0 \
or extent.height() <= 0 \
or extent == self.mSpatialExtent:
return
if self.mSpatialExtent == extent:
return
self.mSpatialExtent = extent
for mapCanvas in self.mapCanvases():
assert isinstance(mapCanvas, MapCanvas)

Benjamin Jakimow
committed
mapCanvas.addToRefreshPipeLine(extent)
if lastExtent != extent:
self.sigSpatialExtentChanged.emit(extent)
Returns the MapViewDock that controls all MapViews
:return: MapViewDock
Sets the MapCanvas background color
:param color: QColor
assert isinstance(self.MVC, MapViewDock)
self.MVC.setMapBackgroundColor(color)
Returns MapCanvases
:param mapView: a MapView to return MapCanvases from only, defaults to None
:return: [list-of-MapCanvas]