mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
Merge pull request #3935 from rouault/group_visibility
[FEATURE] Change of ergonomy of the visibility of layers inside groups
This commit is contained in:
commit
f67cdc3965
@ -691,6 +691,13 @@ QgsCptCitySelectionItem {#qgis_api_break_3_0_QgsCptCitySelectionItem}
|
||||
|
||||
- parseXML() has been renamed to parseXml()
|
||||
|
||||
|
||||
QgsCustomLayerOrderWidget {#qgis_api_break_3_0_QgsCustomLayerOrderWidget}
|
||||
-------------------------
|
||||
|
||||
- the signature of the visibilityChanged() signal is changed to visibilityChanged( QgsLayerTreeNode *node )
|
||||
|
||||
|
||||
QgsCRSCache {#qgis_api_break_3_0_QgsCRSCache}
|
||||
-----------
|
||||
|
||||
@ -1075,12 +1082,16 @@ QgsLayerTreeGroup {#qgis_api_break_3_0_QgsLayerTreeGroup}
|
||||
-----------------
|
||||
|
||||
- readChildrenFromXML() has been renamed to readChildrenFromXml()
|
||||
|
||||
- isVisible() is moved to QgsLayerTreeNode
|
||||
- setVisible() is replaced by QgsLayerTreeNode::setItemVisibilityChecked()
|
||||
- protected methods updateVisibilityFromChildren() and updateChildVisibility() removed
|
||||
|
||||
QgsLayerTreeLayer {#qgis_api_break_3_0_QgsLayerTreeLayer}
|
||||
-----------------
|
||||
|
||||
- setLayerName(), layerName() were renamed to setName(), name()
|
||||
- isVisible() is moved to QgsLayerTreeNode
|
||||
- setVisible() is replaced by QgsLayerTreeNode::setItemVisibilityChecked()
|
||||
|
||||
|
||||
QgsLayerTreeModel {#qgis_api_break_3_0_QgsLayerTreeMode}
|
||||
@ -1106,7 +1117,7 @@ QgsLayerTreeNode {#qgis_api_break_3_0_QgsLayerTreeNode}
|
||||
|
||||
- readCommonXML() has been renamed to readCommonXml()
|
||||
- writeCommonXML() has been renamed to writeCommonXml()
|
||||
|
||||
- the signature of the visibilityChanged() signal is changed to visibilityChanged( QgsLayerTreeNode *node )
|
||||
|
||||
QgsLimitedRandomColorRampDialog {#qgis_api_break_3_0_QgsLimitedRandomRampDialog}
|
||||
-------------------------------
|
||||
|
@ -71,11 +71,6 @@ class QgsLayerTreeGroup : QgsLayerTreeNode
|
||||
//! Return a clone of the group. The children are cloned too.
|
||||
virtual QgsLayerTreeGroup* clone() const /Factory/;
|
||||
|
||||
//! Return the check state of the group node
|
||||
Qt::CheckState isVisible() const;
|
||||
//! Set check state of the group node - will also update children
|
||||
void setVisible( Qt::CheckState state );
|
||||
|
||||
//! Return whether the group is mutually exclusive (only one child can be checked at a time)
|
||||
//! @note added in 2.12
|
||||
bool isMutuallyExclusive() const;
|
||||
@ -86,14 +81,10 @@ class QgsLayerTreeGroup : QgsLayerTreeNode
|
||||
void setIsMutuallyExclusive( bool enabled, int initialChildIndex = -1 );
|
||||
|
||||
protected slots:
|
||||
void layerDestroyed();
|
||||
void nodeVisibilityChanged( QgsLayerTreeNode* node );
|
||||
|
||||
protected:
|
||||
//! Set check state of this group from its children
|
||||
void updateVisibilityFromChildren();
|
||||
//! Set check state of children (when this group's check state changes) - if not mutually exclusive
|
||||
void updateChildVisibility();
|
||||
|
||||
//! Set check state of children - if mutually exclusive
|
||||
void updateChildVisibilityMutuallyExclusive();
|
||||
|
||||
|
@ -38,9 +38,6 @@ class QgsLayerTreeLayer : QgsLayerTreeNode
|
||||
//! @note added in 3.0
|
||||
void setName( const QString& n );
|
||||
|
||||
Qt::CheckState isVisible() const;
|
||||
void setVisible( Qt::CheckState visible );
|
||||
|
||||
static QgsLayerTreeLayer* readXml( QDomElement& element ) /Factory/;
|
||||
virtual void writeXml( QDomElement& parentElement );
|
||||
|
||||
|
@ -61,6 +61,7 @@ class QgsLayerTreeModel : QAbstractItemModel
|
||||
AllowNodeRename, //!< Allow renaming of groups and layers
|
||||
AllowNodeChangeVisibility, //!< Allow user to set node visibility with a check box
|
||||
AllowLegendChangeState, //!< Allow check boxes for legend nodes (if supported by layer's legend)
|
||||
ActionHierarchical, //!< Check/uncheck action has consequences on children (or parents for leaf node)
|
||||
};
|
||||
typedef QFlags<QgsLayerTreeModel::Flag> Flags;
|
||||
|
||||
|
@ -94,6 +94,34 @@ class QgsLayerTreeNode : QObject
|
||||
//! Create a copy of the node. Returns new instance
|
||||
virtual QgsLayerTreeNode *clone() const = 0 /Factory/;
|
||||
|
||||
//! Returns whether a node is really visible (ie checked and all its ancestors checked as well)
|
||||
//! @note added in 3.0
|
||||
bool isVisible() const;
|
||||
|
||||
//! Returns whether a node is checked (independantly of its ancestors or children)
|
||||
//! @note added in 3.0
|
||||
bool itemVisibilityChecked() const;
|
||||
|
||||
//! Check or uncheck a node (independantly of its ancestors or children)
|
||||
//! @note added in 3.0
|
||||
void setItemVisibilityChecked( bool checked );
|
||||
|
||||
//! Check or uncheck a node and all its children (taking into account exclusion rules)
|
||||
//! @note added in 3.0
|
||||
virtual void setItemVisibilityCheckedRecursive( bool checked );
|
||||
|
||||
//! Check or uncheck a node and all its parents
|
||||
//! @note added in 3.0
|
||||
void setItemVisibilityCheckedParentRecursive( bool checked );
|
||||
|
||||
//! Return whether this node is checked and all its children.
|
||||
//! @note added in 3.0
|
||||
bool isItemVisibilityCheckedRecursive() const;
|
||||
|
||||
//! Return whether this node is unchecked and all its children.
|
||||
//! @note added in 3.0
|
||||
bool isItemVisibilityUncheckedRecursive() const;
|
||||
|
||||
//! Return whether the node should be shown as expanded or collapsed in GUI
|
||||
bool isExpanded() const;
|
||||
//! Set whether the node should be shown as expanded or collapsed in GUI
|
||||
@ -121,7 +149,7 @@ class QgsLayerTreeNode : QObject
|
||||
//! Emitted when one or more nodes has been removed from a node within the tree
|
||||
void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
|
||||
//! Emitted when check state of a node within the tree has been changed
|
||||
void visibilityChanged( QgsLayerTreeNode *node, Qt::CheckState state );
|
||||
void visibilityChanged( QgsLayerTreeNode *node );
|
||||
//! Emitted when a custom property of a node within the tree has been changed or removed
|
||||
void customPropertyChanged( QgsLayerTreeNode *node, const QString& key );
|
||||
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
|
||||
|
@ -20,7 +20,8 @@ class QgsCustomLayerOrderWidget : QWidget
|
||||
protected slots:
|
||||
void bridgeHasCustomLayerOrderChanged( bool state );
|
||||
void bridgeCustomLayerOrderChanged( const QStringList& order );
|
||||
void nodeVisibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
|
||||
//! Slot triggered when the ivsibility of a node changes
|
||||
void nodeVisibilityChanged( QgsLayerTreeNode* node );
|
||||
|
||||
void modelUpdated();
|
||||
};
|
||||
|
@ -20,6 +20,15 @@ class QgsLayerTreeViewDefaultActions : QObject
|
||||
QAction* actionRenameGroupOrLayer( QObject* parent = 0 ) /Factory/;
|
||||
QAction* actionShowFeatureCount( QObject* parent = 0 ) /Factory/;
|
||||
|
||||
//! Action to check a group and all its children
|
||||
QAction* actionCheckAndAllChildren( QObject* parent = nullptr );
|
||||
|
||||
//! Action to uncheck a group and all its children
|
||||
QAction* actionUncheckAndAllChildren( QObject* parent = nullptr );
|
||||
|
||||
//! Action to check a group and all its parents
|
||||
QAction* actionCheckAndAllParents( QObject* parent = nullptr );
|
||||
|
||||
QAction* actionZoomToLayer( QgsMapCanvas* canvas, QObject* parent = 0 ) /Factory/;
|
||||
QAction* actionZoomToGroup( QgsMapCanvas* canvas, QObject* parent = 0 ) /Factory/;
|
||||
// TODO: zoom to selected
|
||||
|
@ -422,7 +422,7 @@ void QgsDwgImportDialog::createGroup( QgsLayerTreeGroup *group, QString name, QS
|
||||
if ( !layerGroup->children().isEmpty() )
|
||||
{
|
||||
layerGroup->setExpanded( false );
|
||||
layerGroup->setVisible( visible ? Qt::Checked : Qt::Unchecked );
|
||||
layerGroup->setItemVisibilityChecked( visible );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2808,7 +2808,7 @@ void QgisApp::setupConnections()
|
||||
this, SLOT( markDirty() ) );
|
||||
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ),
|
||||
this, SLOT( updateNewLayerInsertionPoint() ) );
|
||||
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ),
|
||||
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( visibilityChanged( QgsLayerTreeNode* ) ),
|
||||
this, SLOT( markDirty() ) );
|
||||
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ),
|
||||
this, SLOT( markDirty() ) );
|
||||
@ -5759,9 +5759,8 @@ void QgisApp::stopRendering()
|
||||
void QgisApp::hideAllLayers()
|
||||
{
|
||||
QgsDebugMsg( "hiding all layers!" );
|
||||
mLayerTreeView->layerTreeModel()->rootGroup()->setItemVisibilityCheckedRecursive( false );
|
||||
|
||||
Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, mLayerTreeView->layerTreeModel()->rootGroup()->findLayers() )
|
||||
nodeLayer->setVisible( Qt::Unchecked );
|
||||
}
|
||||
|
||||
|
||||
@ -5769,9 +5768,7 @@ void QgisApp::hideAllLayers()
|
||||
void QgisApp::showAllLayers()
|
||||
{
|
||||
QgsDebugMsg( "Showing all layers!" );
|
||||
|
||||
Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, mLayerTreeView->layerTreeModel()->rootGroup()->findLayers() )
|
||||
nodeLayer->setVisible( Qt::Checked );
|
||||
mLayerTreeView->layerTreeModel()->rootGroup()->setItemVisibilityCheckedRecursive( true );
|
||||
}
|
||||
|
||||
//reimplements method from base (gui) class
|
||||
@ -5781,10 +5778,7 @@ void QgisApp::hideSelectedLayers()
|
||||
|
||||
Q_FOREACH ( QgsLayerTreeNode* node, mLayerTreeView->selectedNodes() )
|
||||
{
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
QgsLayerTree::toGroup( node )->setVisible( Qt::Unchecked );
|
||||
else if ( QgsLayerTree::isLayer( node ) )
|
||||
QgsLayerTree::toLayer( node )->setVisible( Qt::Unchecked );
|
||||
node->setItemVisibilityChecked( false );
|
||||
}
|
||||
}
|
||||
|
||||
@ -5796,7 +5790,7 @@ void QgisApp::hideDeselectedLayers()
|
||||
{
|
||||
if ( selectedLayerNodes.contains( nodeLayer ) )
|
||||
continue;
|
||||
nodeLayer->setVisible( Qt::Unchecked );
|
||||
nodeLayer->setItemVisibilityChecked( false );
|
||||
}
|
||||
}
|
||||
|
||||
@ -5807,10 +5801,12 @@ void QgisApp::showSelectedLayers()
|
||||
|
||||
Q_FOREACH ( QgsLayerTreeNode* node, mLayerTreeView->selectedNodes() )
|
||||
{
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
QgsLayerTree::toGroup( node )->setVisible( Qt::Checked );
|
||||
else if ( QgsLayerTree::isLayer( node ) )
|
||||
QgsLayerTree::toLayer( node )->setVisible( Qt::Checked );
|
||||
QgsLayerTreeNode* nodeIter = node;
|
||||
while ( nodeIter )
|
||||
{
|
||||
nodeIter->setItemVisibilityChecked( true );
|
||||
nodeIter = nodeIter->parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8373,7 +8369,7 @@ void QgisApp::layerSubsetString()
|
||||
// hide the old layer
|
||||
QgsLayerTreeLayer* vLayerTreeLayer = QgsProject::instance()->layerTreeRoot()->findLayer( vlayer->id() );
|
||||
if ( vLayerTreeLayer )
|
||||
vLayerTreeLayer->setVisible( Qt::Unchecked );
|
||||
vLayerTreeLayer->setItemVisibilityChecked( false );
|
||||
vlayer = newLayer;
|
||||
}
|
||||
else
|
||||
@ -8663,7 +8659,7 @@ void QgisApp::duplicateLayers( const QList<QgsMapLayer *>& lyrList )
|
||||
QgsLayerTreeLayer* nodeDupLayer = parentGroup->insertLayer( parentGroup->children().indexOf( nodeSelectedLyr ) + 1, dupLayer );
|
||||
|
||||
// always set duplicated layers to not visible so layer can be configured before being turned on
|
||||
nodeDupLayer->setVisible( Qt::Unchecked );
|
||||
nodeDupLayer->setItemVisibilityChecked( false );
|
||||
|
||||
// duplicate the layer style
|
||||
QString errMsg;
|
||||
|
@ -80,6 +80,10 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
|
||||
|
||||
menu->addAction( actions->actionMutuallyExclusiveGroup( menu ) );
|
||||
|
||||
menu->addAction( actions->actionCheckAndAllChildren( menu ) );
|
||||
|
||||
menu->addAction( actions->actionUncheckAndAllChildren( menu ) );
|
||||
|
||||
if ( mView->selectedNodes( true ).count() >= 2 )
|
||||
menu->addAction( actions->actionGroupSelected( menu ) );
|
||||
|
||||
@ -125,6 +129,8 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
|
||||
if ( !layer->isInScaleRange( mCanvas->scale() ) )
|
||||
menu->addAction( tr( "Zoom to &Visible Scale" ), QgisApp::instance(), SLOT( zoomToLayerScale() ) );
|
||||
|
||||
menu->addAction( actions->actionCheckAndAllParents( menu ) );
|
||||
|
||||
// set layer crs
|
||||
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetCRS.png" ) ), tr( "Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCrs() ) );
|
||||
|
||||
|
@ -309,7 +309,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||
// use visibility as selection
|
||||
mLayersDependenciesTreeModel->setFlag( QgsLayerTreeModel::AllowNodeChangeVisibility );
|
||||
|
||||
mLayersDependenciesTreeGroup->setVisible( Qt::Unchecked );
|
||||
mLayersDependenciesTreeGroup->setItemVisibilityChecked( false );
|
||||
|
||||
QSet<QString> dependencySources;
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, mLayer->dependencies() )
|
||||
@ -318,7 +318,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||
}
|
||||
Q_FOREACH ( QgsLayerTreeLayer* layer, mLayersDependenciesTreeGroup->findLayers() )
|
||||
{
|
||||
layer->setVisible( dependencySources.contains( layer->layerId() ) ? Qt::Checked : Qt::Unchecked );
|
||||
layer->setItemVisibilityChecked( dependencySources.contains( layer->layerId() ) );
|
||||
}
|
||||
|
||||
mLayersDependenciesTreeView->setModel( mLayersDependenciesTreeModel.data() );
|
||||
|
@ -24,26 +24,24 @@
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
QgsLayerTreeGroup::QgsLayerTreeGroup( const QString& name, Qt::CheckState checked )
|
||||
: QgsLayerTreeNode( NodeGroup )
|
||||
QgsLayerTreeGroup::QgsLayerTreeGroup( const QString& name, bool checked )
|
||||
: QgsLayerTreeNode( NodeGroup, checked )
|
||||
, mName( name )
|
||||
, mChecked( checked )
|
||||
, mChangingChildVisibility( false )
|
||||
, mMutuallyExclusive( false )
|
||||
, mMutuallyExclusiveChildIndex( -1 )
|
||||
{
|
||||
connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
|
||||
connect( this, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeGroup::nodeVisibilityChanged );
|
||||
}
|
||||
|
||||
QgsLayerTreeGroup::QgsLayerTreeGroup( const QgsLayerTreeGroup& other )
|
||||
: QgsLayerTreeNode( other )
|
||||
, mName( other.mName )
|
||||
, mChecked( other.mChecked )
|
||||
, mChangingChildVisibility( other.mChangingChildVisibility )
|
||||
, mMutuallyExclusive( other.mMutuallyExclusive )
|
||||
, mMutuallyExclusiveChildIndex( other.mMutuallyExclusiveChildIndex )
|
||||
{
|
||||
connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
|
||||
connect( this, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeGroup::nodeVisibilityChanged );
|
||||
}
|
||||
|
||||
QString QgsLayerTreeGroup::name() const
|
||||
@ -118,7 +116,7 @@ void QgsLayerTreeGroup::insertChildNodes( int index, const QList<QgsLayerTreeNod
|
||||
// the child could have change its index - or the new children may have been also set as visible
|
||||
mMutuallyExclusiveChildIndex = mChildren.indexOf( meChild );
|
||||
}
|
||||
else if ( mChecked == Qt::Checked )
|
||||
else if ( mChecked )
|
||||
{
|
||||
// we have not picked a child index yet, but we should pick one now
|
||||
// ... so pick the first one from the newly added
|
||||
@ -128,8 +126,6 @@ void QgsLayerTreeGroup::insertChildNodes( int index, const QList<QgsLayerTreeNod
|
||||
}
|
||||
updateChildVisibilityMutuallyExclusive();
|
||||
}
|
||||
|
||||
updateVisibilityFromChildren();
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::addChildNode( QgsLayerTreeNode* node )
|
||||
@ -173,11 +169,9 @@ void QgsLayerTreeGroup::removeChildren( int from, int count )
|
||||
// the child could have change its index - or may have been removed completely
|
||||
mMutuallyExclusiveChildIndex = mChildren.indexOf( meChild );
|
||||
// we need to uncheck this group
|
||||
if ( mMutuallyExclusiveChildIndex == -1 )
|
||||
setVisible( Qt::Unchecked );
|
||||
//if ( mMutuallyExclusiveChildIndex == -1 )
|
||||
// setItemVisibilityChecked( false );
|
||||
}
|
||||
|
||||
updateVisibilityFromChildren();
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::removeChildrenGroupWithoutLayers()
|
||||
@ -266,7 +260,7 @@ QgsLayerTreeGroup* QgsLayerTreeGroup::readXml( QDomElement& element )
|
||||
|
||||
QString name = element.attribute( QStringLiteral( "name" ) );
|
||||
bool isExpanded = ( element.attribute( QStringLiteral( "expanded" ), QStringLiteral( "1" ) ) == QLatin1String( "1" ) );
|
||||
Qt::CheckState checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( QStringLiteral( "checked" ) ) );
|
||||
bool checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked;
|
||||
bool isMutuallyExclusive = element.attribute( QStringLiteral( "mutually-exclusive" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
|
||||
int mutuallyExclusiveChildIndex = element.attribute( QStringLiteral( "mutually-exclusive-child" ), QStringLiteral( "-1" ) ).toInt();
|
||||
|
||||
@ -288,7 +282,7 @@ void QgsLayerTreeGroup::writeXml( QDomElement& parentElement )
|
||||
QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-group" ) );
|
||||
elem.setAttribute( QStringLiteral( "name" ), mName );
|
||||
elem.setAttribute( QStringLiteral( "expanded" ), mExpanded ? "1" : "0" );
|
||||
elem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( mChecked ) );
|
||||
elem.setAttribute( QStringLiteral( "checked" ), mChecked ? QStringLiteral( "Qt::Checked" ) : QStringLiteral( "Qt::Unchecked" ) );
|
||||
if ( mMutuallyExclusive )
|
||||
{
|
||||
elem.setAttribute( QStringLiteral( "mutually-exclusive" ), QStringLiteral( "1" ) );
|
||||
@ -321,7 +315,7 @@ void QgsLayerTreeGroup::readChildrenFromXml( QDomElement& element )
|
||||
|
||||
QString QgsLayerTreeGroup::dump() const
|
||||
{
|
||||
QString header = QStringLiteral( "GROUP: %1 visible=%2 expanded=%3\n" ).arg( name() ).arg( mChecked ).arg( mExpanded );
|
||||
QString header = QStringLiteral( "GROUP: %1 checked=%2 expanded=%3\n" ).arg( name() ).arg( mChecked ).arg( mExpanded );
|
||||
QStringList childrenDump;
|
||||
Q_FOREACH ( QgsLayerTreeNode* node, mChildren )
|
||||
childrenDump << node->dump().split( '\n' );
|
||||
@ -335,54 +329,9 @@ QgsLayerTreeGroup* QgsLayerTreeGroup::clone() const
|
||||
return new QgsLayerTreeGroup( *this );
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::setVisible( Qt::CheckState state )
|
||||
{
|
||||
if ( mChecked == state )
|
||||
return;
|
||||
|
||||
mChecked = state;
|
||||
emit visibilityChanged( this, state );
|
||||
|
||||
if ( mMutuallyExclusive )
|
||||
{
|
||||
if ( mMutuallyExclusiveChildIndex < 0 || mMutuallyExclusiveChildIndex >= mChildren.count() )
|
||||
mMutuallyExclusiveChildIndex = 0; // just choose the first one if we have lost the active one
|
||||
updateChildVisibilityMutuallyExclusive();
|
||||
}
|
||||
else if ( mChecked == Qt::Unchecked || mChecked == Qt::Checked )
|
||||
{
|
||||
updateChildVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::updateChildVisibility()
|
||||
{
|
||||
mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
|
||||
|
||||
// update children to have the correct visibility
|
||||
Q_FOREACH ( QgsLayerTreeNode* child, mChildren )
|
||||
{
|
||||
if ( QgsLayerTree::isGroup( child ) )
|
||||
QgsLayerTree::toGroup( child )->setVisible( mChecked );
|
||||
else if ( QgsLayerTree::isLayer( child ) )
|
||||
QgsLayerTree::toLayer( child )->setVisible( mChecked );
|
||||
}
|
||||
|
||||
mChangingChildVisibility = false;
|
||||
}
|
||||
|
||||
|
||||
static bool _nodeIsChecked( QgsLayerTreeNode* node )
|
||||
{
|
||||
Qt::CheckState state;
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
state = QgsLayerTree::toGroup( node )->isVisible();
|
||||
else if ( QgsLayerTree::isLayer( node ) )
|
||||
state = QgsLayerTree::toLayer( node )->isVisible();
|
||||
else
|
||||
return false;
|
||||
|
||||
return state == Qt::Checked || state == Qt::PartiallyChecked;
|
||||
return node->itemVisibilityChecked();
|
||||
}
|
||||
|
||||
|
||||
@ -398,7 +347,6 @@ void QgsLayerTreeGroup::setIsMutuallyExclusive( bool enabled, int initialChildIn
|
||||
|
||||
if ( !enabled )
|
||||
{
|
||||
updateVisibilityFromChildren();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -433,14 +381,6 @@ QStringList QgsLayerTreeGroup::findLayerIds() const
|
||||
return lst;
|
||||
}
|
||||
|
||||
|
||||
void QgsLayerTreeGroup::layerDestroyed()
|
||||
{
|
||||
//QgsMapLayer* layer = static_cast<QgsMapLayer*>( sender() );
|
||||
//removeLayer( layer );
|
||||
}
|
||||
|
||||
|
||||
void QgsLayerTreeGroup::nodeVisibilityChanged( QgsLayerTreeNode* node )
|
||||
{
|
||||
int childIndex = mChildren.indexOf( node );
|
||||
@ -451,69 +391,12 @@ void QgsLayerTreeGroup::nodeVisibilityChanged( QgsLayerTreeNode* node )
|
||||
{
|
||||
if ( _nodeIsChecked( node ) )
|
||||
mMutuallyExclusiveChildIndex = childIndex;
|
||||
else if ( mMutuallyExclusiveChildIndex == childIndex )
|
||||
mMutuallyExclusiveChildIndex = -1;
|
||||
|
||||
// we need to update this node's check status in two cases:
|
||||
// 1. it was unchecked and a child node got checked
|
||||
// 2. it was checked and the only checked child got unchecked
|
||||
updateVisibilityFromChildren();
|
||||
|
||||
// we also need to make sure there is only one child node checked
|
||||
// we need to make sure there is only one child node checked
|
||||
updateChildVisibilityMutuallyExclusive();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateVisibilityFromChildren();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::updateVisibilityFromChildren()
|
||||
{
|
||||
if ( mChangingChildVisibility )
|
||||
return;
|
||||
|
||||
if ( mChildren.isEmpty() )
|
||||
return;
|
||||
|
||||
if ( mMutuallyExclusive )
|
||||
{
|
||||
// if in mutually exclusive mode, our check state depends only on the check state of the chosen child index
|
||||
|
||||
if ( mMutuallyExclusiveChildIndex < 0 || mMutuallyExclusiveChildIndex >= mChildren.count() )
|
||||
return;
|
||||
|
||||
Qt::CheckState meChildState = _nodeIsChecked( mChildren.at( mMutuallyExclusiveChildIndex ) ) ? Qt::Checked : Qt::Unchecked;
|
||||
|
||||
setVisible( meChildState );
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasVisible = false, hasHidden = false;
|
||||
|
||||
Q_FOREACH ( QgsLayerTreeNode* child, mChildren )
|
||||
{
|
||||
if ( QgsLayerTree::isLayer( child ) )
|
||||
{
|
||||
bool layerVisible = QgsLayerTree::toLayer( child )->isVisible() == Qt::Checked;
|
||||
if ( layerVisible ) hasVisible = true;
|
||||
if ( !layerVisible ) hasHidden = true;
|
||||
}
|
||||
else if ( QgsLayerTree::isGroup( child ) )
|
||||
{
|
||||
Qt::CheckState state = QgsLayerTree::toGroup( child )->isVisible();
|
||||
if ( state == Qt::Checked || state == Qt::PartiallyChecked ) hasVisible = true;
|
||||
if ( state == Qt::Unchecked || state == Qt::PartiallyChecked ) hasHidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
Qt::CheckState newState;
|
||||
if ( hasVisible && !hasHidden )
|
||||
newState = Qt::Checked;
|
||||
else if ( hasHidden && !hasVisible )
|
||||
newState = Qt::Unchecked;
|
||||
else
|
||||
newState = Qt::PartiallyChecked;
|
||||
|
||||
setVisible( newState );
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::updateChildVisibilityMutuallyExclusive()
|
||||
@ -526,11 +409,23 @@ void QgsLayerTreeGroup::updateChildVisibilityMutuallyExclusive()
|
||||
int index = 0;
|
||||
Q_FOREACH ( QgsLayerTreeNode* child, mChildren )
|
||||
{
|
||||
Qt::CheckState checked = ( index == mMutuallyExclusiveChildIndex ? mChecked : Qt::Unchecked );
|
||||
if ( QgsLayerTree::isGroup( child ) )
|
||||
QgsLayerTree::toGroup( child )->setVisible( checked );
|
||||
else if ( QgsLayerTree::isLayer( child ) )
|
||||
QgsLayerTree::toLayer( child )->setVisible( checked );
|
||||
child->setItemVisibilityChecked( index == mMutuallyExclusiveChildIndex );
|
||||
++index;
|
||||
}
|
||||
|
||||
mChangingChildVisibility = false;
|
||||
}
|
||||
|
||||
void QgsLayerTreeGroup::setItemVisibilityCheckedRecursive( bool checked )
|
||||
{
|
||||
QgsLayerTreeNode::setItemVisibilityChecked( checked );
|
||||
|
||||
mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
|
||||
|
||||
int index = 0;
|
||||
Q_FOREACH ( QgsLayerTreeNode* child, mChildren )
|
||||
{
|
||||
child->setItemVisibilityCheckedRecursive( checked && ( mMutuallyExclusiveChildIndex < 0 || index == mMutuallyExclusiveChildIndex ) );
|
||||
++index;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,8 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsLayerTreeGroup( const QString& name = QString(), Qt::CheckState checked = Qt::Checked );
|
||||
//! Constructor
|
||||
QgsLayerTreeGroup( const QString& name = QString(), bool checked = true );
|
||||
QgsLayerTreeGroup( const QgsLayerTreeGroup& other );
|
||||
|
||||
//! Get group's name
|
||||
@ -92,10 +93,8 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
|
||||
//! Return a clone of the group. The children are cloned too.
|
||||
virtual QgsLayerTreeGroup* clone() const override;
|
||||
|
||||
//! Return the check state of the group node
|
||||
Qt::CheckState isVisible() const { return mChecked; }
|
||||
//! Set check state of the group node - will also update children
|
||||
void setVisible( Qt::CheckState state );
|
||||
//! Check or uncheck a node and all its children (taking into account exclusion rules)
|
||||
virtual void setItemVisibilityCheckedRecursive( bool checked ) override;
|
||||
|
||||
//! Return whether the group is mutually exclusive (only one child can be checked at a time)
|
||||
//! @note added in 2.12
|
||||
@ -107,20 +106,15 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
|
||||
void setIsMutuallyExclusive( bool enabled, int initialChildIndex = -1 );
|
||||
|
||||
protected slots:
|
||||
void layerDestroyed();
|
||||
void nodeVisibilityChanged( QgsLayerTreeNode* node );
|
||||
|
||||
protected:
|
||||
//! Set check state of this group from its children
|
||||
void updateVisibilityFromChildren();
|
||||
//! Set check state of children (when this group's check state changes) - if not mutually exclusive
|
||||
void updateChildVisibility();
|
||||
|
||||
//! Set check state of children - if mutually exclusive
|
||||
void updateChildVisibilityMutuallyExclusive();
|
||||
|
||||
protected:
|
||||
QString mName;
|
||||
Qt::CheckState mChecked;
|
||||
|
||||
bool mChangingChildVisibility;
|
||||
|
||||
|
@ -21,21 +21,19 @@
|
||||
|
||||
|
||||
QgsLayerTreeLayer::QgsLayerTreeLayer( QgsMapLayer *layer )
|
||||
: QgsLayerTreeNode( NodeLayer )
|
||||
: QgsLayerTreeNode( NodeLayer, true )
|
||||
, mLayerId( layer->id() )
|
||||
, mLayer( nullptr )
|
||||
, mVisible( Qt::Checked )
|
||||
{
|
||||
Q_ASSERT( QgsProject::instance()->mapLayer( mLayerId ) == layer );
|
||||
attachToLayer();
|
||||
}
|
||||
|
||||
QgsLayerTreeLayer::QgsLayerTreeLayer( const QString& layerId, const QString& name )
|
||||
: QgsLayerTreeNode( NodeLayer )
|
||||
: QgsLayerTreeNode( NodeLayer, true )
|
||||
, mLayerId( layerId )
|
||||
, mLayerName( name )
|
||||
, mLayer( nullptr )
|
||||
, mVisible( Qt::Checked )
|
||||
{
|
||||
attachToLayer();
|
||||
}
|
||||
@ -45,7 +43,6 @@ QgsLayerTreeLayer::QgsLayerTreeLayer( const QgsLayerTreeLayer& other )
|
||||
, mLayerId( other.mLayerId )
|
||||
, mLayerName( other.mLayerName )
|
||||
, mLayer( nullptr )
|
||||
, mVisible( other.mVisible )
|
||||
{
|
||||
attachToLayer();
|
||||
}
|
||||
@ -94,15 +91,6 @@ void QgsLayerTreeLayer::setName( const QString& n )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayerTreeLayer::setVisible( Qt::CheckState state )
|
||||
{
|
||||
if ( mVisible == state )
|
||||
return;
|
||||
|
||||
mVisible = state;
|
||||
emit visibilityChanged( this, state );
|
||||
}
|
||||
|
||||
QgsLayerTreeLayer* QgsLayerTreeLayer::readXml( QDomElement& element )
|
||||
{
|
||||
if ( element.tagName() != QLatin1String( "layer-tree-layer" ) )
|
||||
@ -124,7 +112,7 @@ QgsLayerTreeLayer* QgsLayerTreeLayer::readXml( QDomElement& element )
|
||||
|
||||
nodeLayer->readCommonXml( element );
|
||||
|
||||
nodeLayer->setVisible( checked );
|
||||
nodeLayer->setItemVisibilityChecked( checked != Qt::Unchecked );
|
||||
nodeLayer->setExpanded( isExpanded );
|
||||
return nodeLayer;
|
||||
}
|
||||
@ -135,7 +123,7 @@ void QgsLayerTreeLayer::writeXml( QDomElement& parentElement )
|
||||
QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-layer" ) );
|
||||
elem.setAttribute( QStringLiteral( "id" ), mLayerId );
|
||||
elem.setAttribute( QStringLiteral( "name" ), name() );
|
||||
elem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( mVisible ) );
|
||||
elem.setAttribute( QStringLiteral( "checked" ), mChecked ? QStringLiteral( "Qt::Checked" ) : QStringLiteral( "Qt::Unchecked" ) );
|
||||
elem.setAttribute( QStringLiteral( "expanded" ), mExpanded ? "1" : "0" );
|
||||
|
||||
writeCommonXml( elem );
|
||||
@ -145,7 +133,7 @@ void QgsLayerTreeLayer::writeXml( QDomElement& parentElement )
|
||||
|
||||
QString QgsLayerTreeLayer::dump() const
|
||||
{
|
||||
return QStringLiteral( "LAYER: %1 visible=%2 expanded=%3 id=%4\n" ).arg( name() ).arg( mVisible ).arg( mExpanded ).arg( layerId() );
|
||||
return QStringLiteral( "LAYER: %1 checked=%2 expanded=%3 id=%4\n" ).arg( name() ).arg( mChecked ).arg( mExpanded ).arg( layerId() );
|
||||
}
|
||||
|
||||
QgsLayerTreeLayer* QgsLayerTreeLayer::clone() const
|
||||
|
@ -58,9 +58,6 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
|
||||
//! @note added in 3.0
|
||||
void setName( const QString& n ) override;
|
||||
|
||||
Qt::CheckState isVisible() const { return mVisible; }
|
||||
void setVisible( Qt::CheckState visible );
|
||||
|
||||
static QgsLayerTreeLayer* readXml( QDomElement& element );
|
||||
virtual void writeXml( QDomElement& parentElement ) override;
|
||||
|
||||
@ -88,7 +85,6 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
|
||||
QString mLayerId;
|
||||
QString mLayerName; // only used if layer does not exist
|
||||
QgsMapLayer* mLayer; // not owned! may be null
|
||||
Qt::CheckState mVisible;
|
||||
};
|
||||
|
||||
|
||||
|
@ -284,12 +284,12 @@ QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
|
||||
if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QgsWkbTypes::NullGeometry )
|
||||
return QVariant(); // do not show checkbox for non-spatial tables
|
||||
}
|
||||
return nodeLayer->isVisible();
|
||||
return nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
else if ( QgsLayerTree::isGroup( node ) )
|
||||
{
|
||||
QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
|
||||
return nodeGroup->isVisible();
|
||||
return nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
}
|
||||
else if ( role == Qt::FontRole )
|
||||
@ -307,7 +307,7 @@ QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
|
||||
if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
const QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer();
|
||||
if ( layer && !layer->isInScaleRange( mLegendMapViewScale ) )
|
||||
if ( !node->isVisible() || ( layer && !layer->isInScaleRange( mLegendMapViewScale ) ) )
|
||||
{
|
||||
brush.setColor( Qt::lightGray );
|
||||
}
|
||||
@ -393,20 +393,22 @@ bool QgsLayerTreeModel::setData( const QModelIndex& index, const QVariant& value
|
||||
if ( !testFlag( AllowNodeChangeVisibility ) )
|
||||
return false;
|
||||
|
||||
if ( QgsLayerTree::isLayer( node ) )
|
||||
bool checked = static_cast< Qt::CheckState >( value.toInt() ) == Qt::Checked;
|
||||
if ( checked && node->children().isEmpty() )
|
||||
{
|
||||
QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
|
||||
layer->setVisible( static_cast< Qt::CheckState >( value.toInt() ) );
|
||||
return true;
|
||||
node->setItemVisibilityCheckedParentRecursive( checked );
|
||||
}
|
||||
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
else if ( testFlag( ActionHierarchical ) )
|
||||
{
|
||||
QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
|
||||
group->setVisible( static_cast< Qt::CheckState >( value.toInt() ) );
|
||||
return true;
|
||||
if ( node->children().isEmpty() )
|
||||
node->setItemVisibilityCheckedParentRecursive( checked );
|
||||
else
|
||||
node->setItemVisibilityCheckedRecursive( checked );
|
||||
}
|
||||
else
|
||||
{
|
||||
node->setItemVisibilityChecked( checked );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( role == Qt::EditRole )
|
||||
@ -934,7 +936,7 @@ void QgsLayerTreeModel::connectToRootNode()
|
||||
connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
|
||||
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
|
||||
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
|
||||
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
|
||||
connect( mRootNode, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeModel::nodeVisibilityChanged );
|
||||
connect( mRootNode, SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeNameChanged( QgsLayerTreeNode*, QString ) ) );
|
||||
|
||||
connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
|
||||
|
@ -87,6 +87,7 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
|
||||
AllowNodeRename = 0x2000, //!< Allow renaming of groups and layers
|
||||
AllowNodeChangeVisibility = 0x4000, //!< Allow user to set node visibility with a check box
|
||||
AllowLegendChangeState = 0x8000, //!< Allow check boxes for legend nodes (if supported by layer's legend)
|
||||
ActionHierarchical = 0x10000, //!< Check/uncheck action has consequences on children (or parents for leaf node)
|
||||
};
|
||||
Q_DECLARE_FLAGS( Flags, Flag )
|
||||
|
||||
|
@ -22,8 +22,9 @@
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
QgsLayerTreeNode::QgsLayerTreeNode( QgsLayerTreeNode::NodeType t )
|
||||
QgsLayerTreeNode::QgsLayerTreeNode( QgsLayerTreeNode::NodeType t, bool checked )
|
||||
: mNodeType( t )
|
||||
, mChecked( checked )
|
||||
, mParent( nullptr )
|
||||
, mExpanded( true )
|
||||
{
|
||||
@ -32,6 +33,7 @@ QgsLayerTreeNode::QgsLayerTreeNode( QgsLayerTreeNode::NodeType t )
|
||||
QgsLayerTreeNode::QgsLayerTreeNode( const QgsLayerTreeNode& other )
|
||||
: QObject()
|
||||
, mNodeType( other.mNodeType )
|
||||
, mChecked( other.mChecked )
|
||||
, mParent( nullptr )
|
||||
, mExpanded( other.mExpanded )
|
||||
, mProperties( other.mProperties )
|
||||
@ -59,11 +61,62 @@ QgsLayerTreeNode* QgsLayerTreeNode::readXml( QDomElement& element )
|
||||
}
|
||||
|
||||
|
||||
void QgsLayerTreeNode::setItemVisibilityChecked( bool checked )
|
||||
{
|
||||
if ( mChecked == checked )
|
||||
return;
|
||||
mChecked = checked;
|
||||
emit visibilityChanged( this );
|
||||
}
|
||||
|
||||
void QgsLayerTreeNode::setItemVisibilityCheckedRecursive( bool checked )
|
||||
{
|
||||
setItemVisibilityChecked( checked );
|
||||
}
|
||||
|
||||
void QgsLayerTreeNode::setItemVisibilityCheckedParentRecursive( bool checked )
|
||||
{
|
||||
setItemVisibilityChecked( checked );
|
||||
if ( mParent )
|
||||
mParent->setItemVisibilityCheckedParentRecursive( checked );
|
||||
}
|
||||
|
||||
bool QgsLayerTreeNode::isVisible() const
|
||||
{
|
||||
return mChecked && ( !mParent || mParent->isVisible() );
|
||||
}
|
||||
|
||||
|
||||
bool QgsLayerTreeNode::isExpanded() const
|
||||
{
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
bool QgsLayerTreeNode::isItemVisibilityCheckedRecursive() const
|
||||
{
|
||||
if ( !mChecked )
|
||||
return false;
|
||||
Q_FOREACH ( QgsLayerTreeNode* child, mChildren )
|
||||
{
|
||||
if ( !child->isItemVisibilityCheckedRecursive() )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsLayerTreeNode::isItemVisibilityUncheckedRecursive() const
|
||||
{
|
||||
if ( mChecked )
|
||||
return false;
|
||||
Q_FOREACH ( QgsLayerTreeNode* child, mChildren )
|
||||
{
|
||||
if ( !child->isItemVisibilityUncheckedRecursive() )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsLayerTreeNode::setExpanded( bool expanded )
|
||||
{
|
||||
@ -134,7 +187,7 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*
|
||||
connect( nodes[i], SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
|
||||
connect( nodes[i], SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ) );
|
||||
connect( nodes[i], SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ) );
|
||||
connect( nodes[i], SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ) );
|
||||
connect( nodes[i], &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeNode::visibilityChanged );
|
||||
connect( nodes[i], SIGNAL( expandedChanged( QgsLayerTreeNode*, bool ) ), this, SIGNAL( expandedChanged( QgsLayerTreeNode*, bool ) ) );
|
||||
connect( nodes[i], SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ), this, SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ) );
|
||||
}
|
||||
|
@ -82,6 +82,8 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
|
||||
QgsLayerTreeNode *parent() { return mParent; }
|
||||
//! Get list of children of the node. Children are owned by the parent
|
||||
QList<QgsLayerTreeNode*> children() { return mChildren; }
|
||||
//! Get list of children of the node. Children are owned by the parent
|
||||
const QList<QgsLayerTreeNode*>& children() const { return mChildren; }
|
||||
|
||||
//! Return name of the node
|
||||
//! @note added in 3.0
|
||||
@ -101,6 +103,34 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
|
||||
//! Create a copy of the node. Returns new instance
|
||||
virtual QgsLayerTreeNode *clone() const = 0;
|
||||
|
||||
//! Returns whether a node is really visible (ie checked and all its ancestors checked as well)
|
||||
//! @note added in 3.0
|
||||
bool isVisible() const;
|
||||
|
||||
//! Returns whether a node is checked (independantly of its ancestors or children)
|
||||
//! @note added in 3.0
|
||||
bool itemVisibilityChecked() const { return mChecked; }
|
||||
|
||||
//! Check or uncheck a node (independantly of its ancestors or children)
|
||||
//! @note added in 3.0
|
||||
void setItemVisibilityChecked( bool checked );
|
||||
|
||||
//! Check or uncheck a node and all its children (taking into account exclusion rules)
|
||||
//! @note added in 3.0
|
||||
virtual void setItemVisibilityCheckedRecursive( bool checked );
|
||||
|
||||
//! Check or uncheck a node and all its parents
|
||||
//! @note added in 3.0
|
||||
void setItemVisibilityCheckedParentRecursive( bool checked );
|
||||
|
||||
//! Return whether this node is checked and all its children.
|
||||
//! @note added in 3.0
|
||||
bool isItemVisibilityCheckedRecursive() const;
|
||||
|
||||
//! Return whether this node is unchecked and all its children.
|
||||
//! @note added in 3.0
|
||||
bool isItemVisibilityUncheckedRecursive() const;
|
||||
|
||||
//! Return whether the node should be shown as expanded or collapsed in GUI
|
||||
bool isExpanded() const;
|
||||
//! Set whether the node should be shown as expanded or collapsed in GUI
|
||||
@ -128,7 +158,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
|
||||
//! Emitted when one or more nodes has been removed from a node within the tree
|
||||
void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
|
||||
//! Emitted when check state of a node within the tree has been changed
|
||||
void visibilityChanged( QgsLayerTreeNode *node, Qt::CheckState state );
|
||||
void visibilityChanged( QgsLayerTreeNode *node );
|
||||
//! Emitted when a custom property of a node within the tree has been changed or removed
|
||||
void customPropertyChanged( QgsLayerTreeNode *node, const QString& key );
|
||||
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
|
||||
@ -139,12 +169,15 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
|
||||
|
||||
protected:
|
||||
|
||||
QgsLayerTreeNode( NodeType t );
|
||||
//! Constructor
|
||||
QgsLayerTreeNode( NodeType t, bool checked = true );
|
||||
QgsLayerTreeNode( const QgsLayerTreeNode &other );
|
||||
|
||||
// low-level utility functions
|
||||
|
||||
//! Read common XML elements.
|
||||
void readCommonXml( QDomElement &element );
|
||||
//! Write common XML elements.
|
||||
void writeCommonXml( QDomElement &element );
|
||||
|
||||
//! Low-level insertion of children to the node. The children must not have any parent yet!
|
||||
@ -155,6 +188,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
|
||||
protected:
|
||||
//! type of the node - determines which subclass is used
|
||||
NodeType mNodeType;
|
||||
bool mChecked;
|
||||
//! pointer to the parent node - null in case of root node
|
||||
QgsLayerTreeNode *mParent;
|
||||
//! list of children - node is responsible for their deletion
|
||||
|
@ -52,7 +52,7 @@ void QgsLayerTreeRegistryBridge::layersAdded( const QList<QgsMapLayer*>& layers
|
||||
Q_FOREACH ( QgsMapLayer* layer, layers )
|
||||
{
|
||||
QgsLayerTreeLayer* nodeLayer = new QgsLayerTreeLayer( layer );
|
||||
nodeLayer->setVisible( mNewLayersVisible ? Qt::Checked : Qt::Unchecked );
|
||||
nodeLayer->setItemVisibilityChecked( mNewLayersVisible );
|
||||
|
||||
nodes << nodeLayer;
|
||||
|
||||
|
@ -112,7 +112,7 @@ static QDomElement _writeOldLegendLayer( QDomDocument& doc, QgsLayerTreeLayer* n
|
||||
QDomElement layerElem = doc.createElement( QStringLiteral( "legendlayer" ) );
|
||||
layerElem.setAttribute( QStringLiteral( "drawingOrder" ), drawingOrder );
|
||||
layerElem.setAttribute( QStringLiteral( "open" ), nodeLayer->isExpanded() ? "true" : "false" );
|
||||
layerElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeLayer->isVisible() ) );
|
||||
layerElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
|
||||
layerElem.setAttribute( QStringLiteral( "name" ), nodeLayer->name() );
|
||||
layerElem.setAttribute( QStringLiteral( "showFeatureCount" ), nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ) ).toInt() );
|
||||
|
||||
@ -123,7 +123,7 @@ static QDomElement _writeOldLegendLayer( QDomDocument& doc, QgsLayerTreeLayer* n
|
||||
QDomElement layerFileElem = doc.createElement( QStringLiteral( "legendlayerfile" ) );
|
||||
layerFileElem.setAttribute( QStringLiteral( "isInOverview" ), nodeLayer->customProperty( QStringLiteral( "overview" ) ).toInt() );
|
||||
layerFileElem.setAttribute( QStringLiteral( "layerid" ), nodeLayer->layerId() );
|
||||
layerFileElem.setAttribute( QStringLiteral( "visible" ), nodeLayer->isVisible() == Qt::Checked ? 1 : 0 );
|
||||
layerFileElem.setAttribute( QStringLiteral( "visible" ), nodeLayer->isVisible() ? 1 : 0 );
|
||||
|
||||
layerElem.appendChild( fileGroupElem );
|
||||
fileGroupElem.appendChild( layerFileElem );
|
||||
@ -138,7 +138,7 @@ static QDomElement _writeOldLegendGroup( QDomDocument& doc, QgsLayerTreeGroup* n
|
||||
QDomElement groupElem = doc.createElement( QStringLiteral( "legendgroup" ) );
|
||||
groupElem.setAttribute( QStringLiteral( "open" ), nodeGroup->isExpanded() ? "true" : "false" );
|
||||
groupElem.setAttribute( QStringLiteral( "name" ), nodeGroup->name() );
|
||||
groupElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeGroup->isVisible() ) );
|
||||
groupElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
|
||||
|
||||
if ( nodeGroup->customProperty( QStringLiteral( "embedded" ) ).toInt() )
|
||||
{
|
||||
@ -210,7 +210,7 @@ static void _readOldLegendGroup( const QDomElement& groupElem, QgsLayerTreeGroup
|
||||
|
||||
QgsLayerTreeGroup* groupNode = new QgsLayerTreeGroup( groupElem.attribute( QStringLiteral( "name" ) ) );
|
||||
|
||||
groupNode->setVisible( QgsLayerTreeUtils::checkStateFromXml( groupElem.attribute( QStringLiteral( "checked" ) ) ) );
|
||||
groupNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( groupElem.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked );
|
||||
groupNode->setExpanded( groupElem.attribute( QStringLiteral( "open" ) ) == QLatin1String( "true" ) );
|
||||
|
||||
if ( groupElem.attribute( QStringLiteral( "embedded" ) ) == QLatin1String( "1" ) )
|
||||
@ -241,7 +241,7 @@ static void _readOldLegendLayer( const QDomElement& layerElem, QgsLayerTreeGroup
|
||||
QString layerId = layerFileElem.attribute( QStringLiteral( "layerid" ) );
|
||||
QgsLayerTreeLayer* layerNode = new QgsLayerTreeLayer( layerId, layerElem.attribute( QStringLiteral( "name" ) ) );
|
||||
|
||||
layerNode->setVisible( QgsLayerTreeUtils::checkStateFromXml( layerElem.attribute( QStringLiteral( "checked" ) ) ) );
|
||||
layerNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( layerElem.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked );
|
||||
layerNode->setExpanded( layerElem.attribute( QStringLiteral( "open" ) ) == QLatin1String( "true" ) );
|
||||
|
||||
if ( layerFileElem.attribute( QStringLiteral( "isInOverview" ) ) == QLatin1String( "1" ) )
|
||||
|
@ -103,7 +103,7 @@ void QgsMapThemeCollection::applyThemeToLayer( QgsLayerTreeLayer* nodeLayer, Qgs
|
||||
MapThemeLayerRecord layerRec;
|
||||
bool isVisible = findRecordForLayer( nodeLayer->layer(), rec, layerRec );
|
||||
|
||||
nodeLayer->setVisible( isVisible ? Qt::Checked : Qt::Unchecked );
|
||||
nodeLayer->setItemVisibilityChecked( isVisible );
|
||||
|
||||
if ( !isVisible )
|
||||
return;
|
||||
|
@ -2009,7 +2009,7 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co
|
||||
QgsLayerTreeLayer *layer = newGroup->findLayer( layerId );
|
||||
if ( layer )
|
||||
{
|
||||
layer->setVisible( invisibleLayers.contains( layerId ) ? Qt::Unchecked : Qt::Checked );
|
||||
layer->setItemVisibilityChecked( invisibleLayers.contains( layerId ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ QgsCustomLayerOrderWidget::QgsCustomLayerOrderWidget( QgsLayerTreeMapCanvasBridg
|
||||
connect( mModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( modelUpdated() ) );
|
||||
connect( mModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( modelUpdated() ) );
|
||||
|
||||
connect( bridge->rootGroup(), SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ) );
|
||||
connect( bridge->rootGroup(), &QgsLayerTreeNode::visibilityChanged, this, &QgsCustomLayerOrderWidget::nodeVisibilityChanged );
|
||||
|
||||
QVBoxLayout* l = new QVBoxLayout;
|
||||
l->setMargin( 0 );
|
||||
@ -76,9 +76,8 @@ void QgsCustomLayerOrderWidget::bridgeCustomLayerOrderChanged( const QStringList
|
||||
mModel->refreshModel( mBridge->hasCustomLayerOrder() ? mBridge->customLayerOrder() : mBridge->defaultLayerOrder() );
|
||||
}
|
||||
|
||||
void QgsCustomLayerOrderWidget::nodeVisibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state )
|
||||
void QgsCustomLayerOrderWidget::nodeVisibilityChanged( QgsLayerTreeNode* node )
|
||||
{
|
||||
Q_UNUSED( state );
|
||||
if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
mModel->updateLayerVisibility( QgsLayerTree::toLayer( node )->layerId() );
|
||||
@ -141,7 +140,7 @@ bool CustomLayerOrderModel::setData( const QModelIndex& index, const QVariant& v
|
||||
QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
|
||||
if ( nodeLayer )
|
||||
{
|
||||
nodeLayer->setVisible( static_cast< Qt::CheckState >( value.toInt() ) );
|
||||
nodeLayer->setItemVisibilityChecked( static_cast< Qt::CheckState >( value.toInt() ) == Qt::Checked );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ class GUI_EXPORT QgsCustomLayerOrderWidget : public QWidget
|
||||
protected slots:
|
||||
void bridgeHasCustomLayerOrderChanged( bool state );
|
||||
void bridgeCustomLayerOrderChanged( const QStringList& order );
|
||||
void nodeVisibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
|
||||
//! Slot triggered when the ivsibility of a node changes
|
||||
void nodeVisibilityChanged( QgsLayerTreeNode* node );
|
||||
|
||||
void modelUpdated();
|
||||
|
||||
|
@ -37,7 +37,7 @@ QgsLayerTreeMapCanvasBridge::QgsLayerTreeMapCanvasBridge( QgsLayerTreeGroup *roo
|
||||
connect( root, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
|
||||
connect( root, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
|
||||
connect( root, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
|
||||
connect( root, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged() ) );
|
||||
connect( root, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged );
|
||||
|
||||
setCanvasLayers();
|
||||
}
|
||||
@ -127,7 +127,7 @@ void QgsLayerTreeMapCanvasBridge::setCanvasLayers()
|
||||
QgsLayerTreeLayer* nodeLayer = mRoot->findLayer( layerId );
|
||||
if ( nodeLayer )
|
||||
{
|
||||
if ( nodeLayer->isVisible() == Qt::Checked )
|
||||
if ( nodeLayer->isVisible() )
|
||||
canvasLayers << nodeLayer->layer();
|
||||
if ( nodeLayer->customProperty( QStringLiteral( "overview" ), 0 ).toInt() )
|
||||
overviewLayers << nodeLayer->layer();
|
||||
@ -262,7 +262,7 @@ void QgsLayerTreeMapCanvasBridge::setCanvasLayers( QgsLayerTreeNode *node, QList
|
||||
if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
|
||||
if ( nodeLayer->isVisible() == Qt::Checked )
|
||||
if ( nodeLayer->isVisible() )
|
||||
canvasLayers << nodeLayer->layer();
|
||||
if ( nodeLayer->customProperty( QStringLiteral( "overview" ), 0 ).toInt() )
|
||||
overviewLayers << nodeLayer->layer();
|
||||
|
@ -382,3 +382,25 @@ void QgsLayerTreeView::collapseAllNodes()
|
||||
_expandAllNodes( layerTreeModel()->rootGroup(), false, layerTreeModel() );
|
||||
collapseAll();
|
||||
}
|
||||
|
||||
void QgsLayerTreeView::mouseReleaseEvent( QMouseEvent *event )
|
||||
{
|
||||
const QgsLayerTreeModel::Flags oldFlags = layerTreeModel()->flags();
|
||||
if ( event->modifiers() & Qt::ControlModifier )
|
||||
layerTreeModel()->setFlags( oldFlags | QgsLayerTreeModel::ActionHierarchical );
|
||||
else
|
||||
layerTreeModel()->setFlags( oldFlags & ~QgsLayerTreeModel::ActionHierarchical );
|
||||
QTreeView::mouseReleaseEvent( event );
|
||||
layerTreeModel()->setFlags( oldFlags );
|
||||
}
|
||||
|
||||
void QgsLayerTreeView::keyPressEvent( QKeyEvent *event )
|
||||
{
|
||||
const QgsLayerTreeModel::Flags oldFlags = layerTreeModel()->flags();
|
||||
if ( event->modifiers() & Qt::ControlModifier )
|
||||
layerTreeModel()->setFlags( oldFlags | QgsLayerTreeModel::ActionHierarchical );
|
||||
else
|
||||
layerTreeModel()->setFlags( oldFlags & ~QgsLayerTreeModel::ActionHierarchical );
|
||||
QTreeView::keyPressEvent( event );
|
||||
layerTreeModel()->setFlags( oldFlags );
|
||||
}
|
||||
|
@ -111,6 +111,9 @@ class GUI_EXPORT QgsLayerTreeView : public QTreeView
|
||||
|
||||
QgsMapLayer* layerForIndex( const QModelIndex& index ) const;
|
||||
|
||||
void mouseReleaseEvent( QMouseEvent *event ) override;
|
||||
void keyPressEvent( QKeyEvent *event ) override;
|
||||
|
||||
protected slots:
|
||||
|
||||
void modelRowsInserted( const QModelIndex& index, int start, int end );
|
||||
|
@ -123,6 +123,60 @@ QAction* QgsLayerTreeViewDefaultActions::actionMutuallyExclusiveGroup( QObject*
|
||||
return a;
|
||||
}
|
||||
|
||||
QAction* QgsLayerTreeViewDefaultActions::actionCheckAndAllChildren( QObject* parent )
|
||||
{
|
||||
QgsLayerTreeNode* node = mView->currentNode();
|
||||
if ( !node || !QgsLayerTree::isGroup( node ) || node->isItemVisibilityCheckedRecursive() )
|
||||
return nullptr;
|
||||
QAction* a = new QAction( tr( "Check and all its children (Ctrl-click)" ), parent );
|
||||
connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::checkAndAllChildren );
|
||||
return a;
|
||||
}
|
||||
|
||||
QAction* QgsLayerTreeViewDefaultActions::actionUncheckAndAllChildren( QObject* parent )
|
||||
{
|
||||
QgsLayerTreeNode* node = mView->currentNode();
|
||||
if ( !node || !QgsLayerTree::isGroup( node ) || node->isItemVisibilityUncheckedRecursive() )
|
||||
return nullptr;
|
||||
QAction* a = new QAction( tr( "Uncheck and all its children (Ctrl-click)" ), parent );
|
||||
connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::uncheckAndAllChildren );
|
||||
return a;
|
||||
}
|
||||
|
||||
QAction* QgsLayerTreeViewDefaultActions::actionCheckAndAllParents( QObject* parent )
|
||||
{
|
||||
QgsLayerTreeNode* node = mView->currentNode();
|
||||
if ( !node || !QgsLayerTree::isLayer( node ) || node->isVisible() )
|
||||
return nullptr;
|
||||
QAction* a = new QAction( tr( "Check and all its parents" ), parent );
|
||||
connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::checkAndAllParents );
|
||||
return a;
|
||||
}
|
||||
|
||||
void QgsLayerTreeViewDefaultActions::checkAndAllChildren()
|
||||
{
|
||||
QgsLayerTreeNode* node = mView->currentNode();
|
||||
if ( !node )
|
||||
return;
|
||||
node->setItemVisibilityCheckedRecursive( true );
|
||||
}
|
||||
|
||||
void QgsLayerTreeViewDefaultActions::uncheckAndAllChildren()
|
||||
{
|
||||
QgsLayerTreeNode* node = mView->currentNode();
|
||||
if ( !node )
|
||||
return;
|
||||
node->setItemVisibilityCheckedRecursive( false );
|
||||
}
|
||||
|
||||
void QgsLayerTreeViewDefaultActions::checkAndAllParents()
|
||||
{
|
||||
QgsLayerTreeNode* node = mView->currentNode();
|
||||
if ( !node )
|
||||
return;
|
||||
node->setItemVisibilityCheckedParentRecursive( true );
|
||||
}
|
||||
|
||||
void QgsLayerTreeViewDefaultActions::addGroup()
|
||||
{
|
||||
QgsLayerTreeGroup* group = mView->currentGroupNode();
|
||||
|
@ -46,6 +46,15 @@ class GUI_EXPORT QgsLayerTreeViewDefaultActions : public QObject
|
||||
QAction* actionRenameGroupOrLayer( QObject* parent = nullptr );
|
||||
QAction* actionShowFeatureCount( QObject* parent = nullptr );
|
||||
|
||||
//! Action to check a group and all its children
|
||||
QAction* actionCheckAndAllChildren( QObject* parent = nullptr );
|
||||
|
||||
//! Action to uncheck a group and all its children
|
||||
QAction* actionUncheckAndAllChildren( QObject* parent = nullptr );
|
||||
|
||||
//! Action to check a group and all its parents
|
||||
QAction* actionCheckAndAllParents( QObject* parent = nullptr );
|
||||
|
||||
QAction* actionZoomToLayer( QgsMapCanvas* canvas, QObject* parent = nullptr );
|
||||
QAction* actionZoomToGroup( QgsMapCanvas* canvas, QObject* parent = nullptr );
|
||||
// TODO: zoom to selected
|
||||
@ -75,6 +84,11 @@ class GUI_EXPORT QgsLayerTreeViewDefaultActions : public QObject
|
||||
//! @note added in 2.12
|
||||
void mutuallyExclusiveGroup();
|
||||
|
||||
private slots:
|
||||
void checkAndAllChildren();
|
||||
void uncheckAndAllChildren();
|
||||
void checkAndAllParents();
|
||||
|
||||
protected:
|
||||
void zoomToLayers( QgsMapCanvas* canvas, const QList<QgsMapLayer*>& layers );
|
||||
|
||||
|
@ -180,12 +180,12 @@ void QgsOfflineEditingPluginGui::restoreState()
|
||||
void QgsOfflineEditingPluginGui::selectAll()
|
||||
{
|
||||
Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, mLayerTree->layerTreeModel()->rootGroup()->findLayers() )
|
||||
nodeLayer->setVisible( Qt::Checked );
|
||||
nodeLayer->setItemVisibilityChecked( true );
|
||||
}
|
||||
|
||||
|
||||
void QgsOfflineEditingPluginGui::unSelectAll()
|
||||
{
|
||||
Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, mLayerTree->layerTreeModel()->rootGroup()->findLayers() )
|
||||
nodeLayer->setVisible( Qt::Unchecked );
|
||||
nodeLayer->setItemVisibilityChecked( false );
|
||||
}
|
||||
|
@ -37,8 +37,7 @@ class TestQgsLayerTree : public QObject
|
||||
void cleanupTestCase();
|
||||
void testGroupNameChanged();
|
||||
void testLayerNameChanged();
|
||||
void testCheckStateParentToChild();
|
||||
void testCheckStateChildToParent();
|
||||
void testCheckStateHiearchical();
|
||||
void testCheckStateMutuallyExclusive();
|
||||
void testCheckStateMutuallyExclusiveEdgeCases();
|
||||
void testShowHideAllSymbolNodes();
|
||||
@ -53,13 +52,19 @@ class TestQgsLayerTree : public QObject
|
||||
|
||||
void testRendererLegend( QgsFeatureRenderer* renderer );
|
||||
|
||||
Qt::CheckState childState( int childIndex )
|
||||
bool childVisiblity( int childIndex ) const
|
||||
{
|
||||
return QgsLayerTree::toGroup( mRoot->children().at( childIndex ) )->isVisible();
|
||||
return mRoot->children().at( childIndex )->isVisible();
|
||||
}
|
||||
void setChildState( int childIndex, Qt::CheckState state )
|
||||
|
||||
bool visibilityChecked( int childIndex ) const
|
||||
{
|
||||
QgsLayerTree::toGroup( mRoot->children().at( childIndex ) )->setVisible( state );
|
||||
return mRoot->children().at( childIndex )->itemVisibilityChecked();
|
||||
}
|
||||
|
||||
void setVisibilityChecked( int childIndex, bool state )
|
||||
{
|
||||
mRoot->children().at( childIndex )->setItemVisibilityChecked( state );
|
||||
}
|
||||
};
|
||||
|
||||
@ -142,39 +147,27 @@ void TestQgsLayerTree::testLayerNameChanged()
|
||||
mRoot->removeChildNode( n );
|
||||
}
|
||||
|
||||
void TestQgsLayerTree::testCheckStateParentToChild()
|
||||
void TestQgsLayerTree::testCheckStateHiearchical()
|
||||
{
|
||||
mRoot->setVisible( Qt::Unchecked );
|
||||
mRoot->setItemVisibilityCheckedRecursive( false );
|
||||
QCOMPARE( mRoot->isItemVisibilityCheckedRecursive(), false );
|
||||
QCOMPARE( mRoot->isItemVisibilityUncheckedRecursive(), true );
|
||||
QCOMPARE( visibilityChecked( 0 ), false );
|
||||
QCOMPARE( visibilityChecked( 1 ), false );
|
||||
QCOMPARE( visibilityChecked( 2 ), false );
|
||||
|
||||
// all children unchecked
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Unchecked );
|
||||
mRoot->children().at( 0 )->setItemVisibilityCheckedParentRecursive( true );
|
||||
QCOMPARE( mRoot->itemVisibilityChecked(), true );
|
||||
|
||||
mRoot->setVisible( Qt::Checked );
|
||||
QCOMPARE( mRoot->isItemVisibilityCheckedRecursive(), false );
|
||||
QCOMPARE( mRoot->isItemVisibilityUncheckedRecursive(), false );
|
||||
|
||||
// all children checked
|
||||
QCOMPARE( childState( 0 ), Qt::Checked );
|
||||
QCOMPARE( childState( 1 ), Qt::Checked );
|
||||
QCOMPARE( childState( 2 ), Qt::Checked );
|
||||
}
|
||||
|
||||
void TestQgsLayerTree::testCheckStateChildToParent()
|
||||
{
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
|
||||
// uncheck a child - parent should be partial
|
||||
setChildState( 0, Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::PartiallyChecked );
|
||||
setChildState( 1, Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::PartiallyChecked );
|
||||
|
||||
// uncheck last child - parent should be unchecked
|
||||
setChildState( 2, Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Unchecked );
|
||||
|
||||
// go back to original state
|
||||
mRoot->setVisible( Qt::Checked );
|
||||
mRoot->setItemVisibilityCheckedRecursive( true );
|
||||
QCOMPARE( mRoot->isItemVisibilityCheckedRecursive(), true );
|
||||
QCOMPARE( mRoot->isItemVisibilityUncheckedRecursive(), false );
|
||||
QCOMPARE( visibilityChecked( 0 ), true );
|
||||
QCOMPARE( visibilityChecked( 1 ), true );
|
||||
QCOMPARE( visibilityChecked( 2 ), true );
|
||||
}
|
||||
|
||||
void TestQgsLayerTree::testCheckStateMutuallyExclusive()
|
||||
@ -182,84 +175,83 @@ void TestQgsLayerTree::testCheckStateMutuallyExclusive()
|
||||
mRoot->setIsMutuallyExclusive( true );
|
||||
|
||||
// only first should be enabled
|
||||
QCOMPARE( childState( 0 ), Qt::Checked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked ); // fully checked, not just partial
|
||||
QCOMPARE( childVisiblity( 0 ), true );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), false );
|
||||
QCOMPARE( mRoot->isVisible(), true ); // fully checked, not just partial
|
||||
|
||||
// switch to some other child
|
||||
setChildState( 2, Qt::Checked );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Checked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
setVisibilityChecked( 2, true );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), true );
|
||||
QCOMPARE( mRoot->isVisible(), true );
|
||||
|
||||
// now uncheck the root
|
||||
mRoot->setVisible( Qt::Unchecked );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Unchecked );
|
||||
mRoot->setItemVisibilityChecked( false );
|
||||
QCOMPARE( mRoot->itemVisibilityChecked(), false );
|
||||
|
||||
// check one of the children - should also check the root
|
||||
setChildState( 2, Qt::Checked );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Checked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( visibilityChecked( 2 ), true );
|
||||
QCOMPARE( childVisiblity( 2 ), false );
|
||||
QCOMPARE( mRoot->isVisible(), false );
|
||||
|
||||
// uncheck the child - should also uncheck the root
|
||||
setChildState( 2, Qt::Unchecked );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Unchecked );
|
||||
// check one of the children - should not modify the root
|
||||
setVisibilityChecked( 2, true );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), false );
|
||||
QCOMPARE( mRoot->itemVisibilityChecked(), false );
|
||||
QCOMPARE( mRoot->isVisible(), false );
|
||||
|
||||
// check the root back - should have the same node
|
||||
mRoot->setVisible( Qt::Checked );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Checked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
// uncheck the child - should not modify the root
|
||||
setVisibilityChecked( 2, false );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), false );
|
||||
QCOMPARE( mRoot->itemVisibilityChecked(), false );
|
||||
QCOMPARE( mRoot->isVisible(), false );
|
||||
|
||||
// check the root back
|
||||
mRoot->setItemVisibilityChecked( true );
|
||||
setVisibilityChecked( 2, true );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), true );
|
||||
QCOMPARE( mRoot->isVisible(), true );
|
||||
|
||||
// remove a child
|
||||
mRoot->removeChildNode( mRoot->children().at( 0 ) );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Checked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), true );
|
||||
QCOMPARE( mRoot->isVisible(), true );
|
||||
|
||||
// add the group back - will not be checked
|
||||
mRoot->insertGroup( 0, QStringLiteral( "grp1" ) );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Checked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), true );
|
||||
QCOMPARE( mRoot->isVisible(), true );
|
||||
|
||||
// remove a child that is checked
|
||||
mRoot->removeChildNode( mRoot->children().at( 2 ) );
|
||||
QCOMPARE( childState( 0 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Unchecked );
|
||||
|
||||
// check the root again - first item should be checked
|
||||
mRoot->setVisible( Qt::Checked );
|
||||
QCOMPARE( childState( 0 ), Qt::Checked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
QCOMPARE( childVisiblity( 0 ), false );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( mRoot->isVisible(), true );
|
||||
|
||||
// add the item back
|
||||
setVisibilityChecked( 0, true );
|
||||
mRoot->addGroup( QStringLiteral( "grp3" ) );
|
||||
QCOMPARE( childState( 0 ), Qt::Checked );
|
||||
QCOMPARE( childState( 1 ), Qt::Unchecked );
|
||||
QCOMPARE( childState( 2 ), Qt::Unchecked );
|
||||
QCOMPARE( mRoot->isVisible(), Qt::Checked );
|
||||
QCOMPARE( childVisiblity( 0 ), true );
|
||||
QCOMPARE( childVisiblity( 1 ), false );
|
||||
QCOMPARE( childVisiblity( 2 ), false );
|
||||
QCOMPARE( mRoot->isVisible(), true );
|
||||
|
||||
mRoot->setIsMutuallyExclusive( false );
|
||||
|
||||
QCOMPARE( mRoot->isVisible(), Qt::PartiallyChecked );
|
||||
|
||||
// go back to original state
|
||||
mRoot->setVisible( Qt::Checked );
|
||||
mRoot->setItemVisibilityChecked( true );
|
||||
}
|
||||
|
||||
void TestQgsLayerTree::testCheckStateMutuallyExclusiveEdgeCases()
|
||||
@ -268,23 +260,23 @@ void TestQgsLayerTree::testCheckStateMutuallyExclusiveEdgeCases()
|
||||
QgsLayerTreeGroup* root2 = new QgsLayerTreeGroup();
|
||||
root2->setIsMutuallyExclusive( true );
|
||||
root2->addGroup( QStringLiteral( "1" ) );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root2->children().at( 0 ) )->isVisible(), Qt::Checked );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root2->children().at( 0 ) )->isVisible(), true );
|
||||
root2->addGroup( QStringLiteral( "2" ) );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root2->children().at( 0 ) )->isVisible(), Qt::Checked );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root2->children().at( 1 ) )->isVisible(), Qt::Unchecked );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root2->children().at( 0 ) )->isVisible(), true );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root2->children().at( 1 ) )->isVisible(), false );
|
||||
delete root2;
|
||||
|
||||
// check-uncheck the only child
|
||||
QgsLayerTreeGroup* root3 = new QgsLayerTreeGroup();
|
||||
root3->setIsMutuallyExclusive( true );
|
||||
root3->addGroup( QStringLiteral( "1" ) );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root3->children().at( 0 ) )->isVisible(), Qt::Checked );
|
||||
QgsLayerTree::toGroup( root3->children().at( 0 ) )->setVisible( Qt::Unchecked );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root3->children().at( 0 ) )->isVisible(), Qt::Unchecked );
|
||||
QCOMPARE( root3->isVisible(), Qt::Unchecked );
|
||||
QgsLayerTree::toGroup( root3->children().at( 0 ) )->setVisible( Qt::Checked );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root3->children().at( 0 ) )->isVisible(), Qt::Checked );
|
||||
QCOMPARE( root3->isVisible(), Qt::Checked );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root3->children().at( 0 ) )->isVisible(), true );
|
||||
QgsLayerTree::toGroup( root3->children().at( 0 ) )->setItemVisibilityChecked( false );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root3->children().at( 0 ) )->isVisible(), false );
|
||||
QCOMPARE( root3->isVisible(), true );
|
||||
QgsLayerTree::toGroup( root3->children().at( 0 ) )->setItemVisibilityChecked( true );
|
||||
QCOMPARE( QgsLayerTree::toGroup( root3->children().at( 0 ) )->isVisible(), true );
|
||||
QCOMPARE( root3->isVisible(), true );
|
||||
delete root3;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user