Skip to content

Commit

Permalink
QgsLayerTreeViewIndicatorProvider refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Oct 21, 2018
1 parent fc53e64 commit a9a5039
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 171 deletions.
6 changes: 4 additions & 2 deletions src/app/CMakeLists.txt
Expand Up @@ -60,11 +60,12 @@ SET(QGIS_APP_SRCS
qgslabelinggui.cpp
qgslabelingwidget.cpp
qgslayercapabilitiesmodel.cpp
qgslayertreeviewindicatorprovider.cpp
qgslayertreeviewembeddedindicator.cpp
qgslayertreeviewfilterindicator.cpp
qgslayertreeviewmemoryindicator.cpp
qgslayertreeviewnonremovableindicator.cpp
qgslayertreeviewbadlayerindicatorprovider.cpp
qgslayertreeviewbadlayerindicator.cpp
qgsmapcanvasdockwidget.cpp
qgsmaplayerstylecategoriesmodel.cpp
qgsmaplayerstyleguiutils.cpp
Expand Down Expand Up @@ -290,11 +291,12 @@ SET (QGIS_APP_MOC_HDRS
qgslabelingwidget.h
qgslabelpropertydialog.h
qgslayercapabilitiesmodel.h
qgslayertreeviewindicatorprovider.h
qgslayertreeviewembeddedindicator.h
qgslayertreeviewmemoryindicator.h
qgslayertreeviewfilterindicator.h
qgslayertreeviewnonremovableindicator.h
qgslayertreeviewbadlayerindicatorprovider.h
qgslayertreeviewbadlayerindicator.h
qgsmapcanvasdockwidget.h
qgsmaplayerstylecategoriesmodel.h
qgsmaplayerstyleguiutils.h
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Expand Up @@ -209,7 +209,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgslayertreeviewembeddedindicator.h"
#include "qgslayertreeviewfilterindicator.h"
#include "qgslayertreeviewmemoryindicator.h"
#include "qgslayertreeviewbadlayerindicatorprovider.h"
#include "qgslayertreeviewbadlayerindicator.h"
#include "qgslayertreeviewnonremovableindicator.h"
#include "qgslayout.h"
#include "qgslayoutatlas.h"
Expand Down
56 changes: 56 additions & 0 deletions src/app/qgslayertreeviewbadlayerindicator.cpp
@@ -0,0 +1,56 @@
/***************************************************************************
qgslayertreeviewbadlayerindicatorprovider.cpp - QgsLayerTreeViewBadLayerIndicatorProvider
---------------------
begin : 17.10.2018
copyright : (C) 2018 by Alessandro Pasotti
email : elpaso@itopen.it
***************************************************************************
* *
* 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 "qgslayertreeviewbadlayerindicator.h"
#include "qgslayertree.h"
#include "qgslayertreeview.h"
#include "qgslayertreeutils.h"
#include "qgslayertreemodel.h"
#include "qgsvectorlayer.h"
#include "qgisapp.h"

QgsLayerTreeViewBadLayerIndicatorProvider::QgsLayerTreeViewBadLayerIndicatorProvider( QgsLayerTreeView *view )
: QgsLayerTreeViewIndicatorProvider( view )
{
}

void QgsLayerTreeViewBadLayerIndicatorProvider::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 )
return;

// TODO: open source select dialog
}

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

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

bool QgsLayerTreeViewBadLayerIndicatorProvider::acceptLayer( QgsMapLayer *layer )
{
return ! layer->isValid();
}
41 changes: 41 additions & 0 deletions src/app/qgslayertreeviewbadlayerindicator.h
@@ -0,0 +1,41 @@
/***************************************************************************
qgslayertreeviewbadlayerindicatorprovider.h - QgsLayerTreeViewBadLayerIndicatorProvider
---------------------
begin : 17.10.2018
copyright : (C) 2018 by Alessandro Pasotti
email : elpaso@itopen.it
***************************************************************************
* *
* 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 QGSLAYERTREEVIEWBADLAYERINDICATORPROVIDER_H
#define QGSLAYERTREEVIEWBADLAYERINDICATORPROVIDER_H

#include "qgslayertreeviewindicatorprovider.h"

#include <QObject>


//! Indicators for bad layers
class QgsLayerTreeViewBadLayerIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
{
Q_OBJECT

public:
explicit QgsLayerTreeViewBadLayerIndicatorProvider( QgsLayerTreeView *view );

private slots:
void onIndicatorClicked( const QModelIndex &index ) override;

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

#endif // QGSLAYERTREEVIEWBADLAYERINDICATORPROVIDER_H
187 changes: 187 additions & 0 deletions src/app/qgslayertreeviewindicatorprovider.cpp
@@ -0,0 +1,187 @@
/***************************************************************************
qgslayertreeviewindicatorprovider.cpp - QgsLayerTreeViewIndicatorProvider
---------------------
begin : 17.10.2018
copyright : (C) 2018 by ale
email : [your-email-here]
***************************************************************************
* *
* 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 "qgslayertreeviewindicatorprovider.h"

#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"
#include "qgsvectorlayer.h"
#include "qgisapp.h"

QgsLayerTreeViewIndicatorProvider::QgsLayerTreeViewIndicatorProvider( QgsLayerTreeView *view )
: QObject( view )
, mLayerTreeView( view )
{

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

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

void QgsLayerTreeViewIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
{
// recursively populate indicators
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 ) )
{
if ( QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( childNode ) )
{
if ( layerNode->layer() )
{
connectSignals( layerNode->layer() );
addOrRemoveIndicator( childNode, layerNode->layer() );
}
else
{
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved)
connect( layerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewIndicatorProvider::onLayerLoaded );
}
}
}
}
}

void QgsLayerTreeViewIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
{
// recursively call disconnect signals

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 ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
disconnectSignals( childLayerNode->layer() );
}
}
}

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

if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
{
if ( vlayer )
{
connectSignals( vlayer );
addOrRemoveIndicator( layerNode, vlayer );
}
}
}

void QgsLayerTreeViewIndicatorProvider::onLayerChanged()
{
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
if ( !layer )
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() == layer )
{
addOrRemoveIndicator( node, layer );
break;
}
}
}

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)
{
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 > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
indicator->setIcon( QgsApplication::getThemeIcon( iconName() ) );
indicator->setToolTip( tooltipText() );
connect( indicator.get(), &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewIndicatorProvider::onIndicatorClicked );
mIndicators.insert( indicator.get() );
return indicator;
}

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

if ( acceptLayer( layer ) )
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );

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

// it does not exist: need to create a new one
mLayerTreeView->addIndicator( node, newIndicator().release() );
}
else
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );

// 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;
}
}

// no indicator was there before, nothing to do
}
}

0 comments on commit a9a5039

Please sign in to comment.