Skip to content
Permalink
Browse files

Some more indicator refactoring

Pass QgsMapLayer instance to tooltip and icon,
in case they needs updates
  • Loading branch information
elpaso committed Oct 17, 2018
1 parent a9a5039 commit 7cbba8135a256e1e724f303f67b074db296993a7
@@ -40,13 +40,15 @@ void QgsLayerTreeViewBadLayerIndicatorProvider::onIndicatorClicked( const QModel
// TODO: open source select dialog
}

QString QgsLayerTreeViewBadLayerIndicatorProvider::iconName()
QString QgsLayerTreeViewBadLayerIndicatorProvider::iconName( QgsMapLayer *layer )
{
Q_UNUSED( layer );
return QStringLiteral( "/mIndicatorBadLayer.svg" );
}

QString QgsLayerTreeViewBadLayerIndicatorProvider::tooltipText()
QString QgsLayerTreeViewBadLayerIndicatorProvider::tooltipText( QgsMapLayer *layer )
{
Q_UNUSED( layer );
return tr( "<b>Bad layer!</b><br>Layer data source could not be found, click here to set a new data source." );
}

@@ -33,8 +33,8 @@ class QgsLayerTreeViewBadLayerIndicatorProvider : public QgsLayerTreeViewIndicat
void onIndicatorClicked( const QModelIndex &index ) override;

private:
QString iconName() override;
QString tooltipText() override;
QString iconName( QgsMapLayer *layer ) override;
QString tooltipText( QgsMapLayer *layer ) override;
bool acceptLayer( QgsMapLayer *layer ) override;
};

@@ -24,115 +24,10 @@


QgsLayerTreeViewFilterIndicatorProvider::QgsLayerTreeViewFilterIndicatorProvider( QgsLayerTreeView *view )
: QObject( view )
, mLayerTreeView( view )
: QgsLayerTreeViewIndicatorProvider( view )
{
mIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIndicatorFilter.svg" ) );

QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup();
onAddedChildren( tree, 0, tree->children().count() - 1 );

connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewFilterIndicatorProvider::onAddedChildren );
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewFilterIndicatorProvider::onWillRemoveChildren );
}


void QgsLayerTreeViewFilterIndicatorProvider::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 ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );

addOrRemoveIndicator( childLayerNode, vlayer );
}
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, &QgsLayerTreeViewFilterIndicatorProvider::onLayerLoaded );
}
}
}
}


void QgsLayerTreeViewFilterIndicatorProvider::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 ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );
}
}
}
}


void QgsLayerTreeViewFilterIndicatorProvider::onLayerLoaded()
{
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( sender() );
if ( !nodeLayer )
return;

if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ) )
{
if ( vlayer )
{
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );

addOrRemoveIndicator( nodeLayer, vlayer );
}
}
}


void QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged()
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( sender() );
if ( !vlayer )
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() == vlayer )
{
addOrRemoveIndicator( node, vlayer );
break;
}
}
}


void QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked( const QModelIndex &index )
{
QgsLayerTreeNode *node = mLayerTreeView->layerTreeModel()->index2node( index );
@@ -150,57 +45,41 @@ void QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked( const QModelIn
vlayer->setSubsetString( qb.sql() );
}

std::unique_ptr<QgsLayerTreeViewIndicator> QgsLayerTreeViewFilterIndicatorProvider::newIndicator( const QString &filter )
QString QgsLayerTreeViewFilterIndicatorProvider::iconName( QgsMapLayer *layer )
{
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
indicator->setIcon( mIcon );
updateIndicator( indicator.get(), filter );
connect( indicator.get(), &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked );
mIndicators.insert( indicator.get() );
return indicator;
Q_UNUSED( layer );
return QStringLiteral( "/mIndicatorFilter.svg" );
}

void QgsLayerTreeViewFilterIndicatorProvider::updateIndicator( QgsLayerTreeViewIndicator *indicator, const QString &filter )
QString QgsLayerTreeViewFilterIndicatorProvider::tooltipText( QgsMapLayer *layer )
{
indicator->setToolTip( QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), filter ) );
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return QString();
return QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), vlayer->subsetString() );
}


void QgsLayerTreeViewFilterIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer )
void QgsLayerTreeViewFilterIndicatorProvider::connectSignals( QgsMapLayer *layer )
{
QString filter = vlayer->subsetString();
if ( !filter.isEmpty() )
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );

// maybe the indicator exists already
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
{
if ( mIndicators.contains( indicator ) )
{
updateIndicator( indicator, filter );
return;
}
}

// it does not exist: need to create a new one
mLayerTreeView->addIndicator( node, newIndicator( filter ).release() );
}
else
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
}

// there may be existing indicator we need to get rid of
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
{
if ( mIndicators.contains( indicator ) )
{
mLayerTreeView->removeIndicator( node, indicator );
indicator->deleteLater();
return;
}
}
void QgsLayerTreeViewFilterIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
}

// no indicator was there before, nothing to do
}
bool QgsLayerTreeViewFilterIndicatorProvider::acceptLayer( QgsMapLayer *layer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return false;
return ! vlayer->subsetString().isEmpty();
}

@@ -16,44 +16,27 @@
#ifndef QGSLAYERTREEVIEWFILTERINDICATOR_H
#define QGSLAYERTREEVIEWFILTERINDICATOR_H

#include "qgslayertreeviewindicator.h"

#include <QSet>
#include <memory>

class QgsLayerTreeNode;
class QgsLayerTreeView;
class QgsVectorLayer;
#include "qgslayertreeviewindicatorprovider.h"

#include <QObject>

//! Adds indicators showing whether vector layers have a filter applied.
class QgsLayerTreeViewFilterIndicatorProvider : public QObject
class QgsLayerTreeViewFilterIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
{
Q_OBJECT
public:
explicit QgsLayerTreeViewFilterIndicatorProvider( 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 onSubsetStringChanged();

void onIndicatorClicked( const QModelIndex &index );

private:
std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator( const QString &filter );
void updateIndicator( QgsLayerTreeViewIndicator *indicator, const QString &filter );
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer );

private:
QgsLayerTreeView *mLayerTreeView = nullptr;
QIcon mIcon;
QSet<QgsLayerTreeViewIndicator *> mIndicators;
bool acceptLayer( QgsMapLayer *layer ) override;
QString iconName( QgsMapLayer *layer ) override;
QString tooltipText( QgsMapLayer *layer ) override;

// QgsLayerTreeViewIndicatorProvider interface
protected slots:
void onIndicatorClicked( const QModelIndex &index ) override;
void connectSignals( QgsMapLayer *layer ) override;
void disconnectSignals( QgsMapLayer *layer ) override;
};

#endif // QGSLAYERTREEVIEWFILTERINDICATOR_H
@@ -3,8 +3,8 @@
---------------------
begin : 17.10.2018
copyright : (C) 2018 by ale
email : [your-email-here]
copyright : (C) 2018 by Alessandro Pasotti
email : elpaso@itopen.it
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
@@ -82,7 +82,7 @@ void QgsLayerTreeViewIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *
{
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
disconnectSignals( childLayerNode->layer() );
disconnectSignals( childLayerNode->layer() );
}
}
}
@@ -121,33 +121,33 @@ void QgsLayerTreeViewIndicatorProvider::onLayerChanged()
}
}

void QgsLayerTreeViewIndicatorProvider::connectSignals(QgsMapLayer* layer)
void QgsLayerTreeViewIndicatorProvider::connectSignals( QgsMapLayer *layer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewIndicatorProvider::onLayerChanged );
}

void QgsLayerTreeViewIndicatorProvider::disconnectSignals(QgsMapLayer* layer)
void QgsLayerTreeViewIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
disconnect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewIndicatorProvider::onLayerChanged );
}

std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewIndicatorProvider::newIndicator()
std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewIndicatorProvider::newIndicator( QgsMapLayer *layer )
{
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
indicator->setIcon( QgsApplication::getThemeIcon( iconName() ) );
indicator->setToolTip( tooltipText() );
indicator->setIcon( QgsApplication::getThemeIcon( iconName( layer ) ) );
indicator->setToolTip( tooltipText( layer ) );
connect( indicator.get(), &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewIndicatorProvider::onIndicatorClicked );
mIndicators.insert( indicator.get() );
return indicator;
}

void QgsLayerTreeViewIndicatorProvider::addOrRemoveIndicator(QgsLayerTreeNode *node, QgsMapLayer* layer )
void QgsLayerTreeViewIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsMapLayer *layer )
{

if ( acceptLayer( layer ) )
@@ -159,12 +159,15 @@ void QgsLayerTreeViewIndicatorProvider::addOrRemoveIndicator(QgsLayerTreeNode *n
{
if ( mIndicators.contains( indicator ) )
{
// Update just in case ...
indicator->setToolTip( tooltipText( layer ) );
indicator->setIcon( QgsApplication::getThemeIcon( iconName( layer ) ) );
return;
}
}

// it does not exist: need to create a new one
mLayerTreeView->addIndicator( node, newIndicator().release() );
mLayerTreeView->addIndicator( node, newIndicator( layer ).release() );
}
else
{
@@ -3,8 +3,8 @@
---------------------
begin : 17.10.2018
copyright : (C) 2018 by ale
email : [your-email-here]
copyright : (C) 2018 by Alessandro Pasotti
email : elpaso@itopen.it
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
@@ -66,9 +66,9 @@ class QgsLayerTreeViewIndicatorProvider : public QObject
private:
//! Layer filter
virtual bool acceptLayer( QgsMapLayer *layer ) = 0;
virtual QString iconName() = 0;
virtual QString tooltipText() = 0;
virtual std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator();
virtual QString iconName( QgsMapLayer *layer ) = 0;
virtual QString tooltipText( QgsMapLayer *layer ) = 0;
virtual std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator( QgsMapLayer *layer );
virtual void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsMapLayer *layer );

protected:

0 comments on commit 7cbba81

Please sign in to comment.
You can’t perform that action at this time.