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 )
79QgsProviderSublayerModelNode *QgsProviderSublayerModelGroup::addChild( std::unique_ptr<QgsProviderSublayerModelNode> child )
84 Q_ASSERT( !child->mParent );
85 child->mParent =
this;
87 QgsProviderSublayerModelNode *res = child.get();
88 mChildren.emplace_back( std::move( child ) );
93int QgsProviderSublayerModelGroup::indexOf( QgsProviderSublayerModelNode *child )
const
95 Q_ASSERT( child->mParent ==
this );
96 auto it = std::find_if( mChildren.begin(), mChildren.end(), [&](
const std::unique_ptr<QgsProviderSublayerModelNode> &p )
98 return p.get() == child;
100 if ( it != mChildren.end() )
101 return std::distance( mChildren.begin(), it );
105QgsProviderSublayerModelNode *QgsProviderSublayerModelGroup::childAt(
int index )
107 if (
static_cast< std::size_t
>( index ) < mChildren.size() )
108 return mChildren[ index ].get();
113void QgsProviderSublayerModelGroup::removeChildAt(
int index )
115 mChildren.erase( mChildren.begin() + index );
118QgsProviderSublayerModelGroup *QgsProviderSublayerModelGroup::findGroup(
const QString &name )
const
120 for (
const auto &node : mChildren )
122 if ( QgsProviderSublayerModelGroup *group =
dynamic_cast< QgsProviderSublayerModelGroup *
>( node.get() ) )
124 if ( group->name() == name )
131QgsProviderSublayerModelGroup *QgsProviderSublayerModelGroup::findGroupForPath(
const QStringList &path )
const
133 const QgsProviderSublayerModelGroup *currentGroup =
this;
134 for (
const QString &part : path )
136 currentGroup = currentGroup->findGroup( part );
138 return const_cast< QgsProviderSublayerModelGroup *
>( currentGroup );
141QgsProviderSublayerModelSublayerNode *QgsProviderSublayerModelGroup::findSublayer(
const QgsProviderSublayerDetails &sublayer )
143 for (
const auto &node : mChildren )
145 if ( QgsProviderSublayerModelGroup *group =
dynamic_cast< QgsProviderSublayerModelGroup *
>( node.get() ) )
147 if ( QgsProviderSublayerModelSublayerNode *node = group->findSublayer( sublayer ) )
150 else if ( QgsProviderSublayerModelSublayerNode *sublayerNode =
dynamic_cast< QgsProviderSublayerModelSublayerNode *
>( node.get() ) )
152 if ( sublayerNode->sublayer() == sublayer )
159QVariant QgsProviderSublayerModelGroup::data(
int role,
int column )
const
163 case Qt::DisplayRole:
164 case Qt::ToolTipRole:
178 case Qt::DecorationRole:
192 : mSublayer( sublayer )
196QVariant QgsProviderSublayerModelSublayerNode::data(
int role,
int column )
const
200 case Qt::DisplayRole:
201 case Qt::ToolTipRole:
207 return mSublayer.name();
210 switch ( mSublayer.type() )
217 count = QObject::tr(
"Uncounted" );
219 count = QLocale().toString( mSublayer.featureCount() );
221 if ( !mSublayer.description().isEmpty() )
222 return u
"%1 - %2 (%3)"_s.arg( mSublayer.description(),
226 return u
"%2 (%3)"_s.arg(
239 return mSublayer.description();
245 return mSublayer.name();
249 case Qt::DecorationRole:
263 return mSublayer.providerKey();
266 return static_cast< int >( mSublayer.type() );
269 return mSublayer.uri();
272 return mSublayer.name();
275 return mSublayer.description();
278 return mSublayer.path();
281 return mSublayer.featureCount();
284 return static_cast< quint32
>( mSublayer.wkbType() );
287 return mSublayer.geometryColumnName();
290 return mSublayer.layerNumber();
293 return static_cast< int >( mSublayer.flags() );
305QVariant QgsProviderSublayerModelNonLayerItemNode::data(
int role,
int column )
const
309 case Qt::DisplayRole:
310 case Qt::ToolTipRole:
318 return mItem.description();
323 case Qt::DecorationRole:
341 return mItem.description();
358 : QAbstractItemModel(
parent )
359 ,
mRootNode( std::make_unique< QgsProviderSublayerModelGroup >( QString() ) )
370 mRootNode->populateFromSublayers( details );
379 for (
int i =
mSublayers.count() - 1; i >= 0; --i )
381 if ( !details.contains(
mSublayers.at( i ) ) )
383 QgsProviderSublayerModelSublayerNode *sublayerNode =
mRootNode->findSublayer(
mSublayers.at( i ) );
384 Q_ASSERT( sublayerNode );
385 Q_ASSERT( sublayerNode->parent() );
386 const int row = sublayerNode->parent()->indexOf( sublayerNode );
388 beginRemoveRows( node2index( sublayerNode->parent() ), row, row );
389 sublayerNode->parent()->removeChildAt( row );
401 QgsProviderSublayerModelGroup *group =
mRootNode->findGroupForPath( sublayer.
path() );
402 beginInsertRows( node2index( group ), group->childCount(), group->childCount() );
403 group->addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
418 if ( QgsProviderSublayerModelSublayerNode *n =
dynamic_cast< QgsProviderSublayerModelSublayerNode *
>( index2node(
index ) ) )
419 return n->sublayer();
426 if ( QgsProviderSublayerModelNonLayerItemNode *n =
dynamic_cast< QgsProviderSublayerModelNonLayerItemNode *
>( index2node(
index ) ) )
435 mRootNode->addChild( std::make_unique< QgsProviderSublayerModelNonLayerItemNode >( item ) );
445 return QModelIndex();
448 QgsProviderSublayerModelGroup *n =
dynamic_cast< QgsProviderSublayerModelGroup *
>( index2node(
parent ) );
450 return QModelIndex();
452 return createIndex( row, column, n->childAt( row ) );
457 if ( !child.isValid() )
458 return QModelIndex();
460 if ( QgsProviderSublayerModelNode *n = index2node( child ) )
462 return indexOfParentNode( n->parent() );
467 return QModelIndex();
479 QgsProviderSublayerModelNode *n = index2node(
parent );
483 return n->childCount();
488 if ( !
index.isValid() )
490 Qt::ItemFlags rootFlags = Qt::ItemFlags();
494 Qt::ItemFlags f = Qt::ItemIsEnabled;
497 if ( !
dynamic_cast< QgsProviderSublayerModelGroup *
>( index2node(
index ) ) )
499 f |= Qt::ItemIsSelectable;
506 if ( !
index.isValid() )
510 QgsProviderSublayerModelNode *node = index2node(
index );
514 return node->data( role,
index.column() );
519 switch ( orientation )
527 case Qt::DisplayRole:
528 case Qt::ToolTipRole:
530 switch (
static_cast< Column>( section ) )
535 return tr(
"Description" );
547QgsProviderSublayerModelNode *QgsProviderSublayerModel::index2node(
const QModelIndex &index )
const
549 if ( !
index.isValid() )
552 return reinterpret_cast<QgsProviderSublayerModelNode *
>(
index.internalPointer() );
555QModelIndex QgsProviderSublayerModel::indexOfParentNode( QgsProviderSublayerModelNode *parentNode )
const
557 Q_ASSERT( parentNode );
559 QgsProviderSublayerModelGroup *grandParentNode = parentNode->parent();
560 if ( !grandParentNode )
561 return QModelIndex();
563 int row = grandParentNode->indexOf( parentNode );
564 Q_ASSERT( row >= 0 );
566 return createIndex( row, 0, parentNode );
569QModelIndex QgsProviderSublayerModel::node2index( QgsProviderSublayerModelNode *node )
const
571 if ( !node || !node->parent() )
572 return QModelIndex();
574 QModelIndex parentIndex = node2index( node->parent() );
576 int row = node->parent()->indexOf( node );
577 Q_ASSERT( row >= 0 );
578 return index( row, 0, parentIndex );
638 return mType == other.mType
639 && mName == other.mName
640 && mDescription == other.mDescription
641 && mUri == other.mUri;
646 return !( *
this == other );
654 : QSortFilterProxyModel(
parent )
656 setRecursiveFilteringEnabled(
true );
657 setDynamicSortFilter(
true );
663 const QModelIndex sourceIndex = sourceModel()->index( source_row, 0, source_parent );
671 if ( mFilterString.trimmed().isEmpty() )
678 const QModelIndex descriptionColumnIndex = sourceModel()->index( source_row, 1, source_parent );
679 if ( sourceModel()->data( descriptionColumnIndex,
static_cast< int >( Qt::DisplayRole ) ).toString().contains( mFilterString, Qt::CaseInsensitive ) )
683 if ( wkbTypeVariant.isValid() )
698 if ( leftIsNonLayer && !rightIsNonLayer )
700 else if ( rightIsNonLayer && !leftIsNonLayer )
706 return QString::localeAwareCompare( leftName, rightName ) < 0;
711 return mIncludeSystemTables;
716 mIncludeSystemTables = include;
722 return mIncludeEmptyLayers;
727 mIncludeEmptyLayers = include;
733 return mFilterString;
738 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.