26#include "moc_qgsprovidersublayermodel.cpp"
33QgsProviderSublayerModelNode::~QgsProviderSublayerModelNode() =
default;
35void QgsProviderSublayerModelGroup::populateFromSublayers(
const QList<QgsProviderSublayerDetails> &sublayers )
39 if ( !sublayer.path().isEmpty() )
41 QStringList currentPath;
42 QStringList remainingPaths = sublayer.path();
43 QgsProviderSublayerModelGroup *groupNode =
this;
45 while ( !remainingPaths.empty() )
47 currentPath << remainingPaths.takeAt( 0 );
49 QgsProviderSublayerModelGroup *nextChild = groupNode->findGroup( currentPath.constLast() );
52 auto newNode = std::make_unique< QgsProviderSublayerModelGroup >( currentPath.constLast() );
53 groupNode = qgis::down_cast< QgsProviderSublayerModelGroup * >( groupNode->addChild( std::move( newNode ) ) );
57 groupNode = nextChild;
61 groupNode->addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
65 addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
70QgsProviderSublayerModelGroup::QgsProviderSublayerModelGroup(
const QString &title )
71 : mGroupTitle( title )
76QgsProviderSublayerModelNode *QgsProviderSublayerModelGroup::addChild( std::unique_ptr<QgsProviderSublayerModelNode> child )
81 Q_ASSERT( !child->mParent );
82 child->mParent =
this;
84 QgsProviderSublayerModelNode *res = child.get();
85 mChildren.emplace_back( std::move( child ) );
90int QgsProviderSublayerModelGroup::indexOf( QgsProviderSublayerModelNode *child )
const
92 Q_ASSERT( child->mParent ==
this );
93 auto it = std::find_if( mChildren.begin(), mChildren.end(), [&](
const std::unique_ptr<QgsProviderSublayerModelNode> &p )
95 return p.get() == child;
97 if ( it != mChildren.end() )
98 return std::distance( mChildren.begin(), it );
102QgsProviderSublayerModelNode *QgsProviderSublayerModelGroup::childAt(
int index )
104 if (
static_cast< std::size_t
>( index ) < mChildren.size() )
105 return mChildren[ index ].get();
110void QgsProviderSublayerModelGroup::removeChildAt(
int index )
112 mChildren.erase( mChildren.begin() + index );
115QgsProviderSublayerModelGroup *QgsProviderSublayerModelGroup::findGroup(
const QString &name )
const
117 for (
const auto &node : mChildren )
119 if ( QgsProviderSublayerModelGroup *group =
dynamic_cast< QgsProviderSublayerModelGroup *
>( node.get() ) )
121 if ( group->name() == name )
128QgsProviderSublayerModelGroup *QgsProviderSublayerModelGroup::findGroupForPath(
const QStringList &path )
const
130 const QgsProviderSublayerModelGroup *currentGroup =
this;
131 for (
const QString &part : path )
133 currentGroup = currentGroup->findGroup( part );
135 return const_cast< QgsProviderSublayerModelGroup *
>( currentGroup );
138QgsProviderSublayerModelSublayerNode *QgsProviderSublayerModelGroup::findSublayer(
const QgsProviderSublayerDetails &sublayer )
140 for (
const auto &node : mChildren )
142 if ( QgsProviderSublayerModelGroup *group =
dynamic_cast< QgsProviderSublayerModelGroup *
>( node.get() ) )
144 if ( QgsProviderSublayerModelSublayerNode *node = group->findSublayer( sublayer ) )
147 else if ( QgsProviderSublayerModelSublayerNode *sublayerNode =
dynamic_cast< QgsProviderSublayerModelSublayerNode *
>( node.get() ) )
149 if ( sublayerNode->sublayer() == sublayer )
156QVariant QgsProviderSublayerModelGroup::data(
int role,
int column )
const
160 case Qt::DisplayRole:
161 case Qt::ToolTipRole:
175 case Qt::DecorationRole:
189 : mSublayer( sublayer )
193QVariant QgsProviderSublayerModelSublayerNode::data(
int role,
int column )
const
197 case Qt::DisplayRole:
198 case Qt::ToolTipRole:
204 return mSublayer.name();
207 switch ( mSublayer.type() )
214 count = QObject::tr(
"Uncounted" );
216 count = QLocale().toString( mSublayer.featureCount() );
218 if ( !mSublayer.description().isEmpty() )
219 return QStringLiteral(
"%1 - %2 (%3)" ).arg( mSublayer.description(),
223 return QStringLiteral(
"%2 (%3)" ).arg(
236 return mSublayer.description();
242 return mSublayer.name();
246 case Qt::DecorationRole:
260 return mSublayer.providerKey();
263 return static_cast< int >( mSublayer.type() );
266 return mSublayer.uri();
269 return mSublayer.name();
272 return mSublayer.description();
275 return mSublayer.path();
278 return mSublayer.featureCount();
281 return static_cast< quint32
>( mSublayer.wkbType() );
284 return mSublayer.geometryColumnName();
287 return mSublayer.layerNumber();
290 return static_cast< int >( mSublayer.flags() );
302QVariant QgsProviderSublayerModelNonLayerItemNode::data(
int role,
int column )
const
306 case Qt::DisplayRole:
307 case Qt::ToolTipRole:
315 return mItem.description();
320 case Qt::DecorationRole:
338 return mItem.description();
355 : QAbstractItemModel(
parent )
356 ,
mRootNode( std::make_unique< QgsProviderSublayerModelGroup >( QString() ) )
367 mRootNode->populateFromSublayers( details );
376 for (
int i =
mSublayers.count() - 1; i >= 0; --i )
378 if ( !details.contains(
mSublayers.at( i ) ) )
380 QgsProviderSublayerModelSublayerNode *sublayerNode =
mRootNode->findSublayer(
mSublayers.at( i ) );
381 Q_ASSERT( sublayerNode );
382 Q_ASSERT( sublayerNode->parent() );
383 const int row = sublayerNode->parent()->indexOf( sublayerNode );
385 beginRemoveRows( node2index( sublayerNode->parent() ), row, row );
386 sublayerNode->parent()->removeChildAt( row );
398 QgsProviderSublayerModelGroup *group =
mRootNode->findGroupForPath( sublayer.
path() );
399 beginInsertRows( node2index( group ), group->childCount(), group->childCount() );
400 group->addChild( std::make_unique< QgsProviderSublayerModelSublayerNode >( sublayer ) );
415 if ( QgsProviderSublayerModelSublayerNode *n =
dynamic_cast< QgsProviderSublayerModelSublayerNode *
>( index2node(
index ) ) )
416 return n->sublayer();
423 if ( QgsProviderSublayerModelNonLayerItemNode *n =
dynamic_cast< QgsProviderSublayerModelNonLayerItemNode *
>( index2node(
index ) ) )
432 mRootNode->addChild( std::make_unique< QgsProviderSublayerModelNonLayerItemNode >( item ) );
442 return QModelIndex();
445 QgsProviderSublayerModelGroup *n =
dynamic_cast< QgsProviderSublayerModelGroup *
>( index2node(
parent ) );
447 return QModelIndex();
449 return createIndex( row, column, n->childAt( row ) );
454 if ( !child.isValid() )
455 return QModelIndex();
457 if ( QgsProviderSublayerModelNode *n = index2node( child ) )
459 return indexOfParentNode( n->parent() );
464 return QModelIndex();
476 QgsProviderSublayerModelNode *n = index2node(
parent );
480 return n->childCount();
485 if ( !
index.isValid() )
487 Qt::ItemFlags rootFlags = Qt::ItemFlags();
491 Qt::ItemFlags f = Qt::ItemIsEnabled;
494 if ( !
dynamic_cast< QgsProviderSublayerModelGroup *
>( index2node(
index ) ) )
496 f |= Qt::ItemIsSelectable;
503 if ( !
index.isValid() )
507 QgsProviderSublayerModelNode *node = index2node(
index );
511 return node->data( role,
index.column() );
516 switch ( orientation )
524 case Qt::DisplayRole:
525 case Qt::ToolTipRole:
527 switch (
static_cast< Column>( section ) )
532 return tr(
"Description" );
544QgsProviderSublayerModelNode *QgsProviderSublayerModel::index2node(
const QModelIndex &index )
const
546 if ( !
index.isValid() )
549 return reinterpret_cast<QgsProviderSublayerModelNode *
>(
index.internalPointer() );
552QModelIndex QgsProviderSublayerModel::indexOfParentNode( QgsProviderSublayerModelNode *parentNode )
const
554 Q_ASSERT( parentNode );
556 QgsProviderSublayerModelGroup *grandParentNode = parentNode->parent();
557 if ( !grandParentNode )
558 return QModelIndex();
560 int row = grandParentNode->indexOf( parentNode );
561 Q_ASSERT( row >= 0 );
563 return createIndex( row, 0, parentNode );
566QModelIndex QgsProviderSublayerModel::node2index( QgsProviderSublayerModelNode *node )
const
568 if ( !node || !node->parent() )
569 return QModelIndex();
571 QModelIndex parentIndex = node2index( node->parent() );
573 int row = node->parent()->indexOf( node );
574 Q_ASSERT( row >= 0 );
575 return index( row, 0, parentIndex );
635 return mType == other.mType
636 && mName == other.mName
637 && mDescription == other.mDescription
638 && mUri == other.mUri;
643 return !( *
this == other );
651 : QSortFilterProxyModel(
parent )
653 setRecursiveFilteringEnabled(
true );
654 setDynamicSortFilter(
true );
660 const QModelIndex sourceIndex = sourceModel()->index( source_row, 0, source_parent );
668 if ( mFilterString.trimmed().isEmpty() )
675 const QModelIndex descriptionColumnIndex = sourceModel()->index( source_row, 1, source_parent );
676 if ( sourceModel()->data( descriptionColumnIndex,
static_cast< int >( Qt::DisplayRole ) ).toString().contains( mFilterString, Qt::CaseInsensitive ) )
680 if ( wkbTypeVariant.isValid() )
695 if ( leftIsNonLayer && !rightIsNonLayer )
697 else if ( rightIsNonLayer && !leftIsNonLayer )
703 return QString::localeAwareCompare( leftName, rightName ) < 0;
708 return mIncludeSystemTables;
713 mIncludeSystemTables = include;
719 return mIncludeEmptyLayers;
724 mIncludeEmptyLayers = include;
730 return mFilterString;
735 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.