Newer
Older
self.mMapCanvases.append(mapCanvas)
#set general canvas properties
mapCanvas.setFixedSize(self.mSize)
mapCanvas.setSpatialExtent(self.mSpatialExtent)

Benjamin Jakimow
committed
#register on map canvas signals
def onChanged(e, mapCanvas0=None):
self.setSpatialExtent(e, mapCanvas0=mapCanvas0)
#mapCanvas.sigSpatialExtentChanged.connect(lambda e: self.setSpatialExtent(e, mapCanvas0=mapCanvas))
mapCanvas.sigSpatialExtentChanged.connect(lambda e: onChanged(e, mapCanvas0=mapCanvas))

Benjamin Jakimow
committed
mapCanvas.sigCrosshairPositionChanged.connect(self.onCrosshairChanged)
def onCrosshairChanged(self, spatialPoint:SpatialPoint):

Benjamin Jakimow
committed
"""
Synchronizes all crosshair positions. Takes care of CRS differences.
:param spatialPoint: SpatialPoint of new Crosshair position

Benjamin Jakimow
committed
"""
from eotimeseriesviewer import CrosshairStyle

Benjamin Jakimow
committed
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):

Benjamin Jakimow
committed
for mapCanvas in dstCanvases:
mapCanvas.setCrosshairPosition(spatialPoint, emitSignal=False)

Benjamin Jakimow
committed
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)

benjamin.jakimow@geo.hu-berlin.de
committed
"""
Sets the Crosshair visiblity
:param b: bool
"""
assert isinstance(b, bool)
self.onCrosshairChanged(b)

benjamin.jakimow@geo.hu-berlin.de
committed
def setVectorLayer(self, lyr:QgsVectorLayer):
"""
Sets a QgsVectorLaye to be shown on top of raster images
:param lyr: QgsVectorLayer
"""

benjamin.jakimow@geo.hu-berlin.de
committed
self.MVC.setVectorLayer(lyr)

benjamin.jakimow@geo.hu-berlin.de
committed
assert isinstance(size, QSize)
from eotimeseriesviewer.mapcanvas import MapCanvas
for mapCanvas in self.mMapCanvases:
assert isinstance(mapCanvas, MapCanvas)
mapCanvas.setFixedSize(size)
self.sigMapSizeChanged.emit(self.mSize)

benjamin.jakimow@geo.hu-berlin.de
committed
self.adjustScrollArea()
def mapSize(self)->QSize:
"""
Returns the MapCanvas size
:return: QSize
"""

benjamin.jakimow@geo.hu-berlin.de
committed
def refresh(self):
"""
Refreshes all visible MapCanvases
"""
for c in self.mapCanvases():
assert isinstance(c, MapCanvas)
c.refresh()
#self.mMapRefreshTimer.stop()

benjamin.jakimow@geo.hu-berlin.de
committed
def adjustScrollArea(self):
"""
Adjusts the scroll area widget to fit all visible widgets
"""

benjamin.jakimow@geo.hu-berlin.de
committed
m = self.targetLayout.contentsMargins()

benjamin.jakimow@geo.hu-berlin.de
committed
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()

benjamin.jakimow@geo.hu-berlin.de
committed
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()

benjamin.jakimow@geo.hu-berlin.de
committed
#s = tsdViews[0].ui.sizeHint()
#s = QSize(nX * (s.width() + spacing) + margins.left() + margins.right(),
# s.height() + margins.top() + margins.bottom())

benjamin.jakimow@geo.hu-berlin.de
committed
#print(sizeX, sizeY)
self.targetLayout.parentWidget().resize(QSize(sizeX, sizeY))

benjamin.jakimow@geo.hu-berlin.de
committed
def setMapTool(self, mapToolKey, *args, **kwds):
"""
Create a maptool instance to each MapCanvas
:param mapToolKey: str which MapTool is to create, or QgsMapTool instance
:param args: optional maptool arguments
:param kwds: optional maptool keywords
:return: [list-of-QgsMapTools]
"""
del self.mMapTools[:]
from eotimeseriesviewer import MapTools, CursorLocationMapTool, SpectralProfileMapTool, TemporalProfileMapTool
for canvas in self.mMapCanvases:
mt = None
if mapToolKey in MapTools.mapToolKeys():
mt = MapTools.create(mapToolKey, canvas, *args, **kwds)
if isinstance(mapToolKey, QgsMapTool):
mt = MapTools.copy(mapToolKey, canvas, *args, **kwds)
if isinstance(mt, QgsMapTool):
canvas.setMapTool(mt)
self.mMapTools.append(mt)
# if required, link map-tool with specific slots
if isinstance(mt, CursorLocationMapTool):
mt.sigLocationRequest[SpatialPoint, QgsMapCanvas].connect(self.onLocationRequest)
return self.mMapTools

benjamin.jakimow@geo.hu-berlin.de
committed
def onLocationRequest(self, pt:SpatialPoint, canvas:QgsMapCanvas):
self.sigShowProfiles.emit(pt, canvas, "")
def setSpatialCenter(self, center, mapCanvas0=None):
"""
Sets the spatial center of all MapCanvases
:param center: SpatialPoint
:param mapCanvas0:
"""
assert isinstance(center, SpatialPoint)
center = center.toCrs(self.mCRS)
if not isinstance(center, SpatialPoint):
return
self.mSpatialExtent.setCenter(center)
for mapCanvas in self.mMapCanvases:
if mapCanvas != mapCanvas0:
oldState = mapCanvas.blockSignals(True)
mapCanvas.setCenter(center)
mapCanvas.blockSignals(oldState)
self.sigSpatialExtentChanged.emit(self.mSpatialExtent)
def setSpatialCenter(self, center:SpatialPoint, mapCanvas0=None):
"""
Sets the MapCanvas center.
:param center: SpatialPoint
:param mapCanvas0: MapCanvas0 optional
"""
assert isinstance(center, SpatialPoint)
center = center.toCrs(self.mCRS)
if not isinstance(center, SpatialPoint):
return None
for mapCanvas in self.mapCanvases():
assert isinstance(mapCanvas, MapCanvas)
if mapCanvas != mapCanvas0:
center0 = mapCanvas.spatialCenter()
if center0 != center:
oldState = mapCanvas.blockSignals(True)
mapCanvas.setCenter(center)
mapCanvas.blockSignals(oldState)
self.mMapRefreshTimer.start()
def setSpatialExtent(self, extent, mapCanvas0=None):
"""
Sets the spatial extent of all MapCanvases
:param extent: SpatialExtent
:param mapCanvas0:
:return:
"""
assert isinstance(extent, SpatialExtent)
extent = extent.toCrs(self.mCRS)
if not isinstance(extent, SpatialExtent) \
or extent.isEmpty() or not extent.isFinite() \
or extent.width() <= 0 \
or extent.height() <= 0 \
or extent == self.mSpatialExtent:
if self.mSpatialExtent == extent:
return
for mapCanvas in self.mapCanvases():
assert isinstance(mapCanvas, MapCanvas)
extent0 = mapCanvas.spatialExtent()
if mapCanvas != mapCanvas0 and extent0 != extent:
self.sigSpatialExtentChanged.emit(extent)

benjamin.jakimow@geo.hu-berlin.de
committed
def setBackgroundColor(self, color:QColor):
"""
Sets the MapCanvas background color
:param color: QColor
"""
assert isinstance(color, QColor)
self.mColor = color
for mapCanvas in self.mMapCanvases:
assert isinstance(mapCanvas, MapCanvas)
mapCanvas.setCanvasColor(color)
def backgroundColor(self)->QColor:
"""
Returns the MapCanvas background color
:return: QColor
"""
return self.mColor

Benjamin Jakimow
committed
def mapCanvases(self, mapView=None)->list:
"""
Returns MapCanvases
:param mapView: a MapView to return MapCanvases from only, defaults to None
:return: [list-of-MapCanvas]
"""
if isinstance(mapView, MapView):
s = ""

Benjamin Jakimow
committed
def mapViews(self)->list:
"""
Returns a list of all mapviews
:return [list-of-MapViews]:
"""
return self.MVC[:]
def setCrs(self, crs):
assert isinstance(crs, QgsCoordinateReferenceSystem)
transform = QgsCoordinateTransform()
transform.setSourceCrs(self.mCRS)
transform.setDestinationCrs(crs)
if transform.isValid() and not transform.isShortCircuited():

Benjamin Jakimow
committed
for mapCanvas in self.mapCanvases():
# print(('STV set CRS {} {}', str(mapCanvas), self.mCRS.description()))
mapCanvas.setDestinationCrs(QgsCoordinateReferenceSystem(crs))
"""
from timeseriesviewer.utils import saveTransform
if saveTransform(self.mSpatialExtent, self.mCRS, crs):
self.mCRS = crs
else:
pass
"""
self.sigCRSChanged.emit(self.crs())
def crs(self)->QgsCoordinateReferenceSystem:
"""
Returns the QgsCoordinateReferenceSystem
:return: QgsCoordinateReferenceSystem
"""
def spatialExtent(self)->SpatialExtent:
"""
Returns the SpatialExtent
:return: SpatialExtent
"""

benjamin.jakimow@geo.hu-berlin.de
committed
return self.mSpatialExtent

benjamin.jakimow@geo.hu-berlin.de
committed
def navigateToTSD(self, TSD:TimeSeriesDatum):
"""
Changes the viewport of the scroll window to show the requested TimeSeriesDatum
:param TSD: TimeSeriesDatum
"""

benjamin.jakimow@geo.hu-berlin.de
committed
assert isinstance(TSD, TimeSeriesDatum)
#get widget related to TSD

benjamin.jakimow@geo.hu-berlin.de
committed
assert isinstance(self.scrollArea, QScrollArea)
self.scrollArea.ensureWidgetVisible(tsdv.ui)

benjamin.jakimow@geo.hu-berlin.de
committed
sigResizeRequired = pyqtSignal()
sigLoadingStarted = pyqtSignal(MapView, TimeSeriesDatum)
sigLoadingFinished = pyqtSignal(MapView, TimeSeriesDatum)

benjamin.jakimow@geo.hu-berlin.de
committed
sigShowProfiles = pyqtSignal(SpatialPoint)
sigSpatialExtentChanged = pyqtSignal(SpatialExtent)

benjamin.jakimow@geo.hu-berlin.de
committed
def __init__(self, STViz):
assert isinstance(STViz, SpatialTemporalVisualization)
super(DateViewCollection, self).__init__()

benjamin.jakimow@geo.hu-berlin.de
committed
#self.tsv = tsv
#self.timeSeries = tsv.TS
self.STV = STViz
self.ui = self.STV.targetLayout.parentWidget()

benjamin.jakimow@geo.hu-berlin.de
committed
self.scrollArea = self.ui.parentWidget().parentWidget()
#potentially there are many more dates than views.
#therefore we implement the addinng/removing of mapviews here
#we reduce the number of layout refresh calls by
#suspending signals, adding the new map view canvases, and sending sigResizeRequired
self.STV.MVC.sigMapViewAdded.connect(self.addMapView)
self.STV.MVC.sigMapViewRemoved.connect(self.removeMapView)

benjamin.jakimow@geo.hu-berlin.de
committed
self.setFocusView(None)

benjamin.jakimow@geo.hu-berlin.de
committed
def tsdFromMapCanvas(self, mapCanvas):
assert isinstance(mapCanvas, MapCanvas)
assert isinstance(view, DatumView)
if mapCanvas in view.mMapCanvases.values():
return view.TSD
return None

benjamin.jakimow@geo.hu-berlin.de
committed
def tsdView(self, tsd):
r = [v for v in self.mViews if v.TSD == tsd]

benjamin.jakimow@geo.hu-berlin.de
committed
if len(r) == 1:
return r[0]
else:
raise Exception('TSD not in list')
def addMapView(self, mapView):
assert isinstance(mapView, MapView)
w = self.ui
#w.setUpdatesEnabled(False)
#for tsdv in self.mViews:
# tsdv.ui.setUpdatesEnabled(False)

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

benjamin.jakimow@geo.hu-berlin.de
committed
tsdv.insertMapView(mapView)
#for tsdv in self.mViews:
# tsdv.ui.setUpdatesEnabled(True)

benjamin.jakimow@geo.hu-berlin.de
committed
#mapView.sigSensorRendererChanged.connect(lambda *args : self.setRasterRenderer(mapView, *args))
mapView.sigMapViewVisibility.connect(lambda: self.sigResizeRequired.emit())
mapView.sigShowProfiles.connect(self.sigShowProfiles.emit)

benjamin.jakimow@geo.hu-berlin.de
committed
self.sigResizeRequired.emit()
def removeMapView(self, mapView):
assert isinstance(mapView, MapView)

benjamin.jakimow@geo.hu-berlin.de
committed
tsdv.removeMapView(mapView)
self.sigResizeRequired.emit()

benjamin.jakimow@geo.hu-berlin.de
committed
def highlightDate(self, tsd):
"""
Highlights a time series data for a specific time our
:param tsd:
:return:
"""
tsdView = self.tsdView(tsd)
if isinstance(tsdView, DatumView):
tsdView.setHighlight(True)

benjamin.jakimow@geo.hu-berlin.de
committed
def setFocusView(self, tsd):
self.focusView = tsd
def orderedViews(self):
#returns the
if self.focusView is not None:
assert isinstance(self.focusView, DatumView)
return sorted(self.mViews, key=lambda v: np.abs(v.TSD.date - self.focusView.TSD.date))

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

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

benjamin.jakimow@geo.hu-berlin.de
committed
def setSubsetSize(self, size):
assert isinstance(size, QSize)
self.subsetSize = size
for tsdView in self.orderedViews():
tsdView.blockSignals(True)
for tsdView in self.orderedViews():
tsdView.setSubsetSize(size)
for tsdView in self.orderedViews():
tsdView.blockSignals(False)

benjamin.jakimow@geo.hu-berlin.de
committed
def addDates(self, tsdList):
"""
Create a new TSDView
:param tsdList:
:return:
"""
for tsd in tsdList:
assert isinstance(tsd, TimeSeriesDatum)
DV.sigLoadingStarted.connect(self.sigLoadingStarted.emit)
DV.sigLoadingFinished.connect(self.sigLoadingFinished.emit)
DV.sigVisibilityChanged.connect(lambda: self.STV.adjustScrollArea())

benjamin.jakimow@geo.hu-berlin.de
committed
for i, mapView in enumerate(self.STV.MVC):
DV.insertMapView(mapView)

benjamin.jakimow@geo.hu-berlin.de
committed
bisect.insort(self.mViews, DV)
i = self.mViews.index(DV)

benjamin.jakimow@geo.hu-berlin.de
committed
DV.ui.setParent(self.STV.targetLayout.parentWidget())
self.STV.targetLayout.insertWidget(i, DV.ui)
DV.ui.show()

benjamin.jakimow@geo.hu-berlin.de
committed
if len(tsdList) > 0:
self.sigResizeRequired.emit()
def removeDates(self, tsdList):
toRemove = [v for v in self.mViews if v.TSD in tsdList]

benjamin.jakimow@geo.hu-berlin.de
committed
removedDates = []

benjamin.jakimow@geo.hu-berlin.de
committed
for mapCanvas in DV.mMapCanvases.values():

benjamin.jakimow@geo.hu-berlin.de
committed
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])

benjamin.jakimow@geo.hu-berlin.de
committed
DV.ui.parent().layout().removeWidget(DV.ui)
DV.ui.hide()
DV.ui.close()
removedDates.append(DV.TSD)
del DV

benjamin.jakimow@geo.hu-berlin.de
committed
if len(removedDates) > 0:
self.sigResizeRequired.emit()
def __len__(self):

benjamin.jakimow@geo.hu-berlin.de
committed
def __iter__(self):

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

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

benjamin.jakimow@geo.hu-berlin.de
committed
class MapViewListModel(QAbstractListModel):
"""
A model to store a list of map views.
"""
sigMapViewsAdded = pyqtSignal(list)
sigMapViewsRemoved = pyqtSignal(list)
def __init__(self, parent=None):
super(MapViewListModel, self).__init__(parent)
self.mMapViewList = []
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
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)
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)
def doRefresh(self, mapViews):
for mapView in mapViews:
idx = self.mapView2idx(mapView)
self.dataChanged.emit(idx, idx)
def removeMapView(self, mapView):
self.removeMapViews([mapView])
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)
def rowCount(self, parent=None, *args, **kwargs):
return len(self.mMapViewList)
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)
def __len__(self):
return len(self.mMapViewList)
def __iter__(self):
return iter(self.mMapViewList)
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)
value = None
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

benjamin.jakimow@geo.hu-berlin.de
committed
class MapViewDock(QgsDockWidget, loadUI('mapviewdock.ui')):
sigMapViewAdded = pyqtSignal(MapView)
sigMapViewRemoved = pyqtSignal(MapView)
sigShowProfiles = pyqtSignal(SpatialPoint, MapCanvas, str)

Benjamin Jakimow
committed
sigMapCanvasColorChanged = pyqtSignal(QColor)
sigSpatialExtentChanged = pyqtSignal(SpatialExtent)
sigCrsChanged = pyqtSignal(QgsCoordinateReferenceSystem)
sigMapSizeChanged = pyqtSignal(QSize)
def setTimeSeries(self, timeSeries:TimeSeries):
self.mTimeSeries = timeSeries
self.mTimeSeries.sigSensorAdded.connect(self.addSensor)
self.mTimeSeries.sigSensorRemoved.connect(self.removeSensor)
super(MapViewDock, self).__init__(parent)
self.setupUi(self)
self.baseTitle = self.windowTitle()
self.btnAddMapView.setDefaultAction(self.actionAddMapView)
self.btnRemoveMapView.setDefaultAction(self.actionRemoveMapView)
self.btnCrs.crsChanged.connect(self.sigCrsChanged)
self.btnMapCanvasColor.colorChanged.connect(self.sigMapCanvasColorChanged)
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()
self.mTimeSeries = None
def mapViews(self)->list:
"""
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

Benjamin Jakimow
committed
def setCrs(self, crs):
if isinstance(crs, QgsCoordinateReferenceSystem):
old = self.btnCrs.crs()
if old != crs:
self.btnCrs.setCrs(crs)
self.btnCrs.setLayerCrs(crs)

Benjamin Jakimow
committed
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
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
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)
def mapSize(self):
return QSize(self.spinBoxMapSizeX.value(),
self.spinBoxMapSizeY.value())
def refreshCurrentMapView(self, *args):
mv = self.currentMapView()
if isinstance(mv, MapView):
mv.refreshMapView()
else:
s =""
def dummySlot(self):
s =""
for mapView in mapViews:
idx = self.stackedWidget.indexOf(mapView.ui)
if idx >= 0:
self.stackedWidget.removeWidget(mapView.ui)
mapView.ui.close()
else:
s = ""
self.actionRemoveMapView.setEnabled(len(self.mMapViews) > 0)
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
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
committed
for mapView in mapViews:
self.sigMapViewAdded.emit(mapView)
def updateButtons(self, *args):
b = len(self.mMapViews) > 0
self.actionRemoveMapView.setEnabled(b)
self.actionApplyStyles.setEnabled(b)
self.actionHighlightMapView.setEnabled(b)
def createMapView(self)->MapView:
"""
Create a new MapView
:return: MapView
"""
mapView = MapView()
n = len(self.mapViews()) + 1
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)
mapView.setTimeSeries(self.mTimeSeries)
self.addMapView(mapView)
return mapView
def addMapView(self, mapView:MapView):
"""
Adds a MapView
:param mapView: MapView
"""
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)
def onToolboxIndexChanged(self):
b = isinstance(self.toolBox.currentWidget(), MapView)
self.actionRemoveMapView.setEnabled(b)
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 item == mapView:
numMV += 1
if mapView.isVisible():
icon = QIcon(":/timeseriesviewer/icons/mapview.svg")
else:
icon = QIcon(":/timeseriesviewer/icons/mapviewHidden.svg")
self.toolBox.setItemIcon(i, icon)
self.toolBox.setItemText(i, 'Map View {} "{}"'.format(numMV, mapView.title()))
break
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))
self.sigMapViewRemoved.emit(mapView)
return mapView
def __len__(self)->int:
"""
Returns the number of MapViews
:return: int
"""
return len(self.mapViews())
"""
Provides an iterator over all MapViews
:return:
"""
return iter(self.mapViews())
def __getitem__(self, slice):
return self.mapViews()[slice]
return mapView in self.mapViews()
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
"""
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:

Benjamin Jakimow
committed
mapView.setCrosshairVisibility(b)
def index(self, mapView):
assert isinstance(mapView, MapView)
return self.mapViewsDefinitions.index(mapView)
def setCurrentMapView(self, mapView):
assert isinstance(mapView, MapView) and mapView in self.mMapViews
idx = self.stackedWidget.indexOf(mapView.ui)
if idx >= 0:
self.stackedWidget.setCurrentIndex(idx)
self.cbMapView.setCurrentIndex(self.mMapViews.mapView2idx(mapView).row())
self.updateTitle()
def updateTitle(self, *args):
# self.btnToggleMapViewVisibility.setChecked(mapView)
mapView = self.currentMapView()
if isinstance(mapView, MapView):
if mapView in self.mMapViews:
i = str(self.mMapViews.mapView2idx(mapView).row()+1)
else:
i = ''
#title = '{} | {} "{}"'.format(self.baseTitle, i, mapView.title())
title = '{} | {}'.format(self.baseTitle, i)
self.setWindowTitle(title)
w = self.toolBox.currentWidget()
if isinstance(w, MapView):
return w
return None