From d722ccbebe083d46104b5d4255621e2ce66ecf9b Mon Sep 17 00:00:00 2001
From: "benjamin.jakimow@geo.hu-berlin.de" <q8DTkxUg-BB>
Date: Tue, 21 Feb 2017 16:34:45 +0100
Subject: [PATCH] minor widget changed, qgis interaction

---
 timeseriesviewer/main.py                |  81 +++--
 timeseriesviewer/tests.py               |  66 +++-
 timeseriesviewer/ui/docks.py            |  40 +-
 timeseriesviewer/ui/renderingdock.ui    |  94 +----
 timeseriesviewer/ui/timeseriesdock.ui   | 465 ++++++++++++++----------
 timeseriesviewer/ui/timeseriesviewer.ui |  35 +-
 timeseriesviewer/ui/widgets.py          |  46 +--
 timeseriesviewer/viewmodels.py          |   4 +-
 8 files changed, 489 insertions(+), 342 deletions(-)

diff --git a/timeseriesviewer/main.py b/timeseriesviewer/main.py
index 4d0a7c56..6fa2c6db 100644
--- a/timeseriesviewer/main.py
+++ b/timeseriesviewer/main.py
@@ -243,8 +243,11 @@ class QgisTsvBridge(QObject):
 
         from timeseriesviewer.ui.widgets import TimeSeriesViewerUI
         assert isinstance(self.ui, TimeSeriesViewerUI)
+
         self.cbQgsVectorLayer = self.ui.dockRendering.cbQgsVectorLayer
         self.gbQgsVectorLayer = self.ui.dockRendering.gbQgsVectorLayer
+        self.cbQgsVectorLayer.setEnabled(True)
+        self.gbQgsVectorLayer.setEnabled(True)
         self.qgsMapCanvas = self.iface.mapCanvas()
         assert isinstance(self.qgsMapCanvas, QgsMapCanvas)
 
@@ -257,7 +260,9 @@ class QgisTsvBridge(QObject):
 
         self.TSV.spatialTemporalVis.sigSpatialExtentChanged.connect(self.syncQgsWithTsv)
 
+        self.gbQgsVectorLayer.clicked.connect(self.onQgsVectorLayerChanged)
         self.cbQgsVectorLayer.layerChanged.connect(self.onQgsVectorLayerChanged)
+        self.onQgsVectorLayerChanged(None)
 
     def syncTsvWithQgs(self, *args):
         if self.syncBlocked:
@@ -265,7 +270,6 @@ class QgisTsvBridge(QObject):
         syncState = self.ui.dockNavigation.qgsSyncState()
         if any(syncState.values()):
             self.syncBlocked = True
-            print(('# QGIS -> TSV#', syncState))
             self.syncBlocked = True
             QTimer.singleShot(500, lambda: self.unblock())
             tsvExt = self.TSV.spatialTemporalVis.extent
@@ -285,7 +289,6 @@ class QgisTsvBridge(QObject):
 
         syncState = self.ui.dockNavigation.qgsSyncState()
         if any(syncState.values()):
-            print(('# TSV -> QGIS #', syncState))
             self.syncBlocked = True
             QTimer.singleShot(500, lambda: self.unblock())
             tsvExt = self.TSV.spatialTemporalVis.extent
@@ -295,7 +298,9 @@ class QgisTsvBridge(QObject):
             self.qgsMapCanvas.setExtent(newExtent)
             self.syncBlocked = False
 
-            #QTimer.singleShot(500, lambda : self.unblock())
+            QTimer.singleShot(1000, lambda : self.unblock())
+
+
     def unblock(self):
         self.syncBlocked = False
 
@@ -314,21 +319,17 @@ class QgisTsvBridge(QObject):
 
 
     def onQgsVectorLayerChanged(self, lyr):
-        dprint('QgisTsvBridge: selected Qgs Vector layer changed')
-        s = ""
+        if self.gbQgsVectorLayer.isChecked() and \
+           isinstance(self.cbQgsVectorLayer.currentLayer(), QgsVectorLayer):
+            self.TSV.spatialTemporalVis.setVectorLayer(self.cbQgsVectorLayer.currentLayer())
+        else:
+            self.TSV.spatialTemporalVis.setVectorLayer(None)
+
 
     def extent(self):
         assert isinstance(self.qgsMapCanvas, QgsMapCanvas)
         return SpatialExtent.fromMapCanvas(self.qgsMapCanvas)
 
-    def getVectorLayerRepresentation(self):
-        if self.ui.gbQgsVectorLayer.isChecked():
-            lyr = self.cbQgsVectorLayer.currentLayer()
-            alpha = self.ui.sliderQgsVectorTransparency.value()
-            return lyr
-        else:
-            return None
-
 
     def syncExtent(self, isChecked):
         if isChecked:
@@ -359,8 +360,7 @@ class MapView(QObject):
     sigTitleChanged = pyqtSignal(str)
     sigSensorRendererChanged = pyqtSignal(SensorInstrument, QgsRasterRenderer)
 
-    sigVectorLayerChanged = pyqtSignal(QgsVectorLayer)
-    sigVectorLayerRemoved = pyqtSignal()
+    sigVectorLayerChanged = pyqtSignal()
 
     sigSpatialExtentChanged = pyqtSignal(SpatialExtent)
     sigShowProfiles = pyqtSignal(QgsPoint, QgsCoordinateReferenceSystem)
@@ -376,6 +376,7 @@ class MapView(QObject):
         self.setVisibility(True)
 
         self.vectorLayer = None
+        self.setVectorLayer(None)
 
         #forward actions with reference to this band view
         self.spatialExtent = None
@@ -389,13 +390,17 @@ class MapView(QObject):
         self.mSpatialExtent = None
 
     def setVectorLayer(self, lyr):
-        if lyr is not None:
-            assert isinstance(lyr, QgsVectorLayer)
+        if isinstance(lyr, QgsVectorLayer):
             self.vectorLayer = lyr
-            self.sigVectorLayerChanged.emit(self.vectorLayer)
+            self.vectorLayer.rendererChanged.connect(self.sigVectorLayerChanged)
+            self.ui.btnVectorOverlayVisibility.setEnabled(True)
+
+
         else:
-            lyr = None
-            self.sigVectorLayerRemoved.emit()
+            self.vectorLayer = None
+            self.ui.btnVectorOverlayVisibility.setEnabled(False)
+
+        self.sigVectorLayerChanged.emit()
 
     def applyStyles(self):
         for sensorView in self.sensorViews.values():
@@ -414,6 +419,12 @@ class MapView(QObject):
     def visibility(self):
         return self.ui.visibility()
 
+    def visibleVectorOverlay(self):
+        return isinstance(self.vectorLayer, QgsVectorLayer) and \
+            self.ui.btnVectorOverlayVisibility.isChecked()
+
+
+
     def setTitle(self, title):
         self.mTitle = title
         #self.ui.setTitle('Map View' + title)
@@ -426,8 +437,12 @@ class MapView(QObject):
     def removeSensor(self, sensor):
         assert type(sensor) is SensorInstrument
         if sensor in self.sensorViews.keys():
-            self.sensorViews[sensor].close()
-            self.sensorViews.pop(sensor)
+            w = self.sensorViews.pop(sensor)
+            from timeseriesviewer.ui.widgets import MapViewSensorSettings
+            assert isinstance(w, MapViewSensorSettings)
+            l = self.ui.sensorList
+            l.removeWidget(w.ui)
+            w.ui.close()
             self.ui.adjustSize()
             return True
         else:
@@ -452,10 +467,6 @@ class MapView(QObject):
         l = self.ui.sensorList
         i = l.count()
         l.addWidget(w.ui)
-        from timeseriesviewer.ui.widgets import maxWidgetSizes
-
-
-        s = ""
 
 
     def getSensorWidget(self, sensor):
@@ -542,7 +553,7 @@ class TimeSeriesDatumView(QObject):
         canvas.close()
         self.adjustBaseMinSize()
 
-    def redraw(self):
+    def refresh(self):
         if self.ui.isVisible():
             for c in self.mapCanvases.values():
                 if c.isVisible():
@@ -601,6 +612,7 @@ class SpatialTemporalVisualization(QObject):
         self.MVC = MapViewCollection(self)
         self.MVC.sigShowProfiles.connect(self.sigShowProfiles.emit)
 
+        self.vectorOverlay = None
 
         self.timeSeriesDateViewCollection = TimeSeriesDateViewCollection(self)
         self.timeSeriesDateViewCollection.sigResizeRequired.connect(self.adjustScrollArea)
@@ -615,6 +627,9 @@ class SpatialTemporalVisualization(QObject):
         self.setSpatialExtent(self.TS.getMaxSpatialExtent())
         self.setSubsetSize(QSize(100,50))
 
+    def setVectorLayer(self, lyr):
+        self.MVC.setVectorLayer(lyr)
+
     def createMapView(self):
         self.MVC.createMapView()
 
@@ -628,9 +643,9 @@ class SpatialTemporalVisualization(QObject):
         self.timeSeriesDateViewCollection.setSubsetSize(size)
         self.adjustScrollArea()
 
-    def redraw(self):
+    def refresh(self):
         for tsdView in self.timeSeriesDateViewCollection:
-            tsdView.redraw()
+            tsdView.refresh()
 
 
     def adjustScrollArea(self):
@@ -859,6 +874,7 @@ class MapViewCollection(QObject):
         self.STViz = STViz
         self.STViz.dockMapViews.actionApplyStyles.triggered.connect(self.applyStyles)
         self.STViz.TS.sigSensorAdded.connect(self.addSensor)
+        self.STViz.TS.sigSensorRemoved.connect(self.removeSensor)
         self.ui = STViz.dockMapViews
         self.btnList = STViz.dockMapViews.BVButtonList
         self.scrollArea = STViz.dockMapViews.scrollAreaMapViews
@@ -883,6 +899,11 @@ class MapViewCollection(QObject):
         #newSize = self.scrollAreaContent.sizeHint()
         self.scrollAreaContent.setFixedSize(newSize)
 
+    def setVectorLayer(self, lyr):
+        for mapView in self.mapViewsDefinitions:
+            assert isinstance(mapView, MapView)
+            mapView.setVectorLayer(lyr)
+
     def addSensor(self, sensor):
         for mapView in self.mapViewsDefinitions:
             mapView.addSensor(sensor)
@@ -1060,7 +1081,7 @@ class TimeSeriesViewer:
 
         D.actionAddTSD.triggered.connect(lambda : self.ua_addTSImages())
         D.actionRemoveTSD.triggered.connect(lambda: self.TS.removeDates(self.ui.dockTimeSeries.selectedTimeSeriesDates()))
-        D.actionRedraw.triggered.connect(self.spatialTemporalVis.redraw)
+        D.actionRefresh.triggered.connect(self.spatialTemporalVis.refresh)
         D.actionLoadTS.triggered.connect(self.loadTimeSeries)
         D.actionClearTS.triggered.connect(self.clearTimeSeries)
         D.actionSaveTS.triggered.connect(self.ua_saveTSFile)
diff --git a/timeseriesviewer/tests.py b/timeseriesviewer/tests.py
index 7387c480..7b9dcf66 100644
--- a/timeseriesviewer/tests.py
+++ b/timeseriesviewer/tests.py
@@ -44,6 +44,17 @@ def test_gui():
         files = files[0:10]
         S.loadImageFiles(files)
         return
+    if False:
+        files = [r'E:\_EnMAP\temp\temp_bj\landsat\37S\EB\LC81720342015129LGN00\LC81720342015129LGN00_sr.tif']
+        S.loadImageFiles(files)
+        return
+    if True:
+        from timeseriesviewer import file_search
+        files = file_search(r'E:\_EnMAP\temp\temp_bj\landsat\37S\EB', '*_sr.tif', recursive=True)
+        #files = files[0:15]
+        print('Load {} images...'.format(len(files)))
+        S.loadImageFiles(files)
+        return
     if False:
         files = [r'H:\\LandsatData\\Landsat_NovoProgresso\\LC82270652013140LGN01\\LC82270652013140LGN01_sr_band4.img']
         S.loadImageFiles(files)
@@ -155,10 +166,58 @@ def test_qgisbridge():
     fakeQGIS.addRasterLayer(example.Images.Img_2014_08_03_LE72270652014215CUB00_BOA)
 
     S.loadImageFiles([example.Images.Img_2014_01_15_LC82270652014015LGN00_BOA])
-
+    S.ui.resize(600,600)
     s = ""
 
 
+def gdal_qgis_benchmark():
+    """Benchmark to compare loading times between GDAL a QGIS"""
+    import numpy as np
+
+    def load_via_gdal(path):
+        ds = gdal.Open(path)
+        assert isinstance(ds, gdal.Dataset)
+        nb = ds.RasterCount
+        ns = ds.RasterXSize
+        nl = ds.RasterYSize
+        wkt = ds.GetProjectionRef()
+        crs = QgsCoordinateReferenceSystem(wkt)
+        return crs, nb, nl, ns
+
+
+    def load_via_qgis(path):
+        lyr = QgsRasterLayer(path)
+        nb = lyr.bandCount()
+        ns = lyr.width()
+        nl = lyr.height()
+        crs = lyr.crs()
+        return crs, nb, nl, ns
+
+    t0 = None
+    dtime = lambda t0 : np.datetime64('now') - t0
+
+    root = r'E:\_EnMAP\temp\temp_bj\landsat\37S\EB'
+    files = file_search(root, '*_sr.tif', recursive=True)
+    #files = files[0:10]
+
+
+    print('Load {} images with gdal...'.format(len(files)))
+    t0 = np.datetime64('now')
+    results_gdal = [load_via_gdal(p) for p in files]
+    dt_gdal = dtime(t0)
+
+    print('Load {} images with qgis...'.format(len(files)))
+    t0 = np.datetime64('now')
+    results_qgis = [load_via_qgis(p) for p in files]
+    dt_qgis = dtime(t0)
+
+    print('gdal: {} qgis: {}'.format(str(dt_gdal), str(dt_qgis)))
+    for t in zip(results_gdal, results_qgis):
+        assert t[0] == t[1]
+        assert t[0][0].authid() == t[1][0].authid()
+    print('Benchmark done')
+    s =""
+
 
 def test_component():
 
@@ -187,8 +246,9 @@ if __name__ == '__main__':
     qgsApp.initQgis()
 
     #run tests
-    if True: test_qgisbridge()
-    if False: test_gui()
+    if False: gdal_qgis_benchmark()
+    if False: test_qgisbridge()
+    if True: test_gui()
     if False: test_component()
 
 
diff --git a/timeseriesviewer/ui/docks.py b/timeseriesviewer/ui/docks.py
index d689a3eb..0fd851c0 100644
--- a/timeseriesviewer/ui/docks.py
+++ b/timeseriesviewer/ui/docks.py
@@ -50,6 +50,11 @@ class RenderingDockUI(TsvDockWidgetBase, load('renderingdock.ui')):
 
         self.subsetSizeWidgets = [self.spinBoxSubsetSizeX, self.spinBoxSubsetSizeY]
 
+        self.gbCrosshair.setVisible(False)
+
+
+
+
     def subsetSize(self):
         return QSize(self.spinBoxSubsetSizeX.value(),
                      self.spinBoxSubsetSizeY.value())
@@ -81,7 +86,6 @@ class RenderingDockUI(TsvDockWidgetBase, load('renderingdock.ui')):
 
 
     def refreshProgressBar(self):
-        #todo: do this delayed
         self.progressBar.setMaximum(len(self.progress.keys()))
         p = len([v for v in self.progress.values() if v == True])
         self.progressBar.setValue(p)
@@ -230,10 +234,34 @@ class TimeSeriesDockUI(TsvDockWidgetBase, load('timeseriesdock.ui')):
         self.btnSaveTS.setDefaultAction(parent.actionSaveTS)
         self.btnClearTS.setDefaultAction(parent.actionClearTS)
 
+        self.progressBar.setMinimum(0)
+        self.setProgressInfo(0,100, 'Add images to fill time series')
+        self.progressBar.setValue(0)
+        self.progressInfo.setText(None)
         self.frameFilters.setVisible(False)
 
         self.connectTimeSeries(None)
 
+    def setStatus(self):
+        from timeseriesviewer.timeseries import TimeSeries
+        if isinstance(self.TS, TimeSeries):
+            ndates = len(self.TS)
+            nsensors = len(set([tsd.sensor for tsd in self.TS]))
+            msg = '{} scene(s) from {} sensor(s)'.format(ndates, nsensors)
+            if ndates > 1:
+                msg += ', {} to {}'.format(str(self.TS[0].date), str(self.TS[-1].date))
+            self.progressInfo.setText(msg)
+
+
+    def setProgressInfo(self, nDone, nMax, message=None):
+        if self.progressBar.maximum() != nMax:
+            self.progressBar.setMaximum(nMax)
+        self.progressBar.setValue(nDone)
+        self.progressInfo.setText(message)
+        QgsApplication.processEvents()
+        if nDone == nMax:
+            QTimer.singleShot(3000, lambda: self.setStatus())
+
 
     def onSelectionChanged(self, *args):
         self.btnRemoveTSD.setEnabled(self.SM is not None and len(self.SM.selectedRows()) > 0)
@@ -247,11 +275,13 @@ class TimeSeriesDockUI(TsvDockWidgetBase, load('timeseriesdock.ui')):
         return []
 
     def connectTimeSeries(self, TS):
+        from timeseriesviewer.timeseries import TimeSeries
         self.TS = TS
         self.TSM = None
         self.SM = None
         self.timeSeriesInitialized = False
-        if TS is not None:
+
+        if isinstance(TS, TimeSeries):
             from timeseriesviewer.viewmodels import TimeSeriesTableModel
             self.TSM = TimeSeriesTableModel(self.TS)
             self.tableView_TimeSeries.setModel(self.TSM)
@@ -259,6 +289,8 @@ class TimeSeriesDockUI(TsvDockWidgetBase, load('timeseriesdock.ui')):
             self.tableView_TimeSeries.setSelectionModel(self.SM)
             self.SM.selectionChanged.connect(self.onSelectionChanged)
             self.tableView_TimeSeries.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
+            TS.sigLoadingProgress.connect(self.setProgressInfo)
+
         self.onSelectionChanged()
 
 class MapViewDockUI(TsvDockWidgetBase, load('mapviewdock.ui')):
@@ -271,7 +303,7 @@ class MapViewDockUI(TsvDockWidgetBase, load('mapviewdock.ui')):
 
         #self.dockLocationChanged.connect(self.adjustLayouts)
 
-    def toogleLayout(self, p):
+    def toggleLayout(self, p):
         newLayout = None
         l = p.layout()
         print('toggle layout {}'.format(str(p.objectName())))
@@ -308,7 +340,7 @@ class MapViewDockUI(TsvDockWidgetBase, load('mapviewdock.ui')):
                         and isinstance(lOld, QHBoxLayout):
 
             #self.toogleLayout(self.scrollAreaMapsViewDockContent)
-            self.toogleLayout(self.BVButtonList)
+            self.toggleLayout(self.BVButtonList)
 
 class LabelingDockUI(TsvDockWidgetBase, load('labelingdock.ui')):
     def __init__(self, parent=None):
diff --git a/timeseriesviewer/ui/renderingdock.ui b/timeseriesviewer/ui/renderingdock.ui
index 6774f679..3ac2d56e 100644
--- a/timeseriesviewer/ui/renderingdock.ui
+++ b/timeseriesviewer/ui/renderingdock.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>400</width>
-    <height>396</height>
+    <width>266</width>
+    <height>368</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -22,53 +22,12 @@
    </property>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
-     <widget class="QFrame" name="frame">
-      <property name="minimumSize">
-       <size>
-        <width>0</width>
-        <height>0</height>
-       </size>
-      </property>
-      <property name="maximumSize">
-       <size>
-        <width>16777215</width>
-        <height>16777215</height>
-       </size>
-      </property>
-      <property name="frameShape">
-       <enum>QFrame::StyledPanel</enum>
-      </property>
-      <property name="frameShadow">
-       <enum>QFrame::Raised</enum>
+     <widget class="QGroupBox" name="groupBox_2">
+      <property name="title">
+       <string>Render progress</string>
       </property>
-      <layout class="QFormLayout" name="formLayout_2">
-       <item row="0" column="0">
-        <widget class="QPushButton" name="btnRefresh">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>125</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="text">
-          <string>Refresh</string>
-         </property>
-        </widget>
-       </item>
-       <item row="0" column="1">
-        <widget class="QCheckBox" name="cbRefreshImmediately">
-         <property name="text">
-          <string>immediately</string>
-         </property>
-        </widget>
-       </item>
-       <item row="1" column="0" colspan="2">
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <item>
         <widget class="QProgressBar" name="progressBar">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -259,6 +218,9 @@
       <property name="checkable">
        <bool>true</bool>
       </property>
+      <property name="checked">
+       <bool>false</bool>
+      </property>
       <property name="saveCheckedState">
        <bool>true</bool>
       </property>
@@ -266,7 +228,7 @@
        <item row="0" column="0">
         <widget class="QLabel" name="label_13">
          <property name="enabled">
-          <bool>true</bool>
+          <bool>false</bool>
          </property>
          <property name="text">
           <string>Type</string>
@@ -276,7 +238,7 @@
        <item row="0" column="1">
         <widget class="QComboBox" name="cbCrosshairStyle">
          <property name="enabled">
-          <bool>true</bool>
+          <bool>false</bool>
          </property>
          <item>
           <property name="text">
@@ -298,7 +260,7 @@
        <item row="1" column="0">
         <widget class="QLabel" name="label_14">
          <property name="enabled">
-          <bool>true</bool>
+          <bool>false</bool>
          </property>
          <property name="text">
           <string>Color</string>
@@ -308,7 +270,7 @@
        <item row="1" column="1">
         <widget class="QgsColorButton" name="btnCrosshairColor">
          <property name="enabled">
-          <bool>true</bool>
+          <bool>false</bool>
          </property>
          <property name="maximumSize">
           <size>
@@ -329,6 +291,9 @@
       <property name="checkable">
        <bool>true</bool>
       </property>
+      <property name="checked">
+       <bool>false</bool>
+      </property>
       <property name="collapsed">
        <bool>false</bool>
       </property>
@@ -342,7 +307,7 @@
        <item row="0" column="0" colspan="2">
         <widget class="QgsMapLayerComboBox" name="cbQgsVectorLayer">
          <property name="enabled">
-          <bool>true</bool>
+          <bool>false</bool>
          </property>
          <property name="sizePolicy">
           <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -352,29 +317,6 @@
          </property>
         </widget>
        </item>
-       <item row="1" column="0">
-        <widget class="QLabel" name="label">
-         <property name="text">
-          <string>Alpha</string>
-         </property>
-        </widget>
-       </item>
-       <item row="1" column="1">
-        <widget class="QSlider" name="sliderQgsVectorTransparency">
-         <property name="maximum">
-          <number>100</number>
-         </property>
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="tickPosition">
-          <enum>QSlider::TicksBelow</enum>
-         </property>
-         <property name="tickInterval">
-          <number>10</number>
-         </property>
-        </widget>
-       </item>
       </layout>
      </widget>
     </item>
diff --git a/timeseriesviewer/ui/timeseriesdock.ui b/timeseriesviewer/ui/timeseriesdock.ui
index eb02450d..4786b0e9 100644
--- a/timeseriesviewer/ui/timeseriesdock.ui
+++ b/timeseriesviewer/ui/timeseriesdock.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>597</width>
-    <height>175</height>
+    <width>640</width>
+    <height>239</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -26,216 +26,95 @@
    <property name="frameShadow">
     <enum>QFrame::Sunken</enum>
    </property>
-   <layout class="QHBoxLayout" name="horizontalLayout_3">
+   <layout class="QVBoxLayout" name="verticalLayout_3">
+    <property name="spacing">
+     <number>0</number>
+    </property>
+    <property name="margin">
+     <number>0</number>
+    </property>
     <item>
-     <widget class="QFrame" name="TSButtonList">
-      <property name="enabled">
-       <bool>true</bool>
-      </property>
-      <property name="sizePolicy">
-       <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
-        <horstretch>1</horstretch>
-        <verstretch>0</verstretch>
-       </sizepolicy>
-      </property>
-      <property name="minimumSize">
-       <size>
-        <width>25</width>
-        <height>0</height>
-       </size>
-      </property>
-      <property name="maximumSize">
-       <size>
-        <width>23</width>
-        <height>16777215</height>
-       </size>
-      </property>
-      <property name="frameShape">
-       <enum>QFrame::NoFrame</enum>
-      </property>
-      <property name="frameShadow">
-       <enum>QFrame::Raised</enum>
-      </property>
-      <layout class="QVBoxLayout" name="verticalLayout">
-       <property name="spacing">
-        <number>1</number>
-       </property>
-       <property name="margin">
-        <number>0</number>
-       </property>
-       <item>
-        <widget class="QToolButton" name="btnAddTSD">
-         <property name="text">
-          <string>...</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QToolButton" name="btnRemoveTSD">
-         <property name="text">
-          <string>...</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QToolButton" name="btnLoadTS">
-         <property name="text">
-          <string>...</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QToolButton" name="btnSaveTS">
-         <property name="text">
-          <string>...</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QToolButton" name="btnClearTS">
-         <property name="text">
-          <string>...</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="verticalSpacer">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>10</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </widget>
-    </item>
-    <item>
-     <widget class="QFrame" name="frame_5">
-      <property name="frameShape">
-       <enum>QFrame::StyledPanel</enum>
-      </property>
-      <property name="frameShadow">
-       <enum>QFrame::Sunken</enum>
-      </property>
-      <layout class="QHBoxLayout" name="horizontalLayout_2">
-       <property name="spacing">
-        <number>1</number>
-       </property>
-       <property name="margin">
-        <number>0</number>
-       </property>
-      </layout>
-     </widget>
-    </item>
-    <item>
-     <widget class="Line" name="line">
-      <property name="orientation">
-       <enum>Qt::Vertical</enum>
-      </property>
-     </widget>
-    </item>
-    <item>
-     <layout class="QVBoxLayout" name="verticalLayout_2">
+     <layout class="QHBoxLayout" name="horizontalLayout_4">
       <item>
-       <widget class="QFrame" name="frameFilters">
+       <widget class="QFrame" name="TSButtonList">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+          <horstretch>1</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>25</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>23</width>
+          <height>16777215</height>
+         </size>
+        </property>
         <property name="frameShape">
-         <enum>QFrame::StyledPanel</enum>
+         <enum>QFrame::NoFrame</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Raised</enum>
         </property>
-        <layout class="QHBoxLayout" name="horizontalLayout">
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <property name="spacing">
+          <number>1</number>
+         </property>
          <property name="margin">
           <number>0</number>
          </property>
          <item>
-          <widget class="QLabel" name="label">
-           <property name="text">
-            <string>Dates</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QToolButton" name="btnIncludeDates">
+          <widget class="QToolButton" name="btnAddTSD">
            <property name="text">
-            <string>i</string>
+            <string>...</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnExcludeDates">
+          <widget class="QToolButton" name="btnRemoveTSD">
            <property name="text">
-            <string>e</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QWidget" name="widget" native="true">
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="autoFillBackground">
-            <bool>false</bool>
-           </property>
-           <property name="styleSheet">
-            <string notr="true">background-color: rgb(0, 85, 0);</string>
+            <string>...</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QLabel" name="label_2">
+          <widget class="QToolButton" name="btnLoadTS">
            <property name="text">
-            <string>Season</string>
+            <string>...</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnIncludeSeason">
+          <widget class="QToolButton" name="btnSaveTS">
            <property name="text">
-            <string>i</string>
+            <string>...</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QToolButton" name="btnExcludeSeason">
+          <widget class="QToolButton" name="btnClearTS">
            <property name="text">
-            <string>e</string>
+            <string>...</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QWidget" name="widget_2" native="true">
-           <property name="minimumSize">
-            <size>
-             <width>100</width>
-             <height>0</height>
-            </size>
-           </property>
-           <property name="autoFillBackground">
-            <bool>false</bool>
-           </property>
-           <property name="styleSheet">
-            <string notr="true">background-color: rgb(0, 85, 0);</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer">
+          <spacer name="verticalSpacer">
            <property name="orientation">
-            <enum>Qt::Horizontal</enum>
+            <enum>Qt::Vertical</enum>
            </property>
            <property name="sizeHint" stdset="0">
             <size>
-             <width>40</width>
-             <height>20</height>
+             <width>20</width>
+             <height>10</height>
             </size>
            </property>
           </spacer>
@@ -244,26 +123,238 @@
        </widget>
       </item>
       <item>
-       <widget class="QTableView" name="tableView_TimeSeries">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-          <horstretch>1</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="frameShape">
-         <enum>QFrame::NoFrame</enum>
-        </property>
-        <property name="alternatingRowColors">
-         <bool>true</bool>
-        </property>
-        <property name="sortingEnabled">
-         <bool>true</bool>
+       <widget class="Line" name="line">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
         </property>
        </widget>
       </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <widget class="QFrame" name="frameFilters">
+          <property name="frameShape">
+           <enum>QFrame::StyledPanel</enum>
+          </property>
+          <property name="frameShadow">
+           <enum>QFrame::Raised</enum>
+          </property>
+          <layout class="QHBoxLayout" name="horizontalLayout">
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="label">
+             <property name="text">
+              <string>Dates</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="btnIncludeDates">
+             <property name="text">
+              <string>i</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="btnExcludeDates">
+             <property name="text">
+              <string>e</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QWidget" name="widget" native="true">
+             <property name="minimumSize">
+              <size>
+               <width>100</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="autoFillBackground">
+              <bool>false</bool>
+             </property>
+             <property name="styleSheet">
+              <string notr="true">background-color: rgb(0, 85, 0);</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="label_2">
+             <property name="text">
+              <string>Season</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="btnIncludeSeason">
+             <property name="text">
+              <string>i</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="btnExcludeSeason">
+             <property name="text">
+              <string>e</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QWidget" name="widget_2" native="true">
+             <property name="minimumSize">
+              <size>
+               <width>100</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="autoFillBackground">
+              <bool>false</bool>
+             </property>
+             <property name="styleSheet">
+              <string notr="true">background-color: rgb(0, 85, 0);</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="horizontalSpacer">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QTableView" name="tableView_TimeSeries">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+            <horstretch>1</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="frameShape">
+           <enum>QFrame::NoFrame</enum>
+          </property>
+          <property name="alternatingRowColors">
+           <bool>true</bool>
+          </property>
+          <property name="sortingEnabled">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
      </layout>
     </item>
+    <item>
+     <widget class="QFrame" name="infoBar">
+      <property name="minimumSize">
+       <size>
+        <width>0</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>16777215</width>
+        <height>15</height>
+       </size>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Raised</enum>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout_3">
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QProgressBar" name="progressBar">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+           <horstretch>1</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>50</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>100</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="value">
+          <number>24</number>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="progressInfo">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+           <horstretch>2</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>150</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>16777215</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>Progress info</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::LogText</enum>
+         </property>
+         <property name="scaledContents">
+          <bool>false</bool>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </item>
    </layout>
   </widget>
  </widget>
diff --git a/timeseriesviewer/ui/timeseriesviewer.ui b/timeseriesviewer/ui/timeseriesviewer.ui
index fa34d301..820ab4dd 100644
--- a/timeseriesviewer/ui/timeseriesviewer.ui
+++ b/timeseriesviewer/ui/timeseriesviewer.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>561</width>
-    <height>603</height>
+    <width>809</width>
+    <height>379</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -80,8 +80,8 @@
         <rect>
          <x>0</x>
          <y>0</y>
-         <width>559</width>
-         <height>526</height>
+         <width>807</width>
+         <height>302</height>
         </rect>
        </property>
        <property name="sizePolicy">
@@ -128,7 +128,7 @@
     <rect>
      <x>0</x>
      <y>0</y>
-     <width>561</width>
+     <width>809</width>
      <height>21</height>
     </rect>
    </property>
@@ -159,6 +159,7 @@
       <string>Panels...</string>
      </property>
     </widget>
+    <addaction name="actionRefresh"/>
     <addaction name="actionAddMapView"/>
     <addaction name="menuPanels"/>
    </widget>
@@ -194,6 +195,7 @@
    <addaction name="actionSaveTS"/>
    <addaction name="actionAddMapView"/>
    <addaction name="separator"/>
+   <addaction name="actionRefresh"/>
    <addaction name="actionSelectCenter"/>
    <addaction name="actionZoomIn"/>
    <addaction name="actionZoomOut"/>
@@ -496,14 +498,6 @@
     <string>Copy labels to clipboard</string>
    </property>
   </action>
-  <action name="actionRedraw">
-   <property name="text">
-    <string>Re-draw</string>
-   </property>
-   <property name="toolTip">
-    <string>Redraws all image subsets</string>
-   </property>
-  </action>
   <action name="actionSettings">
    <property name="icon">
     <iconset resource="resources.qrc">
@@ -537,6 +531,21 @@
     <string>Identify pixel time series for specific coordinate</string>
    </property>
   </action>
+  <action name="actionRefresh">
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/timeseriesviewer/icons/mActionRefresh.png</normaloff>:/timeseriesviewer/icons/mActionRefresh.png</iconset>
+   </property>
+   <property name="text">
+    <string>Refresh</string>
+   </property>
+   <property name="toolTip">
+    <string>Refresh maps</string>
+   </property>
+   <property name="shortcut">
+    <string>F5</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
diff --git a/timeseriesviewer/ui/widgets.py b/timeseriesviewer/ui/widgets.py
index 7b7b23bb..c9d42b5b 100644
--- a/timeseriesviewer/ui/widgets.py
+++ b/timeseriesviewer/ui/widgets.py
@@ -70,13 +70,13 @@ class TsvMapCanvas(QgsMapCanvas):
         self.tsdView = tsdView
         self.mapView = mapView
         self.vectorLayer = None
-        self.mapView.sigVectorLayerChanged.connect(self.onVectorLayerChanged)
+        self.mapView.sigVectorLayerChanged.connect(self.refresh)
         self.mapView.sigVectorVisibility.connect(self.refresh)
         self.renderMe = False
         self.setRenderMe()
 
         self.sensorView = self.mapView.sensorViews[self.tsdView.Sensor]
-        self.mapView.sigMapViewVisibility.connect(self.setMapLayers)
+        self.mapView.sigMapViewVisibility.connect(self.refresh)
         self.mapView.sigSpatialExtentChanged.connect(self.setSpatialExtent)
         self.referenceLayer = QgsRasterLayer(self.tsdView.TSD.pathImg)
         QgsMapLayerRegistry.instance().addMapLayer(self.referenceLayer, False)
@@ -100,32 +100,30 @@ class TsvMapCanvas(QgsMapCanvas):
 
     def setMapLayers(self, *args):
         del self.MapCanvasLayers[:]
+        if self.mapView.visibleVectorOverlay():
+            #if necessary, register new vector layer
+            refLyr = self.mapView.vectorLayer
+            uri = refLyr.dataProvider().dataSourceUri()
+
+            if self.vectorLayer is None or self.vectorLayer.dataProvider().dataSourceUri() != uri:
+                providerKey = refLyr.dataProvider().name()
+                baseName = os.path.basename(uri)
+                self.vectorLayer = QgsVectorLayer(uri, baseName, providerKey)
+                QgsMapLayerRegistry.instance().addMapLayer(self.vectorLayer, False)
+
+            #update layer style
+            self.vectorLayer.setRendererV2(refLyr.rendererV2().clone())
 
-        if self.vectorLayer:
             self.MapCanvasLayers.append(QgsMapCanvasLayer(self.vectorLayer))
         if self.referenceLayer:
             self.MapCanvasLayers.append(QgsMapCanvasLayer(self.referenceLayer))
 
         self.setLayerSet(self.MapCanvasLayers)
-        self.refresh()
-
-    def onVectorLayerChanged(self, lyr=None):
-        if isinstance(lyr, QgsRasterLayer):
-
-            self.vectorLayer = QgsVectorLayer()
-            QgsMapLayerRegistry.instance().addMapLayer(self.vectorLayer, False)
-        else:
-
-            self.vectorLayer = False
-
-        self.setMapLayers()
-        self.refresh()
 
 
 
     def refresh(self):
-
-
+        self.setMapLayers()
         self.setRenderMe()
         super(TsvMapCanvas, self).refresh()
 
@@ -454,8 +452,8 @@ class TimeSeriesViewerUI(QMainWindow,
         self.dockRendering = addDockWidget(docks.RenderingDockUI(self))
         self.dockNavigation = addDockWidget(docks.NavigationDockUI(self))
         self.dockLabeling = addDockWidget(docks.LabelingDockUI(self))
-        self.tabifyDockWidget(self.dockNavigation, self.dockRendering)
-        self.tabifyDockWidget(self.dockNavigation, self.dockLabeling)
+        #self.tabifyDockWidget(self.dockNavigation, self.dockRendering)
+        #self.tabifyDockWidget(self.dockNavigation, self.dockLabeling)
 
         from timeseriesviewer.sensorvisualization import SensorDockUI
         self.dockSensors = addDockWidget(SensorDockUI(self))
@@ -478,17 +476,13 @@ class TimeSeriesViewerUI(QMainWindow,
             self.menuPanels.addAction(dock.toggleViewAction())
 
 
-
+        self.dockLabeling.setHidden(True)
 
         self.dockTimeSeries.raise_()
         self.dockNavigation.raise_()
 
         self.dockMapViews.btnAddMapView.setDefaultAction(self.actionAddMapView)
 
-        #connect QPushButtons
-        self.dockRendering.btnRefresh.clicked.connect(self.actionRedraw.trigger)
-
-
 
         #todo: move to QGS_TSV_Bridge
         self.dockRendering.cbQgsVectorLayer.setFilters(QgsMapLayerProxyModel.VectorLayer)
@@ -778,7 +772,7 @@ class MapViewSensorSettings(QObject):
 
 
         nb = self.sensor.nb
-        lyr = QgsRasterLayer(self.sensor.refUri)
+        lyr = QgsRasterLayer(self.sensor.pathImg)
 
         #define default renderers:
         bands = [min([b,nb-1]) for b in range(3)]
diff --git a/timeseriesviewer/viewmodels.py b/timeseriesviewer/viewmodels.py
index a9e943f9..5ca3087b 100644
--- a/timeseriesviewer/viewmodels.py
+++ b/timeseriesviewer/viewmodels.py
@@ -12,7 +12,7 @@ from timeseriesviewer.timeseries import TimeSeries, TimeSeriesDatum, SensorInstr
 
 
 class TimeSeriesTableModel(QAbstractTableModel):
-    columnames = ['date', 'sensor', 'ns', 'nl', 'nb', 'image', 'mask']
+    columnames = ['date', 'sensor', 'ns', 'nl', 'nb', 'image']
 
     def __init__(self, TS, parent=None, *args):
 
@@ -119,8 +119,6 @@ class TimeSeriesTableModel(QAbstractTableModel):
                 value = '{}'.format(TSD.date)
             elif columnName == 'image':
                 value = TSD.pathImg
-            elif columnName == 'mask':
-                value = TSD.pathMsk
             elif columnName in keys:
                 value = TSD.__dict__[columnName]
             else:
-- 
GitLab