Skip to content

Commit

Permalink
Some more indicator refactoring
Browse files Browse the repository at this point in the history
Pass QgsMapLayer instance to tooltip and icon,
in case they needs updates
  • Loading branch information
elpaso committed Oct 21, 2018
1 parent a9a5039 commit 7cbba81
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 202 deletions.
6 changes: 4 additions & 2 deletions src/app/qgslayertreeviewbadlayerindicator.cpp
Expand Up @@ -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." );
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/qgslayertreeviewbadlayerindicator.h
Expand Up @@ -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;
};

Expand Down
179 changes: 29 additions & 150 deletions src/app/qgslayertreeviewfilterindicator.cpp
Expand Up @@ -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 );
Expand All @@ -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();
}

41 changes: 12 additions & 29 deletions src/app/qgslayertreeviewfilterindicator.h
Expand Up @@ -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
23 changes: 13 additions & 10 deletions src/app/qgslayertreeviewindicatorprovider.cpp
Expand Up @@ -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 *
Expand Down Expand Up @@ -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() );
}
}
}
Expand Down Expand Up @@ -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 ) )
Expand All @@ -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
{
Expand Down
10 changes: 5 additions & 5 deletions src/app/qgslayertreeviewindicatorprovider.h
Expand Up @@ -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 *
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 7cbba81

Please sign in to comment.