Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] Indicators for layer tree view + filter indicator implement…
…ation This adds a mini-framework for display of extra icons in layer tree views next to layer and group names. Tool tip text can be associated with indicators to give extra context for indicators. In addition, a signal gets emitted when user clicks indicators and custom actions can be defined. The main window's layer tree view (ToC) gets support for indicators that are shown when a vector layer has a filter applied. This makes it easier for users to understand that they are looking at a subset of all data. Clicking the indicator's icon brings up query builder.
- Loading branch information
Showing
14 changed files
with
708 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/gui/layertree/qgslayertreeviewindicator.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ | ||
|
||
|
||
|
||
|
||
class QgsLayerTreeViewIndicator : QObject | ||
{ | ||
%Docstring | ||
Indicator that can be used in a layer tree view to display icons next to items of the layer tree. | ||
They add extra context to the item and interactivity (using clicked() signal). | ||
|
||
Indicators can be added/removed to individual layer tree items using :py:func:`QgsLayerTreeView.addIndicator()` | ||
and QgsLayerTreeView.removeIndicator() calls. | ||
|
||
.. versionadded:: 3.2 | ||
%End | ||
|
||
%TypeHeaderCode | ||
#include "qgslayertreeviewindicator.h" | ||
%End | ||
public: | ||
explicit QgsLayerTreeViewIndicator( QObject *parent /TransferThis/ = 0 ); | ||
|
||
QIcon icon() const; | ||
%Docstring | ||
Indicator icon that will be displayed in the layer tree view | ||
%End | ||
void setIcon( const QIcon &icon ); | ||
%Docstring | ||
Sets indicator icon that will be displayed in the layer tree view | ||
%End | ||
|
||
QString toolTip() const; | ||
%Docstring | ||
Returns tool tip text that will be shown when user hovers mouse over the indicator | ||
%End | ||
void setToolTip( const QString &tip ); | ||
%Docstring | ||
Sets tool tip text | ||
%End | ||
|
||
signals: | ||
void clicked( const QModelIndex &index ); | ||
%Docstring | ||
Signal that is emitted when user clicks on the indicator | ||
%End | ||
|
||
}; | ||
|
||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/gui/layertree/qgslayertreeviewindicator.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/*************************************************************************** | ||
qgslayertreeviewfilterindicator.cpp | ||
-------------------------------------- | ||
Date : Januray 2018 | ||
Copyright : (C) 2018 by Martin Dobias | ||
Email : wonder dot sk at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgslayertreeviewfilterindicator.h" | ||
|
||
#include "qgslayertree.h" | ||
#include "qgslayertreemodel.h" | ||
#include "qgslayertreeview.h" | ||
#include "qgsquerybuilder.h" | ||
#include "qgsvectorlayer.h" | ||
|
||
|
||
QgsLayerTreeViewFilterIndicatorManager::QgsLayerTreeViewFilterIndicatorManager( QgsLayerTreeView *view ) | ||
: QObject( view ) | ||
, mLayerTreeView( view ) | ||
{ | ||
mIndicator = new QgsLayerTreeViewIndicator( this ); | ||
mIndicator->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFilter2.svg" ) ) ); | ||
mIndicator->setToolTip( "Filtered" ); | ||
connect( mIndicator, &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewFilterIndicatorManager::onIndicatorClicked ); | ||
|
||
QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup(); | ||
onAddedChildren( tree, 0, tree->children().count() - 1 ); | ||
|
||
connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewFilterIndicatorManager::onAddedChildren ); | ||
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewFilterIndicatorManager::onWillRemoveChildren ); | ||
} | ||
|
||
|
||
void QgsLayerTreeViewFilterIndicatorManager::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ) | ||
{ | ||
// recursively connect to providers' dataChanged() signal | ||
|
||
QList<QgsLayerTreeNode *> children = node->children(); | ||
for ( int i = indexFrom; i <= indexTo; ++i ) | ||
{ | ||
QgsLayerTreeNode *childNode = children[i]; | ||
|
||
if ( QgsLayerTree::isGroup( childNode ) ) | ||
{ | ||
onAddedChildren( childNode, 0, childNode->children().count() - 1 ); | ||
} | ||
else if ( QgsLayerTree::isLayer( childNode ) ) | ||
{ | ||
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode ); | ||
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) ) | ||
{ | ||
if ( vlayer->dataProvider() ) | ||
{ | ||
connect( vlayer->dataProvider(), &QgsDataProvider::dataChanged, this, &QgsLayerTreeViewFilterIndicatorManager::onProviderDataChanged ); | ||
|
||
addOrRemoveIndicator( childLayerNode, vlayer->dataProvider() ); | ||
} | ||
} | ||
else if ( !childLayerNode->layer() ) | ||
{ | ||
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved) | ||
connect( childLayerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewFilterIndicatorManager::onLayerLoaded ); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
void QgsLayerTreeViewFilterIndicatorManager::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ) | ||
{ | ||
// recursively disconnect from providers' dataChanged() signal | ||
|
||
QList<QgsLayerTreeNode *> children = node->children(); | ||
for ( int i = indexFrom; i <= indexTo; ++i ) | ||
{ | ||
QgsLayerTreeNode *childNode = children[i]; | ||
|
||
if ( QgsLayerTree::isGroup( childNode ) ) | ||
{ | ||
onWillRemoveChildren( childNode, 0, childNode->children().count() - 1 ); | ||
} | ||
else if ( QgsLayerTree::isLayer( childNode ) ) | ||
{ | ||
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode ); | ||
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) ) | ||
{ | ||
if ( vlayer->dataProvider() ) | ||
disconnect( vlayer->dataProvider(), &QgsDataProvider::dataChanged, this, &QgsLayerTreeViewFilterIndicatorManager::onProviderDataChanged ); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
void QgsLayerTreeViewFilterIndicatorManager::onLayerLoaded() | ||
{ | ||
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( sender() ); | ||
if ( !nodeLayer ) | ||
return; | ||
|
||
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ) ) | ||
{ | ||
if ( vlayer->dataProvider() ) | ||
{ | ||
connect( vlayer->dataProvider(), &QgsDataProvider::dataChanged, this, &QgsLayerTreeViewFilterIndicatorManager::onProviderDataChanged ); | ||
|
||
addOrRemoveIndicator( nodeLayer, vlayer->dataProvider() ); | ||
} | ||
} | ||
} | ||
|
||
|
||
void QgsLayerTreeViewFilterIndicatorManager::onProviderDataChanged() | ||
{ | ||
QgsVectorDataProvider *provider = qobject_cast<QgsVectorDataProvider *>( sender() ); | ||
if ( !provider ) | ||
return; | ||
|
||
// walk the tree and find layer node that needs to be updated | ||
const QList<QgsLayerTreeLayer *> layerNodes = mLayerTreeView->layerTreeModel()->rootGroup()->findLayers(); | ||
for ( QgsLayerTreeLayer *node : layerNodes ) | ||
{ | ||
if ( node->layer() && node->layer()->dataProvider() == provider ) | ||
{ | ||
addOrRemoveIndicator( node, provider ); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
|
||
void QgsLayerTreeViewFilterIndicatorManager::onIndicatorClicked( const QModelIndex &index ) | ||
{ | ||
QgsLayerTreeNode *node = mLayerTreeView->layerTreeModel()->index2node( index ); | ||
if ( !QgsLayerTree::isLayer( node ) ) | ||
return; | ||
|
||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( QgsLayerTree::toLayer( node )->layer() ); | ||
if ( !vlayer || !vlayer->dataProvider() ) | ||
return; | ||
|
||
// launch the query builder | ||
QgsQueryBuilder qb( vlayer ); | ||
qb.setSql( vlayer->dataProvider()->subsetString() ); | ||
if ( qb.exec() ) | ||
vlayer->dataProvider()->setSubsetString( qb.sql() ); | ||
} | ||
|
||
|
||
void QgsLayerTreeViewFilterIndicatorManager::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorDataProvider *provider ) | ||
{ | ||
QString filter = provider->subsetString(); | ||
if ( !filter.isEmpty() ) | ||
mLayerTreeView->addIndicator( node, mIndicator ); | ||
else | ||
mLayerTreeView->removeIndicator( node, mIndicator ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/*************************************************************************** | ||
qgslayertreeviewfilterindicator.h | ||
-------------------------------------- | ||
Date : Januray 2018 | ||
Copyright : (C) 2018 by Martin Dobias | ||
Email : wonder dot sk at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSLAYERTREEVIEWFILTERINDICATOR_H | ||
#define QGSLAYERTREEVIEWFILTERINDICATOR_H | ||
|
||
#include "qgslayertreeviewindicator.h" | ||
|
||
class QgsLayerTreeNode; | ||
class QgsLayerTreeView; | ||
class QgsVectorDataProvider; | ||
|
||
|
||
//! Adds indicators showing whether vector layers have a filter applied. | ||
class QgsLayerTreeViewFilterIndicatorManager : public QObject | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit QgsLayerTreeViewFilterIndicatorManager( QgsLayerTreeView *view ); | ||
|
||
private slots: | ||
//! Connects to signals of layers newly added to the tree | ||
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ); | ||
//! Disconnects from layers about to be removed from the tree | ||
void onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo ); | ||
//! Starts listening to layer provider's dataChanged signal | ||
void onLayerLoaded(); | ||
//! Adds/removes indicator of a layer | ||
void onProviderDataChanged(); | ||
|
||
void onIndicatorClicked( const QModelIndex &index ); | ||
|
||
private: | ||
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorDataProvider *provider ); | ||
|
||
private: | ||
QgsLayerTreeView *mLayerTreeView; | ||
QgsLayerTreeViewIndicator *mIndicator = nullptr; | ||
}; | ||
|
||
#endif // QGSLAYERTREEVIEWFILTERINDICATOR_H |
Oops, something went wrong.