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