diff --git a/python/core/auto_generated/qgsmaplayer.sip.in b/python/core/auto_generated/qgsmaplayer.sip.in index e8ebda602da0..cf9181401173 100644 --- a/python/core/auto_generated/qgsmaplayer.sip.in +++ b/python/core/auto_generated/qgsmaplayer.sip.in @@ -1237,7 +1237,7 @@ Returns true if the refresh on provider nofification is enabled .. versionadded:: 3.0 %End - QString originalXmlProperties() const; + QDomDocument originalXmlProperties() const; %Docstring Returns the XML properties of the original layer as they were when the layer was first read from the project file. In case of new layers this is normally empty. @@ -1247,7 +1247,7 @@ The storage format for the XML is qlr .. versionadded:: 3.6 %End - void setOriginalXmlProperties( const QString &originalXmlProperties ); + void setOriginalXmlProperties( const QDomDocument &originalXmlProperties ); %Docstring Sets the original XML properties for the layer to ``originalXmlProperties`` diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 2a9c15ff869e..a4d340a2e865 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -6955,26 +6955,17 @@ void QgisApp::changeDataSource( QgsMapLayer *layer ) bool layerIsValid( layer->isValid() ); layer->setDataSource( uri.uri, layer->name(), uri.providerKey, QgsDataProvider::ProviderOptions() ); // Re-apply style - if ( !( layerIsValid || layer->originalXmlProperties().isEmpty() ) ) + if ( !( layerIsValid || layer->originalXmlProperties().isNull() ) ) { QgsReadWriteContext context; context.setPathResolver( QgsProject::instance()->pathResolver() ); context.setProjectTranslator( QgsProject::instance() ); QString errorMsg; - QDomDocument doc; - if ( doc.setContent( layer->originalXmlProperties() ) ) + QDomDocument doc( layer->originalXmlProperties() ); + QDomNode layer_node( doc.firstChild( ) ); + if ( ! layer->readSymbology( layer_node, errorMsg, context ) ) { - QDomNode layer_node( doc.firstChild( ) ); - if ( ! layer->readSymbology( layer_node, errorMsg, context ) ) - { - QgsDebugMsg( QStringLiteral( "Failed to restore original layer style from stored XML for layer %1: %2" ) - .arg( layer->name( ) ) - .arg( errorMsg ) ); - } - } - else - { - QgsDebugMsg( QStringLiteral( "Failed to create XML QDomDocument for layer %1: %2" ) + QgsDebugMsg( QStringLiteral( "Failed to restore original layer style from stored XML for layer %1: %2" ) .arg( layer->name( ) ) .arg( errorMsg ) ); } diff --git a/src/core/layertree/qgslayertreeutils.cpp b/src/core/layertree/qgslayertreeutils.cpp index 98b2f14d3b39..b6a13235467f 100644 --- a/src/core/layertree/qgslayertreeutils.cpp +++ b/src/core/layertree/qgslayertreeutils.cpp @@ -329,10 +329,7 @@ void QgsLayerTreeUtils::storeOriginalLayersProperties( QgsLayerTreeGroup *group, QDomDocument document( documentType ); QDomElement element = mlNode.toElement(); document.appendChild( element ); - QString str; - QTextStream stream( &str ); - document.save( stream, 4 /*indent*/ ); - l->setOriginalXmlProperties( str ); + l->setOriginalXmlProperties( document ); } } } diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp index f452d40ad5e3..8d7b83d8076d 100644 --- a/src/core/qgsmaplayer.cpp +++ b/src/core/qgsmaplayer.cpp @@ -1833,12 +1833,12 @@ bool QgsMapLayer::isReadOnly() const return true; } -QString QgsMapLayer::originalXmlProperties() const +QDomDocument QgsMapLayer::originalXmlProperties() const { return mOriginalXmlProperties; } -void QgsMapLayer::setOriginalXmlProperties( const QString &originalXmlProperties ) +void QgsMapLayer::setOriginalXmlProperties( const QDomDocument &originalXmlProperties ) { mOriginalXmlProperties = originalXmlProperties; } diff --git a/src/core/qgsmaplayer.h b/src/core/qgsmaplayer.h index 00f53ef5ed71..fcc1674fb5f5 100644 --- a/src/core/qgsmaplayer.h +++ b/src/core/qgsmaplayer.h @@ -1109,7 +1109,7 @@ class CORE_EXPORT QgsMapLayer : public QObject * * \since QGIS 3.6 */ - QString originalXmlProperties() const; + QDomDocument originalXmlProperties() const; /** * Sets the original XML properties for the layer to \a originalXmlProperties @@ -1118,7 +1118,7 @@ class CORE_EXPORT QgsMapLayer : public QObject * * \since QGIS 3.6 */ - void setOriginalXmlProperties( const QString &originalXmlProperties ); + void setOriginalXmlProperties( const QDomDocument &originalXmlProperties ); public slots: @@ -1529,7 +1529,7 @@ class CORE_EXPORT QgsMapLayer : public QObject * * This information can be used to pass through the bad layers or to reset changes on a good layer */ - QString mOriginalXmlProperties; + QDomDocument mOriginalXmlProperties; }; diff --git a/src/core/qgsproject.cpp b/src/core/qgsproject.cpp index 20c04f18ce5f..53efc3f86e6b 100644 --- a/src/core/qgsproject.cpp +++ b/src/core/qgsproject.cpp @@ -1774,17 +1774,10 @@ bool QgsProject::writeProjectFile( const QString &filename ) maplayerElem = doc->createElement( QStringLiteral( "maplayer" ) ); ml->writeLayerXml( maplayerElem, *doc, context ); } - else if ( ! ml->originalXmlProperties().isEmpty() ) + else if ( ! ml->originalXmlProperties().isNull() ) { - QDomDocument document; - if ( document.setContent( ml->originalXmlProperties() ) ) - { - maplayerElem = document.firstChildElement(); - } - else - { - QgsDebugMsg( QStringLiteral( "Could not restore layer properties for layer %1" ).arg( ml->id() ) ); - } + QDomDocument document( ml->originalXmlProperties() ); + maplayerElem = document.firstChildElement(); } emit writeMapLayer( ml, maplayerElem, *doc ); diff --git a/tests/src/python/test_qgsprojectbadlayers.py b/tests/src/python/test_qgsprojectbadlayers.py index 75a4d0a33a6e..0b94ad7e5b29 100644 --- a/tests/src/python/test_qgsprojectbadlayers.py +++ b/tests/src/python/test_qgsprojectbadlayers.py @@ -35,6 +35,7 @@ from qgis.PyQt.QtGui import QFont, QColor from qgis.PyQt.QtTest import QSignalSpy from qgis.PyQt.QtCore import QT_VERSION_STR, QTemporaryDir, QSize +from qgis.PyQt.QtXml import QDomDocument, QDomNode, QDomImplementation from qgis.testing import start_app, unittest from utilities import (unitTestDataPath, renderMapToImage) @@ -99,8 +100,12 @@ def test_project_roundtrip(self): self.assertTrue(raster.originalXmlProperties() != '') self.assertTrue(raster_copy.originalXmlProperties() != '') # Test setter - raster.setOriginalXmlProperties('pippo') - self.assertEqual(raster.originalXmlProperties(), 'pippo') + domimp = QDomImplementation() + documentType = domimp.createDocumentType("qgis", "http://mrcc.com/qgis.dtd", "SYSTEM") + document = QDomDocument(documentType) + document.setContent("pluto") + raster.setOriginalXmlProperties(document) + self.assertEqual(raster.originalXmlProperties(), document) # Now create and invalid project: bad_project_path = os.path.join(temp_dir.path(), 'project_bad.qgs') @@ -144,7 +149,7 @@ def test_project_roundtrip(self): self.assertTrue(raster_copy.isValid()) def test_project_relations(self): - """Tests that a project with bad layers and relations can be saved with relations""" + """Tests that a project with bad layers and relations can be maintained""" temp_dir = QTemporaryDir() p = QgsProject.instance() @@ -235,7 +240,6 @@ def testStyles(self): p = QgsProject.instance() project_path = os.path.join(temp_dir.path(), 'good_layers_test.qgs') copyfile(os.path.join(TEST_DATA_DIR, 'projects', 'good_layers_test.qgs'), project_path) - copyfile(os.path.join(TEST_DATA_DIR, 'projects', 'bad_layers_test.gpkg'), os.path.join(temp_dir.path(), 'bad_layers_test.gpkg')) for f in ( 'bad_layer_raster_test.tfw', 'bad_layer_raster_test.tiff',