Skip to content

Commit

Permalink
Add layer tree support into QgsProject
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed May 21, 2014
1 parent 1fecde4 commit de146fb
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 50 deletions.
4 changes: 1 addition & 3 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3201,9 +3201,7 @@ void QgisApp::fileNew( bool thePromptToSaveFlag, bool forceBlank )
closeProject();

QgsProject* prj = QgsProject::instance();
prj->title( QString::null );
prj->setFileName( QString::null );
prj->clearProperties(); // why carry over properties from previous projects?
prj->clear();

//set the color for selections
//the default can be set in qgisoptions
Expand Down
32 changes: 24 additions & 8 deletions src/core/layertree/qgslayertreenode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
QgsLayerTreeNode* QgsLayerTreeNode::readXML(QDomElement& element)
{
QgsLayerTreeNode* node = 0;
if (element.tagName() == "tree-group")
if (element.tagName() == "layer-tree-group")
node = QgsLayerTreeGroup::readXML(element);
else if (element.tagName() == "tree-layer")
else if (element.tagName() == "layer-tree-layer")
node = QgsLayerTreeLayer::readXML(element);

return node;
Expand Down Expand Up @@ -129,8 +129,8 @@ void QgsLayerTreeGroup::connectToChildNode(QgsLayerTreeNode* node)
if (node->nodeType() == QgsLayerTreeNode::NodeLayer)
{
// TODO: this could be handled directly by LayerTreeLayer by listening to QgsMapLayerRegistry...
QgsLayerTreeLayer* nodeLayer = static_cast<QgsLayerTreeLayer*>(node);
connect(nodeLayer->layer(), SIGNAL(destroyed()), this, SLOT(layerDestroyed()));
//QgsLayerTreeLayer* nodeLayer = static_cast<QgsLayerTreeLayer*>(node);
//connect(nodeLayer->layer(), SIGNAL(destroyed()), this, SLOT(layerDestroyed()));
}

connect(node, SIGNAL(visibilityChanged(Qt::CheckState)), this, SLOT(updateVisibilityFromChildren()));
Expand Down Expand Up @@ -211,7 +211,7 @@ QgsLayerTreeLayer *QgsLayerTreeGroup::findLayer(const QString& layerId)

QgsLayerTreeGroup* QgsLayerTreeGroup::readXML(QDomElement& element)
{
if (element.tagName() != "tree-group")
if (element.tagName() != "layer-tree-group")
return 0;

QString name = element.attribute("name");
Expand Down Expand Up @@ -239,7 +239,7 @@ QgsLayerTreeGroup* QgsLayerTreeGroup::readXML(QDomElement& element)
void QgsLayerTreeGroup::writeXML(QDomElement& parentElement)
{
QDomDocument doc = parentElement.ownerDocument();
QDomElement elem = doc.createElement("tree-group");
QDomElement elem = doc.createElement("layer-tree-group");
elem.setAttribute("name", mName);
elem.setAttribute("expanded", mExpanded ? "1" : "0");
elem.setAttribute("checked", QgsLayerTreeUtils::checkStateToXml(mChecked));
Expand All @@ -252,6 +252,17 @@ void QgsLayerTreeGroup::writeXML(QDomElement& parentElement)
parentElement.appendChild(elem);
}

QString QgsLayerTreeGroup::dump() const
{
QString header = QString( "GROUP: %1 visible=%2 expanded=%3\n" ).arg( name() ).arg( mChecked ).arg( mExpanded );
QStringList childrenDump;
foreach (QgsLayerTreeNode* node, mChildren)
childrenDump << node->dump().split( "\n" );
for (int i = 0; i < childrenDump.count(); ++i)
childrenDump[i].prepend( " " );
return header + childrenDump.join( "\n" );
}

void QgsLayerTreeGroup::setVisible(Qt::CheckState state)
{
if (mChecked == state)
Expand Down Expand Up @@ -360,7 +371,7 @@ void QgsLayerTreeLayer::setVisible(bool state)

QgsLayerTreeLayer* QgsLayerTreeLayer::readXML(QDomElement& element)
{
if (element.tagName() != "tree-layer")
if (element.tagName() != "layer-tree-layer")
return 0;

QString layerID = element.attribute("id");
Expand Down Expand Up @@ -388,7 +399,7 @@ QgsLayerTreeLayer* QgsLayerTreeLayer::readXML(QDomElement& element)
void QgsLayerTreeLayer::writeXML(QDomElement& parentElement)
{
QDomDocument doc = parentElement.ownerDocument();
QDomElement elem = doc.createElement("tree-layer");
QDomElement elem = doc.createElement("layer-tree-layer");
elem.setAttribute("id", mLayerId);
elem.setAttribute("name", layerName());
elem.setAttribute("visible", mVisible ? "1" : "0");
Expand All @@ -399,6 +410,11 @@ void QgsLayerTreeLayer::writeXML(QDomElement& parentElement)
parentElement.appendChild(elem);
}

QString QgsLayerTreeLayer::dump() const
{
return QString( "LAYER: %1 visible=%2 expanded=%3 id=%4\n" ).arg( layerName() ).arg( mVisible ).arg( mExpanded ).arg( layerId() );
}

void QgsLayerTreeLayer::registryLayersAdded(QList<QgsMapLayer*> layers)
{
foreach (QgsMapLayer* l, layers)
Expand Down
6 changes: 6 additions & 0 deletions src/core/layertree/qgslayertreenode.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
static QgsLayerTreeNode* readXML(QDomElement& element);
virtual void writeXML(QDomElement& parentElement) = 0;

virtual QString dump() const = 0;

bool isExpanded() const { return mExpanded; }
void setExpanded(bool expanded) { mExpanded = expanded; }

Expand Down Expand Up @@ -109,6 +111,8 @@ class QgsLayerTreeLayer : public QgsLayerTreeNode
static QgsLayerTreeLayer* readXML(QDomElement& element);
virtual void writeXML(QDomElement& parentElement);

virtual QString dump() const;

protected slots:
void registryLayersAdded(QList<QgsMapLayer*> layers);

Expand Down Expand Up @@ -148,6 +152,8 @@ class QgsLayerTreeGroup : public QgsLayerTreeNode
static QgsLayerTreeGroup* readXML(QDomElement& element);
virtual void writeXML(QDomElement& parentElement);

virtual QString dump() const;

Qt::CheckState isVisible() const { return mChecked; }
void setVisible(Qt::CheckState state);

Expand Down
3 changes: 3 additions & 0 deletions src/core/layertree/qgslayertreeutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

QgsLayerTreeGroup* QgsLayerTreeUtils::readOldLegend(const QDomElement& legendElem)
{
if (legendElem.isNull())
return 0;

QDomNodeList legendChildren = legendElem.childNodes();
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;

Expand Down
2 changes: 1 addition & 1 deletion src/core/layertree/qgslayertreeutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CORE_EXPORT QgsLayerTreeUtils
{
public:

// return a new instance
// return a new instance - or null on error
static QgsLayerTreeGroup* readOldLegend(const QDomElement& legendElem);

static QString checkStateToXml(Qt::CheckState state);
Expand Down
98 changes: 70 additions & 28 deletions src/core/qgsproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "qgsdatasourceuri.h"
#include "qgsexception.h"
#include "qgslayertreenode.h"
#include "qgslayertreeutils.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgspluginlayer.h"
Expand Down Expand Up @@ -304,7 +306,7 @@ struct QgsProject::Imp
bool dirty;

Imp()
: title( "" )
: title( )
, dirty( false )
{ // top property node is the root
// "properties" that contains all plug-in
Expand All @@ -318,14 +320,10 @@ struct QgsProject::Imp
{
//QgsDebugMsg( "Clearing project properties Impl->clear();" );

file.setFileName( QString() );
properties_.clearKeys();
title = "";

// reset some default project properties
// XXX THESE SHOULD BE MOVED TO STATUSBAR RELATED SOURCE
QgsProject::instance()->writeEntry( "PositionPrecision", "/Automatic", true );
QgsProject::instance()->writeEntry( "PositionPrecision", "/DecimalPlaces", 2 );
QgsProject::instance()->writeEntry( "Paths", "/Absolute", false );
title.clear();
dirty = false;
}

}; // struct QgsProject::Imp
Expand All @@ -336,15 +334,10 @@ QgsProject::QgsProject()
: imp_( new QgsProject::Imp )
, mBadLayerHandler( new QgsProjectBadLayerDefaultHandler() )
, mRelationManager( new QgsRelationManager( this ) )
, mRootGroup( 0 )
{
// Set some default project properties
// XXX THESE SHOULD BE MOVED TO STATUSBAR RELATED SOURCE
writeEntry( "PositionPrecision", "/Automatic", true );
writeEntry( "PositionPrecision", "/DecimalPlaces", 2 );
writeEntry( "Paths", "/Absolute", false );
// XXX writeEntry() makes the project dirty, but it doesn't make sense
// for a new project to be dirty, so let's clean it up
dirty( false );
clear();

} // QgsProject ctor


Expand All @@ -353,6 +346,7 @@ QgsProject::~QgsProject()
{
delete mBadLayerHandler;
delete mRelationManager;
delete mRootGroup;

// note that std::auto_ptr automatically deletes imp_ when it's destroyed
} // QgsProject dtor
Expand All @@ -375,6 +369,11 @@ void QgsProject::title( QString const &title )
dirty( true );
} // void QgsProject::title

void QgsProject::setTitle( const QString& t )
{
title( t );
}


QString const & QgsProject::title() const
{
Expand All @@ -393,6 +392,11 @@ void QgsProject::dirty( bool b )
imp_->dirty = b;
} // bool QgsProject::isDirty()

void QgsProject::setDirty(bool b)
{
dirty( b );
}



void QgsProject::setFileName( QString const &name )
Expand All @@ -409,6 +413,24 @@ QString QgsProject::fileName() const
return imp_->file.fileName();
} // QString QgsProject::fileName() const

void QgsProject::clear()
{
imp_->clear();
mEmbeddedLayers.clear();
mRelationManager->clear();

delete mRootGroup;
mRootGroup = new QgsLayerTreeGroup;

// reset some default project properties
// XXX THESE SHOULD BE MOVED TO STATUSBAR RELATED SOURCE
writeEntry( "PositionPrecision", "/Automatic", true );
writeEntry( "PositionPrecision", "/DecimalPlaces", 2 );
writeEntry( "Paths", "/Absolute", false );

setDirty( false );
}



/// basically a debugging tool to dump property list values
Expand Down Expand Up @@ -858,13 +880,11 @@ bool QgsProject::read()

}

// before we start loading everything, let's clear out the current set of
// properties first so that we don't have the properties from the previous
// project still hanging around
// start new project, just keep the file name

imp_->clear();
mEmbeddedLayers.clear();
mRelationManager->clear();
QString fileName = imp_->file.fileName();
clear();
imp_->file.setFileName(fileName);

// now get any properties
_getProperties( *doc, imp_->properties_ );
Expand All @@ -873,12 +893,28 @@ bool QgsProject::read()

dump_( imp_->properties_ );


// restore the canvas' area of interest

// now get project title
_getTitle( *doc, imp_->title );

// read the layer tree from project file

QgsLayerTreeGroup* newRoot = 0;
QDomElement layerTreeElem = doc->documentElement().firstChildElement( "layer-tree-group" );
if ( !layerTreeElem.isNull() )
{
newRoot = QgsLayerTreeGroup::readXML( layerTreeElem );
}
else
{
newRoot = QgsLayerTreeUtils::readOldLegend( doc->documentElement().firstChildElement( "legend" ) );
}

if ( newRoot )
{
delete mRootGroup;
mRootGroup = newRoot;
QgsDebugMsg( "Loaded layer tree:\n " + mRootGroup->dump() );
}

// get the map layers
QPair< bool, QList<QDomNode> > getMapLayersResults = _getMapLayers( *doc );
Expand Down Expand Up @@ -992,6 +1028,9 @@ bool QgsProject::write()
QDomText titleText = doc->createTextNode( title() ); // XXX why have title TWICE?
titleNode.appendChild( titleText );

// write layer tree
mRootGroup->writeXML( qgisNode );

// let map canvas and legend write their information
emit writeProject( *doc );

Expand Down Expand Up @@ -1093,9 +1132,7 @@ bool QgsProject::write()

void QgsProject::clearProperties()
{
//QgsDebugMsg("entered.");

imp_->clear();
clear();

dirty( true );
} // QgsProject::clearProperties()
Expand Down Expand Up @@ -1830,3 +1867,8 @@ QgsRelationManager* QgsProject::relationManager() const
{
return mRelationManager;
}

QgsLayerTreeGroup* QgsProject::layerTreeRoot() const
{
return mRootGroup;
}

0 comments on commit de146fb

Please sign in to comment.