From 23243dbec873c0fd8ed04d359dcbdd0ff14b705c Mon Sep 17 00:00:00 2001 From: "benjamin.jakimow@geo.hu-berlin.de" <q8DTkxUg-BB> Date: Tue, 20 Feb 2018 12:09:32 +0100 Subject: [PATCH] Refactoring profile GUI profilevisualization: date2num num2date now based on decimalyear values --- timeseriesviewer/profilevisualization.py | 402 +++++++++--- timeseriesviewer/ui/profileviewdock.ui | 739 ++++++++++++----------- timeseriesviewer/ui/renderingdock.ui | 40 +- 3 files changed, 734 insertions(+), 447 deletions(-) diff --git a/timeseriesviewer/profilevisualization.py b/timeseriesviewer/profilevisualization.py index acf690b2..f487f087 100644 --- a/timeseriesviewer/profilevisualization.py +++ b/timeseriesviewer/profilevisualization.py @@ -48,6 +48,18 @@ import numpy as np DEBUG = False +LABEL_DN = 'DN or Index' +LABEL_TIME = 'Date' + + +OPENGL_AVAILABLE = False + +try: + import OpenGL + OPENGL_AVAILABLE = True +except: + pass + def getTextColorWithContrast(c): assert isinstance(c, QColor) if c.lightness() < 0.5: @@ -113,10 +125,10 @@ class _SensorPoints(pg.PlotDataItem): self.menu = None def boundingRect(self): - return super(SensorPoints,self).boundingRect() + return super(_SensorPoints,self).boundingRect() def paint(self, p, *args): - super(SensorPoints, self).paint(p, *args) + super(_SensorPoints, self).paint(p, *args) # On right-click, raise the context menu @@ -172,33 +184,51 @@ class TemporalProfilePlotDataItem(pg.PlotDataItem): assert isinstance(plotStyle, TemporalProfilePlotStyle) - super(TemporalProfilePlotDataItem, self).__init__([1,2,3], [2,3,4], parent=parent) + super(TemporalProfilePlotDataItem, self).__init__([], [], parent=parent) self.mPlotStyle = plotStyle - self.mPlotStyle.sigUpdated.connect(self.updateStyle) - self.setClickable(True) - self.updateData() + self.mPlotStyle.sigUpdated.connect(self.updateDataAndStyle) self.updateStyle() - def updateData(self): + def updateDataAndStyle(self): + TP = self.mPlotStyle.temporalProfile() sensor = self.mPlotStyle.sensor() + if isinstance(TP, TemporalProfile) and isinstance(sensor, SensorInstrument): x, y = TP.dataFromExpression(self.mPlotStyle.sensor(), self.mPlotStyle.expression()) + x = np.asarray(x, dtype=np.float) + y = np.asarray(y, dtype=np.float) if len(y) > 0: self.setData(x=x, y=y) else: - self.setData(x=[1,2,3], y=[1,2,3]) #dummy - self.update() + self.setData(x=[], y=[]) #dummy + self.updateStyle() def updateStyle(self): """ Updates visibility properties """ + + if DEBUG: + print('{} updateStyle'.format(self)) + from pyqtgraph.graphicsItems.ScatterPlotItem import drawSymbol +# path = drawSymbol(p, self.markerSymbol, self.markerSize, self.markerPen, self.markerBrush) + # #painter, symbol, size, pen, brush self.setVisible(self.mPlotStyle.isVisible()) + self.setSymbol(self.mPlotStyle.markerSymbol) + self.setSymbolSize(self.mPlotStyle.markerSize) + self.setSymbolBrush(self.mPlotStyle.markerBrush) + self.setSymbolPen(self.mPlotStyle.markerPen) self.setPen(self.mPlotStyle.linePen) - #self.setBrush(self.mPlotStyle.markerBrush) + self.update() + + #self.setPen(fn.mkPen(self.mPlotStyle.linePen)) + #self.setFillBrush(fn.mkBrush(self.mPlotStyle.mExpression)) + #self.setSymbolBrush(fn.mkBrush(self.mPlotStyle.markerBrush)) - #self.setFillBrush(self.mPlotStyle.) + # self.setFillBrush(self.mPlotStyle.) + + #self.update() def setClickable(self, b, width=None): assert isinstance(b, bool) @@ -211,7 +241,6 @@ class TemporalProfilePlotDataItem(pg.PlotDataItem): self.setPen(color) def pen(self): - return fn.mkPen(self.opts['pen']) def color(self): @@ -290,7 +319,7 @@ class PlotSettingsWidgetDelegate(QStyledItemDelegate): model = tableView.model() assert isinstance(model, PlotSettingsModel) - for c in [model.cnSensor, model.cnExpression, model.cnStyle,model.cnTemporalProfile]: + for c in [model.cnSensor, model.cnExpression, model.cnStyle, model.cnTemporalProfile]: i = model.columNames.index(c) tableView.setItemDelegateForColumn(i, self) @@ -322,7 +351,7 @@ class PlotSettingsWidgetDelegate(QStyledItemDelegate): #todo: w.setLayer(sv.memLyr) w.setExpressionDialogTitle('Values') - w.setToolTip('Set an expression to calculate the plot y-values.') + w.setToolTip('Set an expression to specify the image band or calculate a spectral index.') w.fieldChanged.connect(lambda : self.checkData(w, w.expression())) elif cname == model.cnStyle: @@ -410,7 +439,7 @@ class PlotSettingsWidgetDelegate(QStyledItemDelegate): elif cname == model.cnStyle: assert isinstance(w, PlotStyleButton) - model.setData(index, w.plotStyle(), Qt.UserRole) + model.setData(index, w.plotStyle(), Qt.EditRole) elif cname == model.cnSensor: assert isinstance(w, QComboBox) @@ -860,7 +889,7 @@ class TemporalProfileCollection(QAbstractTableModel): class TemporalProfilePlotStyle(PlotStyle): - sigUpdated = pyqtSignal() + sigExpressionUpdated = pyqtSignal() def __init__(self, temporalProfile): super(TemporalProfilePlotStyle, self).__init__() @@ -885,13 +914,22 @@ class TemporalProfilePlotStyle(PlotStyle): assert isinstance(temporalPofile, TemporalProfile) b = temporalPofile != self.mTP self.mTP = temporalPofile - if b: self.sigUpdated.emit() + if b: self.update() def setSensor(self, sensor): assert isinstance(sensor, SensorInstrument) b = sensor != self.mSensor self.mSensor = sensor - if b: self.sigUpdated.emit() + if b: self.update() + + + def update(self): + super(TemporalProfilePlotStyle, self).update() + + for pdi in self.mPlotItems: + assert isinstance(pdi, TemporalProfilePlotDataItem) + pdi.updateStyle() + #pdi.updateItems() @@ -903,7 +941,9 @@ class TemporalProfilePlotStyle(PlotStyle): assert isinstance(exp, unicode) b = self.mExpression != exp self.mExpression = exp - if b: self.sigUpdated.emit() + if b: + self.update() + self.sigExpressionUpdated.emit() def expression(self): return self.mExpression @@ -937,6 +977,7 @@ class DateTimeViewBox(pg.ViewBox): #self.menu = None + """ def raiseContextMenu(self, ev): pt = self.mapDeviceToView(ev.pos()) @@ -948,7 +989,7 @@ class DateTimeViewBox(pg.ViewBox): a.triggered.connect(lambda : self.sigMoveToDate.emit(date)) self.scene().addParentContextMenus(self, menu, ev) menu.exec_(ev.screenPos().toPoint()) - + """ @@ -962,10 +1003,11 @@ class DateTimePlotWidget(pg.PlotWidget): """ super(DateTimePlotWidget, self).__init__(parent, viewBox=DateTimeViewBox()) self.plotItem = pg.PlotItem( - #axisItems={'bottom':DateTimeAxis(orientation='bottom')}, + axisItems={'bottom':DateTimeAxis(orientation='bottom')}, viewBox=DateTimeViewBox() ) self.setCentralItem(self.plotItem) + self.xAxisInitialized = False @@ -987,7 +1029,7 @@ class PlotSettingsModel(QAbstractTableModel): self.cnID = 'ID' self.cnSensor = 'sensor' - self.cnExpression = 'y-value' + self.cnExpression = LABEL_DN self.cnStyle = 'style' self.cnTemporalProfile = 'px' self.columNames = [self.cnTemporalProfile, self.cnSensor, self.cnStyle, self.cnExpression] @@ -1207,13 +1249,13 @@ class PlotSettingsModel(QAbstractTableModel): result = False plotStyle = self.idx2plotStyle(index) if isinstance(plotStyle, TemporalProfilePlotStyle): - if role in [Qt.DisplayRole, Qt.EditRole]: + if role in [Qt.DisplayRole]: if columnName == self.cnExpression: plotStyle.setExpression(value) result = True elif columnName == self.cnStyle: if isinstance(value, PlotStyle): - plotStyle.plotStyle.copyFrom(value) + plotStyle.copyFrom(value) result = True if role == Qt.CheckStateRole: @@ -1301,22 +1343,19 @@ class ProfileViewDockUI(QgsDockWidget, loadUI('profileviewdock.ui')): def __init__(self, parent=None): super(ProfileViewDockUI, self).__init__(parent) self.setupUi(self) - from timeseriesviewer import OPENGL_AVAILABLE, SETTINGS #TBD. #self.line.setVisible(False) #self.listWidget.setVisible(False) self.stackedWidget.setCurrentWidget(self.page2D) - + self.plotWidget3D = None if OPENGL_AVAILABLE: - l = self.page3D.layout() + l = self.labelDummy3D.parentWidget().layout() l.removeWidget(self.labelDummy3D) self.labelDummy3D.setVisible(False) from pyqtgraph.opengl import GLViewWidget self.plotWidget3D = GLViewWidget(parent=self.page3D) l.addWidget(self.plotWidget3D) - else: - self.plotWidget3D = None #pi = self.plotWidget2D.plotItem #ax = DateAxis(orientation='bottom', showValues=True) @@ -1337,7 +1376,62 @@ class ProfileViewDockUI(QgsDockWidget, loadUI('profileviewdock.ui')): self.tableViewTemporalProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.tableViewTemporalProfiles.setSortingEnabled(True) + +def date2sse(date): # returns seconds since epoch + if isinstance(date, np.datetime64): + date = date.astype(datetime.datetime) + return time.mktime(date.timetuple()) + +def sse2date(secondsSinceEpoch): + return time.localtime(secondsSinceEpoch) + + +def dateDOY(date): + if isinstance(date, np.datetime64): + date = date.astype(datetime.date) + return date.timetuple().tm_yday + +def daysPerYear(year): + if isinstance(year, np.datetime64): + year = year.astype(datetime.date) + if isinstance(year, datetime.date): + year = year.timetuple().tm_year + + return dateDOY(datetime.date(year=year, month=12, day=31)) + def date2num(d): + #kindly taken from https://stackoverflow.com/questions/6451655/python-how-to-convert-datetime-dates-to-decimal-years + if isinstance(d, np.datetime64): + d = d.astype(datetime.datetime) + assert isinstance(d, datetime.date) + + yearDuration = daysPerYear(d) + yearElapsed = d.timetuple().tm_yday + fraction = float(yearElapsed) / float(yearDuration) + return float(d.year) + fraction + +def num2date(n, dt64=True): + n = float(n) + + year = int(n) + fraction = n - year + yearDuration = daysPerYear(year) + yearElapsed = fraction * yearDuration + + import math + doy = round(yearElapsed) + date = datetime.date(year, 1, 1) + datetime.timedelta(days=doy-1) + if dt64: + return np.datetime64(date) + else: + date + + + + #return np.datetime64('{:04}-01-01'.format(year), 'D') + np.timedelta64(int(yearElapsed), 'D') + + +def depr_date2num(d): d2 = d.astype(datetime.datetime) o = d2.toordinal() @@ -1345,7 +1439,7 @@ def date2num(d): return o -def num2date(n): +def depr_num2date(n): n = int(np.round(n)) if n < 1: n = 1 @@ -1425,10 +1519,15 @@ class TemporalProfile(QObject): self.updateLoadingStatus() self.mUpdated = True + def resetUpdated(self): + self.mUpdated = False + + def updated(self): + return self.mUpdated def qgsFieldFromKeyValue(self, key, value): t = type(value) - if t in [int, float]: + if t in [int, float] or np.isreal(value): fLen = 0 fPrec = 0 @@ -1443,30 +1542,53 @@ class TemporalProfile(QObject): assert dateType in ['date','doy'] x = [] y = [] + + if not isinstance(expression, QgsExpression): expression = QgsExpression(expression) assert isinstance(expression, QgsExpression) - fields = QgsFields() - f = QgsFeature() - for i, tsd in enumerate(sorted([tsd for tsd in self.mData.keys() if tsd.sensor == sensor])): - assert isinstance(tsd, TimeSeriesDatum) - data = self.mData[tsd] + expression = QgsExpression(expression) - if i == 0: - #initialize the fields - for k in data.keys(): - field = self.qgsFieldFromKeyValue(k, data[k]) - fields.append(field) - f.setFields(fields) + fields = QgsFields() + sensorTSDs = sorted([tsd for tsd in self.mData.keys() if tsd.sensor == sensor]) + for tsd in sensorTSDs: + data = self.mData[tsd] + for k, v in data.items(): + if v is not None and fields.fieldNameIndex(k) == -1: + fields.append(self.qgsFieldFromKeyValue(k, v)) + for i, tsd in enumerate(sensorTSDs): + assert isinstance(tsd, TimeSeriesDatum) + data = self.mData[tsd] + context = QgsExpressionContext() + scope = QgsExpressionContextScope() + f = QgsFeature() + f.setFields(fields) + f.setValid(True) for k, v in data.items(): + if v is None: + continue + idx = f.fieldNameIndex(k) + field = f.fields().field(idx) + if field.typeName() == 'text': + v = str(v) + else: + v = float(v) + f.setAttribute(k,v) - value = expression.evaluate(f) - if value not in [None, NULL]: + scope.setFeature(f) + context.appendScope(scope) + #value = expression.evaluatePrepared(f) + value = expression.evaluate(context) + + + if value in [None, NULL]: + s = "" + else: if dateType == 'date': x.append(date2num(tsd.date)) elif dateType == 'doy': @@ -1474,6 +1596,7 @@ class TemporalProfile(QObject): y.append(value) #return np.asarray(x), np.asarray(y) + assert len(x) == len(y) return x, y def data(self, tsd): @@ -1529,10 +1652,6 @@ class SpectralTemporalVisualization(QObject): def __init__(self, ui): super(SpectralTemporalVisualization, self).__init__() - #assert isinstance(timeSeries, TimeSeries) - - if not isinstance(ui, ProfileViewDockUI): - print('UI : {}'.format(ui)) assert isinstance(ui, ProfileViewDockUI), 'arg ui of type: {} {}'.format(type(ui), str(ui)) self.ui = ui @@ -1551,8 +1670,22 @@ class SpectralTemporalVisualization(QObject): self.TV = ui.tableView2DProfiles self.TV.setSortingEnabled(False) self.plot2D = ui.plotWidget2D - self.plot2D.plotItem.getViewBox().sigMoveToDate.connect(self.sigMoveToDate) + self.plot2D.getPlotItem().getViewBox().sigMoveToDate.connect(self.sigMoveToDate) + self.plot2D.getPlotItem().getAxis('bottom').setLabel(LABEL_TIME) + self.plot2D.getPlotItem().getAxis('left').setLabel(LABEL_DN) + self.plot3D = ui.plotWidget3D + self.plot3D.setCameraPosition(distance=50) + + ## Add a grid to the view + if OPENGL_AVAILABLE: + import pyqtgraph.opengl as gl + self.glGridItem = gl.GLGridItem() + self.glGridItem.scale(2, 2, 1) + self.glGridItem.setDepthValue(10) # draw grid after surfaces since they may be translucent + self.glPlotDataItem = [] + self.plot3D.addItem(self.glGridItem) + self.tpCollection = TemporalProfileCollection() self.tpCollectionListModel = TemporalProfileCollectionListModel(self.tpCollection) @@ -1563,7 +1696,6 @@ class SpectralTemporalVisualization(QObject): #self.pxCollection.sigPixelRemoved.connect(self.clear) self.plotSettingsModel = None - self.pixelLoader.sigLoadingStarted.connect(self.clear) self.pixelLoader.sigLoadingFinished.connect(lambda : self.plot2D.enableAutoRange('x', False)) @@ -1574,7 +1706,7 @@ class SpectralTemporalVisualization(QObject): self.updateRequested = True self.updateTimer = QTimer(self) - self.updateTimer.timeout.connect(self.updatePlot) + self.updateTimer.timeout.connect(self.onDataUpdate) self.updateTimer.start(5000) self.sigMoveToDate.connect(self.onMoveToDate) @@ -1584,29 +1716,33 @@ class SpectralTemporalVisualization(QObject): def createNewPlotStyle(self): l = len(self.tpCollection) if l > 0: - TP = self.tpCollection[0] - PS = TemporalProfilePlotStyle(TP) + temporalProfile = self.tpCollection[0] + plotStyle = TemporalProfilePlotStyle(temporalProfile) + plotStyle.sigExpressionUpdated.connect(self.updatePlot2D) sensors = self.TS.Sensors.keys() if len(sensors) > 0: - PS.setSensor(sensors[0]) - self.plotSettingsModel.insertPlotStyles([PS]) - pdi = PS.createPlotItem(self.plot2D) - plotItem = self.plot2D.getPlotItem() - assert isinstance(plotItem, pg.PlotItem) - plotItem.addItem(pdi) - plotItem.update() + plotStyle.setSensor(sensors[0]) + self.plotSettingsModel.insertPlotStyles([plotStyle]) + pdi = plotStyle.createPlotItem(self.plot2D) + + assert isinstance(pdi, TemporalProfilePlotDataItem) + + self.plot2D.getPlotItem().addItem(pdi) + #self.plot2D.getPlotItem().addItem(pg.PlotDataItem(x=[1, 2, 3], y=[1, 2, 3])) #plotItem.addDataItem(pdi) - plotItem.plot().sigPlotChanged.emit(plotItem) - self.updatePlot() + #plotItem.plot().sigPlotChanged.emit(plotItem) + self.updatePlot2D() + def initActions(self): self.ui.btnAddView.setDefaultAction(self.ui.actionAddView) self.ui.btnRemoveView.setDefaultAction(self.ui.actionRemoveView) - self.ui.btnRefresh2D.setDefaultAction(self.ui.actionRefresh) - self.ui.btnRefresh3D.setDefaultAction(self.ui.actionRefresh) - self.ui.actionRefresh.triggered.connect(self.updatePlot) + self.ui.btnRefresh2D.setDefaultAction(self.ui.actionRefresh2D) + self.ui.btnRefresh3D.setDefaultAction(self.ui.actionRefresh3D) + self.ui.actionRefresh2D.triggered.connect(self.updatePlot2D) + self.ui.actionRefresh3D.triggered.connect(self.updatePlot3D) self.ui.actionAddView.triggered.connect(self.createNewPlotStyle) #todo: self.ui.actionRemoveView.triggered.connect(self.plotSettingsModel.createPlotStyle) @@ -1723,7 +1859,7 @@ class SpectralTemporalVisualization(QObject): pass - def loadCoordinate(self, spatialPoints=None): + def loadCoordinate(self, spatialPoints=None, LUT_bandIndices=None): """ Loads a temporal profile for a single or multiple geometries. :param spatialPoints: SpatialPoint | [list-of-SpatialPoints] @@ -1741,12 +1877,17 @@ class SpectralTemporalVisualization(QObject): tasks = [] TPs = [] theGeometries = [] - LUT_bandIndices = dict() + # Define a which (new) bands need to be loaded for each sensor - for sensor in self.TS.Sensors: - LUT_bandIndices[sensor] = self.plotSettingsModel.requiredBandsIndices(sensor) + if LUT_bandIndices is None: + LUT_bandIndices = dict() + for sensor in self.TS.Sensors: + LUT_bandIndices[sensor] = self.plotSettingsModel.requiredBandsIndices(sensor) + assert isinstance(LUT_bandIndices, dict) + for sensor in self.TS.Sensors: + assert sensor in LUT_bandIndices.keys() #update new / existing points if isinstance(spatialPoints, SpatialPoint): @@ -1828,32 +1969,130 @@ class SpectralTemporalVisualization(QObject): self.setData2D(sensorView) @QtCore.pyqtSlot() - def updatePlot(self): + def onDataUpdate(self): + + + for plotSetting in self.plotSettingsModel: + assert isinstance(plotSetting, TemporalProfilePlotStyle) + if plotSetting.temporalProfile().updated(): + for pdi in plotSetting.mPlotItems: + assert isinstance(pdi, TemporalProfilePlotDataItem) + pdi.updateDataAndStyle() + plotSetting.temporalProfile().resetUpdated() + + for i in self.plot2D.getPlotItem().dataItems: + i.updateItems() + + + if not self.plot2D.xAxisInitialized: + x0 = x1 = None + for plotSetting in self.plotSettingsModel: + assert isinstance(plotSetting, TemporalProfilePlotStyle) + for pdi in plotSetting.mPlotItems: + assert isinstance(pdi, TemporalProfilePlotDataItem) + if x0 is None: + x0 = pdi.xData.min() + x1 = pdi.xData.max() + else: + x0 = min(pdi.xData.min(), x0) + x1 = max(pdi.xData.max(), x1) + + if x0 is not None: + self.plot2D.getPlotItem().setXRange(x0, x1) + self.plot2D.xAxisInitialized = True + + @QtCore.pyqtSlot() + def updatePlot3D(self): + if OPENGL_AVAILABLE: + from pyqtgraph.opengl import GLViewWidget + import pyqtgraph.opengl as gl + assert isinstance(self.plot3D, GLViewWidget) + w = self.plot3D + + #we need the data from all bands + + + + del self.glPlotDataItem[:] + idx = self.ui.cbTemporalProfile3D.currentIndex() + if idx >= 0: + self.ui.cbTemporalProfile3D.currentIndex() + tp = self.ui.cbTemporalProfile3D.itemData(idx, role=Qt.UserRole) + assert isinstance(tp, TemporalProfile) + + #1. ensure that data from all bands will be loaded + LUT_bandIndices = dict() + for sensor in self.TS.sensors(): + assert isinstance(sensor, SensorInstrument) + LUT_bandIndices[sensor] = list(range(sensor.nb)) + + self.loadCoordinate(tp.mCoordinate, LUT_bandIndices=LUT_bandIndices) + + #2. visualize already loaded data + profileData = {} + + #x = + #y = + + for sensor in tp.mTimeSeries.sensors(): + profileData[sensor] = {'x':[],'y':[],'z':[]} + for tsd in tp.mTimeSeries: + data = tp.data(tsd) + bandKeys = sorted([k for k in data.keys() if k.startswith('b') and data[k] != None], key=lambda k: bandKey2bandIndex(k)) + + t = date2num(tsd.date) + return + + n = len(bandKeys) + + pos = np.ones((n,3), dtype=np.float) + + pos = 2 + #pos = (N,3) array of floats specifying point locations. + + plt = gl.GLLinePlotItem(pos=pts, color=pg.glColor((i, n * 1.3)), width=(i + 1) / 10., + antialias=True) + w.addItem(plt) + """ + for sensor, values in data.items(): + if len(values['z']) > 0: + x = values['x'] + y = values['y'] + z = values['z'] + + p2 = gl.GLSurfacePlotItem(x=x, y=y, z=z, shader='normalColor') + p2.translate(-10, -10, 0) + w.addItem(p2) + """ + + @QtCore.pyqtSlot() + def updatePlot2D(self): if isinstance(self.plotSettingsModel, PlotSettingsModel): if DEBUG: print('Update plot...') - - pi = self.plot2D.getPlotItem() piDataItems = pi.listDataItems() + locations = set() for plotSetting in self.plotSettingsModel: assert isinstance(plotSetting, TemporalProfilePlotStyle) locations.add(plotSetting.temporalProfile().mCoordinate) + for pdi in plotSetting.mPlotItems: assert isinstance(pdi, TemporalProfilePlotDataItem) - pdi.updateStyle() - pdi.updateData() - assert pdi in piDataItems - pi.addItem(pdi) + pdi.updateDataAndStyle() + + #for i in pi.dataItems: + # i.updateItems() + + #self.plot2D.update() #2. load pixel data self.loadCoordinate(list(locations)) - # https://github.com/pyqtgraph/pyqtgraph/blob/5195d9dd6308caee87e043e859e7e553b9887453/examples/customPlot.py return @@ -1948,7 +2187,7 @@ if __name__ == '__main__': qgsApp = utils.initQgisApplication() DEBUG = True - for date in ['2012-01-01', '2017-12-23']: + for date in ['2012-01-01', '2017-12-23', '2017-12-31']: dt1 = np.datetime64(date) n = date2num(dt1) @@ -1979,9 +2218,10 @@ if __name__ == '__main__': #STVis.loadCoordinate(cp3) STVis.createNewPlotStyle() - for tp in STVis.tpCollection: - assert isinstance(tp, TemporalProfile) - tp.plot() + if False: + for tp in STVis.tpCollection: + assert isinstance(tp, TemporalProfile) + tp.plot() qgsApp.exec_() diff --git a/timeseriesviewer/ui/profileviewdock.ui b/timeseriesviewer/ui/profileviewdock.ui index d20ef183..45bfe12f 100644 --- a/timeseriesviewer/ui/profileviewdock.ui +++ b/timeseriesviewer/ui/profileviewdock.ui @@ -14,23 +14,14 @@ <set>QDockWidget::AllDockWidgetFeatures</set> </property> <property name="windowTitle"> - <string>Profile View</string> + <string>Temporal Profiles</string> </property> <widget class="QWidget" name="dockWidgetContents"> <layout class="QVBoxLayout" name="verticalLayout"> <property name="spacing"> <number>0</number> </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> @@ -45,16 +36,7 @@ <property name="spacing"> <number>1</number> </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> @@ -74,7 +56,7 @@ </property> <property name="maximumSize"> <size> - <width>50</width> + <width>35</width> <height>16777215</height> </size> </property> @@ -87,6 +69,12 @@ <property name="frameShadow"> <enum>QFrame::Sunken</enum> </property> + <property name="iconSize"> + <size> + <width>25</width> + <height>25</height> + </size> + </property> <property name="layoutMode"> <enum>QListView::SinglePass</enum> </property> @@ -105,7 +93,10 @@ </item> <item> <property name="text"> - <string>Pixel</string> + <string/> + </property> + <property name="toolTip"> + <string>Overview on loaded temporal profiles</string> </property> <property name="icon"> <iconset resource="resources.qrc"> @@ -126,372 +117,425 @@ <number>1</number> </property> <widget class="QWidget" name="page2D"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout_3"> <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> + <number>1</number> </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QSplitter" name="splitter"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> + <widget class="QSplitter" name="splitter2D"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QFrame" name="frameSettings2D"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="spacing"> + <number>1</number> </property> - <widget class="QFrame" name="frameSettings2D"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>100</width> - <height>0</height> - </size> - </property> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Sunken</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> <property name="spacing"> - <number>2</number> - </property> - <property name="leftMargin"> - <number>2</number> + <number>1</number> </property> <property name="topMargin"> - <number>2</number> - </property> - <property name="rightMargin"> - <number>2</number> - </property> - <property name="bottomMargin"> - <number>2</number> + <number>0</number> </property> <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <property name="spacing"> - <number>0</number> + <widget class="QToolButton" name="btnLoadProfile1"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</iconset> </property> - <property name="topMargin"> - <number>0</number> + <property name="autoRaise"> + <bool>true</bool> </property> - <item> - <widget class="QToolButton" name="btnLoadProfile1"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</iconset> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="btnRefresh2D"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mActionRefresh.png</normaloff>:/timeseriesviewer/icons/mActionRefresh.png</iconset> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="btnAddView"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mActionAdd.svg</normaloff>:/timeseriesviewer/icons/mActionAdd.svg</iconset> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="btnRemoveView"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mActionRemove.svg</normaloff>:/timeseriesviewer/icons/mActionRemove.svg</iconset> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <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="tableView2DProfiles"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> + <widget class="QToolButton" name="btnRefresh2D"> + <property name="text"> + <string>...</string> </property> - <property name="minimumSize"> - <size> - <width>150</width> - <height>0</height> - </size> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mActionRefresh.png</normaloff>:/timeseriesviewer/icons/mActionRefresh.png</iconset> </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <attribute name="horizontalHeaderMinimumSectionSize"> - <number>5</number> - </attribute> - <attribute name="horizontalHeaderShowSortIndicator" stdset="0"> + <property name="autoRaise"> <bool>true</bool> - </attribute> - <attribute name="horizontalHeaderStretchLastSection"> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="btnAddView"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mActionAdd.svg</normaloff>:/timeseriesviewer/icons/mActionAdd.svg</iconset> + </property> + <property name="autoRaise"> <bool>true</bool> - </attribute> - <attribute name="verticalHeaderShowSortIndicator" stdset="0"> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="btnRemoveView"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mActionRemove.svg</normaloff>:/timeseriesviewer/icons/mActionRemove.svg</iconset> + </property> + <property name="autoRaise"> <bool>true</bool> - </attribute> + </property> </widget> </item> + <item> + <spacer name="horizontalSpacer_2"> + <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> - <widget class="DateTimePlotWidget" name="plotWidget2D"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>3</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="styleSheet"> - <string notr="true">background-color: rgb(0, 0, 0);</string> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="backgroundBrush"> - <brush brushstyle="NoBrush"> - <color alpha="255"> - <red>0</red> - <green>0</green> - <blue>0</blue> - </color> - </brush> - </property> - <property name="foregroundBrush"> - <brush brushstyle="NoBrush"> - <color alpha="255"> - <red>0</red> - <green>0</green> - <blue>0</blue> - </color> - </brush> - </property> - </widget> - </widget> - </item> - </layout> + </item> + <item> + <widget class="QTableView" name="tableView2DProfiles"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <attribute name="horizontalHeaderMinimumSectionSize"> + <number>5</number> + </attribute> + <attribute name="horizontalHeaderShowSortIndicator" stdset="0"> + <bool>true</bool> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderShowSortIndicator" stdset="0"> + <bool>true</bool> + </attribute> + </widget> + </item> + </layout> + </widget> + <widget class="DateTimePlotWidget" name="plotWidget2D"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="styleSheet"> + <string notr="true">background-color: rgb(0, 0, 0);</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="backgroundBrush"> + <brush brushstyle="NoBrush"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </property> + <property name="foregroundBrush"> + <brush brushstyle="NoBrush"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </property> + </widget> + </widget> </item> </layout> </widget> <widget class="QWidget" name="page3D"> - <layout class="QVBoxLayout" name="verticalLayout_5"> + <layout class="QVBoxLayout" name="verticalLayout_6"> <property name="spacing"> <number>1</number> </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <property name="spacing"> - <number>2</number> - </property> - <property name="topMargin"> - <number>0</number> + <widget class="QSplitter" name="splitter3D"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <item> - <widget class="QToolButton" name="btnRefresh3D"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mActionRefresh.png</normaloff>:/timeseriesviewer/icons/mActionRefresh.png</iconset> + <widget class="QFrame" name="frameSettings3D"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <property name="spacing"> + <number>1</number> </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Pixel</string> + <property name="margin"> + <number>0</number> </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="cbTemporalProfile3D"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <property name="spacing"> + <number>1</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QToolButton" name="toolButton"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</iconset> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="btnRefresh3D"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mActionRefresh.png</normaloff>:/timeseriesviewer/icons/mActionRefresh.png</iconset> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Pixel</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cbTemporalProfile3D"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Selects the coordinate for which to show the profile data</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <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> + </item> + <item> + <widget class="QTableView" name="tableView3DProfiles"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget"> + <layout class="QVBoxLayout" name="layout3DPlotWidget"> + <property name="spacing"> + <number>1</number> </property> - </spacer> - </item> - </layout> - </item> - <item> - <widget class="QLabel" name="labelDummy3D"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>3</horstretch> - <verstretch>2</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>9</pointsize> - </font> - </property> - <property name="styleSheet"> - <string notr="true">color: rgb(255, 255, 0); + <item> + <widget class="QLabel" name="labelDummy3D"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>3</horstretch> + <verstretch>2</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <pointsize>9</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(255, 255, 0); background-color: rgb(0, 0, 0);</string> - </property> - <property name="text"> - <string>Unable to initialize 3D plot window. + </property> + <property name="text"> + <string>Unable to initialize 3D plot window. Please ensure that PyOpenGL is installed (http://pyopengl.sourceforge.net)</string> - </property> - <property name="openExternalLinks"> - <bool>true</bool> - </property> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> </widget> <widget class="QWidget" name="pagePixel"> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout_7"> <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> + <number>1</number> </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <property name="spacing"> - <number>1</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <item> - <widget class="QToolButton" name="btnLoadProfile2"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</iconset> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="btnRemoveTemporalProfile"> - <property name="text"> - <string>...</string> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/timeseriesviewer/icons/mActionRemove.svg</normaloff>:/timeseriesviewer/icons/mActionRemove.svg</iconset> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_4"> - <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> - </item> - <item> - <widget class="QTableView" name="tableViewTemporalProfiles"> + <widget class="QFrame" name="frameTemporalProfiles"> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> - <property name="sortingEnabled"> - <bool>true</bool> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> </property> - <attribute name="horizontalHeaderStretchLastSection"> - <bool>true</bool> - </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>1</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <property name="spacing"> + <number>1</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QToolButton" name="btnLoadProfile2"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</normaloff>:/timeseriesviewer/icons/mIconTemporalProfile.svg</iconset> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="btnRemoveTemporalProfile"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/timeseriesviewer/icons/mActionRemove.svg</normaloff>:/timeseriesviewer/icons/mActionRemove.svg</iconset> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <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> + </item> + <item> + <widget class="QTableView" name="tableViewTemporalProfiles"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + </widget> + </item> + </layout> </widget> </item> </layout> @@ -525,16 +569,7 @@ Please ensure that PyOpenGL is installed <enum>QFrame::Raised</enum> </property> <layout class="QHBoxLayout" name="horizontalLayout_3"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> @@ -611,7 +646,7 @@ Please ensure that PyOpenGL is installed </item> </layout> </widget> - <action name="actionRefresh"> + <action name="actionRefresh2D"> <property name="icon"> <iconset resource="resources.qrc"> <normaloff>:/timeseriesviewer/icons/mActionRefresh.png</normaloff>:/timeseriesviewer/icons/mActionRefresh.png</iconset> @@ -653,6 +688,18 @@ Please ensure that PyOpenGL is installed <string>loadProfile</string> </property> </action> + <action name="actionRefresh3D"> + <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 plot</string> + </property> + </action> </widget> <customwidgets> <customwidget> diff --git a/timeseriesviewer/ui/renderingdock.ui b/timeseriesviewer/ui/renderingdock.ui index e005930e..6b7bf844 100644 --- a/timeseriesviewer/ui/renderingdock.ui +++ b/timeseriesviewer/ui/renderingdock.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>201</width> - <height>270</height> + <height>298</height> </rect> </property> <property name="windowTitle"> @@ -259,7 +259,7 @@ <property name="flat"> <bool>false</bool> </property> - <layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0" columnstretch="0,0,2"> + <layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0" columnstretch="0,0,0"> <property name="sizeConstraint"> <enum>QLayout::SetMinimumSize</enum> </property> @@ -269,19 +269,13 @@ <property name="spacing"> <number>2</number> </property> - <item row="1" column="0"> - <widget class="QToolButton" name="btnGetQGISCenter"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + <item row="2" column="0" colspan="2"> + <widget class="QCheckBox" name="cbLoadCenterPixelProfile"> <property name="toolTip"> - <string>Take the map center from QGIS</string> + <string>Loads the temporal profile of the map center pixel</string> </property> <property name="text"> - <string>Get Center</string> + <string>Load center profile</string> </property> </widget> </item> @@ -298,8 +292,8 @@ </property> </spacer> </item> - <item row="0" column="0"> - <widget class="QToolButton" name="btnSetQGISCenter"> + <item row="1" column="0"> + <widget class="QToolButton" name="btnGetQGISCenter"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -307,10 +301,10 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Set QGIS Map to the same map center</string> + <string>Take the map center from QGIS</string> </property> <property name="text"> - <string>Set Center</string> + <string>Get Center</string> </property> </widget> </item> @@ -346,13 +340,19 @@ </property> </widget> </item> - <item row="2" column="0" colspan="2"> - <widget class="QCheckBox" name="cbLoadCenterPixelProfile"> + <item row="0" column="0"> + <widget class="QToolButton" name="btnSetQGISCenter"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="toolTip"> - <string>Loads the temporal profile of the map center pixel</string> + <string>Set QGIS Map to the same map center</string> </property> <property name="text"> - <string>Load center profile</string> + <string>Set Center</string> </property> </widget> </item> -- GitLab