Skip to content

Commit

Permalink
Merge pull request #2492 from SebDieBln/NoCopyPasteOnDuplicateLayer
Browse files Browse the repository at this point in the history
[Bugfix] Avoid using copyStyle() / pasteStyle() within duplicateLayers()
  • Loading branch information
nyalldawson committed Jan 12, 2016
2 parents 9dccce8 + 7b5c96c commit d01307f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 63 deletions.
72 changes: 16 additions & 56 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6941,39 +6941,12 @@ void QgisApp::copyStyle( QgsMapLayer * sourceLayer )

if ( selectionLayer )
{
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
"qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( "qgis" );
rootNode.setAttribute( "version", QString( "%1" ).arg( QGis::QGIS_VERSION ) );
doc.appendChild( rootNode );
QString errorMsg;
QDomDocument doc( "qgis" );
selectionLayer->exportNamedStyle( doc, errorMsg );

rootNode.setAttribute( "hasScaleBasedVisibilityFlag", selectionLayer->hasScaleBasedVisibility() ? 1 : 0 );
rootNode.setAttribute( "minimumScale", QString::number( selectionLayer->minimumScale() ) );
rootNode.setAttribute( "maximumScale", QString::number( selectionLayer->maximumScale() ) );

/*
* Check to see if the layer is vector - in which case we should also copy its geometryType
* to avoid eventually pasting to a layer with a different geometry
*/
if ( selectionLayer->type() == 0 )
{
//Getting the selectionLayer geometry
QgsVectorLayer *SelectionGeometry = static_cast<QgsVectorLayer*>( selectionLayer );
QString geoType = QString::number( SelectionGeometry->geometryType() );

//Adding geometryinformation
QDomElement layerGeometryType = doc.createElement( "layerGeometryType" );
QDomText type = doc.createTextNode( geoType );

layerGeometryType.appendChild( type );
rootNode.appendChild( layerGeometryType );
}

QString errorMsg;
if ( !selectionLayer->writeSymbology( rootNode, doc, errorMsg ) )
if ( !errorMsg.isEmpty() )
{
messageBar()->pushMessage( errorMsg,
tr( "Cannot copy style: %1" ),
Expand All @@ -6987,7 +6960,7 @@ void QgisApp::copyStyle( QgsMapLayer * sourceLayer )
}
}
/**
\param destinatioLayer The layer that the clipboard will be pasted to
\param destinationLayer The layer that the clipboard will be pasted to
(defaults to the active layer on the legend)
*/

Expand All @@ -7011,34 +6984,14 @@ void QgisApp::pasteStyle( QgsMapLayer * destinationLayer )
return;
}

QDomElement rootNode = doc.firstChildElement( "qgis" );

//Test for matching geometry type on vector layers when pasting
if ( selectionLayer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer *selectionVectorLayer = static_cast<QgsVectorLayer*>( selectionLayer );
int pasteLayerGeometryType = doc.elementsByTagName( "layerGeometryType" ).item( 0 ).toElement().text().toInt();
if ( selectionVectorLayer->geometryType() != pasteLayerGeometryType )
{
messageBar()->pushMessage( tr( "Cannot paste style to layer with a different geometry type" ),
tr( "Your copied style does not match the layer you are pasting to" ),
QgsMessageBar::INFO, messageTimeout() );
return;
}
}

if ( !selectionLayer->readSymbology( rootNode, errorMsg ) )
if ( !selectionLayer->importNamedStyle( doc, errorMsg ) )
{
messageBar()->pushMessage( errorMsg,
tr( "Cannot read style: %1" ),
tr( "Cannot paste style: %1" ),
QgsMessageBar::CRITICAL, messageTimeout() );
return;
}

selectionLayer->setScaleBasedVisibility( rootNode.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
selectionLayer->setMinimumScale( rootNode.attribute( "minimumScale" ).toFloat() );
selectionLayer->setMaximumScale( rootNode.attribute( "maximumScale" ).toFloat() );

mLayerTreeView->refreshLayerSymbology( selectionLayer->id() );
mMapCanvas->clearCache();
mMapCanvas->refresh();
Expand Down Expand Up @@ -7704,8 +7657,15 @@ void QgisApp::duplicateLayers( const QList<QgsMapLayer *>& lyrList )
nodeDupLayer->setVisible( Qt::Unchecked );

// duplicate the layer style
copyStyle( selectedLyr );
pasteStyle( dupLayer );
QString errMsg;
QDomDocument style;
selectedLyr->exportNamedStyle( style, errMsg );
if ( errMsg.isEmpty() )
dupLayer->importNamedStyle( style, errMsg );
if ( !errMsg.isEmpty() )
messageBar()->pushMessage( errMsg,
tr( "Cannot copy style to duplicated layer." ),
QgsMessageBar::CRITICAL, messageTimeout() );

QgsVectorLayer* vLayer = dynamic_cast<QgsVectorLayer*>( selectedLyr );
QgsVectorLayer* vDupLayer = dynamic_cast<QgsVectorLayer*>( dupLayer );
Expand Down
43 changes: 36 additions & 7 deletions src/core/qgsmaplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1174,8 +1174,15 @@ QString QgsMapLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag

bool QgsMapLayer::importNamedStyle( QDomDocument& myDocument, QString& myErrorMessage )
{
QDomElement myRoot = myDocument.firstChildElement( "qgis" );
if ( myRoot.isNull() )
{
myErrorMessage = tr( "Root <qgis> element could not be found" );
return false;
}

// get style file version string, if any
QgsProjectVersion fileVersion( myDocument.firstChildElement( "qgis" ).attribute( "version" ) );
QgsProjectVersion fileVersion( myRoot.attribute( "version" ) );
QgsProjectVersion thisVersion( QGis::QGIS_VERSION );

if ( thisVersion > fileVersion )
Expand All @@ -1191,13 +1198,16 @@ bool QgsMapLayer::importNamedStyle( QDomDocument& myDocument, QString& myErrorMe
// styleFile.dump();
}

// now get the layer node out and pass it over to the layer
// to deserialise...
QDomElement myRoot = myDocument.firstChildElement( "qgis" );
if ( myRoot.isNull() )
//Test for matching geometry type on vector layers when applying, if geometry type is given in the style
if ( type() == QgsMapLayer::VectorLayer && !myRoot.firstChildElement( "layerGeometryType" ).isNull() )
{
myErrorMessage = tr( "Root <qgis> element could not be found" );
return false;
QgsVectorLayer *vl = static_cast<QgsVectorLayer*>( this );
int importLayerGeometryType = myRoot.firstChildElement( "layerGeometryType" ).text().toInt();
if ( vl->geometryType() != importLayerGeometryType )
{
myErrorMessage = tr( "Cannot apply style to layer with a different geometry type" );
return false;
}
}

// use scale dependent visibility flag
Expand Down Expand Up @@ -1247,6 +1257,25 @@ void QgsMapLayer::exportNamedStyle( QDomDocument &doc, QString &errorMsg )
errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
return;
}

/*
* Check to see if the layer is vector - in which case we should also export its geometryType
* to avoid eventually pasting to a layer with a different geometry
*/
if ( type() == QgsMapLayer::VectorLayer )
{
//Getting the selectionLayer geometry
QgsVectorLayer *vl = static_cast<QgsVectorLayer*>( this );
QString geoType = QString::number( vl->geometryType() );

//Adding geometryinformation
QDomElement layerGeometryType = myDocument.createElement( "layerGeometryType" );
QDomText type = myDocument.createTextNode( geoType );

layerGeometryType.appendChild( type );
myRootNode.appendChild( layerGeometryType );
}

doc = myDocument;
}

Expand Down

0 comments on commit d01307f

Please sign in to comment.