Skip to content

Commit

Permalink
Fix tree model loading from xml
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Nov 10, 2020
1 parent 525aded commit 8d7f540
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 18 deletions.
2 changes: 2 additions & 0 deletions python/core/auto_generated/layertree/qgslayertreenode.sip.in
Expand Up @@ -98,6 +98,8 @@ Gets pointer to the parent. If parent is ``None``, the node is a root node
Gets list of children of the node. Children are owned by the parent
%End



virtual QString name() const = 0;
%Docstring
Returns name of the node
Expand Down
5 changes: 4 additions & 1 deletion src/app/qgsprojectlayergroupdialog.cpp
Expand Up @@ -204,7 +204,10 @@ void QgsProjectLayerGroupDialog::changeProjectFile()
QDomElement layerTreeElem = projectDom.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
if ( !layerTreeElem.isNull() )
{
mRootGroup->readChildrenFromXml( layerTreeElem, QgsReadWriteContext() );
// Use a temporary tree to read the nodes to prevent signals being delivered to the models
QgsLayerTree tempTree;
tempTree.readChildrenFromXml( layerTreeElem, QgsReadWriteContext() );
mRootGroup->insertChildNodes( -1, tempTree.abandonChildren() );
}
else
{
Expand Down
19 changes: 9 additions & 10 deletions src/core/layertree/qgslayertreemodel.cpp
Expand Up @@ -899,12 +899,12 @@ void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer *nodeLayer )
{
// in order to connect to layer, we need to have it loaded.
// keep an eye on the layer ID: once loaded, we will use it
connect( nodeLayer, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeModel::nodeLayerLoaded );
connect( nodeLayer, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeModel::nodeLayerLoaded, Qt::UniqueConnection );
return;
}

// watch if the layer is getting removed
connect( nodeLayer, &QgsLayerTreeLayer::layerWillBeUnloaded, this, &QgsLayerTreeModel::nodeLayerWillBeUnloaded );
connect( nodeLayer, &QgsLayerTreeLayer::layerWillBeUnloaded, this, &QgsLayerTreeModel::nodeLayerWillBeUnloaded, Qt::UniqueConnection );

if ( testFlag( ShowLegend ) )
{
Expand Down Expand Up @@ -1003,14 +1003,13 @@ void QgsLayerTreeModel::connectToRootNode()
{
Q_ASSERT( mRootNode );

connect( mRootNode, &QgsLayerTreeNode::willAddChildren, this, &QgsLayerTreeModel::nodeWillAddChildren );
connect( mRootNode, &QgsLayerTreeNode::addedChildren, this, &QgsLayerTreeModel::nodeAddedChildren );
connect( mRootNode, &QgsLayerTreeNode::willRemoveChildren, this, &QgsLayerTreeModel::nodeWillRemoveChildren );
connect( mRootNode, &QgsLayerTreeNode::removedChildren, this, &QgsLayerTreeModel::nodeRemovedChildren );
connect( mRootNode, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeModel::nodeVisibilityChanged );
connect( mRootNode, &QgsLayerTreeNode::nameChanged, this, &QgsLayerTreeModel::nodeNameChanged );

connect( mRootNode, &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayerTreeModel::nodeCustomPropertyChanged );
connect( mRootNode, &QgsLayerTreeNode::willAddChildren, this, &QgsLayerTreeModel::nodeWillAddChildren, Qt::ConnectionType::UniqueConnection );
connect( mRootNode, &QgsLayerTreeNode::addedChildren, this, &QgsLayerTreeModel::nodeAddedChildren, Qt::ConnectionType::UniqueConnection );
connect( mRootNode, &QgsLayerTreeNode::willRemoveChildren, this, &QgsLayerTreeModel::nodeWillRemoveChildren, Qt::ConnectionType::UniqueConnection );
connect( mRootNode, &QgsLayerTreeNode::removedChildren, this, &QgsLayerTreeModel::nodeRemovedChildren, Qt::ConnectionType::UniqueConnection );
connect( mRootNode, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeModel::nodeVisibilityChanged, Qt::ConnectionType::UniqueConnection );
connect( mRootNode, &QgsLayerTreeNode::nameChanged, this, &QgsLayerTreeModel::nodeNameChanged, Qt::ConnectionType::UniqueConnection );
connect( mRootNode, &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayerTreeModel::nodeCustomPropertyChanged, Qt::ConnectionType::UniqueConnection );

connectToLayers( mRootNode );
}
Expand Down
1 change: 1 addition & 0 deletions src/core/layertree/qgslayertreenode.cpp
Expand Up @@ -61,6 +61,7 @@ QList<QgsLayerTreeNode *> QgsLayerTreeNode::abandonChildren()

void QgsLayerTreeNode::makeOrphan()
{
disconnect();
mParent = nullptr;
}

Expand Down
13 changes: 11 additions & 2 deletions src/core/layertree/qgslayertreenode.h
Expand Up @@ -112,9 +112,18 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
QList<QgsLayerTreeNode *> children() { return mChildren; }
//! Gets list of children of the node. Children are owned by the parent
QList<QgsLayerTreeNode *> children() const { return mChildren; } SIP_SKIP
//! Remove the childrens and sets their parent to null

/**
* Removes the childrens, disconnect all their signals and sets their parent to NULLPTR
* \return the removed children
* \since QGIS 3.16
*/
QList<QgsLayerTreeNode *> abandonChildren() SIP_SKIP;
//! Set parent to null

/**
* Sets parent to NULLPTR and disconnects all signals
* \since QGIS 3.16
*/
void makeOrphan() SIP_SKIP;

/**
Expand Down
5 changes: 4 additions & 1 deletion src/core/qgsproject.cpp
Expand Up @@ -1536,7 +1536,10 @@ bool QgsProject::readProjectFile( const QString &filename, QgsProject::ReadFlags
QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
if ( !layerTreeElem.isNull() )
{
mRootGroup->readChildrenFromXml( layerTreeElem, context );
// Use a temporary tree to read the nodes to prevent signals being delivered to the models
QgsLayerTree tempTree;
tempTree.readChildrenFromXml( layerTreeElem, context );
mRootGroup->insertChildNodes( -1, tempTree.abandonChildren() );
}
else
{
Expand Down
43 changes: 39 additions & 4 deletions src/gui/layertree/qgslayertreeview.cpp
Expand Up @@ -89,9 +89,6 @@ void QgsLayerTreeView::setModel( QAbstractItemModel *model )
if ( !treeModel )
return;

connect( treeModel, &QAbstractItemModel::rowsInserted, this, &QgsLayerTreeView::modelRowsInserted );
connect( treeModel, &QAbstractItemModel::rowsRemoved, this, &QgsLayerTreeView::modelRowsRemoved );

if ( mMessageBar )
connect( treeModel, &QgsLayerTreeModel::messageEmitted,
[ = ]( const QString & message, Qgis::MessageLevel level = Qgis::Info, int duration = 5 )
Expand All @@ -100,6 +97,9 @@ void QgsLayerTreeView::setModel( QAbstractItemModel *model )

mProxyModel = new QgsLayerTreeProxyModel( treeModel, this );

connect( mProxyModel, &QAbstractItemModel::rowsInserted, this, &QgsLayerTreeView::modelRowsInserted );
connect( mProxyModel, &QAbstractItemModel::rowsRemoved, this, &QgsLayerTreeView::modelRowsRemoved );

#ifdef ENABLE_MODELTEST
new ModelTest( treeModel, this );
new ModelTest( mProxyModel, this );
Expand All @@ -118,6 +118,8 @@ void QgsLayerTreeView::setModel( QAbstractItemModel *model )
connect( treeModel, &QAbstractItemModel::dataChanged, this, &QgsLayerTreeView::onDataChanged );

updateExpandedStateFromNode( treeModel->rootGroup() );

//checkModel();
}

QgsLayerTreeModel *QgsLayerTreeView::layerTreeModel() const
Expand Down Expand Up @@ -186,7 +188,7 @@ void QgsLayerTreeView::contextMenuEvent( QContextMenuEvent *event )

void QgsLayerTreeView::modelRowsInserted( const QModelIndex &index, int start, int end )
{
QgsLayerTreeNode *parentNode = layerTreeModel()->index2node( index );
QgsLayerTreeNode *parentNode = index2node( index );
if ( !parentNode )
return;

Expand Down Expand Up @@ -313,6 +315,8 @@ void QgsLayerTreeView::onCurrentChanged()
layerTreeModel()->setCurrentIndex( mProxyModel->mapToSource( proxyModelNodeLayerIndex ) );
}

//checkModel();

emit currentLayerChanged( layerCurrent );
}

Expand Down Expand Up @@ -342,6 +346,7 @@ void QgsLayerTreeView::onCustomPropertyChanged( QgsLayerTreeNode *node, const QS
void QgsLayerTreeView::onModelReset()
{
updateExpandedStateFromNode( layerTreeModel()->rootGroup() );
//checkModel();
}

void QgsLayerTreeView::updateExpandedStateFromNode( QgsLayerTreeNode *node )
Expand Down Expand Up @@ -650,7 +655,37 @@ void QgsLayerTreeView::onDataChanged( const QModelIndex &topLeft, const QModelIn

if ( roles.contains( Qt::SizeHintRole ) )
viewport()->update();

//checkModel();
}

#if 0
// for model debugging
void QgsLayerTreeView::checkModel()
{
std::function<void( QgsLayerTreeNode *, int )> debug;
debug = [ & ]( QgsLayerTreeNode * node, int depth )
{
if ( depth == 1 )
qDebug() << "----------------------------------------------";

qDebug() << depth << node->name() << node2index( node ) << layerTreeModel()->rowCount( node2sourceIndex( node ) ) << mProxyModel->rowCount( node2index( node ) );
Q_ASSERT( node == index2node( node2index( node ) ) );
Q_ASSERT( node == layerTreeModel()->index2node( node2sourceIndex( node ) ) );
Q_ASSERT( layerTreeModel()->rowCount( node2sourceIndex( node ) ) == mProxyModel->rowCount( node2index( node ) ) );

for ( int i = 0; i < mProxyModel->rowCount( node2index( node ) ); i++ )
{
QgsLayerTreeNode *childNode { index2node( mProxyModel->index( i, 0, node2index( node ) ) ) };
if ( childNode )
debug( childNode, depth + 1 );
else
qDebug() << "Warning no child node!";
}
};
debug( layerTreeModel()->rootGroup(), 1 );
}
#endif

QgsLayerTreeProxyModel *QgsLayerTreeView::proxyModel() const
{
Expand Down
4 changes: 4 additions & 0 deletions src/gui/layertree/qgslayertreeview.h
Expand Up @@ -80,6 +80,7 @@ class GUI_EXPORT QgsLayerTreeProxyModel : public QSortFilterProxyModel
QgsLayerTreeModel *mLayerTreeModel = nullptr;
QString mFilterText;
bool mShowPrivateLayers = false;

};


Expand Down Expand Up @@ -403,6 +404,9 @@ class GUI_EXPORT QgsLayerTreeView : public QTreeView

bool mShowPrivateLayers = false;

// For model debugging
// void checkModel( );

// friend so it can access viewOptions() method and mLastReleaseMousePos without making them public
friend class QgsLayerTreeViewItemDelegate;
};
Expand Down

0 comments on commit 8d7f540

Please sign in to comment.