diff --git a/python/core/core.sip b/python/core/core.sip index 6c8e1ce75730..98da6d6b6522 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -31,7 +31,6 @@ %Include qgscolorschemeregistry.sip %Include qgsconditionalstyle.sip %Include qgscontexthelp.sip -%Include qgsconfigurationmap.sip %Include qgscoordinatereferencesystem.sip %Include qgscoordinatetransform.sip %Include qgscredentials.sip diff --git a/python/core/qgsconfigurationmap.sip b/python/core/qgsconfigurationmap.sip deleted file mode 100644 index 237a65631f1e..000000000000 --- a/python/core/qgsconfigurationmap.sip +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************** - qgsconfigurationmap.sip - QgsConfigurationMap - - --------------------- - begin : 11.11.2016 - copyright : (C) 2016 by Matthias Kuhn - email : matthias@opengis.ch - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ -class QgsConfigurationMap -{ -%TypeHeaderCode -#include "qgsconfigurationmap.h" -%End - - public: - QgsConfigurationMap(); - - QgsConfigurationMap( QVariantMap value ); - - QVariantMap get() const; - - void set( const QVariantMap& value ); - - void toXml( QDomElement& parentElement ) const; - - void fromXml( const QDomElement& element ); -}; diff --git a/python/core/qgsxmlutils.sip b/python/core/qgsxmlutils.sip index f784949af429..6476d7cdb5e1 100644 --- a/python/core/qgsxmlutils.sip +++ b/python/core/qgsxmlutils.sip @@ -28,4 +28,6 @@ class QgsXmlUtils static QDomElement writeMapUnits( QgsUnitTypes::DistanceUnit units, QDomDocument& doc ); static QDomElement writeRectangle( const QgsRectangle& rect, QDomDocument& doc ); + static QDomElement writeVariant( const QVariant& value, QDomDocument& doc ); + static QVariant readVariant( const QDomElement& element ); }; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c419f1a551ac..4994cce5454c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -97,7 +97,6 @@ SET(QGIS_CORE_SRCS qgscolorscheme.cpp qgscolorschemeregistry.cpp qgsconditionalstyle.cpp - qgsconfigurationmap.cpp qgscontexthelp.cpp qgscoordinatereferencesystem.cpp qgscoordinatetransform.cpp @@ -639,7 +638,6 @@ SET(QGIS_CORE_HDRS qgscolorramp.h qgscolorscheme.h qgscolorschemeregistry.h - qgsconfigurationmap.h qgsconnectionpool.h qgscontexthelp.h qgsconditionalstyle.h diff --git a/src/core/qgsconfigurationmap.cpp b/src/core/qgsconfigurationmap.cpp deleted file mode 100644 index 1ad64b944d99..000000000000 --- a/src/core/qgsconfigurationmap.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/*************************************************************************** - qgsconfigurationmap.cpp - QgsConfigurationMap - - --------------------- - begin : 11.11.2016 - copyright : (C) 2016 by Matthias Kuhn - email : matthias@opengis.ch - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ -#include "qgsconfigurationmap.h" -#include -#include "qgis.h" - -QgsConfigurationMap::QgsConfigurationMap() -{ - -} - -QgsConfigurationMap::QgsConfigurationMap( const QVariantMap& value ) - : mValue( value ) -{ -} - -QVariantMap QgsConfigurationMap::get() const -{ - return mValue; -} - -void QgsConfigurationMap::set( const QVariantMap& value ) -{ - mValue = value; -} - -void QgsConfigurationMap::toXml( QDomElement& parentElement ) const -{ - return toXml( parentElement, mValue ); -} - -void QgsConfigurationMap::fromXml( const QDomElement& element ) -{ - mValue = fromXmlHelper( element ).toMap(); -} - -void QgsConfigurationMap::toXml( QDomElement& parentElement, const QVariant& value ) const -{ - switch ( value.type() ) - { - case QVariant::Map: - { - QVariantMap map = value.toMap(); - - for ( auto option = map.constBegin(); option != map.constEnd(); ++option ) - { - QDomElement optionElement = parentElement.ownerDocument().createElement( "Option" ); - optionElement.setAttribute( "name", option.key() ); - toXml( optionElement, option.value() ); - parentElement.appendChild( optionElement ); - parentElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Map" ) ); - } - break; - } - - case QVariant::Int: - parentElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Int" ) ); - parentElement.setAttribute( QStringLiteral( "value" ), value.toString() ); - break; - - case QVariant::Bool: - parentElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Bool" ) ); - parentElement.setAttribute( QStringLiteral( "value" ), value.toString() ); - break; - - case QVariant::Double: - parentElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Double" ) ); - parentElement.setAttribute( QStringLiteral( "value" ), value.toString() ); - break; - - case QVariant::String: - parentElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "String" ) ); - parentElement.setAttribute( QStringLiteral( "value" ), value.toString() ); - break; - - default: - parentElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Unknown" ) ); - parentElement.setAttribute( QStringLiteral( "value" ), value.toString() ); - break; - } -} - -QVariant QgsConfigurationMap::fromXmlHelper( const QDomElement& element ) const -{ - QString type = element.attribute( QStringLiteral( "type" ) ); - - if ( type == QLatin1String( "Int" ) ) - { - return element.attribute( QStringLiteral( "value" ) ).toInt(); - } - else if ( type == QLatin1String( "Double" ) ) - { - return element.attribute( QStringLiteral( "value" ) ).toDouble(); - } - else if ( type == QLatin1String( "String" ) ) - { - return element.attribute( QStringLiteral( "value" ) ); - } - else if ( type == QLatin1String( "Bool" ) ) - { - return element.attribute( QStringLiteral( "value" ) ) == QLatin1String( "true" ); - } - else if ( type == QLatin1String( "Map" ) ) - { - QVariantMap map; - QDomNodeList options = element.childNodes(); - - for ( int i = 0; i < options.count(); ++i ) - { - QDomElement elem = options.at( i ).toElement(); - if ( elem.tagName() == QLatin1String( "Option" ) ) - map.insert( elem.attribute( QStringLiteral( "name" ) ), fromXmlHelper( elem ) ); - } - return map; - } - else - { - return QVariant(); - } -} diff --git a/src/core/qgsconfigurationmap.h b/src/core/qgsconfigurationmap.h deleted file mode 100644 index 3747fb786d54..000000000000 --- a/src/core/qgsconfigurationmap.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** - qgsconfigurationmap.h - QgsConfigurationMap - - --------------------- - begin : 11.11.2016 - copyright : (C) 2016 by Matthias Kuhn - email : matthias@opengis.ch - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ -#ifndef QGSCONFIGURATIONMAP_H -#define QGSCONFIGURATIONMAP_H - -#include -#include - -/** - * A configuration map holds a QVariantMap as a - * key-value store where each value can be a string, - * boolean, integer, double or yet another map. - * - * \note Added in QGIS 3.0 - * \ingroup core - */ - -class CORE_EXPORT QgsConfigurationMap -{ - public: - - /** - * Create a new empty configuration map - */ - QgsConfigurationMap(); - - /** - * Create a new configuration map from an existing - * QVariantMap. - */ - QgsConfigurationMap( const QVariantMap& value ); - - /** - * Get the content of this configuration map - * as QVariantMap. - */ - QVariantMap get() const; - - /** - * Set the content of this configuration map - * to a QVariantMap. - */ - void set( const QVariantMap& value ); - - /** - * Write this map into the provided parentElement. - * The attribute type of the parentElement will be - * used internally. - */ - void toXml( QDomElement& parentElement ) const; - - /** - * Read this map from the provided element. - */ - void fromXml( const QDomElement& element ); - - private: - QVariantMap mValue; - - void toXml( QDomElement& parentElement, const QVariant& value ) const; - - QVariant fromXmlHelper( const QDomElement& element ) const; -}; - -#endif // QGSCONFIGURATIONMAP_H diff --git a/src/core/qgsprojectfiletransform.cpp b/src/core/qgsprojectfiletransform.cpp index cd81cccef79a..6747eba8aa80 100644 --- a/src/core/qgsprojectfiletransform.cpp +++ b/src/core/qgsprojectfiletransform.cpp @@ -30,7 +30,7 @@ #include "qgsprojectproperty.h" #include "qgsrasterbandstats.h" #include "qgsrasterdataprovider.h" -#include "qgsconfigurationmap.h" +#include "qgsxmlutils.h" typedef QgsProjectVersion PFV; @@ -699,8 +699,7 @@ void QgsProjectFileTransform::transform2180to2990() editWidgetConfiguration.insert( QStringLiteral( "map" ), map ); } - QgsConfigurationMap editWidgetConfigurationMap( editWidgetConfiguration ); - editWidgetConfigurationMap.toXml( editWidgetConfigElement ); + editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( editWidgetConfiguration, mDom ) ); } } } diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index d2f1dd003fb5..4322acb1c931 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -82,7 +82,7 @@ #include "qgssimplifymethod.h" #include "qgsexpressioncontext.h" #include "qgsfeedback.h" -#include "qgsconfigurationmap.h" +#include "qgsxmlutils.h" #include "diagram/qgsdiagram.h" @@ -1847,9 +1847,9 @@ bool QgsVectorLayer::readSymbology( const QDomNode& layerNode, QString& errorMes const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) ); const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement(); - QgsConfigurationMap editWidgetConfiguration; - editWidgetConfiguration.fromXml( cfgElem ); - QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, editWidgetConfiguration.get() ); + const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement(); + QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap(); + QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap ); mFieldWidgetSetups[fieldName] = setup; } @@ -1997,7 +1997,7 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& editWidgetElement.setAttribute( "type", field.editorWidgetSetup().type() ); QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) ); - QgsConfigurationMap( widgetSetup.config() ).toXml( editWidgetConfigElement ); + editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config() , doc ) ); editWidgetElement.appendChild( editWidgetConfigElement ); // END TODO : wrap this part in an if to only save if it was user-modified diff --git a/src/core/qgsxmlutils.cpp b/src/core/qgsxmlutils.cpp index 1b00a7e8cadb..0236cd740d3a 100644 --- a/src/core/qgsxmlutils.cpp +++ b/src/core/qgsxmlutils.cpp @@ -99,3 +99,78 @@ QDomElement QgsXmlUtils::writeRectangle( const QgsRectangle& rect, QDomDocument& extentNode.appendChild( yMax ); return extentNode; } + +QDomElement QgsXmlUtils::writeVariant( const QVariant& value, QDomDocument& doc ) +{ + QDomElement element = doc.createElement( QStringLiteral( "Option" ) ); + switch ( value.type() ) + { + case QVariant::Map: + { + QVariantMap map = value.toMap(); + + for ( auto option = map.constBegin(); option != map.constEnd(); ++option ) + { + QDomElement optionElement = writeVariant( option.value(), doc ); + optionElement.setAttribute( QStringLiteral( "name" ), option.key() ); + element.appendChild( optionElement ); + element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Map" ) ); + } + break; + } + + case QVariant::Int: + case QVariant::Bool: + case QVariant::Double: + case QVariant::String: + element.setAttribute( QStringLiteral( "type" ), QVariant::typeToName( value.type() ) ); + element.setAttribute( QStringLiteral( "value" ), value.toString() ); + break; + + default: + element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "Unknown" ) ); + element.setAttribute( QStringLiteral( "value" ), value.toString() ); + break; + } + + return element; +} + +QVariant QgsXmlUtils::readVariant( const QDomElement& element ) +{ + QString type = element.attribute( QStringLiteral( "type" ) ); + + if ( type == QLatin1String( "int" ) ) + { + return element.attribute( QStringLiteral( "value" ) ).toInt(); + } + else if ( type == QLatin1String( "double" ) ) + { + return element.attribute( QStringLiteral( "value" ) ).toDouble(); + } + else if ( type == QLatin1String( "QString" ) ) + { + return element.attribute( QStringLiteral( "value" ) ); + } + else if ( type == QLatin1String( "bool" ) ) + { + return element.attribute( QStringLiteral( "value" ) ) == QLatin1String( "true" ); + } + else if ( type == QLatin1String( "Map" ) ) + { + QVariantMap map; + QDomNodeList options = element.childNodes(); + + for ( int i = 0; i < options.count(); ++i ) + { + QDomElement elem = options.at( i ).toElement(); + if ( elem.tagName() == QLatin1String( "Option" ) ) + map.insert( elem.attribute( QStringLiteral( "name" ) ), readVariant( elem ) ); + } + return map; + } + else + { + return QVariant(); + } +} diff --git a/src/core/qgsxmlutils.h b/src/core/qgsxmlutils.h index e2584ae7d115..40b0fbb4752c 100644 --- a/src/core/qgsxmlutils.h +++ b/src/core/qgsxmlutils.h @@ -52,6 +52,24 @@ class CORE_EXPORT QgsXmlUtils static QDomElement writeMapUnits( QgsUnitTypes::DistanceUnit units, QDomDocument& doc ); static QDomElement writeRectangle( const QgsRectangle& rect, QDomDocument& doc ); + + /** + * Write a QVariant to a QDomElement. + * + * Supported types are + * + * - QVariant::Map + * - QVariant::Int + * - QVariant::Double + * - QVariant::String + * + */ + static QDomElement writeVariant( const QVariant& value, QDomDocument& doc ); + + /** + * Read a QVariant from a QDomElement. + */ + static QVariant readVariant( const QDomElement& element ); }; diff --git a/src/providers/postgres/qgspostgresprovider.cpp b/src/providers/postgres/qgspostgresprovider.cpp index 5781e09690c4..87962cc68f74 100644 --- a/src/providers/postgres/qgspostgresprovider.cpp +++ b/src/providers/postgres/qgspostgresprovider.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -1039,9 +1039,7 @@ void QgsPostgresProvider::setEditorWidgets() QDomDocument doc; if ( doc.setContent( configTxt ) ) { - QgsConfigurationMap configMap; - configMap.fromXml( doc.documentElement() ); - config = configMap.get(); + config = QgsXmlUtils::readVariant( doc.documentElement() ).toMap(); } else { diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 29f9ea58118d..a5afff28276b 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -36,7 +36,7 @@ ADD_PYTHON_TEST(PyQgsComposerPolyline test_qgscomposerpolyline.py) ADD_PYTHON_TEST(PyQgsComposerView test_qgscomposerview.py) ADD_PYTHON_TEST(PyQgsComposition test_qgscomposition.py) ADD_PYTHON_TEST(PyQgsConditionalStyle test_qgsconditionalstyle.py) -ADD_PYTHON_TEST(PyQgsConfigurationMap test_qgsconfigurationmap.py) +ADD_PYTHON_TEST(PyQgsXmlUtils test_qgsxmlutils.py) ADD_PYTHON_TEST(PyQgsCoordinateTransform test_qgscoordinatetransform.py) ADD_PYTHON_TEST(PyQgsDateTimeStatisticalSummary test_qgsdatetimestatisticalsummary.py) ADD_PYTHON_TEST(PyQgsDelimitedTextProvider test_qgsdelimitedtextprovider.py) diff --git a/tests/src/python/test_qgsconfigurationmap.py b/tests/src/python/test_qgsconfigurationmap.py deleted file mode 100644 index 2662f175a9c8..000000000000 --- a/tests/src/python/test_qgsconfigurationmap.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- coding: utf-8 -*- -"""QGIS Unit tests for QgsConfigurationMap. - -.. note:: This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. -""" -__author__ = 'Matthias Kuhn' -__date__ = '18/11/2016' -__copyright__ = 'Copyright 2016, The QGIS Project' -# This will get replaced with a git SHA1 when you do a git archive -__revision__ = '$Format:%H$' - -import qgis # switch sip api - -from qgis.core import QgsConfigurationMap - -from qgis.PyQt.QtXml import ( - QDomDocument, - QDomElement -) - -from qgis.testing import ( - start_app, - unittest -) - -start_app() - - -class TestQgsConfigurationMap(unittest.TestCase): - - def create_doc(self): - doc = QDomDocument("properties") - element = doc.createElement("test") - doc.appendChild(element) - return (doc, element) - - def test_integer(self): - """ - Test that maps are correctly loaded and written - """ - doc, element = self.create_doc() - - my_properties = {'a': 1, 'b': 2, 'c': 3, 'd': -1} - prop = QgsConfigurationMap(my_properties) - prop.toXml(element) - - self.assertEquals(prop.get(), my_properties) - - prop2 = QgsConfigurationMap() - - prop2.fromXml(element) - self.assertEquals(my_properties, prop2.get()) - - def test_string(self): - """ - Test that maps are correctly loaded and written - """ - doc, element = self.create_doc() - - my_properties = {'a': 'a', 'b': 'b', 'c': 'something_else', 'empty': ''} - prop = QgsConfigurationMap(my_properties) - prop.toXml(element) - - self.assertEquals(prop.get(), my_properties) - - prop2 = QgsConfigurationMap() - - prop2.fromXml(element) - self.assertEquals(my_properties, prop2.get()) - - def test_double(self): - """ - Test that maps are correctly loaded and written - """ - doc, element = self.create_doc() - - my_properties = {'a': 0.27, 'b': 1.0, 'c': 5} - prop = QgsConfigurationMap(my_properties) - prop.toXml(element) - - self.assertEquals(prop.get(), my_properties) - - prop2 = QgsConfigurationMap() - - prop2.fromXml(element) - self.assertEquals(my_properties, prop2.get()) - - def test_boolean(self): - """ - Test that maps are correctly loaded and written - """ - doc, element = self.create_doc() - - my_properties = {'a': True, 'b': False} - prop = QgsConfigurationMap(my_properties) - prop.toXml(element) - - print(doc.toString()) - - self.assertEquals(prop.get(), my_properties) - - prop2 = QgsConfigurationMap() - - prop2.fromXml(element) - self.assertEquals(my_properties, prop2.get()) - - def test_complex(self): - """ - Test that maps are correctly loaded and written - """ - doc, element = self.create_doc() - - my_properties = {'boolean': True, 'integer': False, 'map': {'a': 1}} - prop = QgsConfigurationMap(my_properties) - prop.toXml(element) - - print(doc.toString()) - - self.assertEquals(prop.get(), my_properties) - - prop2 = QgsConfigurationMap() - - prop2.fromXml(element) - self.assertEquals(my_properties, prop2.get()) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/src/python/test_qgsxmlutils.py b/tests/src/python/test_qgsxmlutils.py new file mode 100644 index 000000000000..ea7f1c5f2a91 --- /dev/null +++ b/tests/src/python/test_qgsxmlutils.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +"""QGIS Unit tests for QgsXmlUtils. + +.. note:: This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +""" +__author__ = 'Matthias Kuhn' +__date__ = '18/11/2016' +__copyright__ = 'Copyright 2016, The QGIS Project' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +import qgis # switch sip api + +from qgis.core import QgsXmlUtils + +from qgis.PyQt.QtXml import ( + QDomDocument, + QDomElement +) + +from qgis.testing import ( + start_app, + unittest +) + +start_app() + + +class TestQgsXmlUtils(unittest.TestCase): + + def test_integer(self): + """ + Test that maps are correctly loaded and written + """ + doc = QDomDocument("properties") + + my_properties = {'a': 1, 'b': 2, 'c': 3, 'd': -1} + elem = QgsXmlUtils.writeVariant(my_properties, doc) + + prop2 = QgsXmlUtils.readVariant(elem) + self.assertEquals(my_properties, prop2) + + def test_string(self): + """ + Test that maps are correctly loaded and written + """ + doc = QDomDocument("properties") + + my_properties = {'a': 'a', 'b': 'b', 'c': 'something_else', 'empty': ''} + elem = QgsXmlUtils.writeVariant(my_properties, doc) + + prop2 = QgsXmlUtils.readVariant(elem) + + self.assertEquals(my_properties, prop2) + + def test_double(self): + """ + Test that maps are correctly loaded and written + """ + doc = QDomDocument("properties") + + my_properties = {'a': 0.27, 'b': 1.0, 'c': 5} + elem = QgsXmlUtils.writeVariant(my_properties, doc) + + prop2 = QgsXmlUtils.readVariant(elem) + + self.assertEquals(my_properties, prop2) + + def test_boolean(self): + """ + Test that maps are correctly loaded and written + """ + doc = QDomDocument("properties") + + my_properties = {'a': True, 'b': False} + elem = QgsXmlUtils.writeVariant(my_properties, doc) + + prop2 = QgsXmlUtils.readVariant(elem) + + self.assertEquals(my_properties, prop2) + + def test_complex(self): + """ + Test that maps are correctly loaded and written + """ + doc = QDomDocument("properties") + + my_properties = {'boolean': True, 'integer': False, 'map': {'a': 1}} + elem = QgsXmlUtils.writeVariant(my_properties, doc) + + prop2 = QgsXmlUtils.readVariant(elem) + + self.assertEquals(my_properties, prop2) + + +if __name__ == '__main__': + unittest.main()