Skip to content
Snippets Groups Projects
Commit 0273af2e authored by Benjamin Jakimow's avatar Benjamin Jakimow
Browse files

layerproperties.py refactoring, imporvied models

labeling.py refactoring, improved return values for QgsVectorFile editing
parent 8f948b8a
No related branches found
No related tags found
No related merge requests found
......@@ -29,8 +29,9 @@ resourceDir = os.path.join(DIR_REPO, 'qgisresources')
QGIS_APP = initQgisApplication(qgisResourceDir=resourceDir)
SHOW_GUI = True
QgsGui.editorWidgetRegistry().initEditors()
reg = QgsGui.editorWidgetRegistry()
if len(reg.factories()) == 0:
reg.initEditors()
class testclassLabelingTest(unittest.TestCase):
......@@ -257,35 +258,6 @@ class testclassLabelingTest(unittest.TestCase):
CONFKEY_CLASSIFICATIONSCHEME: classScheme2}))
return classScheme1, classScheme2
def test_FieldConfigEditorWidget(self):
reg = QgsGui.editorWidgetRegistry()
if len(reg.factories()) == 0:
reg.initEditors()
registerLabelShortcutEditorWidget()
lyr = self.createVectorLayer()
w = FieldConfigEditorWidget(None, lyr, 3)
w.show()
conf1 = w.currentFieldConfig()
self.assertEqual(conf1.config(), w.mInitialConf)
self.assertEqual(conf1.factoryKey(), w.mInitialFactoryKey)
w.setFactory('CheckBox')
conf2 = w.currentFieldConfig()
self.assertTrue(conf1 != conf2)
self.assertTrue(w.hasChanged())
w.setFactory(conf1.factoryKey())
conf3 = w.currentFieldConfig()
self.assertEqual(conf3.factoryKey(), conf1.factoryKey())
self.assertFalse(w.hasChanged())
if SHOW_GUI:
QGIS_APP.exec_()
def test_LabelingDock(self):
......@@ -299,9 +271,7 @@ class testclassLabelingTest(unittest.TestCase):
reg = QgsGui.editorWidgetRegistry()
if len(reg.factories()) == 0:
reg.initEditors()
registerLabelShortcutEditorWidget()
......@@ -345,9 +315,6 @@ class testclassLabelingTest(unittest.TestCase):
self.assertTrue(dock.mVectorLayerComboBox.currentLayer() == lyr)
if SHOW_GUI:
dock.show()
QGIS_APP.exec_()
......
# noinspection PyPep8Naming
import os, sys, re
from timeseriesviewer.tests import initQgisApplication, testRasterFiles
from qgis.core import *
from qgis.gui import *
from timeseriesviewer.tests import initQgisApplication, testRasterFiles, TestObjects
import unittest, tempfile
from timeseriesviewer.layerproperties import *
from timeseriesviewer import DIR_REPO
from timeseriesviewer.mapcanvas import MapCanvas
from timeseriesviewer.tests import TestObjects
resourceDir = os.path.join(DIR_REPO, 'qgisresources')
QGIS_APP = initQgisApplication(qgisResourceDir=resourceDir)
SHOW_GUI = True
......@@ -15,7 +16,7 @@ SHOW_GUI = True
QgsGui.editorWidgetRegistry().initEditors()
class testclassLabelingTest(unittest.TestCase):
class TestLayerproperties(unittest.TestCase):
def createVectorLayer(self) -> QgsVectorLayer:
lyr = TestObjects.createVectorLayer()
......@@ -35,9 +36,7 @@ class testclassLabelingTest(unittest.TestCase):
return lyr
def test_fieldModel(self):
def test_LabelFieldModel(self):
lyr = self.createVectorLayer()
......@@ -45,6 +44,12 @@ class testclassLabelingTest(unittest.TestCase):
fm = LabelFieldModel(w)
fm.setLayer(lyr)
self.assertEqual(fm.layer(), lyr)
newName = 'Layer Fields'
fm.setHeaderData(0, Qt.Horizontal, newName, role=Qt.EditRole)
self.assertEqual(newName, fm.headerData(0, Qt.Horizontal))
w.setModel(fm)
w.show()
......@@ -52,6 +57,33 @@ class testclassLabelingTest(unittest.TestCase):
if SHOW_GUI:
QGIS_APP.exec_()
def test_FieldConfigEditorWidget(self):
lyr = self.createVectorLayer()
w = FieldConfigEditorWidget(None, lyr, 3)
self.assertIsInstance(w, FieldConfigEditorWidget)
w.show()
conf1 = w.currentFieldConfig()
self.assertEqual(conf1.config(), w.mInitialConf)
self.assertEqual(conf1.factoryKey(), w.mInitialFactoryKey)
w.setFactory('CheckBox')
conf2 = w.currentFieldConfig()
self.assertTrue(conf1 != conf2)
self.assertTrue(w.changed())
w.setFactory(conf1.factoryKey())
conf3 = w.currentFieldConfig()
self.assertEqual(conf3.factoryKey(), conf1.factoryKey())
self.assertFalse(w.changed())
if SHOW_GUI:
QGIS_APP.exec_()
def test_LayerFieldConfigEditorWidget(self):
......@@ -64,8 +96,14 @@ class testclassLabelingTest(unittest.TestCase):
self.assertTrue(w.layer() == None)
w.setLayer(lyr)
self.assertTrue(w.layer() == lyr)
w.setLayer(None)
self.assertTrue(w.layer() == None)
if SHOW_GUI:
QGIS_APP.exec_()
\ No newline at end of file
QGIS_APP.exec_()
if __name__ == "__main__":
SHOW_GUI = False
unittest.main()
......@@ -12,7 +12,7 @@ from timeseriesviewer.classification.classificationscheme \
import ClassificationSchemeWidget, ClassificationScheme, ClassInfo, ClassificationSchemeComboBox
from timeseriesviewer.timeseries import TimeSeriesDatum
from timeseriesviewer.layerproperties import *
#the QgsProject(s) and QgsMapLayerStore(s) to search for QgsVectorLayers
MAP_LAYER_STORES = [QgsProject.instance()]
......@@ -68,7 +68,7 @@ def layerClassSchemes(layer:QgsVectorLayer)->list:
setup = layer.editorWidgetSetup(i)
assert isinstance(setup, QgsEditorWidgetSetup)
if setup.type() == EDITOR_WIDGET_REGISTRY_KEY:
results.append(layer)
schemes.append(layer)
break
return schemes
......@@ -490,10 +490,6 @@ class LabelingDock(QgsDockWidget, loadUI('labelingdock.ui')):
#self.mLabelAttributeModel = LabelAttributeTableModel()
self.mLayerFieldModel = LabelFieldModel(self)
self.configTableView.setModel(self.mLayerFieldModel)
self.configSelectionModel = self.configTableView.selectionModel()
self.configSelectionModel.currentRowChanged.connect(lambda idx: self.stackedFieldConfigs.setCurrentIndex(idx.row()))
self.mVectorLayerComboBox.setAllowEmptyLayer(True)
allowed = ['DB2', 'WFS', 'arcgisfeatureserver', 'delimitedtext', 'memory', 'mssql', 'ogr', 'oracle', 'ows',
......@@ -503,8 +499,7 @@ class LabelingDock(QgsDockWidget, loadUI('labelingdock.ui')):
self.mVectorLayerComboBox.setExcludedProviders(excluded)
self.mVectorLayerComboBox.currentIndexChanged.connect(self.onVectorLayerChanged)
self.mLastConf = {}
self.mCurrentConfigWidget = None
self.mDualView = None
self.mCanvas = QgsMapCanvas(self)
self.mCanvas.setVisible(False)
......@@ -585,22 +580,9 @@ class LabelingDock(QgsDockWidget, loadUI('labelingdock.ui')):
def onVectorLayerChanged(self):
lyr = self.currentVectorSource()
self.mLayerFieldModel.setLayer(lyr)
# remove old config widget
while self.stackedFieldConfigs.count() > 0:
w = self.stackedFieldConfigs.widget(0)
self.stackedFieldConfigs.removeWidget(w)
w.setParent(None)
btnApply = self.buttonBoxEditorWidget.button(QDialogButtonBox.Apply)
btnApply.setEnabled(False)
self.layerFieldConfigEditorWidget.setLayer(lyr)
# add a config widget for each QgsField
if isinstance(lyr, QgsVectorLayer):
for i in range(lyr.fields().count()):
w = FieldConfigEditorWidget(self.stackedFieldConfigs, lyr, i)
w.sigChanged.connect(self.onCheckApply)
self.stackedFieldConfigs.addWidget(w)
lyr.editingStarted.connect(lambda : self.actionToggleEditing.setChecked(True))
lyr.editingStopped.connect(lambda: self.actionToggleEditing.setChecked(False))
......@@ -682,9 +664,6 @@ class LabelingDock(QgsDockWidget, loadUI('labelingdock.ui')):
self.btnToggleEditing.setDefaultAction(self.actionToggleEditing)
self.btnAddOgrLayer.setDefaultAction(self.actionAddOgrLayer)
# QgsVectorLayer settings view buttons
self.buttonBoxEditorWidget.button(QDialogButtonBox.Apply).clicked.connect(self.onApply)
self.buttonBoxEditorWidget.button(QDialogButtonBox.Reset).clicked.connect(self.onReset)
# bottom button bar
self.btnAttributeView.setDefaultAction(self.actionSwitchToTableView)
......@@ -821,6 +800,11 @@ class LabelShortcutEditorWidgetWrapper(QgsEditorWidgetWrapper):
return self.config(CONFKEY_CLASSIFICATIONSCHEME)
def createWidget(self, parent: QWidget):
"""
Create the data input widget
:param parent: QWidget
:return: ClassificationSchemeComboBox | default widget
"""
#log('createWidget')
labelType = self.configLabelType()
if labelType == LabelShortcutType.Classification:
......@@ -849,36 +833,58 @@ class LabelShortcutEditorWidgetWrapper(QgsEditorWidgetWrapper):
s = ""
def valid(self, *args, **kwargs)->bool:
"""
Returns True if a valid editor widget exists
:param args:
:param kwargs:
:return: bool
"""
return isinstance(self.mEditor, (ClassificationSchemeComboBox, QLineEdit))
def value(self, *args, **kwargs):
"""
Reuturns the value
:param args:
:param kwargs:
:return:
"""
typeCode = self.field().type()
if isinstance(self.mEditor, ClassificationSchemeComboBox):
classInfo = self.mEditor.currentClassInfo()
if isinstance(classInfo, ClassInfo):
if typeCode == QVariant.String:
return classInfo.name()
if typeCode in [QVariant.Int, QVariant.Double]:
return classInfo.label()
elif isinstance(self.mEditor, QLineEdit):
txt = self.mEditor.text()
if len(txt) == '':
return self.defaultValue()
if typeCode == QVariant.String:
return txt
try:
txt = txt.strip()
if typeCode == QVariant.Int:
return int(txt)
if typeCode == QVariant.Double:
return float(txt)
except Exception as e:
return self.defaultValue()
return txt
return self.mLineEdit.text()
return None
return self.defaultValue()
def setEnabled(self, enabled:bool):
......@@ -895,7 +901,10 @@ class LabelShortcutEditorWidgetWrapper(QgsEditorWidgetWrapper):
i = cs.classIndexFromValue(value)
self.mEditor.setCurrentIndex(max(i, 0))
elif isinstance(self.mEditor, QLineEdit):
self.mEditor.setText(str(value))
if value in [QVariant(), None]:
self.mEditor.setText(None)
else:
self.mEditor.setText(str(value))
class LabelShortcutWidgetFactory(QgsEditorWidgetFactory):
......
......@@ -5,23 +5,31 @@ from qgis.gui import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from osgeo import gdal
from timeseriesviewer.utils import loadUI, qgisInstance
from timeseriesviewer.classification.classificationscheme \
import ClassificationSchemeWidget, ClassificationScheme, ClassInfo, ClassificationSchemeComboBox
from timeseriesviewer.timeseries import TimeSeriesDatum
from timeseriesviewer.utils import loadUI
class LabelFieldModel(QgsFieldModel):
"""
A model to show the QgsFields of an QgsVectorLayer.
Inherits QgsFieldModel and allows to change the name of the 1st column.
"""
def __init__(self, parent):
"""
Constructor
:param parent:
"""
super(LabelFieldModel, self).__init__(parent)
self.mColumnNames = ['Fields', 'Type']
self.mColumnNames = ['Fields']
def headerData(self, col, orientation, role):
def headerData(self, col, orientation, role=Qt.DisplayRole):
"""
Returns header data
:param col: int
:param orientation: Qt.Horizontal | Qt.Vertical
:param role:
:return: value
"""
if Qt is None:
return None
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
......@@ -30,7 +38,24 @@ class LabelFieldModel(QgsFieldModel):
return col
return None
def setHeaderData(self, col, orientation, value, role=Qt.EditRole):
"""
Sets the header data.
:param col: int
:param orientation:
:param value: any
:param role:
"""
result = False
if role == Qt.EditRole:
if orientation == Qt.Horizontal and col < len(self.mColumnNames) and isinstance(value, str):
self.mColumnNames[col] = value
result = True
if result == True:
self.headerDataChanged.emit(orientation, col, col)
return result
class FieldConfigEditorWidget(QWidget):
......@@ -251,20 +276,27 @@ class LayerFieldConfigEditorWidget(QWidget, loadUI('layerfieldconfigeditorwidget
super(LayerFieldConfigEditorWidget, self).__init__(parent, *args, **kwds)
self.setupUi(self)
self.scrollArea.resizeEvent = self.onScrollAreaResize
self.mFieldModel = LabelFieldModel(self)
self.treeView.setModel(self.mFieldModel)
self.treeView.selectionModel().currentRowChanged.connect(self.onSelectionChanged)
self.treeView.selectionModel().currentRowChanged.connect(
lambda current, _ : self.stackedWidget.setCurrentIndex(current.row())
)
self.btnApply = self.buttonBox.button(QDialogButtonBox.Apply)
self.btnReset = self.buttonBox.button(QDialogButtonBox.Reset)
self.btnApply.clicked.connect(self.onApply)
self.btnReset.clicked.connect(self.onReset)
def onSelectionChanged(self, current:QModelIndex, previous:QModelIndex):
sw = self.stackedWidget
assert isinstance(sw, QStackedWidget)
sw.setCurrentWidget(sw.widget(current.row()))
s = ""
pass
def onScrollAreaResize(self, resizeEvent:QResizeEvent):
"""
Forces the stackedWidget's width to fit into the scrollAreas viewport
:param resizeEvent: QResizeEvent
"""
assert isinstance(resizeEvent, QResizeEvent)
self.stackedWidget.setMaximumWidth(resizeEvent.size().width())
s =""
def onReset(self):
......@@ -278,6 +310,10 @@ class LayerFieldConfigEditorWidget(QWidget, loadUI('layerfieldconfigeditorwidget
self.onSettingsChanged()
def onApply(self):
"""
Applies all changes to the QgsVectorLayer
:return:
"""
sw = self.stackedWidget
assert isinstance(sw, QStackedWidget)
......@@ -291,13 +327,24 @@ class LayerFieldConfigEditorWidget(QWidget, loadUI('layerfieldconfigeditorwidget
def setLayer(self, layer:QgsVectorLayer):
"""
Sets the QgsVectorLayer
:param layer:
"""
self.mFieldModel.setLayer(layer)
self.updateFieldWidgets()
def updateFieldWidgets(self):
def layer(self)->QgsVectorLayer:
"""
Returns the current QgsVectorLayer
:return:
"""
return self.mFieldModel.layer()
def updateFieldWidgets(self):
"""
Empties the stackedWidget and populates it with a FieldConfigEditor
for each QgsVectorLayer field.
"""
sw = self.stackedWidget
assert isinstance(sw, QStackedWidget)
while sw.count() > 0:
......@@ -312,10 +359,11 @@ class LayerFieldConfigEditorWidget(QWidget, loadUI('layerfieldconfigeditorwidget
self.onSettingsChanged()
def onSettingsChanged(self):
"""
Enables/disables buttons
:return:
"""
b = False
for i in range(self.stackedWidget.count()):
w = self.stackedWidget.widget(i)
......@@ -324,15 +372,6 @@ class LayerFieldConfigEditorWidget(QWidget, loadUI('layerfieldconfigeditorwidget
b = True
break
self.btnReset.setEnabled(b)
self.btnApply.setEnabled(b)
def layer(self)->QgsVectorLayer:
"""
Returns the current QgsVectorLayer
:return:
"""
return self.mFieldModel.layer()
......@@ -227,88 +227,12 @@
<number>0</number>
</property>
<item>
<widget class="QTableView" name="configTableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollAreaWidgetTypes">
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetTypesContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>392</width>
<height>239</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>2</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">
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="stackedFieldConfigs">
<property name="autoFillBackground">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="LayerFieldConfigEditorWidget" name="layerFieldConfigEditorWidget" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBoxEditorWidget">
<property name="standardButtons">
<set>QDialogButtonBox::Apply</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="btnBar2" native="true">
<layout class="QHBoxLayout" name="btnBarBottom">
......@@ -481,6 +405,12 @@
<extends>QComboBox</extends>
<header>qgsmaplayercombobox.h</header>
</customwidget>
<customwidget>
<class>LayerFieldConfigEditorWidget</class>
<extends>QWidget</extends>
<header>timeseriesviewer.layerproperties</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="resources.qrc"/>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment