Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
with
390 additions
and 171 deletions.
- +4 −2 src/app/CMakeLists.txt
- +1 −1 src/app/qgisapp.cpp
- +56 −0 src/app/qgslayertreeviewbadlayerindicator.cpp
- +41 −0 src/app/qgslayertreeviewbadlayerindicator.h
- +187 −0 src/app/qgslayertreeviewindicatorprovider.cpp
- +79 −0 src/app/qgslayertreeviewindicatorprovider.h
- +15 −143 src/app/qgslayertreeviewmemoryindicator.cpp
- +7 −25 src/app/qgslayertreeviewmemoryindicator.h
@@ -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(); | ||
} |
@@ -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 |
@@ -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 | ||
} | ||
} | ||
|
Oops, something went wrong.