27#include "moc_qgsprovidersublayermodel.cpp"
29using namespace Qt::StringLiterals;
36QgsProviderSublayerModelNode::~QgsProviderSublayerModelNode() =
default;
38void QgsProviderSublayerModelGroup::populateFromSublayers(
const QList<QgsProviderSublayerDetails> &sublayers )
42 if ( !sublayer.path().isEmpty() )
44 QStringList currentPath;
45 QStringList remainingPaths = sublayer.path();
46 QgsProviderSublayerModelGroup *groupNode =
this;
48 while ( !remainingPaths.empty() )
50 currentPath << remainingPaths.takeAt( 0 );
52 QgsProviderSublayerModelGroup *nextChild = groupNode->findGroup( currentPath.constLast() );
55 auto newNode = std::make_unique< QgsProviderSublayerModelGroup >( currentPath.constLast() );
56 groupNode = qgis::down_cast< QgsProviderSublayerModelGroup * >( groupNode->addChild( std::move( newNode ) ) );
60 groupNode = nextChild;
64 groupNode->addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
68 addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
73QgsProviderSublayerModelGroup::QgsProviderSublayerModelGroup(
const QString &title )
74 : mGroupTitle( title )
77QgsProviderSublayerModelNode *QgsProviderSublayerModelGroup::addChild( std::unique_ptr<QgsProviderSublayerModelNode> child )
82 Q_ASSERT( !child->mParent );
83 child->mParent =
this;
85 QgsProviderSublayerModelNode *res = child.get();
86 mChildren.emplace_back( std::move( child ) );
91int QgsProviderSublayerModelGroup::indexOf( QgsProviderSublayerModelNode *child )
const
93 Q_ASSERT( child->mParent ==
this );
94 auto it = std::find_if( mChildren.begin(), mChildren.end(), [&](
const std::unique_ptr<QgsProviderSublayerModelNode> &p ) { return p.get() == child; } );
95 if ( it != mChildren.end() )
96 return std::distance( mChildren.begin(), it );
100QgsProviderSublayerModelNode *QgsProviderSublayerModelGroup::childAt(
int index )
102 if (
static_cast< std::size_t
>( index ) < mChildren.size() )
103 return mChildren[index].get();
108void QgsProviderSublayerModelGroup::removeChildAt(
int index )
110 mChildren.erase( mChildren.begin() + index );
113QgsProviderSublayerModelGroup *QgsProviderSublayerModelGroup::findGroup(
const QString &name )
const
115 for (
const auto &node : mChildren )
117 if ( QgsProviderSublayerModelGroup *group =
dynamic_cast< QgsProviderSublayerModelGroup *
>( node.get() ) )
119 if ( group->name() == name )
126QgsProviderSublayerModelGroup *QgsProviderSublayerModelGroup::findGroupForPath(
const QStringList &path )
const
128 const QgsProviderSublayerModelGroup *currentGroup =
this;
129 for (
const QString &part : path )
131 currentGroup = currentGroup->findGroup( part );
133 return const_cast< QgsProviderSublayerModelGroup *
>( currentGroup );
136QgsProviderSublayerModelSublayerNode *QgsProviderSublayerModelGroup::findSublayer(
const QgsProviderSublayerDetails &sublayer )
138 for (
const auto &node : mChildren )
140 if ( QgsProviderSublayerModelGroup *group =
dynamic_cast< QgsProviderSublayerModelGroup *
>( node.get() ) )
142 if ( QgsProviderSublayerModelSublayerNode *node = group->findSublayer( sublayer ) )
145 else if ( QgsProviderSublayerModelSublayerNode *sublayerNode =
dynamic_cast< QgsProviderSublayerModelSublayerNode *
>( node.get() ) )
147 if ( sublayerNode->sublayer() == sublayer )
154QVariant QgsProviderSublayerModelGroup::data(
int role,
int column )
const
158 case Qt::DisplayRole:
159 case Qt::ToolTipRole:
173 case Qt::DecorationRole:
187 : mSublayer( sublayer )
190QVariant QgsProviderSublayerModelSublayerNode::data(
int role,
int column )
const
194 case Qt::DisplayRole:
195 case Qt::ToolTipRole:
201 return mSublayer.name();
204 switch ( mSublayer.type() )
211 count = QObject::tr(
"Uncounted" );
213 count = QLocale().toString( mSublayer.featureCount() );
215 if ( !mSublayer.description().isEmpty() )
229 return mSublayer.description();
234 return mSublayer.name();
237 case Qt::DecorationRole:
250 return mSublayer.providerKey();
253 return static_cast< int >( mSublayer.type() );
256 return mSublayer.uri();
259 return mSublayer.name();
262 return mSublayer.description();
265 return mSublayer.path();
268 return mSublayer.featureCount();
271 return static_cast< quint32
>( mSublayer.wkbType() );
274 return mSublayer.geometryColumnName();
277 return mSublayer.layerNumber();
280 return static_cast< int >( mSublayer.flags() );
291QVariant QgsProviderSublayerModelNonLayerItemNode::data(
int role,
int column )
const
295 case Qt::DisplayRole:
296 case Qt::ToolTipRole:
304 return mItem.description();
309 case Qt::DecorationRole:
327 return mItem.description();
344 : QAbstractItemModel(
parent )
345 ,
mRootNode( std::make_unique< QgsProviderSublayerModelGroup >( QString() ) )
354 mRootNode->populateFromSublayers( details );
363 for (
int i =
mSublayers.count() - 1; i >= 0; --i )
365 if ( !details.contains(
mSublayers.at( i ) ) )
367 QgsProviderSublayerModelSublayerNode *sublayerNode =
mRootNode->findSublayer(
mSublayers.at( i ) );
368 Q_ASSERT( sublayerNode );
369 Q_ASSERT( sublayerNode->parent() );
370 const int row = sublayerNode->parent()->indexOf( sublayerNode );
372 beginRemoveRows( node2index( sublayerNode->parent() ), row, row );
373 sublayerNode->parent()->removeChildAt( row );
385 QgsProviderSublayerModelGroup *group =
mRootNode->findGroupForPath( sublayer.
path() );
386 beginInsertRows( node2index( group ), group->childCount(), group->childCount() );
387 group->addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
402 if ( QgsProviderSublayerModelSublayerNode *n =
dynamic_cast< QgsProviderSublayerModelSublayerNode *
>( index2node(
index ) ) )
403 return n->sublayer();
410 if ( QgsProviderSublayerModelNonLayerItemNode *n =
dynamic_cast< QgsProviderSublayerModelNonLayerItemNode *
>( index2node(
index ) ) )
419 mRootNode->addChild( std::make_unique< QgsProviderSublayerModelNonLayerItemNode >( item ) );
428 return QModelIndex();
431 QgsProviderSublayerModelGroup *n =
dynamic_cast< QgsProviderSublayerModelGroup *
>( index2node(
parent ) );
433 return QModelIndex();
435 return createIndex( row, column, n->childAt( row ) );
440 if ( !child.isValid() )
441 return QModelIndex();
443 if ( QgsProviderSublayerModelNode *n = index2node( child ) )
445 return indexOfParentNode( n->parent() );
450 return QModelIndex();
462 QgsProviderSublayerModelNode *n = index2node(
parent );
466 return n->childCount();
471 if ( !
index.isValid() )
473 Qt::ItemFlags rootFlags = Qt::ItemFlags();
477 Qt::ItemFlags f = Qt::ItemIsEnabled;
480 if ( !
dynamic_cast< QgsProviderSublayerModelGroup *
>( index2node(
index ) ) )
482 f |= Qt::ItemIsSelectable;
489 if ( !
index.isValid() )
493 QgsProviderSublayerModelNode *node = index2node(
index );
497 return node->data( role,
index.column() );
502 switch ( orientation )
510 case Qt::DisplayRole:
511 case Qt::ToolTipRole:
513 switch (
static_cast< Column>( section ) )
518 return tr(
"Description" );
530QgsProviderSublayerModelNode *QgsProviderSublayerModel::index2node(
const QModelIndex &index )
const
532 if ( !
index.isValid() )
535 return reinterpret_cast<QgsProviderSublayerModelNode *
>(
index.internalPointer() );
538QModelIndex QgsProviderSublayerModel::indexOfParentNode( QgsProviderSublayerModelNode *parentNode )
const
540 Q_ASSERT( parentNode );
542 QgsProviderSublayerModelGroup *grandParentNode = parentNode->parent();
543 if ( !grandParentNode )
544 return QModelIndex();
546 int row = grandParentNode->indexOf( parentNode );
547 Q_ASSERT( row >= 0 );
549 return createIndex( row, 0, parentNode );
552QModelIndex QgsProviderSublayerModel::node2index( QgsProviderSublayerModelNode *node )
const
554 if ( !node || !node->parent() )
555 return QModelIndex();
557 QModelIndex parentIndex = node2index( node->parent() );
559 int row = node->parent()->indexOf( node );
560 Q_ASSERT( row >= 0 );
561 return index( row, 0, parentIndex );
621 return mType == other.mType && mName == other.mName && mDescription == other.mDescription && mUri == other.mUri;
626 return !( *
this == other );
634 : QSortFilterProxyModel(
parent )
636 setRecursiveFilteringEnabled(
true );
637 setDynamicSortFilter(
true );
643 const QModelIndex sourceIndex = sourceModel()->index( source_row, 0, source_parent );
645 if ( !mIncludeSystemTables
652 if ( mFilterString.trimmed().isEmpty() )
659 const QModelIndex descriptionColumnIndex = sourceModel()->index( source_row, 1, source_parent );
660 if ( sourceModel()->data( descriptionColumnIndex,
static_cast< int >( Qt::DisplayRole ) ).toString().contains( mFilterString, Qt::CaseInsensitive ) )
664 if ( wkbTypeVariant.isValid() )
679 if ( leftIsNonLayer && !rightIsNonLayer )
681 else if ( rightIsNonLayer && !leftIsNonLayer )
687 return QString::localeAwareCompare( leftName, rightName ) < 0;
692 return mIncludeSystemTables;
697 mIncludeSystemTables = include;
703 return mIncludeEmptyLayers;
708 mIncludeEmptyLayers = include;
714 return mFilterString;
719 mFilterString = filter;
@ SystemTable
Sublayer is a system or internal table, which should be hidden by default.
QFlags< SublayerFlag > SublayerFlags
Sublayer flags.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
WkbType
The WKB type describes the number of dimensions a geometry has.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Contains utility functions for working with icons.
static QIcon iconForWkbType(Qgis::WkbType type)
Returns the icon for a vector layer whose geometry type is provided.
Contains details about a sub layer available from a dataset.
QStringList path() const
Returns the path to the sublayer.
Contains details for a non-sublayer item to include in a QgsProviderSublayerModel.
void setName(const QString &name)
Sets the item's name.
void setDescription(const QString &description)
Sets the item's description.
void setType(const QString &type)
Sets the item's type.
QString type() const
Returns the item's type.
QString uri() const
Returns the item's URI.
QString name() const
Returns the item's name.
QIcon icon() const
Returns the item's icon.
bool operator!=(const QgsProviderSublayerModel::NonLayerItem &other) const
void setUri(const QString &uri)
Set the item's uri.
bool operator==(const QgsProviderSublayerModel::NonLayerItem &other) const
QString description() const
Returns the item's description.
void setIcon(const QIcon &icon)
Sets the item's icon.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QList< QgsProviderSublayerDetails > mSublayers
Sublayer list.
QList< QgsProviderSublayerDetails > sublayerDetails() const
Returns the sublayer details shown in the model.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
QgsProviderSublayerModel(QObject *parent=nullptr)
Constructor for QgsProviderSublayerModel, with the specified parent object.
QgsProviderSublayerDetails indexToSublayer(const QModelIndex &index) const
Returns the sublayer corresponding to the given index.
std::unique_ptr< QgsProviderSublayerModelGroup > mRootNode
@ NonLayerItemType
Item type (for non-sublayer items).
@ IsNonLayerItem
true if item is a non-sublayer item (e.g. an embedded project)
@ FeatureCount
Feature count (for vector sublayers).
@ GeometryColumnName
Geometry column name (for vector sublayers).
@ Description
Layer description.
@ WkbType
WKB geometry type (for vector sublayers).
@ ProviderKey
Provider key.
@ LayerNumber
Layer number.
QgsProviderSublayerModel::NonLayerItem indexToNonLayerItem(const QModelIndex &index) const
Returns the non layer item corresponding to the given index.
void addNonLayerItem(const QgsProviderSublayerModel::NonLayerItem &item)
Adds a non-layer item (e.g.
void setSublayerDetails(const QList< QgsProviderSublayerDetails > &details)
Sets the sublayer details to show in the model.
QModelIndex parent(const QModelIndex &index) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
@ Description
Layer description.
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override
bool includeSystemTables() const
Returns true if system and internal tables will be shown in the model.
void setIncludeSystemTables(bool include)
Sets whether system and internal tables will be shown in the model.
QgsProviderSublayerProxyModel(QObject *parent=nullptr)
Constructor for QgsProviderSublayerProxyModel, with the specified parent object.
QString filterString() const
Returns the filter string used for filtering items in the model.
bool includeEmptyLayers() const
Returns true if empty tables will be shown in the model.
void setFilterString(const QString &filter)
Sets the filter string used for filtering items in the model.
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
void setIncludeEmptyLayers(bool include)
Sets whether empty tables will be shown in the model.
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
@ Uncounted
Feature count not yet computed.
@ UnknownCount
Provider returned an unknown feature count.