* Save and restore visiblity state of embedded group layers (fixes #4097)

* Adds support for lists in custom properties
This commit is contained in:
Juergen E. Fischer 2015-01-13 14:51:16 +01:00
parent 3711fd5899
commit b49da36c7f
8 changed files with 87 additions and 22 deletions

View File

@ -11,11 +11,11 @@ class QgsLayerTreeUtils
public:
//! Try to load layer tree from <legend> tag from project files from QGIS 2.2 and below
//! Try to load layer tree from \verbatim <legend> \endverbatim tag from project files from QGIS 2.2 and below
static bool readOldLegend( QgsLayerTreeGroup* root, const QDomElement& legendElem );
//! Try to load custom layer order from <legend> tag from project files from QGIS 2.2 and below
//! Try to load custom layer order from \verbatim <legend> \endverbatim tag from project files from QGIS 2.2 and below
static bool readOldLegendLayerOrder( const QDomElement& legendElem, bool& hasCustomOrder, QStringList& order );
//! Return <legend> tag used in QGIS 2.2 and below
//! Return \verbatim <legend> \endverbatim tag used in QGIS 2.2 and below
static QDomElement writeOldLegend( QDomDocument& doc, QgsLayerTreeGroup* root, bool hasCustomOrder, const QStringList& order );
//! Convert Qt::CheckState to QString
@ -31,7 +31,10 @@ class QgsLayerTreeUtils
//! Remove layer nodes that refer to invalid layers
static void removeInvalidLayers( QgsLayerTreeGroup* group );
//! Remove subtree of embedded groups. Useful when saving layer tree
static void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );
//! Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers
static void replaceChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );
//! get invisible layers
static QStringList invisibleLayerList( QgsLayerTreeNode *node );
};

View File

@ -252,10 +252,11 @@ class QgsProject : QObject
bool createEmbeddedLayer( const QString& layerId, const QString& projectFilePath, QList<QDomNode>& brokenNodes,
QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList, bool saveFlag = true );
*/
/** Create layer group instance defined in an arbitrary project file.
* @note: added in version 2.4
*/
QgsLayerTreeGroup* createEmbeddedGroup( const QString& groupName, const QString& projectFilePath );
QgsLayerTreeGroup* createEmbeddedGroup( const QString& groupName, const QString& projectFilePath, const QStringList &invisibleLayers );
/** Convenience function to set snap settings per layer */
void setSnapSettingsForLayer( const QString& layerId, bool enabled, QgsSnapper::SnappingType type, QgsTolerance::UnitType unit, double tolerance,
@ -305,9 +306,6 @@ class QgsProject : QObject
//! @note not available in python bindings
// void loadEmbeddedNodes( QgsLayerTreeGroup* group );
//! @note not available in python bindings
// void updateEmbeddedGroupsProjectPath( QgsLayerTreeGroup* group );
signals:
//! emitted when project is being read
void readProject( const QDomDocument & );

View File

@ -7958,7 +7958,7 @@ void QgisApp::embedLayers()
QStringList::const_iterator groupIt = groups.constBegin();
for ( ; groupIt != groups.constEnd(); ++groupIt )
{
QgsLayerTreeGroup* newGroup = QgsProject::instance()->createEmbeddedGroup( *groupIt, projectFile );
QgsLayerTreeGroup* newGroup = QgsProject::instance()->createEmbeddedGroup( *groupIt, projectFile, QStringList() );
if ( newGroup )
QgsProject::instance()->layerTreeRoot()->addChildNode( newGroup );
@ -9935,7 +9935,7 @@ void QgisApp::writeProject( QDomDocument &doc )
// can be opened in older versions of QGIS without loosing information about layer groups.
QgsLayerTreeNode* clonedRoot = QgsProject::instance()->layerTreeRoot()->clone();
QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
QgsLayerTreeUtils::updateEmbeddedGroupsProjectPath( QgsLayerTree::toGroup( clonedRoot ) ); // convert absolute paths to relative paths if required
QDomElement oldLegendElem = QgsLayerTreeUtils::writeOldLegend( doc, QgsLayerTree::toGroup( clonedRoot ),
mLayerTreeCanvasBridge->hasCustomLayerOrder(), mLayerTreeCanvasBridge->customLayerOrder() );

View File

@ -304,16 +304,43 @@ void QgsLayerTreeUtils::removeInvalidLayers( QgsLayerTreeGroup* group )
group->removeChildNode( node );
}
void QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group )
QStringList QgsLayerTreeUtils::invisibleLayerList( QgsLayerTreeNode *node )
{
QStringList list;
if ( QgsLayerTree::isGroup( node ) )
{
foreach ( QgsLayerTreeNode *child, QgsLayerTree::toGroup( node )->children() )
{
list << invisibleLayerList( child );
}
}
else if ( QgsLayerTree::isLayer( node ) )
{
QgsLayerTreeLayer *layer = QgsLayerTree::toLayer( node );
if ( !layer->isVisible() )
list << layer->layerId();
}
return list;
}
void QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group )
{
foreach ( QgsLayerTreeNode* child, group->children() )
{
if ( QgsLayerTree::isGroup( child ) )
{
if ( child->customProperty( "embedded" ).toInt() )
{
child->setCustomProperty( "embedded-invisible-layers", invisibleLayerList( child ) );
QgsLayerTree::toGroup( child )->removeAllChildren();
}
else
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
{
replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
}
}
}
}

View File

@ -23,6 +23,7 @@ class QDomElement;
class QDomDocument;
class QStringList;
class QgsLayerTreeNode;
class QgsLayerTreeGroup;
class QgsLayerTreeLayer;
@ -55,12 +56,14 @@ class CORE_EXPORT QgsLayerTreeUtils
//! Remove layer nodes that refer to invalid layers
static void removeInvalidLayers( QgsLayerTreeGroup* group );
//! Remove subtree of embedded groups. Useful when saving layer tree
static void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );
//! Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers
static void replaceChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );
//! @note not available in python bindings
static void updateEmbeddedGroupsProjectPath( QgsLayerTreeGroup* group );
//! get invisible layers
static QStringList invisibleLayerList( QgsLayerTreeNode *node );
};
#endif // QGSLAYERTREEUTILS_H

View File

@ -88,8 +88,24 @@ void QgsObjectCustomProperties::readXml( const QDomNode& parentNode, const QStri
QString key = propElement.attribute( "key" );
if ( key.isEmpty() || key.startsWith( keyStartsWith ) )
{
QString value = propElement.attribute( "value" );
mMap[key] = QVariant( value );
if ( propElement.hasAttribute( "value" ) )
{
QString value = propElement.attribute( "value" );
mMap[key] = QVariant( value );
}
else
{
QStringList list;
for ( QDomElement itemElement = propElement.firstChildElement( "value" );
!itemElement.isNull();
itemElement = itemElement.nextSiblingElement( "value" ) )
{
list << itemElement.text();
}
mMap[key] = QVariant( list );
}
}
}
@ -110,7 +126,19 @@ void QgsObjectCustomProperties::writeXml( QDomNode& parentNode, QDomDocument& do
{
QDomElement propElement = doc.createElement( "property" );
propElement.setAttribute( "key", it.key() );
propElement.setAttribute( "value", it.value().toString() );
if ( it.value().canConvert<QString>() )
{
propElement.setAttribute( "value", it.value().toString() );
}
else if ( it.value().canConvert<QStringList>() )
{
foreach ( QString value, it.value().toStringList() )
{
QDomElement itemElement = doc.createElement( "value" );
itemElement.appendChild( doc.createTextNode( value ) );
propElement.appendChild( itemElement );
}
}
propsElement.appendChild( propElement );
}

View File

@ -974,7 +974,7 @@ void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup* group )
QString projectPath = readPath( childGroup->customProperty( "embedded_project" ).toString() );
childGroup->setCustomProperty( "embedded_project", projectPath );
QgsLayerTreeGroup* newGroup = createEmbeddedGroup( childGroup->name(), projectPath );
QgsLayerTreeGroup* newGroup = createEmbeddedGroup( childGroup->name(), projectPath, childGroup->customProperty( "embedded-invisible-layers" ).toStringList() );
if ( newGroup )
{
QList<QgsLayerTreeNode*> clonedChildren;
@ -1083,7 +1083,7 @@ bool QgsProject::write()
// write layer tree - make sure it is without embedded subgroups
QgsLayerTreeNode* clonedRoot = mRootGroup->clone();
QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
QgsLayerTreeUtils::updateEmbeddedGroupsProjectPath( QgsLayerTree::toGroup( clonedRoot ) ); // convert absolute paths to relative paths if required
clonedRoot->writeXML( qgisNode );
delete clonedRoot;
@ -1794,7 +1794,7 @@ bool QgsProject::createEmbeddedLayer( const QString& layerId, const QString& pro
}
QgsLayerTreeGroup* QgsProject::createEmbeddedGroup( const QString& groupName, const QString& projectFilePath )
QgsLayerTreeGroup* QgsProject::createEmbeddedGroup( const QString& groupName, const QString& projectFilePath, const QStringList &invisibleLayers )
{
//open project file, get layer ids in group, add the layers
QFile projectFile( projectFilePath );
@ -1863,6 +1863,12 @@ QgsLayerTreeGroup* QgsProject::createEmbeddedGroup( const QString& groupName, co
thisProjectIdentifyDisabledLayers.append( layerId );
QgsProject::instance()->writeEntry( "Identify", "/disabledLayers", thisProjectIdentifyDisabledLayers );
}
QgsLayerTreeLayer *layer = newGroup->findLayer( layerId );
if ( layer )
{
layer->setVisible( invisibleLayers.contains( layerId ) ? Qt::Unchecked : Qt::Checked );
}
}
return newGroup;

View File

@ -299,7 +299,7 @@ class CORE_EXPORT QgsProject : public QObject
/** Create layer group instance defined in an arbitrary project file.
* @note: added in version 2.4
*/
QgsLayerTreeGroup* createEmbeddedGroup( const QString& groupName, const QString& projectFilePath );
QgsLayerTreeGroup* createEmbeddedGroup( const QString& groupName, const QString& projectFilePath, const QStringList &invisibleLayers );
/** Convenience function to set snap settings per layer */
void setSnapSettingsForLayer( const QString& layerId, bool enabled, QgsSnapper::SnappingType type, QgsTolerance::UnitType unit, double tolerance,