Skip to content

Commit

Permalink
OriginalXmlProperties optimization
Browse files Browse the repository at this point in the history
Dramatic speed improvement in XML original properties storage.

The original implementation used a call to QDomNodeList::count() method
that calls QDomNodeListPrivate::createList() -> DETACH!

By using a while loop we prevent the detach and it's more than 10 times faster.

(cherry picked from commit a3b4a48)
  • Loading branch information
elpaso authored and nyalldawson committed Dec 21, 2020
1 parent 86374a1 commit cf34d22
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 9 deletions.
16 changes: 8 additions & 8 deletions src/core/layertree/qgslayertreeutils.cpp
Expand Up @@ -314,9 +314,8 @@ void QgsLayerTreeUtils::removeInvalidLayers( QgsLayerTreeGroup *group )

void QgsLayerTreeUtils::storeOriginalLayersProperties( QgsLayerTreeGroup *group, const QDomDocument *doc )
{
const QDomNodeList mlNodeList( doc->documentElement()
.firstChildElement( QStringLiteral( "projectlayers" ) )
.elementsByTagName( QStringLiteral( "maplayer" ) ) );

const QDomElement projectLayersElement { doc->documentElement().firstChildElement( QStringLiteral( "projectlayers" ) ) };

std::function<void ( QgsLayerTreeNode * )> _store = [ & ]( QgsLayerTreeNode * node )
{
Expand All @@ -325,22 +324,23 @@ void QgsLayerTreeUtils::storeOriginalLayersProperties( QgsLayerTreeGroup *group,
QgsMapLayer *l( QgsLayerTree::toLayer( node )->layer() );
if ( l )
{
for ( int i = 0; i < mlNodeList.count(); i++ )
QDomElement layerElement { projectLayersElement.firstChildElement( QStringLiteral( "maplayer" ) ) };
while ( ! layerElement.isNull() )
{
QDomNode mlNode( mlNodeList.at( i ) );
QString id( mlNode.firstChildElement( QStringLiteral( "id" ) ).firstChild().nodeValue() );
const QString id( layerElement.firstChildElement( QStringLiteral( "id" ) ).firstChild().nodeValue() );
if ( id == l->id() )
{
QDomImplementation DomImplementation;
QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument document( documentType );
QDomElement element = mlNode.toElement();
document.appendChild( element );
document.appendChild( layerElement );
QString str;
QTextStream stream( &str );
document.save( stream, 4 /*indent*/ );
l->setOriginalXmlProperties( str );
break;
}
layerElement = layerElement.nextSiblingElement( );
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsproject.cpp
Expand Up @@ -1663,6 +1663,7 @@ bool QgsProject::readProjectFile( const QString &filename, QgsProject::ReadFlags
// or wanted to pass them through when saving
if ( !( flags & QgsProject::ReadFlag::FlagDontStoreOriginalStyles ) )
{
profile.switchTask( tr( "Storing original layer properties" ) );
QgsLayerTreeUtils::storeOriginalLayersProperties( mRootGroup, doc.get() );
}

Expand Down
2 changes: 1 addition & 1 deletion tests/src/python/test_qgsprojectbadlayers.py
Expand Up @@ -129,7 +129,7 @@ def test_project_roundtrip(self):
raster.setOriginalXmlProperties('pippo')
self.assertEqual(raster.originalXmlProperties(), 'pippo')

# Now create and invalid project:
# Now create an invalid project:
bad_project_path = os.path.join(temp_dir.path(), 'project_bad.qgs')
with open(project_path, 'r') as infile:
with open(bad_project_path, 'w+') as outfile:
Expand Down

0 comments on commit cf34d22

Please sign in to comment.