diff --git a/timeseriesviewer/ui/widgets.py b/timeseriesviewer/ui/widgets.py
index 9257f6192931b58534ef2d4e87b1b2ac0e9657e2..144b2c0de139ee6f8a46a57624b6927001d9913c 100644
--- a/timeseriesviewer/ui/widgets.py
+++ b/timeseriesviewer/ui/widgets.py
@@ -24,22 +24,34 @@ from qgis.gui import *
 from PyQt4 import uic
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
+import PyQt4.QtWebKit
 
 import sys, re, os, six
 
-from timeseriesviewer import jp
+from timeseriesviewer import jp, SETTINGS
 from timeseriesviewer.ui import loadUIFormClass, DIR_UI
 from timeseriesviewer.main import SpatialExtent
 
 PATH_MAIN_UI = jp(DIR_UI, 'timeseriesviewer.ui')
-PATH_BANDVIEWSETTINGS_UI = jp(DIR_UI, 'bandviewsettings.ui')
-PATH_BANDVIEWRENDERSETTINGS_UI = jp(DIR_UI, 'bandviewrendersettings.ui')
-PATH_BANDVIEW_UI = jp(DIR_UI, 'bandview.ui')
+PATH_MAPVIEWSETTINGS_UI = jp(DIR_UI, 'mapviewsettings.ui')
+PATH_MAPVIEWRENDERSETTINGS_UI = jp(DIR_UI, 'mapviewrendersettings.ui')
+PATH_MAPVIEWDEFINITION_UI = jp(DIR_UI, 'mapviewdefinition.ui')
 PATH_TSDVIEW_UI = jp(DIR_UI, 'timeseriesdatumview.ui')
+PATH_ABOUTDIALOG_UI = jp(DIR_UI, 'aboutdialog.ui')
+PATH_SETTINGSDIALOG_UI = jp(DIR_UI, 'settingsdialog.ui')
+
+PATH_PROFILEVIEWDOCK_UI = jp(DIR_UI, 'profileviewdock.ui')
+PATH_RENDERINGDOCK_UI = jp(DIR_UI, 'renderingdock.ui')
+
+
+
+
 
 class TimeSeriesViewerUI(QMainWindow,
                          loadUIFormClass(PATH_MAIN_UI)):
 
+    sigQgsSyncChanged = pyqtSignal(bool, bool, bool)
+
     def __init__(self, parent=None):
         """Constructor."""
         super(TimeSeriesViewerUI, self).__init__(parent)
@@ -55,6 +67,41 @@ class TimeSeriesViewerUI(QMainWindow,
         #I don't know why this is not possible in the QDesigner when QToolButtons are
         #placed outside a toolbar
 
+        import timeseriesviewer.ui.docks as docks
+
+        area = None
+
+        def addDockWidget(dock):
+            """
+            shortcut to add a created dock and return it
+            :param dock:
+            :return:
+            """
+            self.addDockWidget(area, dock)
+            return dock
+
+        area = Qt.LeftDockWidgetArea
+        self.dockSensors = addDockWidget(docks.SensorDockUI(self))
+
+        area = Qt.RightDockWidgetArea
+        self.dockProfiles = addDockWidget(docks.ProfileViewDockUI(self))
+
+        area = Qt.BottomDockWidgetArea
+        self.dockMapViews = addDockWidget(docks.MapViewDockUI(self))
+
+        for dock in self.findChildren(QDockWidget):
+            self.menuPanels.addAction(dock.toggleViewAction())
+
+        self.tabifyDockWidget(self.dockNavigation, self.dockRendering)
+        self.tabifyDockWidget(self.dockNavigation, self.dockLabeling)
+
+        self.tabifyDockWidget(self.dockTimeSeries, self.dockMapViews)
+        self.tabifyDockWidget(self.dockTimeSeries, self.dockProfiles)
+
+        self.dockTimeSeries.raise_()
+        self.dockNavigation.raise_()
+
+
         self.btnNavToFirstTSD.setDefaultAction(self.actionFirstTSD)
         self.btnNavToLastTSD.setDefaultAction(self.actionLastTSD)
         self.btnNavToPreviousTSD.setDefaultAction(self.actionPreviousTSD)
@@ -65,26 +112,75 @@ class TimeSeriesViewerUI(QMainWindow,
         self.btnLoadTS.setDefaultAction(self.actionLoadTS)
         self.btnSaveTS.setDefaultAction(self.actionSaveTS)
         self.btnClearTS.setDefaultAction(self.actionClearTS)
+        self.dockMapViews.btnAddMapView.setDefaultAction(self.actionAddMapView)
+
+        #connect QPushButtons
+        self.btnRefresh.clicked.connect(self.actionRedraw.trigger)
+
+
+        self.cbSyncQgsMapExtent.clicked.connect(self.syncExtent)
+        self.cbSyncQgsMapCenter.clicked.connect(self.qgsSyncStateChanged)
+        self.cbSyncQgsCRS.clicked.connect(self.qgsSyncStateChanged)
+
+        self.cbQgsVectorLayer.setFilters(QgsMapLayerProxyModel.VectorLayer)
 
         #define subset-size behaviour
         self.spinBoxSubsetSizeX.valueChanged.connect(lambda: self.onSubsetValueChanged('X'))
         self.spinBoxSubsetSizeY.valueChanged.connect(lambda: self.onSubsetValueChanged('Y'))
 
-        self.tabifyDockWidget(self.dockNavigation, self.dockRendering)
-        self.tabifyDockWidget(self.dockNavigation, self.dockLabeling)
-
 
         self.subsetRatio = None
+        self.lastSubsetSizeX = self.spinBoxSubsetSizeX.value()
+        self.lastSubsetSizeY = self.spinBoxSubsetSizeY.value()
+
+
 
 
-        self.subsetSizeWidgets = [self.spinBoxSubsetSizeX, self.spinBoxSubsetSizeY]
+        self.subsetSizeWidgets    = [self.spinBoxSubsetSizeX, self.spinBoxSubsetSizeY]
         self.spatialExtentWidgets = [self.spinBoxExtentCenterX, self.spinBoxExtentCenterY,
                                      self.spinBoxExtentWidth, self.spinBoxExtentHeight]
 
-    def setQgsLinkWidgets(self, b):
-        #enable/disable widgets that rely on QGIS instance interaction
+
+        self.restoreSettings()
+
+
+
+
+    def syncExtent(self, isChecked):
+        if isChecked:
+            self.cbSyncQgsMapCenter.setEnabled(False)
+            self.cbSyncQgsMapCenter.blockSignals(True)
+            self.cbSyncQgsMapCenter.setChecked(True)
+            self.cbSyncQgsMapCenter.blockSignals(False)
+        else:
+            self.cbSyncQgsMapCenter.setEnabled(True)
+        self.qgsSyncStateChanged()
+
+    def qgsSyncState(self):
+        return (self.cbSyncQgsMapCenter.isChecked(),
+                self.cbSyncQgsMapExtent.isChecked(),
+                self.cbSyncQgsCRS.isChecked())
+
+    def qgsSyncStateChanged(self, *args):
+        s = self.qgsSyncState()
+        self.sigQgsSyncChanged.emit(s[0], s[1], s[2])
+
+    def restoreSettings(self):
+        from timeseriesviewer import SETTINGS
+
+        #set last CRS
+        self.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
         s = ""
 
+
+    def setQgsLinkWidgets(self):
+        #enable/disable widgets that rely on QGIS instance interaction
+        from timeseriesviewer import QGIS_TSV_BRIDGE
+        from timeseriesviewer.main import QgsInstanceInteraction
+        b = isinstance(QGIS_TSV_BRIDGE, QgsInstanceInteraction)
+        self.gbSyncQgs.setEnabled(b)
+        self.gbQgsVectorLayer.setEnabled(b)
+
     def _blockSignals(self, widgets, block=True):
         states = dict()
         if isinstance(widgets, dict):
@@ -199,6 +295,66 @@ class TimeSeriesViewerUI(QMainWindow,
 
         self.actionSetSubsetSize.activate(QAction.Trigger)
 
+
+
+
+
+class AboutDialogUI(QDialog,
+                    loadUIFormClass(PATH_ABOUTDIALOG_UI)):
+    def __init__(self, parent=None):
+        """Constructor."""
+        super(AboutDialogUI, self).__init__(parent)
+        # Set up the user interface from Designer.
+        # After setupUI you can access any designer object by doing
+        # self.<objectname>, and you can use autoconnect slots - see
+        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
+        # #widgets-and-dialogs-with-auto-connect
+        self.setupUi(self)
+
+        self.init()
+
+    def init(self):
+        self.mTitle = self.windowTitle()
+        self.listWidget.currentItemChanged.connect(lambda: self.setAboutTitle())
+        self.setAboutTitle()
+
+        # page About
+        from timeseriesviewer import PATH_LICENSE, VERSION, DIR_DOCS
+        import pyqtgraph
+        self.labelVersion.setText('Version ' + VERSION)
+
+        lf = lambda p: str(open(p).read())
+        # page Changed
+        self.tbChanges.setText(lf(jp(DIR_DOCS, 'CHANGES.html')))
+
+        # page Credits
+        self.CREDITS = dict()
+        self.CREDITS['QGIS'] = lf(jp(DIR_DOCS, 'README_QGIS.html'))
+        self.CREDITS['PYQTGRAPH'] = lf(jp(DIR_DOCS, 'README_PyQtGraph.html'))
+        self.webViewCredits.setHtml(self.CREDITS['QGIS'])
+        self.btnPyQtGraph.clicked.connect(lambda: self.showCredits('PYQTGRAPH'))
+        self.btnQGIS.clicked.connect(lambda: self.showCredits('QGIS'))
+
+        # page License
+        self.tbLicense.setText(lf(PATH_LICENSE))
+
+
+    def showCredits(self, key):
+        self.webViewCredits.setHtml(self.CREDITS[key])
+        self.setAboutTitle(key)
+
+    def setAboutTitle(self, suffix=None):
+        item = self.listWidget.currentItem()
+
+        if item:
+            title = '{} | {}'.format(self.mTitle, item.text())
+        else:
+            title = self.mTitle
+        if suffix:
+            title += ' ' + suffix
+        self.setWindowTitle(title)
+
+
 class VerticalLabel(QLabel):
     def __init__(self, text, orientation='vertical', forceWidth=True):
         QLabel.__init__(self, text)
@@ -261,23 +417,34 @@ class VerticalLabel(QLabel):
             else:
                 return QSize(50, 19)
 
-class BandViewUI(QFrame, loadUIFormClass(PATH_BANDVIEW_UI)):
-
-    def __init__(self, title='View',parent=None):
-        super(BandViewUI, self).__init__(parent)
+class MapViewDefinitionUI(QFrame, loadUIFormClass(PATH_MAPVIEWDEFINITION_UI)):
 
-        self.setupUi(self)
-        self.btnRemoveBandView.setDefaultAction(self.actionRemoveBandView)
-        self.btnAddBandView.setDefaultAction(self.actionAddBandView)
-        self.btnHideBandView.setDefaultAction(self.actionHideBandView)
-        s= ""
+    sigHideMapView = pyqtSignal()
+    sigShowMapView = pyqtSignal()
 
+    def __init__(self, mapViewDefinition,parent=None):
+        super(MapViewDefinitionUI, self).__init__(parent)
 
-    def bandViewVisibility(self):
-        return self.btnHideBandView.isChecked()
+        self.setupUi(self)
+        self.mMapViewDefinition = mapViewDefinition
+        self.btnRemoveMapView.setDefaultAction(self.actionRemoveMapView)
+        self.btnMapViewVisibility.setDefaultAction(self.actionToggleVisibility)
+        self.actionToggleVisibility.toggled.connect(lambda: self.setVisibility(not self.actionToggleVisibility.isChecked()))
+
+    def mapViewDefinition(self):
+        return self.mMapViewDefinition
+
+    def setVisibility(self, isVisible):
+        print(('Set to',isVisible))
+        if isVisible != self.actionToggleVisibility.isChecked():
+            self.btnMapViewVisibility.setChecked(isVisible)
+            if isVisible:
+                self.sigShowMapView.emit()
+            else:
+                self.sigHideMapView.emit()
 
-    def setBandViewVisibility(self, show):
-        self.btnHideBandView.setChecked(show)  # send signal to thoose that need to know the visibility
+    def visibility(self):
+        return self.actionToggleVisibility.isChecked()
 
 class TimeSeriesDatumViewUI(QFrame, loadUIFormClass(PATH_TSDVIEW_UI)):
     def __init__(self, title='<#>', parent=None):
@@ -289,30 +456,17 @@ class TimeSeriesDatumViewUI(QFrame, loadUIFormClass(PATH_TSDVIEW_UI)):
     def sizeHint(self):
 
         w = self.minimumWidth()
-        canvases = self.findChildren(BandViewMapCanvas)
+        canvases = self.findChildren(MapViewMapCanvas)
         h = self.emptyHeight + len(canvases) * w
         return QSize(w,h)
 
-class LineWidget(QFrame):
-
-    def __init__(self, parent=None, orientation='horizontal'):
-        super(LineWidget, self).__init__(parent)
 
-        self.setFrameShadow(QFrame.Sunken)
-        self.setFixedHeight(3)
-        self.setStyleSheet("background-color: #c0c0c0;")
-        self.orientation = orientation
-        if self.orientation == 'horizontal':
-            self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
-        else:
-            self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
-
-class BandViewRenderSettingsUI(QGroupBox,
-                               loadUIFormClass(PATH_BANDVIEWRENDERSETTINGS_UI)):
+class MapViewRenderSettingsUI(QGroupBox,
+                              loadUIFormClass(PATH_MAPVIEWRENDERSETTINGS_UI)):
 
     def __init__(self, parent=None):
         """Constructor."""
-        super(BandViewRenderSettingsUI, self).__init__(parent)
+        super(MapViewRenderSettingsUI, self).__init__(parent)
         # Set up the user interface from Designer.
         # After setupUI you can access any designer object by doing
         # self.<objectname>, and you can use autoconnect slots - see
@@ -327,18 +481,32 @@ class BandViewRenderSettingsUI(QGroupBox,
         self.btn453.setDefaultAction(self.actionSet453)
 
 
-class BandViewMapCanvas(QgsMapCanvas):
+class MapViewMapCanvas(QgsMapCanvas):
 
     def __init__(self, parent=None):
-        super(BandViewMapCanvas, self).__init__(parent)
+        super(MapViewMapCanvas, self).__init__(parent)
         self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
         self.lyr = None
         self.renderer = None
         self.registry = QgsMapLayerRegistry.instance()
 
+        self.setCanvasColor(SETTINGS.value('CANVAS_BACKGROUND_COLOR', QColor(0,0,0)))
+
+
+        self.MAPTOOLS = dict()
+        self.MAPTOOLS['zoomOut'] = QgsMapToolZoom(self, True)
+        self.MAPTOOLS['zoomIn'] = QgsMapToolZoom(self, False)
+        self.MAPTOOLS['pan'] = QgsMapToolPan(self)
+
+    def activateMapTool(self, key):
+        if key is None:
+            self.setMapTool(None)
+        else:
+            self.setMapTool(self.MAPTOOLS[key])
+
+
     def setLayer(self, uri):
         assert isinstance(uri, str)
-
         self.setLayerSet([])
         if self.lyr is not None:
             #de-register layer
@@ -347,33 +515,51 @@ class BandViewMapCanvas(QgsMapCanvas):
         self.lyr = QgsRasterLayer(uri)
         self.lyr.setRenderer(self.renderer)
         self.registry.addMapLayer(self.lyr, False)
-
         lset = [QgsMapCanvasLayer(self.lyr)]
+
+        from timeseriesviewer import QGIS_TSV_BRIDGE
+
+        if QGIS_TSV_BRIDGE:
+            lyrVec = QGIS_TSV_BRIDGE.getVectorLayerRepresentation()
+            if lyrVec:
+                self.registry.addMapLayer(lyrVec, False)
+                lset.append(QgsMapCanvasLayer(self.lyr))
+        lset = list(reversed(lset))
         self.setLayerSet(lset)
 
     def setRenderer(self, renderer):
-        s = ""
         self.renderer = renderer.clone()
 
+    def setSpatialExtent(self, spatialExtent):
+        assert isinstance(spatialExtent, SpatialExtent)
+        if self.spatialExtent() != spatialExtent:
+            self.blockSignals(True)
+            self.setDestinationCrs(spatialExtent.crs())
+            self.setExtent(spatialExtent)
+            self.blockSignals(False)
+            self.refresh()
+
+    def spatialExtent(self):
+        return SpatialExtent.fromMapCanvas(self)
 
 
 
-class BandViewRenderSettings(QObject):
+class MapViewRenderSettings(QObject):
 
     #define signals
 
-    sigBandViewVisibility = pyqtSignal(bool)
+    sigMapViewVisibility = pyqtSignal(bool)
     sigRendererChanged = pyqtSignal(QgsRasterRenderer)
     sigRemoveView = pyqtSignal()
 
     def __init__(self, sensor, parent=None):
         """Constructor."""
-        super(BandViewRenderSettings, self).__init__(parent)
+        super(MapViewRenderSettings, self).__init__(parent)
 
-        self.ui = BandViewRenderSettingsUI(parent)
+        self.ui = MapViewRenderSettingsUI(parent)
         self.ui.create()
 
-        self.ui.setTitle(sensor.sensorName)
+        self.ui.labelTitle.setText(sensor.sensorName)
         self.ui.bandNames = sensor.bandNames
         self.minValues = [self.ui.tbRedMin, self.ui.tbGreenMin, self.ui.tbBlueMin]
         self.maxValues = [self.ui.tbRedMax, self.ui.tbGreenMax, self.ui.tbBlueMax]
@@ -413,15 +599,8 @@ class BandViewRenderSettings(QObject):
             self.ui.btnTrueColor.setEnabled(False)
             self.ui.btnCIR.setEnabled(False)
             self.ui.btn453.setEnabled(False)
-        s = ""
 
 
-    def showSensorName(self, b):
-        if b:
-            self.ui.setTitle(self.sensor.sensorName)
-        else:
-            self.ui.setTitle(None)
-
     def setBandSelection(self, key):
 
         if key == 'default':
@@ -521,4 +700,42 @@ class BandViewRenderSettings(QObject):
 
         menu.exec_(event.globalPos())
 
+class PropertyDialogUI(QDialog, loadUIFormClass(PATH_SETTINGSDIALOG_UI)):
+
+    def __init__(self, parent=None):
+        super(PropertyDialogUI, self).__init__(parent)
+        self.setupUi(self)
+
+
+
+if __name__ == '__main__':
+    import site, sys
+    #add site-packages to sys.path as done by enmapboxplugin.py
+
+    from timeseriesviewer import DIR_SITE_PACKAGES
+    site.addsitedir(DIR_SITE_PACKAGES)
+
+    #prepare QGIS environment
+    if sys.platform == 'darwin':
+        PATH_QGS = r'/Applications/QGIS.app/Contents/MacOS'
+        os.environ['GDAL_DATA'] = r'/usr/local/Cellar/gdal/1.11.3_1/share'
+    else:
+        # assume OSGeo4W startup
+        PATH_QGS = os.environ['QGIS_PREFIX_PATH']
+    assert os.path.exists(PATH_QGS)
+
+    qgsApp = QgsApplication([], True)
+    QApplication.addLibraryPath(r'/Applications/QGIS.app/Contents/PlugIns')
+    QApplication.addLibraryPath(r'/Applications/QGIS.app/Contents/PlugIns/qgis')
+    qgsApp.setPrefixPath(PATH_QGS, True)
+    qgsApp.initQgis()
+
+    #run tests
+    #d = AboutDialogUI()
+    #d.show()
 
+    d = PropertyDialogUI()
+    d.exec_()
+    #close QGIS
+    qgsApp.exec_()
+    qgsApp.exitQgis()