Commit 20c1abb0 authored by Benjamin Jakimow's avatar Benjamin Jakimow
Browse files

updated QPS


refactored map labels (now controlled with QgsExpression)
Signed-off-by: Benjamin Jakimow's avatarBenjamin Jakimow benjamin.jakimow@geo.hu-berlin.de <benjamin.jakimow@geo.hu-berlin.de>
parent f920a066
Pipeline #14070 failed with stage
in 5 seconds
==============
Changelog
==============
2020-11-16 (version 1.15):
2020-11-23 (version 1.15):
* map canvases can be organized in multiple rows per map view
* map descriptions are now defined with QgsExpressions
* quick labels: CTRL + right mouse button opens map menu even when the feature modify map tool is activates
* source visibility update can be run on entire time series or (new and faster) for the next time steps only
* added "follow current date" option to time series table to keep focus on the map window date range
......
......@@ -1342,7 +1342,7 @@ def days_per_year(year):
1. If the year is evenly divisible by 4, go to step 2. Otherwise, False.
2. If the year is evenly divisible by 100, go to step 3. Otherwise, False
3. If the year is evenly divisible by 400, True Otherwise, False
"""
"""
Every year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100,
......@@ -1554,7 +1554,7 @@ def parseFWHM(dataset) -> typing.Tuple[np.ndarray]:
def checkWavelength(key: str, values: str, expected: int = 1) -> np.ndarray:
wl: np.ndarray = None
if re.search(r'^wavelengths?$', key, re.I):
if re.search(r'^(center[ _]*)?wavelengths?$', key, re.I):
# remove trailing / ending { } and whitespace
values = re.sub('[{}]', '', values).strip()
if ',' not in values:
......@@ -1569,6 +1569,7 @@ def checkWavelength(key: str, values: str, expected: int = 1) -> np.ndarray:
pass
return wl
def checkWavelengthUnit(key: str, value: str) -> str:
wlu: str = None
value = value.strip()
......@@ -1606,6 +1607,13 @@ def parseWavelength(dataset) -> typing.Tuple[np.ndarray, str]:
:return: (wl, wl_u) or (None, None), if not existing
"""
def sort_domains(domains) -> typing.List[str]:
if not isinstance(domains, list):
domains = []
return sorted(domains, key=lambda n: n != ['ENVI'])
try:
dataset = gdalDataset(dataset)
except AssertionError:
......@@ -1613,67 +1621,63 @@ def parseWavelength(dataset) -> typing.Tuple[np.ndarray, str]:
if isinstance(dataset, gdal.Dataset):
# 1. check on raster level
domains = dataset.GetMetadataDomainList()
if isinstance(domains, list):
for domain in domains:
# see http://www.harrisgeospatial.com/docs/ENVIHeaderFiles.html for supported wavelength units
for domain in sort_domains(dataset.GetMetadataDomainList()):
# see http://www.harrisgeospatial.com/docs/ENVIHeaderFiles.html for supported wavelength units
mdDict = dataset.GetMetadata_Dict(domain)
mdDict = dataset.GetMetadata_Dict(domain)
domainWLU: str = None
domainWL: np.ndarray = None
# search domain
for key, values in mdDict.items():
if domainWL is None:
domainWL = checkWavelength(key, values, expected=dataset.RasterCount)
if domainWLU is None:
domainWLU = checkWavelengthUnit(key, values)
domainWLU: str = None
domainWL: np.ndarray = None
# search domain
for key, values in mdDict.items():
if domainWL is None:
domainWL = checkWavelength(key, values, expected=dataset.RasterCount)
if domainWLU is None:
domainWLU = checkWavelengthUnit(key, values)
if isinstance(domainWL, np.ndarray) and isinstance(domainWLU, str):
if domain == 'FORCE' and domainWLU == 'DecimalYear':
# make decimal-year values leap-year sensitive
domainWL = convertDateUnit(datetime64(domainWL, dpy=365), 'DecimalYear')
if isinstance(domainWL, np.ndarray) and isinstance(domainWLU, str):
if domain == 'FORCE' and domainWLU == 'DecimalYear':
# make decimal-year values leap-year sensitive
domainWL = convertDateUnit(datetime64(domainWL, dpy=365), 'DecimalYear')
if len(domainWL) > dataset.RasterCount:
domainWL = domainWL[0:dataset.RasterCount]
if len(domainWL) > dataset.RasterCount:
domainWL = domainWL[0:dataset.RasterCount]
return domainWL, domainWLU
return domainWL, domainWLU
# 2. check on band level. collect wl from each single band
# first domain that defines wl and wlu is prototyp domain for all other bands
wl = [] # list of wavelength values
wlu: str = None # wavelength unit string
wlDomain: str = None # the domain in which the WL and WLU are defined
wlKey: str = None # key that stores the wavelength value
wluKey: str = None # key that stores the wavelength unit
wl = [] # list of wavelength values
wlu: str = None # wavelength unit string
wlDomain: str = None # the domain in which the WL and WLU are defined
wlKey: str = None # key that stores the wavelength value
wluKey: str = None # key that stores the wavelength unit
for b in range(dataset.RasterCount):
band: gdal.Band = dataset.GetRasterBand(b + 1)
if b == 0:
domains = band.GetMetadataDomainList()
if isinstance(domains, list):
for domain in domains:
# see http://www.harrisgeospatial.com/docs/ENVIHeaderFiles.html for supported wavelength units
domainWL = domainWLU = None
mdDict = band.GetMetadata_Dict(domain)
for key, values in mdDict.items():
if domainWLU is None:
domainWLU = checkWavelengthUnit(key, values)
if domainWLU:
wluKey = key
if domainWL is None:
domainWL = checkWavelength(key, values, expected=1)
if isinstance(domainWL, np.ndarray):
wlKey = key
if isinstance(domainWL, np.ndarray) and isinstance(domainWLU, str):
wlDomain = domain
wlu = domainWLU
wl.append(domainWL[0])
for domain in sort_domains(band.GetMetadataDomainList()):
# see http://www.harrisgeospatial.com/docs/ENVIHeaderFiles.html for supported wavelength units
domainWL = domainWLU = None
mdDict = band.GetMetadata_Dict(domain)
for key, values in mdDict.items():
if domainWLU is None:
domainWLU = checkWavelengthUnit(key, values)
if domainWLU:
wluKey = key
if domainWL is None:
domainWL = checkWavelength(key, values, expected=1)
if isinstance(domainWL, np.ndarray):
wlKey = key
if isinstance(domainWL, np.ndarray) and isinstance(domainWLU, str):
wlDomain = domain
wlu = domainWLU
wl.append(domainWL[0])
if len(wl) == 0:
# we did not found a WL + WLU for the 1st band. stop searching and return
......@@ -1700,7 +1704,6 @@ def parseWavelength(dataset) -> typing.Tuple[np.ndarray, str]:
return None, None
class Singleton(type):
_instances = {}
......
......@@ -896,6 +896,10 @@ class EOTimeSeriesViewer(QgisInterface, QObject):
mapView.addLayer(self.profileDock.temporalProfileLayer())
mapView.addSpectralProfileLayers()
if len(self.mapViews()) == 1:
mapView.setMapInfoExpression("@map_date + '\n' + @map_sensor")
def temporalProfileLayer(self) -> TemporalProfileLayer:
"""
Returns the TemporalProfileLayer
......
......@@ -38,7 +38,7 @@ from qgis.core import QgsMapLayer, QgsRasterLayer, QgsVectorLayer, QgsContrastEn
QgsSingleBandPseudoColorRenderer, QgsWkbTypes, QgsRasterLayerTemporalProperties, QgsRasterDataProvider, \
QgsTextFormat, QgsMapLayerStore, QgsMultiBandColorRenderer, QgsSingleBandGrayRenderer, QgsField, \
QgsRectangle, QgsPolygon, QgsMultiBandColorRenderer, QgsRectangle, QgsSingleBandGrayRenderer, \
QgsLayerTreeGroup, QgsUnitTypes, QgsMimeDataUtils, QgsExpression
QgsLayerTreeGroup, QgsUnitTypes, QgsMimeDataUtils, QgsExpression, QgsExpressionContext, QgsExpressionContextScope
from qgis.gui import QgsMapCanvas, QgisInterface, QgsFloatingWidget, QgsUserInputWidget, \
QgsAdvancedDigitizingDockWidget, QgsMapCanvasItem, \
......@@ -130,8 +130,7 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
super(MapCanvasInfoItem, self).__init__(mapCanvas)
self.mCanvas = mapCanvas
self.mExpression: typing.Dict[int, QgsExpression] = dict()
self.mInfoText: typing.Dict[int, QgsExpression] = dict()
self.mWrapChar = '\n'
self.mTextFormat = QgsTextFormat()
self.mTextFormat.setSizeUnit(QgsUnitTypes.RenderPixels)
......@@ -150,10 +149,12 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
def wrapChar(self) -> str:
return self.mWrapChar
def setExpression(self, expression: QgsExpression, alignment: Qt.Alignment = Qt.AlignTop | Qt.AlignHCenter):
assert isinstance(expression, QgsExpression)
self.mExpression[alignment] = expression
def setInfoText(self, text: str, alignment: Qt.Alignment = Qt.AlignTop | Qt.AlignHCenter):
if text in [None, '']:
self.mInfoText[alignment] = None
else:
assert isinstance(text, str)
self.mInfoText[alignment] = text
def setTextFormat(self, format: QgsTextFormat):
assert isinstance(format, QgsTextFormat)
......@@ -282,8 +283,8 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
def setLowerRight(self, expression: QgsExpression):
self.setText(expression, Qt.AlignBottom | Qt.AlignRight)
def clearExpression(self):
self.mExpression.clear()
def clearInfoText(self):
self.mInfoText.clear()
def paint(self, painter, QStyleOptionGraphicsItem=None, QWidget_widget=None):
"""
......@@ -293,10 +294,7 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
:param QWidget_widget:
:return:
"""
for alignment, expression in self.mExpression.items():
if isinstance(expression, QgsExpression):
s = ""
txt = expression.evaluate()
for alignment, text in self.mInfoText.items():
if isinstance(text, str) and len(text) > 0:
self.paintText(painter, text, alignment)
......@@ -688,7 +686,7 @@ class MapCanvas(QgsMapCanvas):
if mapView is None or self.tsd() is None:
self.setLayers([])
self.mInfoItem.clearExpression()
self.mInfoItem.clearInfoText()
self.update()
return
......
......@@ -39,7 +39,7 @@ from qgis.PyQt.QtGui import \
QColor, QIcon, QGuiApplication, QMouseEvent
from qgis.PyQt.QtWidgets import \
QWidget, QLayoutItem, QFrame, QLabel, QGridLayout, QSlider, QMenu, \
QToolBox, QDialog, QAction, QSpinBox, QCheckBox
QToolBox, QDialog, QAction, QSpinBox, QCheckBox, QLineEdit
from qgis.PyQt.QtXml import \
QDomDocument, QDomNode, QDomElement
from qgis.core import \
......@@ -48,7 +48,8 @@ from qgis.core import \
QgsLayerTreeModel, QgsLayerTreeGroup, QgsPointXY, \
QgsLayerTree, QgsLayerTreeLayer, QgsReadWriteContext, QgsVector, \
QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsMapLayerProxyModel, QgsColorRamp, \
QgsSingleBandPseudoColorRenderer, QgsExpressionContextGenerator, QgsExpressionContext, QgsExpressionContextUtils
QgsSingleBandPseudoColorRenderer, QgsExpressionContextGenerator, QgsExpressionContext, \
QgsExpressionContextUtils, QgsExpression, QgsExpressionContextScope
from qgis.gui import \
QgsDockWidget, QgsMapCanvas, QgsMapTool, QgsCollapsibleGroupBox, QgsLayerTreeView, \
QgisInterface, QgsLayerTreeViewMenuProvider, QgsLayerTreeMapCanvasBridge, \
......@@ -190,25 +191,58 @@ class MapView(QFrame):
self.mIsVisible = True
self.setTitle(name)
self.cbShowInfoExpression: QCheckBox
self.tbInfoExpression: QgsExpressionLineEdit
self.tbInfoExpression: QLineEdit
self.tbInfoExpression.textChanged.connect(self.onMapInfoExpressionChanged)
self.btnShowInfoExpression.setDefaultAction(self.optionShowInfoExpression)
self.optionShowInfoExpression.toggled.connect(self.tbInfoExpression.setEnabled)
self.optionShowInfoExpression.toggled.connect(self.actionSetInfoExpression.setEnabled)
self.btnSetInfoExpression.setDefaultAction(self.actionSetInfoExpression)
self.actionSetInfoExpression.triggered.connect(self.onSetInfoExpression)
self._fakeLyr: QgsVectorLayer = QgsVectorLayer("point?crs=epsg:4326", "Scratch point layer", "memory")
self.mLyr = QgsVectorLayer()
#self.tbInfoExpression.setLayer(self.mLyr)
self.mExpressionContextGenerator = MapViewExpressionContextGenerator()
self.mExpressionContextGenerator.setMapView(self)
self.cbShowInfoExpression.toggled.connect(self.tbInfoExpression.setEnabled)
self.tbInfoExpression.setEnabled(self.cbShowInfoExpression.isChecked())
#self.mExpressionContextGenerator = MapViewExpressionContextGenerator()
#self.mExpressionContextGenerator.setMapView(self)
self.tbInfoExpression.setEnabled(self.optionShowInfoExpression.isChecked())
self.tbInfoExpression.registerExpressionContextGenerator(self.mExpressionContextGenerator)
self.cbShowInfoExpression.toggled.connect(self.sigCanvasAppearanceChanged)
#self.tbInfoExpression.registerExpressionContextGenerator(self.mExpressionContextGenerator)
self.optionShowInfoExpression.toggled.connect(self.sigCanvasAppearanceChanged)
#self.tbInfoExpression.expressionChanged.connect(self.sigCanvasAppearanceChanged)
for action in m.actions():
action.toggled.connect(self.sigCanvasAppearanceChanged)
fixMenuButtons(self)
def onMapInfoExpressionChanged(self, text: str):
self.sigCanvasAppearanceChanged.emit()
s = ""
def onSetInfoExpression(self, *args):
from qgis.gui import QgsExpressionBuilderDialog, QgsAttributeForm
from qgis.core import QgsExpressionContextScope
context = QgsExpressionContext(QgsExpressionContextUtils.globalProjectLayerScopes(self._fakeLyr))
c = self.currentMapCanvas()
if isinstance(c, MapCanvas):
context.appendScope(QgsExpressionContextScope(c.expressionContextScope()))
expression = self.tbInfoExpression.text()
# taken from qgsfeaturefilterwidget.cpp : void QgsFeatureFilterWidget::filterExpressionBuilder()
dlg = QgsExpressionBuilderDialog(self._fakeLyr, expression,
self,
'generic', context)
dlg.setWindowTitle('Expression Based Filter')
#myDa = QgsDistanceArea()
#myDa.setSourceCrs(self.mLayer.crs(), QgsProject.instance().transformContext())
#myDa.setEllipsoid(QgsProject.instance().ellipsoid())
#dlg.setGeomCalculator(myDa)
if dlg.exec() == QDialog.Accepted:
self.tbInfoExpression.setText(dlg.expressionText())
def __iter__(self) -> typing.Iterator[TimeSeriesDate]:
return iter(self.mapCanvases())
......@@ -263,7 +297,7 @@ class MapView(QFrame):
nodeMapView.setAttribute('name', self.name())
nodeMapView.setAttribute('bg', self.mapBackgroundColor().name())
nodeMapView.setAttribute('visible', str(self.isVisible()))
nodeMapView.setAttribute('infoexpression', self.tbInfoExpression.expression())
nodeMapView.setAttribute('infoexpression', self.mapInfoExpression())
context = QgsReadWriteContext()
nodeTextStyle = self.mapTextFormat().writeXml(doc, context)
......@@ -287,6 +321,13 @@ class MapView(QFrame):
def name(self) -> str:
return self.title()
def setMapInfoExpression(self, expression: str):
self.tbInfoExpression.setText(expression)
def mapInfoExpression(self) -> str:
return f'{self.tbInfoExpression.text()}'.strip()
def setMapTextFormat(self, textformat: QgsTextFormat) -> QgsTextFormat:
if not equalTextFormats(self.mapTextFormat(), textformat):
self.mMapTextFormat = textformat
......@@ -1419,6 +1460,7 @@ class MapWidget(QFrame):
self.mTimeSeries.sigTimeSeriesDatesAdded.disconnect(self._updateSliderRange)
self.mTimeSeries.sigTimeSeriesDatesRemoved.disconnect(self._updateSliderRange)
self.mTimeSeries.sigFindOverlapTaskFinished.disconnect(self._updateCanvasDates)
self.mTimeSeries.sigSensorNameChanged.disconnect(self._updateCanvasAppearance)
self.mTimeSeries = ts
if isinstance(self.mTimeSeries, TimeSeries):
......@@ -1427,7 +1469,7 @@ class MapWidget(QFrame):
self.mTimeSeries.sigFindOverlapTaskFinished.connect(self._updateCanvasDates)
self.mTimeSeries.sigTimeSeriesDatesAdded.connect(self._updateSliderRange)
self.mTimeSeries.sigTimeSeriesDatesRemoved.connect(self._updateSliderRange)
self.mTimeSeries.sigSensorNameChanged.connect(self._updateCanvasAppearance)
if len(self.mTimeSeries) > 0:
self.mCurrentDate = self.mTimeSeries[0]
else:
......@@ -2060,9 +2102,7 @@ class MapWidget(QFrame):
bg = mapView.mapBackgroundColor()
tf = mapView.mapTextFormat()
#showName = mapView.optionShowMapViewName.isChecked()
#showSensor = mapView.optionShowSensorName.isChecked()
infoItemVisible: bool = mapView.optionShowInfoExpression.isChecked()
for canvas in self.mCanvases[mapView]:
assert isinstance(canvas, MapCanvas)
......@@ -2071,8 +2111,29 @@ class MapWidget(QFrame):
if canvas.isVisible() != v:
canvas.setVisible(v)
tsd = canvas.tsd()
infoItem: MapCanvasInfoItem = canvas.infoItem()
infoItem.setTextFormat(tf)
infoItem.setVisible(infoItemVisible)
expr = QgsExpression(mapView.mapInfoExpression())
if isinstance(expr, QgsExpression) and expr.expression() != '':
#context = QgsExpressionContext([QgsExpressionContextScope(canvas.expressionContextScope())])
context: QgsExpressionContext = QgsExpressionContext()
context.appendScope(QgsExpressionContextUtils.globalScope())
context.appendScope(QgsExpressionContextScope(canvas.expressionContextScope()))
if expr.isValid():
expr2 = QgsExpression(expr)
infoText = expr2.evaluate(context)
if not expr2.hasEvalError():
#print(infoText)
infoItem.setInfoText(str(infoText))
else:
#print(expr.evalErrorString(), file=sys.stderr)
infoItem.setInfoText('')
canvas.addToRefreshPipeLine(MapCanvas.Command.UpdateMapItems)
if canvas.canvasColor() != bg:
canvas.addToRefreshPipeLine(mapView.mapBackgroundColor())
......
......@@ -1419,6 +1419,7 @@ class TimeSeries(QAbstractItemModel):
sigSensorAdded = pyqtSignal(SensorInstrument)
sigSensorRemoved = pyqtSignal(SensorInstrument)
sigSensorNameChanged = pyqtSignal(SensorInstrument)
sigSourcesAdded = pyqtSignal(list)
sigSourcesRemoved = pyqtSignal(list)
......@@ -1892,6 +1893,7 @@ class TimeSeries(QAbstractItemModel):
idx0 = self.index(0, c)
idx1 = self.index(self.rowCount() - 1, c)
self.dataChanged.emit(idx0, idx1)
self.sigSensorNameChanged.emit(sensor)
s = ""
def checkSensorList(self):
......
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>239</width>
<width>250</width>
<height>238</height>
</rect>
</property>
......@@ -52,78 +52,94 @@
<number>1</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>1</number>
</property>
<item>
<widget class="QToolButton" name="btnToggleMapViewVisibility">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QToolButton" name="btnToggleCrosshair">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Toggle map view visibility</string>
<string>Show/hide crosshair</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="eotsv_resources.qrc">
<normaloff>:/eotimeseriesviewer/icons/mapviewHidden.svg</normaloff>:/eotimeseriesviewer/icons/mapviewHidden.svg</iconset>
<normaloff>:/eotimeseriesviewer/icons/crosshair.svg</normaloff>:/eotimeseriesviewer/icons/crosshair.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="popupMode">
<enum>QToolButton::DelayedPopup</enum>
<enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnToggleCrosshair">
<item row="0" column="0">
<widget class="QToolButton" name="btnToggleMapViewVisibility">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Show/hide crosshair</string>
<string>Toggle map view visibility</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="eotsv_resources.qrc">
<normaloff>:/eotimeseriesviewer/icons/crosshair.svg</normaloff>:/eotimeseriesviewer/icons/crosshair.svg</iconset>
<normaloff>:/eotimeseriesviewer/icons/mapviewHidden.svg</normaloff>:/eotimeseriesviewer/icons/mapviewHidden.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
<enum>QToolButton::DelayedPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<item row="0" column="3">
<widget class="QLineEdit" name="tbName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="frame">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Map View Name</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="btnAddLayer">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
......@@ -161,65 +177,58 @@
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="tbName">
<item row="0" column="4">
<widget class="QToolButton" name="btnHighlightMapView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
<string>?</string>
</property>
<property name="frame">
<bool>true</bool>
<property name="icon">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<normaloff>:/images/themes/default/mActionContextHelp.png</normaloff>:/images/themes/default/mActionContextHelp.png</iconset>
</property>
<property name="placeholderText">
<string>Map View Name</string>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnHighlightMapView">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>