Skip to content
Snippets Groups Projects
mapvisualization.py 62.7 KiB
Newer Older
        mapView.sigMapViewVisibilityChanged.connect(lambda *args, mv=mapView : self.onMapViewUpdated(mv))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        i = self.toolBox.addItem(mapView, mapView.windowIcon(), mapView.title())
        self.toolBox.setCurrentIndex(i)
        self.onMapViewUpdated(mapView)
        self.sigMapViewAdded.emit(mapView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def onToolboxIndexChanged(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        b = isinstance(self.toolBox.currentWidget(), MapView)
        self.actionRemoveMapView.setEnabled(b)
Benjamin Jakimow's avatar
Benjamin Jakimow 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)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            if isinstance(item, MapView):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                numMV += 1
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            if item == mapView:

Benjamin Jakimow's avatar
Benjamin Jakimow committed
                if mapView.isVisible():
                    icon = QIcon(":/timeseriesviewer/icons/mapview.svg")
                else:
                    icon = QIcon(":/timeseriesviewer/icons/mapviewHidden.svg")
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                self.toolBox.setItemIcon(i, icon)
                self.toolBox.setItemText(i, 'Map View {} "{}"'.format(numMV, mapView.title()))
                break
Benjamin Jakimow's avatar
Benjamin Jakimow 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's avatar
Benjamin Jakimow committed
        self.sigMapViewRemoved.emit(mapView)
        return mapView
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def __len__(self)->int:
        """
        Returns the number of MapViews
        :return: int
        """
        return len(self.mapViews())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        """
        Provides an iterator over all MapViews
        :return:
        """
        return iter(self.mapViews())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        return self.mapViews()[slice]
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def __contains__(self, mapView):
        return mapView in self.mapViews()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def index(self, mapView):
        assert isinstance(mapView, MapView)
        return self.mapViews().index(mapView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def addSensor(self, sensor:SensorInstrument):
        """
        Adds a new SensorInstrument
        :param sensor: SensorInstrument
        """
        for mapView in self.mapViews():
            mapView.addSensor(sensor)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def removeSensor(self, sensor:SensorInstrument):
        """
        Removes a Sensor
        :param sensor: SensorInstrument
        """
        for mapView in self.mMapViews:
            mapView.removeSensor(sensor)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def applyStyles(self):
        for mapView in self.mMapViews:
            mapView.applyStyles()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def setCrosshairStyle(self, crosshairStyle):
        for mapView in self.mMapViews:
            mapView.setCrosshairStyle(crosshairStyle)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def setShowCrosshair(self, b):
        for mapView in self.mMapViews:
            mapView.setCrosshairVisibility(b)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def index(self, mapView):
        assert isinstance(mapView, MapView)
        return self.mapViewsDefinitions.index(mapView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def setCurrentMapView(self, mapView):
        assert isinstance(mapView, MapView) and mapView in self.mapViews()
        self.toolBox.setCurrentWidget(mapView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.updateTitle()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

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

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    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


    sigSpatialExtentChanged = pyqtSignal(SpatialExtent)
    sigCRSChanged = pyqtSignal(QgsCoordinateReferenceSystem)
    sigMapSizeChanged = pyqtSignal(QSize)
    sigMapsPerMapViewChanged = pyqtSignal(int)
    sigMapViewsChanged = pyqtSignal()
    sigCurrentDateChanged = pyqtSignal(TimeSeriesDate)
    sigViewModeChanged = pyqtSignal(ViewMode)

    def __init__(self, *args, **kwds):
        super(MapWidget, self).__init__(*args, **kwds)
        self.setupUi(self)
        self.setContentsMargins(1,1,1,1)
        self.mGrid = QGridLayout()
        self.setLayout(self.mGrid)
        self.mGrid.setSpacing(0)
        self.mGrid.setContentsMargins(0,0,0,0)

        self.mMapLayerStore = QgsMapLayerStore()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mMapViews = []
        self.mCanvases = dict()
        self.mTimeSeries = None

        self.mMapToolKey = MapTools.Pan
        self.mMapToolMode = None

        self.mViewMode = MapWidget.ViewMode.MapViewByRows
        self.mMpMV = 3

        self.mSpatialExtent = SpatialExtent.world()
        self.mCrs = self.mSpatialExtent.crs()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mCurrentDate = None
        self.mMapSize = QSize(200, 200)

        self.mMapRefreshTimer = QTimer(self)
        self.mMapRefreshTimer.timeout.connect(self.timedRefresh)
        self.mMapRefreshTimer.setInterval(500)
        self.mMapRefreshTimer.start()

        #self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))

    def setMapTool(self, mapToolKey:MapTools, mode):

        if self.mMapToolKey != mapToolKey or mode != self.mMapToolMode:
            self.mMapToolKey = mapToolKey
            self.mMapToolMode = mode

            for c in self.mapCanvases():
                assert isinstance(c, MapCanvas)
                mts = c.mapTools()
                mts.setSelectionMode()

    def visibleTSDs(self):

        for mv in self.mMapViews:
            tsds = []
            for c in self.mCanvases[mv]:
                if isinstance(c.tsd(), TimeSeriesDate):
                    tsds.append(c.tsd())

            return tsds
        return []

    def spatialExtent(self)->SpatialExtent:
        """
        Returns the current SpatialExtent
        :return: SpatialExtent
        """
        return self.mSpatialExtent

    def setSpatialExtent(self, extent:SpatialExtent)->SpatialExtent:
        """
        Sets a SpatialExtent to all MapCanvases.
        :param extent: SpatialExtent
        :return: SpatialExtent the current SpatialExtent
        """

        if self.mSpatialExtent != extent:
            self.mSpatialExtent = extent

            for c in self.mapCanvases():
                assert isinstance(c, MapCanvas)
                c.addToRefreshPipeLine(extent)

            self.sigSpatialExtentChanged.emit(self.mSpatialExtent.__copy__())
        return self.spatialExtent()

    def setCrs(self, crs:QgsCoordinateReferenceSystem):
        """
        Sets the MapCanvas CRS.
        :param crs: QgsCoordinateReferenceSystem
        :return: QgsCoordinateReferenceSystem
        """

        self.mCrs = crs
        if isinstance(crs, QgsCoordinateReferenceSystem):
            for c in self.mapCanvases():
                c.setCrs(crs)

        return self.crs()

    def timedRefresh(self):
        """
        Calls the timedRefresh() routine for all MapCanvases
        """
        for c in self.mapCanvases():
            assert isinstance(c, MapCanvas)
            c.timedRefresh()

    def crs(self)->QgsCoordinateReferenceSystem:
        return self.mCrs

    def setTimeSeries(self, ts:TimeSeries)->TimeSeries:
        assert ts == None or isinstance(ts, TimeSeries)
        self.mTimeSeries = ts

    def timeSeries(self)->TimeSeries:
        return self.mTimeSeries

    def setMode(self, mode:ViewMode):

        if mode != self.mViewMode:
            self.mViewMode = mode
            self._updateGrid()
            self.sigViewModeChanged.emit(self.mViewMode)

    def setMapsPerMapView(self, n:int):
        assert n > 0

        if n != self.mMpMV:
            self.mMpMV = n
            self._updateGrid()
            self.sigMapsPerMapViewChanged.emit(n)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def setMapSize(self, size:QSize):

        if size != self.mMapSize:
            for canvas in self.mapCanvases():
                canvas.setFixedSize(size)

            self.mMapSize = size
            self._updateWidgetSize()
            self.sigMapSizeChanged.emit(size)


    def mapSize(self)->QSize:
        return self.mMapSize
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def mapCanvases(self)->list:
        return self.findChildren(MapCanvas)

    def mapViewCanvases(self, mapView:MapView):
        return self.mCanvases[mapView]

    def setCurrentDate(self, tsd:TimeSeriesDate):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        assert isinstance(tsd, TimeSeriesDate)

        b = tsd != self.mCurrentDate
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mCurrentDate = tsd

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def currentDate(self)->TimeSeriesDate:
        return self.mCurrentDate


    def addMapView(self, mapView:MapView):
        assert isinstance(mapView, MapView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if mapView not in self.mMapViews:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.mMapViews.append(mapView)

            # connect signals
            mapView.sigMapViewVisibilityChanged
            mapView.sigCrosshairVisibilityChanged

            self._updateGrid()
            self.sigMapViewsChanged.emit()


    def removeMapView(self, mapView:MapView):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if mapView in self.mMapViews:
            self.mMapViews.remove(mapView)

            # disconnect signals


            self._updateGrid()
            self.sigMapViewsChanged.emit()



    def mapViews(self)->list:
        return self.mMapViews[:]
        if self.mViewMode == MapWidget.ViewMode.MapViewByRows:

            nr = len(self.mapViews())
        else:
            raise NotImplementedError()

        toRemove = []
        for row in range(nr, self.mGrid.rowCount()):
            for col in range(self.mGrid.columnCount()):
                item = self.mGrid.itemAtPosition(row, col)
                if isinstance(item, QLayoutItem) and isinstance(item.widget(), QWidget):
                    toRemove.append(item.widget())
        for col in range(nc, self.mGrid.columnCount()):
            for row in range(self.mGrid.rowCount()):
                item = self.mGrid.itemAtPosition(row, col)
                if isinstance(item, QLayoutItem) and isinstance(item.widget(), QWidget):
                    toRemove.append(item.widget())

        for w in toRemove:
            self.mGrid.removeWidget(w)
            w.setParent(None)
            w.setVisible(False)

    def _createMapCanvas(self)->MapCanvas:
        mapCanvas = MapCanvas()
        mapCanvas.setMapLayerStore(self.mMapLayerStore)

        # set general canvas properties
        mapCanvas.setFixedSize(self.mMapSize)
        mapCanvas.setDestinationCrs(self.mCrs)
        mapCanvas.setSpatialExtent(self.mSpatialExtent)

        # activate the current map tool
        mapTools = mapCanvas.mapTools()
        mapTools.activate(self.mMapToolKey)

        mt = mapCanvas.mapTool()
        if isinstance(mt, QgsMapToolSelect):
            mt.setSelectionMode(self.mMapToolMode)

        # connect signals
        self._connectCanvasSignals(mapCanvas)
        return mapCanvas

    def _connectCanvasSignals(self, mapCanvas:MapCanvas):
        mapCanvas.sigSpatialExtentChanged.connect(self.setSpatialExtent)
        mapCanvas.sigDestinationCrsChanged.connect(self.setCrs)
        mapCanvas.sigCrosshairPositionChanged.connect(self.onCrosshairPositionChanged)

    def _disconnectCanvasSignals(self, mapCanvas:MapCanvas):
        mapCanvas.sigSpatialExtentChanged.disconnect(self.setSpatialExtent)
        mapCanvas.sigDestinationCrsChanged.disconnect(self.setCrs)
        mapCanvas.sigCrosshairPositionChanged.disconnect(self.onCrosshairPositionChanged)
    def onCrosshairPositionChanged(self, spatialPoint:SpatialPoint):
        self.TSV.setCurrentLocation(point, canvas)
        # lambda point, canvas=mapCanvas: self.TSV.setCurrentLocation(point, canvas))

    def _updateGrid(self):

        self._cropGrid() #remove canvases that we do not need

        oldCanvases = self.findChildren(MapCanvas)

        usedCanvases = []
        self.mCanvases.clear()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        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.mMpMV):
                    item = self.mGrid.itemAtPosition(row, col)
                    if isinstance(item, QLayoutItem) and isinstance(item.widget(), MapCanvas):
                        c = item.widget()
                    else:
                        self.mGrid.addWidget(c, row, col)
                    assert isinstance(c, MapCanvas)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                    c.setFixedSize(self.mMapSize)
                    c.setTSD(None)
                    c.setMapView(mv)
                    usedCanvases.append(c)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                    self.mCanvases[mv].append(c)
        else:
            raise NotImplementedError()
        self._updateWidgetSize()
        self._updateCanvasDates()

        # remove old canvases
        for c in oldCanvases:
            if c not in usedCanvases:
                self._disconnectCanvasSignals(c)




    def _updateWidgetSize(self):

        self.mGrid.update()
        # self.resize(self.sizeHint())
        # self.setMaximumSize(self.sizeHint())
        self.setFixedSize(self.sizeHint())
        if self.parentWidget():
            w = self.parentWidget()
            assert isinstance(w, QWidget)

            rect = QGuiApplication.primaryScreen().geometry()

            maxw, maxh = 0.66*rect.width(), 0.66*rect.height()
            hint = self.sizeHint()
            minw, minh = min(hint.width(), maxw), min(hint.height(), maxh)

            w.setMinimumSize(minw, minh)
            #w.setFixedSize(self.sizeHint())
            w.layout().update()
            w.update()


    def sizeHint(self):
        if True:
            w, h = self.mMapSize.width(), self.mMapSize.height()

            nx = self.mMpMV
            ny = len(self.mMapViews)

            m = self.contentsMargins()
            s = self.layout().spacing()
            w = w * nx + m.right() + m.left() + nx * s
            h = h * ny + m.top() + m.bottom() + ny * s
            return QSize(w, h)
        sh = super(MapWidget, self).sizeHint()
        return sh
        if not (isinstance(self.mCurrentDate, TimeSeriesDate) and isinstance(self.timeSeries(), TimeSeries)):
            for c in self.findChildren(MapCanvas):
                assert isinstance(c, MapCanvas)
                c.setTSD(None)
        else:

            visible = [tsd for tsd in self.timeSeries() if tsd.isVisible()]
            if len(visible) == 0:
                return

            t = self.mCurrentDate.date()
            visible = sorted(visible, key=lambda tsd: abs(tsd.date() - t))
            visible = visible[0:min(len(visible), self.mMpMV)]
            visible = sorted(visible)

            for mapView in self.mapViews():
                for tsd, canvas in zip(visible, self.mCanvases[mapView]):
                    assert isinstance(tsd, TimeSeriesDate)
                    assert isinstance(canvas, MapCanvas)
                    canvas.setTSD(tsd)

                    #canvas.setLayers()
        self._updateCanvasInfo()
    def _updateCanvasInfo(self):
        for mapView in self.mapViews():
            assert isinstance(mapView, MapView)
            for canvas in self.mCanvases[mapView]:
                assert isinstance(canvas, MapCanvas)
                tsd = canvas.tsd()
                info = canvas.infoItem()
                assert isinstance(info, MapCanvasInfoItem)
                uc = []
                lc = []
                if isinstance(tsd, TimeSeriesDate):
                    if mapView.optionShowDate.isChecked():
                        uc += ['{}'.format(tsd.date())]
                    if mapView.optionShowMapViewName.isChecked():
                        lc += ['{}'.format(mapView.title())]
                    if mapView.optionShowSensorName.isChecked():
                        uc += ['{}'.format(tsd.sensor().name())]

                info.mUCText = ':'.join(uc)
                info.mLCText = ':'.join(lc)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
class SpatialTemporalVisualization(QObject):
    """
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    """
    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)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    sigVisibleDatesChanged = pyqtSignal(list)

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def __init__(self, timeSeriesViewer):
        super(SpatialTemporalVisualization, self).__init__()
        # assert isinstance(timeSeriesViewer, TimeSeriesViewer), timeSeriesViewer
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        # default map settings
        self.mSpatialExtent = SpatialExtent.world()
        #self.mCRS = self.mSpatialExtent.crs()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.ui = timeSeriesViewer.ui
        self.TSV = timeSeriesViewer
        self.TS = timeSeriesViewer.timeSeries()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        self.mMapWidget = self.ui.mapWidget
        assert isinstance(self.mMapWidget, MapWidget)
        self.mMapWidget.mMapLayerStore = self.TSV.mapLayerStore()
        self.mMapViewDock = self.ui.dockMapViews
        assert isinstance(self.mMapViewDock, MapViewDock)

        self.mMapViewDock.setTimeSeries(self.TS)
        self.mMapWidget.setTimeSeries(self.TS)
        self.mMapWidget.setMapSize(self.mapSize())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        # map-tool handling
        self.mMapToolKey = MapTools.Pan
        self.mMapToolMode = None
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        for mv in self.mMapViewDock:
            self.mMapWidget.addMapView(mv)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mMapViewDock.sigShowProfiles.connect(self.sigShowProfiles.emit)

        self.mMapViewDock.sigMapViewAdded.connect(self.mMapWidget.addMapView)
        self.mMapViewDock.sigMapViewRemoved.connect(self.mMapWidget.removeMapView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mMapViewDock.sigMapViewAdded.connect(self.sigMapViewAdded.emit)
        self.mMapViewDock.sigMapViewRemoved.connect(self.sigMapViewRemoved.emit)
        self.mMapViewDock.sigMapsPerMapViewChanged.connect(self.mMapWidget.setMapsPerMapView)
        self.mMapViewDock.sigCrsChanged.connect(self.mMapWidget.setCrs)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if len(self.TS) > 0:
            self.setSpatialExtent(self.TS.maxSpatialExtent())
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mNumberOfHiddenMapsToRefresh = 2
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def setMapTool(self, mapToolKey, mode):
        self.mMapWidget.setMapTool(mapToolKey, 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:
            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)
    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 self.mMapWidget.visibleTSDs()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def timedCanvasRefresh(self, *args, force:bool=False):
        self.mMapWidget.timedRefresh()

    def createMapView(self, name:str=None)->MapView:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Create a new MapWiew
        :return: MapView
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        return self.mMapViewDock.createMapView(name=name)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    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's avatar
Benjamin Jakimow committed
        self.mMapViewDock.setVectorLayer(lyr)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def setMapSize(self, size:QSize):
        """
        Sets the MapCanvas size.
        :param size: QSize
        """
        self.mMapWidget.setMapSize(size)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def mapSize(self)->QSize:
        """
        Returns the MapCanvas size
        :return: QSize
        """
        return self.mMapViewDock.mapSize()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def refresh(self):
        """
        Refreshes all visible MapCanvases
        """
        for c in self.mapCanvases():
            assert isinstance(c, MapCanvas)
            c.refresh()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        #self.mMapRefreshTimer.stop()
    def doAdjustScrollArea(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        m = self.targetLayout.contentsMargins()
        nX = len(self.DVC)
        w = h = 0
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        s = QSize()
        r = None
        tsdViews = [v for v in self.DVC if v.ui.isVisible()]
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        mapViews = [v for v in self.mMapViewDock if v.isVisible()]
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        nX = len(tsdViews)
        nY = len(mapViews)
        spacing = self.targetLayout.spacing()
        margins = self.targetLayout.contentsMargins()
Benjamin Jakimow's avatar
Benjamin Jakimow 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()
                sizeY = s
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            #s = tsdViews[0].ui.sizeHint()
            #s = QSize(nX * (s.width() + spacing) + margins.left() + margins.right(),
            #          s.height() + margins.top() + margins.bottom())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        #print(sizeX, sizeY)
        self.targetLayout.parentWidget().resize(QSize(sizeX, sizeY))

    def onLocationRequest(self, pt:SpatialPoint, canvas:QgsMapCanvas):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.sigShowProfiles.emit(pt, canvas, "")
    def setSpatialCenter(self, center:SpatialPoint, mapCanvas0=None):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Sets the spatial center of all MapCanvases
        :param center: SpatialPoint
        :param mapCanvas0:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        assert isinstance(center, SpatialPoint)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        if isinstance(extent, SpatialExtent):
            centerOld = extent.center()
            center = center.toCrs(extent.crs())
            if center != centerOld and isinstance(center, SpatialPoint):
                extent = extent.__copy__()
                extent.setCenter(center)
                self.setSpatialExtent(extent)
    def spatialCenter(self)->SpatialPoint:
        return self.spatialExtent().spatialCenter()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def setSpatialExtent(self, extent, mapCanvas0=None):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Sets the spatial extent of all MapCanvases
        :param extent: SpatialExtent
        :param mapCanvas0:
        :return:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        assert isinstance(extent, SpatialExtent)
        extent = extent.toCrs(self.crs())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        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
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if self.mSpatialExtent == extent:
            return

        self.mSpatialExtent = extent
        for mapCanvas in self.mapCanvases():
            assert isinstance(mapCanvas, MapCanvas)
        if lastExtent != extent:
            self.sigSpatialExtentChanged.emit(extent)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def mapViewDock(self)->MapViewDock:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Returns the MapViewDock that controls all MapViews
        :return: MapViewDock
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        return self.mMapViewDock
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def setMapBackgroundColor(self, color:QColor):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Sets the MapCanvas background color
        :param color: QColor
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        assert isinstance(self.mMapViewDock, MapViewDock)
        self.mMapViewDock.setMapBackgroundColor(color)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def mapCanvases(self, mapView=None)->list:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Returns MapCanvases
        :param mapView: a MapView to return MapCanvases from only, defaults to None
        :return: [list-of-MapCanvas]
        return self.mMapWidget.mapCanvases()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def mapViews(self)->list:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Returns a list of all mapviews
        :return [list-of-MapViews]:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        return self.mMapViewDock[:]
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def setCrs(self, crs):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        assert isinstance(crs, QgsCoordinateReferenceSystem)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        if self.mMapWidget.crs() != crs:
            self.mMapWidget.setCrs(crs)
            self.sigCRSChanged.emit(self.crs())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def crs(self)->QgsCoordinateReferenceSystem:
        """
        Returns the QgsCoordinateReferenceSystem
        :return: QgsCoordinateReferenceSystem
        """
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def spatialExtent(self)->SpatialExtent:
        """
        Returns the SpatialExtent
        :return: SpatialExtent
        """
        return self.mMapWidget.spatialExtent()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def navigateToTSD(self, tsd:TimeSeriesDate):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        """
        Changes the viewport of the scroll window to show the requested TimeSeriesDate
        :param TSD: TimeSeriesDate
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        """
        self.mMapWidget.setCurrentDate(tsd)