Commit f920a066 authored by Benjamin Jakimow's avatar Benjamin Jakimow
Browse files

added map view title expression widget


Signed-off-by: Benjamin Jakimow's avatarBenjamin Jakimow benjamin.jakimow@geo.hu-berlin.de <benjamin.jakimow@geo.hu-berlin.de>
parent 88027ad6
Pipeline #14062 failed with stage
in 37 seconds
......@@ -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
QgsLayerTreeGroup, QgsUnitTypes, QgsMimeDataUtils, QgsExpression
from qgis.gui import QgsMapCanvas, QgisInterface, QgsFloatingWidget, QgsUserInputWidget, \
QgsAdvancedDigitizingDockWidget, QgsMapCanvasItem, \
......@@ -130,7 +130,8 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
super(MapCanvasInfoItem, self).__init__(mapCanvas)
self.mCanvas = mapCanvas
self.mText = dict()
self.mExpression: typing.Dict[int, QgsExpression] = dict()
self.mWrapChar = '\n'
self.mTextFormat = QgsTextFormat()
self.mTextFormat.setSizeUnit(QgsUnitTypes.RenderPixels)
......@@ -149,9 +150,10 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
def wrapChar(self) -> str:
return self.mWrapChar
def setText(self, text: str, alignment: Qt.Alignment = Qt.AlignTop | Qt.AlignHCenter):
self.mText[alignment] = text
def setExpression(self, expression: QgsExpression, alignment: Qt.Alignment = Qt.AlignTop | Qt.AlignHCenter):
assert isinstance(expression, QgsExpression)
self.mExpression[alignment] = expression
def setTextFormat(self, format: QgsTextFormat):
assert isinstance(format, QgsTextFormat)
......@@ -253,35 +255,35 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
poo = QPointF(x, y)
r.drawText(poo, rotation, hAlign, text, context, textFormat)
def setUpperLeft(self, text: str):
self.setText(text, Qt.AlignTop | Qt.AlignLeft)
def setUpperLeft(self, expression: QgsExpression):
self.setText(expression, Qt.AlignTop | Qt.AlignLeft)
def setMiddleLeft(self, text: str):
self.setText(text, Qt.AlignVCenter | Qt.AlignLeft)
def setMiddleLeft(self, expression: QgsExpression):
self.setText(expression, Qt.AlignVCenter | Qt.AlignLeft)
def setLowerLeft(self, text: str):
self.setText(text, Qt.AlignBottom | Qt.AlignLeft)
def setLowerLeft(self, expression: QgsExpression):
self.setText(expression, Qt.AlignBottom | Qt.AlignLeft)
def setUpperCenter(self, text: str):
self.setText(text, Qt.AlignTop | Qt.AlignHCenter)
def setUpperCenter(self, expression: QgsExpression):
self.setText(expression, Qt.AlignTop | Qt.AlignHCenter)
def setMiddleCenter(self, text: str):
self.setText(text, Qt.AlignVCenter | Qt.AlignHCenter)
def setMiddleCenter(self, expression: QgsExpression):
self.setText(expression, Qt.AlignVCenter | Qt.AlignHCenter)
def setLowerCenter(self, text: str):
self.setText(text, Qt.AlignBottom | Qt.AlignHCenter)
def setLowerCenter(self, expression: QgsExpression):
self.setText(expression, Qt.AlignBottom | Qt.AlignHCenter)
def setUpperRight(self, text: str):
self.setText(text, Qt.AlignTop | Qt.AlignRight)
def setUpperRight(self, expression: QgsExpression):
self.setText(expression, Qt.AlignTop | Qt.AlignRight)
def setMiddleRight(self, text: str):
self.setText(text, Qt.AlignVCenter | Qt.AlignRight)
def setMiddleRight(self, expression: QgsExpression):
self.setText(expression, Qt.AlignVCenter | Qt.AlignRight)
def setLowerRight(self, text: str):
self.setText(text, Qt.AlignBottom | Qt.AlignRight)
def setLowerRight(self, expression: QgsExpression):
self.setText(expression, Qt.AlignBottom | Qt.AlignRight)
def clearText(self):
self.mText.clear()
def clearExpression(self):
self.mExpression.clear()
def paint(self, painter, QStyleOptionGraphicsItem=None, QWidget_widget=None):
"""
......@@ -291,7 +293,10 @@ class MapCanvasInfoItem(QgsMapCanvasItem):
:param QWidget_widget:
:return:
"""
for alignment, text in self.mText.items():
for alignment, expression in self.mExpression.items():
if isinstance(expression, QgsExpression):
s = ""
txt = expression.evaluate()
if isinstance(text, str) and len(text) > 0:
self.paintText(painter, text, alignment)
......@@ -683,7 +688,7 @@ class MapCanvas(QgsMapCanvas):
if mapView is None or self.tsd() is None:
self.setLayers([])
self.mInfoItem.clearText()
self.mInfoItem.clearExpression()
self.update()
return
......
......@@ -39,19 +39,20 @@ 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
QToolBox, QDialog, QAction, QSpinBox, QCheckBox
from qgis.PyQt.QtXml import \
QDomDocument, QDomNode, QDomElement
from qgis.core import \
QgsCoordinateReferenceSystem, QgsVectorLayer, QgsTextFormat, \
QgsCoordinateReferenceSystem, QgsVectorLayer, QgsTextFormat, QgsProject, \
QgsRectangle, QgsRasterRenderer, QgsMapLayerStore, QgsMapLayerStyle, \
QgsLayerTreeModel, QgsLayerTreeGroup, QgsPointXY, \
QgsLayerTree, QgsLayerTreeLayer, QgsReadWriteContext, QgsVector, \
QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsMapLayerProxyModel, QgsColorRamp, QgsSingleBandPseudoColorRenderer
QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsMapLayerProxyModel, QgsColorRamp, \
QgsSingleBandPseudoColorRenderer, QgsExpressionContextGenerator, QgsExpressionContext, QgsExpressionContextUtils
from qgis.gui import \
QgsDockWidget, QgsMapCanvas, QgsMapTool, QgsCollapsibleGroupBox, QgsLayerTreeView, \
QgisInterface, QgsLayerTreeViewMenuProvider, QgsLayerTreeMapCanvasBridge, \
QgsProjectionSelectionWidget, QgsMessageBar
QgsProjectionSelectionWidget, QgsMessageBar, QgsFieldExpressionWidget, QgsFilterLineEdit, QgsExpressionLineEdit
from .externals.qps.crosshair.crosshair import getCrosshairStyle, CrosshairStyle, CrosshairMapCanvasItem
from .externals.qps.layerproperties import VectorLayerTools
from .externals.qps.maptools import MapTools
......@@ -80,6 +81,24 @@ class MapViewLayerTreeModel(QgsLayerTreeModel):
def __init__(self, rootNode, parent=None):
super(MapViewLayerTreeModel, self).__init__(rootNode, parent=parent)
class MapViewExpressionContextGenerator(QgsExpressionContextGenerator):
def __init__(self, *args, **kwds):
super().__init__(*args, **kwds)
self.mMapView: MapView = None
def setMapView(self, mapView):
self.mMapView = mapView
def createExpressionContext(self) -> QgsExpressionContext:
context = QgsExpressionContext([QgsExpressionContextUtils.projectScope(QgsProject.instance())])
if False and isinstance(self.mMapView, MapView):
canvas = self.mMapView.currentMapCanvas()
context.appendScope(canvas.expressionContextScope())
#self._context = context
return context
class MapView(QFrame):
"""
......@@ -171,22 +190,26 @@ class MapView(QFrame):
self.mIsVisible = True
self.setTitle(name)
self.cbShowInfoExpression: QCheckBox
self.tbInfoExpression: QgsExpressionLineEdit
self.optionShowDate: QAction
self.optionShowSensorName: QAction
self.optionShowMapViewName: QAction
self.mLyr = QgsVectorLayer()
#self.tbInfoExpression.setLayer(self.mLyr)
m = QMenu()
m.addAction(self.optionShowDate)
m.addAction(self.optionShowSensorName)
m.addAction(self.optionShowMapViewName)
self.btnInfoOptions.setMenu(m)
self.mExpressionContextGenerator = MapViewExpressionContextGenerator()
self.mExpressionContextGenerator.setMapView(self)
self.cbShowInfoExpression.toggled.connect(self.tbInfoExpression.setEnabled)
self.tbInfoExpression.setEnabled(self.cbShowInfoExpression.isChecked())
self.tbInfoExpression.registerExpressionContextGenerator(self.mExpressionContextGenerator)
self.cbShowInfoExpression.toggled.connect(self.sigCanvasAppearanceChanged)
#self.tbInfoExpression.expressionChanged.connect(self.sigCanvasAppearanceChanged)
for action in m.actions():
action.toggled.connect(self.sigCanvasAppearanceChanged)
fixMenuButtons(self)
def __iter__(self) -> typing.Iterator[TimeSeriesDate]:
return iter(self.mapCanvases())
......@@ -209,9 +232,10 @@ class MapView(QFrame):
mapView.setName(nodeMapView.attribute('name'))
mapView.setMapBackgroundColor(QColor(nodeMapView.attribute('bg')))
mapView.setVisibility(to_bool(nodeMapView.attribute('visible')))
mapView.optionShowDate.setChecked(to_bool(nodeMapView.attribute('showDate')))
mapView.optionShowSensorName.setChecked(to_bool(nodeMapView.attribute('showSensorName')))
mapView.optionShowMapViewName.setChecked(to_bool(nodeMapView.attribute('showMapViewName')))
#mapView.optionShowDate.setChecked(to_bool(nodeMapView.attribute('showDate')))
#mapView.optionShowSensorName.setChecked(to_bool(nodeMapView.attribute('showSensorName')))
#mapView.optionShowMapViewName.setChecked(to_bool(nodeMapView.attribute('showMapViewName')))
# nodeMapView.setAttribute('showDate', str(self.optionShowDate.checked()))
# nodeMapView.setAttribute('showSensorName', str(self.optionShowSensorName.checked()))
......@@ -239,9 +263,7 @@ class MapView(QFrame):
nodeMapView.setAttribute('name', self.name())
nodeMapView.setAttribute('bg', self.mapBackgroundColor().name())
nodeMapView.setAttribute('visible', str(self.isVisible()))
nodeMapView.setAttribute('showDate', str(self.optionShowDate.isChecked()))
nodeMapView.setAttribute('showSensorName', str(self.optionShowSensorName.isChecked()))
nodeMapView.setAttribute('showMapViewName', str(self.optionShowMapViewName.isChecked()))
nodeMapView.setAttribute('infoexpression', self.tbInfoExpression.expression())
context = QgsReadWriteContext()
nodeTextStyle = self.mapTextFormat().writeXml(doc, context)
......@@ -435,8 +457,7 @@ class MapView(QFrame):
self.setWindowTitle('Map View "{}"'.format(self.title()))
self.sigTitleChanged.emit(self.title())
if self.optionShowMapViewName.isChecked():
self.sigCanvasAppearanceChanged.emit()
self.sigCanvasAppearanceChanged.emit()
def setMapWidget(self, w):
if isinstance(w, MapWidget):
......@@ -2039,9 +2060,9 @@ class MapWidget(QFrame):
bg = mapView.mapBackgroundColor()
tf = mapView.mapTextFormat()
showDate = mapView.optionShowDate.isChecked()
showName = mapView.optionShowMapViewName.isChecked()
showSensor = mapView.optionShowSensorName.isChecked()
#showName = mapView.optionShowMapViewName.isChecked()
#showSensor = mapView.optionShowSensorName.isChecked()
for canvas in self.mCanvases[mapView]:
assert isinstance(canvas, MapCanvas)
......@@ -2055,29 +2076,6 @@ class MapWidget(QFrame):
if canvas.canvasColor() != bg:
canvas.addToRefreshPipeLine(mapView.mapBackgroundColor())
# set info text
info = canvas.infoItem()
assert isinstance(info, MapCanvasInfoItem)
info.setTextFormat(tf)
uc = []
lc = []
if isinstance(tsd, TimeSeriesDate):
if showDate:
uc += ['{}'.format(tsd.date())]
if showName:
lc += ['{}'.format(mapView.title(maskNewLines=False))]
if showSensor:
uc += ['{}'.format(tsd.sensor().name())]
uc = '\n'.join(uc)
lc = '\n'.join(lc)
info.setUpperCenter(uc)
info.setLowerCenter(lc)
# canvas.addToRefreshPipeLine(MapCanvas.Command.UpdateMapItems)
class MapViewDock(QgsDockWidget):
sigMapViewAdded = pyqtSignal(MapView)
......@@ -2141,9 +2139,8 @@ class MapViewDock(QgsDockWidget):
def onMapCanvasColorChanged(self, color: QColor):
# todo: find a way to display the map canvas color in background
# css = f"QToolButton: {{background-color#{self.btnTextFormat.objectName()}: {color.name()}}}"
# self.btnTextFormat.parent().setStyleSheet(css)
# self.btnTextFormat.setStyleSheet(css)
css = f"QgsFontButton#btnTextFormat{{background-color:{color.name()}; }}"
self.btnTextFormat.setStyleSheet(css)
self.sigMapCanvasColorChanged.emit(color)
def onApplyButtonClicked(self):
......@@ -2379,8 +2376,9 @@ class MapViewDock(QgsDockWidget):
title = 'Map View {}'.format(n)
if n == 1:
mapView.optionShowDate.setChecked(True)
mapView.optionShowSensorName.setChecked(True)
pass
#mapView.optionShowDate.setChecked(True)
#mapView.optionShowSensorName.setChecked(True)
mapView.setTitle(title)
mapView.sigShowProfiles.connect(self.sigShowProfiles)
......
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>414</width>
<width>239</width>
<height>238</height>
</rect>
</property>
......@@ -123,40 +123,6 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnInfoOptions">
<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/>
</property>
<property name="text">
<string>T</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnAddLayer">
<property name="sizePolicy">
......@@ -178,7 +144,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../QGIS/images/images.qrc">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<normaloff>:/images/themes/default/mActionDataSourceManager.svg</normaloff>:/images/themes/default/mActionDataSourceManager.svg</iconset>
</property>
<property name="checkable">
......@@ -210,7 +176,7 @@
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Map View Title</string>
<string>Map View Name</string>
</property>
</widget>
</item>
......@@ -232,6 +198,33 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="cbShowInfoExpression">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QgsExpressionLineEdit" name="tbInfoExpression" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QgsLayerTreeView" name="mLayerTreeView"/>
</item>
......@@ -294,7 +287,7 @@
</action>
<action name="actionAddVectorLayer">
<property name="icon">
<iconset resource="../../../QGIS/images/images.qrc">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<normaloff>:/images/themes/default/mActionAddOgrLayer.svg</normaloff>:/images/themes/default/mActionAddOgrLayer.svg</iconset>
</property>
<property name="text">
......@@ -306,7 +299,7 @@
</action>
<action name="actionAddRasterLayer">
<property name="icon">
<iconset resource="../../../QGIS/images/images.qrc">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<normaloff>:/images/themes/default/mActionAddRasterLayer.svg</normaloff>:/images/themes/default/mActionAddRasterLayer.svg</iconset>
</property>
<property name="text">
......@@ -316,42 +309,9 @@
<string>Add a raster layer</string>
</property>
</action>
<action name="optionShowSensorName">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Sensor Name</string>
</property>
<property name="toolTip">
<string>Activate to show the sensor name</string>
</property>
</action>
<action name="optionShowMapViewName">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Map View Name</string>
</property>
<property name="toolTip">
<string>Activate to show the name of the map view</string>
</property>
</action>
<action name="optionShowDate">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Date</string>
</property>
<property name="toolTip">
<string>Activate to show the observate date</string>
</property>
</action>
<action name="actionAddMapLayer">
<property name="icon">
<iconset resource="../../../QGIS/images/images.qrc">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<normaloff>:/images/themes/default/mActionDataSourceManager.svg</normaloff>:/images/themes/default/mActionDataSourceManager.svg</iconset>
</property>
<property name="text">
......@@ -361,6 +321,15 @@
<string>Add Map Layers</string>
</property>
</action>
<action name="actionSetInfoExpression">
<property name="icon">
<iconset resource="../../../QGIS_Images/images/images.qrc">
<normaloff>:/images/themes/default/mIconDataDefineExpression.svg</normaloff>:/images/themes/default/mIconDataDefineExpression.svg</iconset>
</property>
<property name="text">
<string>Set Map Info</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
......@@ -368,10 +337,16 @@
<extends>QTreeView</extends>
<header>qgis.gui</header>
</customwidget>
<customwidget>
<class>QgsExpressionLineEdit</class>
<extends>QWidget</extends>
<header>qgis.gui</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="eotsv_resources.qrc"/>
<include location="../../../QGIS/images/images.qrc"/>
<include location="../../../QGIS_Images/images/images.qrc"/>
</resources>
<connections/>
</ui>
This diff is collapsed.
......@@ -105,9 +105,9 @@ class TestMapCanvas(EOTSVTestCase):
mc.mInfoItem.setLowerRight('Lower\nRight')
if False:
for k in mc.mInfoItem.mText.keys():
v = mc.mInfoItem.mText[k]
mc.mInfoItem.mText[k] = v.replace('\n', ' ')
for k in mc.mInfoItem.mExpression.keys():
v = mc.mInfoItem.mExpression[k]
mc.mInfoItem.mExpression[k] = v.replace('\n', ' ')
item = mc.mInfoItem
self.assertIsInstance(item, MapCanvasInfoItem)
......
......@@ -26,8 +26,8 @@ from qgis.core import QgsProject, QgsMapLayer, QgsRasterLayer, QgsVectorLayer, \
QgsSingleBandGrayRenderer, QgsSingleBandPseudoColorRenderer, QgsMultiBandColorRenderer, \
QgsPalettedRasterRenderer, QgsSingleBandColorDataRenderer, QgsHillshadeRenderer, \
QgsRasterShader, \
QgsVirtualLayerDefinition
from qgis.gui import QgsFontButton
QgsVirtualLayerDefinition, QgsExpressionContextGenerator, QgsExpressionContextUtils, QgsExpressionContext, QgsProject
from qgis.gui import QgsFontButton, QgsExpressionLineEdit
import unittest
import xmlrunner
from eotimeseriesviewer.utils import *
......@@ -241,10 +241,10 @@ class TestMapVisualization(EOTSVTestCase):
MW.setTimeSeries(TS)
tsd = TS[0]
MW.setMapsPerMapView(1)
MW.setMapsPerMapView(3, 2)
MW.addMapView(mapview)
MW.setCurrentDate(tsd)
self.assertTrue(len(MW.mapCanvases()) == 1)
self.assertTrue(len(MW.mapCanvases()) == 6)
canvas = MW.mapCanvases()[0]
self.assertIsInstance(canvas, MapCanvas)
......@@ -259,12 +259,52 @@ class TestMapVisualization(EOTSVTestCase):
MW.setSpatialExtent(SpatialExtent.fromLayer(l))
self.showGui()
def test_expressionLineEdit(self):
#vl = TestObjects.createVectorLayer()
uri = "point?crs=epsg:4326&field=id:integer"
vl = QgsVectorLayer(uri, "Scratch point layer", "memory")
class Generator(QgsExpressionContextGenerator):
def __init__(self, *args, **kwds):
super().__init__(*args, **kwds)
self._context = None
def createExpressionContext(self) -> QgsExpressionContext:
#context = QgsExpressionContext([QgsExpressionContextUtils.projectScope(QgsProject.instance())])
context = QgsExpressionContext([QgsExpressionContextUtils.globalScope(),
QgsExpressionContextUtils.projectScope(QgsProject.instance())])
if False and isinstance(self.mMapView, MapView):
canvas = self.mMapView.currentMapCanvas()
context.appendScope(canvas.expressionContextScope())
self._context = context
return context
gen = Generator()
w2 = QWidget()
w = QgsExpressionLineEdit(parent=w2)
#w.setLayer(vl)
#w.show()
#w.setLayer(vl)
w.registerExpressionContextGenerator(gen)
w2.setLayout(QHBoxLayout())
w2.layout().addWidget(w)
self.showGui(w2)
def test_mapViewDock(self):
TS = TestObjects.createTimeSeries()
mw = MapWidget()
mw.setTimeSeries(TS)
mw.setMapsPerMapView(1)
mw.setMapsPerMapView(1, 2)
mw.setMapTool(MapTools.CursorLocation)
dock = MapViewDock()
self.assertIsInstance(dock, MapViewDock)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment