Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for filtering system tables in QgsProviderSublayerProxyModel
  • Loading branch information
nyalldawson committed Aug 26, 2021
1 parent 7f090f6 commit f2f4009
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 1 deletion.
3 changes: 2 additions & 1 deletion python/core/auto_additions/qgsprovidersublayermodel.py
Expand Up @@ -12,7 +12,8 @@
QgsProviderSublayerModel.Role.LayerNumber.__doc__ = "Layer number"
QgsProviderSublayerModel.Role.IsNonLayerItem.__doc__ = "``True`` if item is a non-sublayer item (e.g. an embedded project)"
QgsProviderSublayerModel.Role.NonLayerItemType.__doc__ = "Item type (for non-sublayer items)"
QgsProviderSublayerModel.Role.__doc__ = 'Custom model roles\n\n' + '* ``ProviderKey``: ' + QgsProviderSublayerModel.Role.ProviderKey.__doc__ + '\n' + '* ``LayerType``: ' + QgsProviderSublayerModel.Role.LayerType.__doc__ + '\n' + '* ``Uri``: ' + QgsProviderSublayerModel.Role.Uri.__doc__ + '\n' + '* ``Name``: ' + QgsProviderSublayerModel.Role.Name.__doc__ + '\n' + '* ``Description``: ' + QgsProviderSublayerModel.Role.Description.__doc__ + '\n' + '* ``Path``: ' + QgsProviderSublayerModel.Role.Path.__doc__ + '\n' + '* ``FeatureCount``: ' + QgsProviderSublayerModel.Role.FeatureCount.__doc__ + '\n' + '* ``WkbType``: ' + QgsProviderSublayerModel.Role.WkbType.__doc__ + '\n' + '* ``GeometryColumnName``: ' + QgsProviderSublayerModel.Role.GeometryColumnName.__doc__ + '\n' + '* ``LayerNumber``: ' + QgsProviderSublayerModel.Role.LayerNumber.__doc__ + '\n' + '* ``IsNonLayerItem``: ' + QgsProviderSublayerModel.Role.IsNonLayerItem.__doc__ + '\n' + '* ``NonLayerItemType``: ' + QgsProviderSublayerModel.Role.NonLayerItemType.__doc__
QgsProviderSublayerModel.Role.Flags.__doc__ = "Sublayer flags"
QgsProviderSublayerModel.Role.__doc__ = 'Custom model roles\n\n' + '* ``ProviderKey``: ' + QgsProviderSublayerModel.Role.ProviderKey.__doc__ + '\n' + '* ``LayerType``: ' + QgsProviderSublayerModel.Role.LayerType.__doc__ + '\n' + '* ``Uri``: ' + QgsProviderSublayerModel.Role.Uri.__doc__ + '\n' + '* ``Name``: ' + QgsProviderSublayerModel.Role.Name.__doc__ + '\n' + '* ``Description``: ' + QgsProviderSublayerModel.Role.Description.__doc__ + '\n' + '* ``Path``: ' + QgsProviderSublayerModel.Role.Path.__doc__ + '\n' + '* ``FeatureCount``: ' + QgsProviderSublayerModel.Role.FeatureCount.__doc__ + '\n' + '* ``WkbType``: ' + QgsProviderSublayerModel.Role.WkbType.__doc__ + '\n' + '* ``GeometryColumnName``: ' + QgsProviderSublayerModel.Role.GeometryColumnName.__doc__ + '\n' + '* ``LayerNumber``: ' + QgsProviderSublayerModel.Role.LayerNumber.__doc__ + '\n' + '* ``IsNonLayerItem``: ' + QgsProviderSublayerModel.Role.IsNonLayerItem.__doc__ + '\n' + '* ``NonLayerItemType``: ' + QgsProviderSublayerModel.Role.NonLayerItemType.__doc__ + '\n' + '* ``Flags``: ' + QgsProviderSublayerModel.Role.Flags.__doc__
# --
# monkey patching scoped based enum
QgsProviderSublayerModel.Column.Name.__doc__ = "Layer name"
Expand Down
Expand Up @@ -46,6 +46,7 @@ embedded project items. The non-sublayer items can be added by calling
LayerNumber,
IsNonLayerItem,
NonLayerItemType,
Flags,
};

enum class Column
Expand Down Expand Up @@ -234,6 +235,20 @@ Returns the filter string used for filtering items in the model.
Sets the ``filter`` string used for filtering items in the model.

.. seealso:: :py:func:`filterString`
%End

bool includeSystemTables() const;
%Docstring
Returns ``True`` if system and internal tables will be shown in the model.

.. seealso:: :py:func:`setIncludeSystemTables`
%End

void setIncludeSystemTables( bool include );
%Docstring
Sets whether system and internal tables will be shown in the model.

.. seealso:: :py:func:`includeSystemTables`
%End

protected:
Expand Down
12 changes: 12 additions & 0 deletions src/app/qgsprovidersublayersdialog.cpp
Expand Up @@ -67,6 +67,18 @@ QVariant QgsProviderSublayerDialogModel::data( const QModelIndex &index, int rol
}
}
}
else if ( details.flags() & Qgis::SublayerFlag::SystemTable )
{
switch ( role )
{
case Qt::FontRole:
{
QFont f = QgsProviderSublayerModel::data( index, role ).value< QFont >();
f.setItalic( true );
return f;
}
}
}
}
return QgsProviderSublayerModel::data( index, role );
}
Expand Down
17 changes: 17 additions & 0 deletions src/core/providers/qgsprovidersublayermodel.cpp
Expand Up @@ -232,6 +232,9 @@ QVariant QgsProviderSublayerModel::data( const QModelIndex &index, int role ) co
case static_cast< int >( Role::LayerNumber ):
return details.layerNumber();

case static_cast< int >( Role::Flags ):
return static_cast< int >( details.flags() );

default:
return QVariant();
}
Expand Down Expand Up @@ -397,6 +400,9 @@ bool QgsProviderSublayerProxyModel::filterAcceptsRow( int source_row, const QMod
{
const QModelIndex sourceIndex = sourceModel()->index( source_row, 0, source_parent );

if ( !mIncludeSystemTables && static_cast< Qgis::SublayerFlags >( sourceModel()->data( sourceIndex, static_cast< int >( QgsProviderSublayerModel::Role::Flags ) ).toInt() ) & Qgis::SublayerFlag::SystemTable )
return false;

if ( mFilterString.trimmed().isEmpty() )
return true;

Expand Down Expand Up @@ -433,6 +439,17 @@ bool QgsProviderSublayerProxyModel::lessThan( const QModelIndex &source_left, co
return QString::localeAwareCompare( leftName, rightName ) < 0;
}

bool QgsProviderSublayerProxyModel::includeSystemTables() const
{
return mIncludeSystemTables;
}

void QgsProviderSublayerProxyModel::setIncludeSystemTables( bool include )
{
mIncludeSystemTables = include;
invalidateFilter();
}

QString QgsProviderSublayerProxyModel::filterString() const
{
return mFilterString;
Expand Down
16 changes: 16 additions & 0 deletions src/core/providers/qgsprovidersublayermodel.h
Expand Up @@ -60,6 +60,7 @@ class CORE_EXPORT QgsProviderSublayerModel: public QAbstractItemModel
LayerNumber, //!< Layer number
IsNonLayerItem, //!< TRUE if item is a non-sublayer item (e.g. an embedded project)
NonLayerItemType, //!< Item type (for non-sublayer items)
Flags, //!< Sublayer flags
};

//! Model columns
Expand Down Expand Up @@ -245,13 +246,28 @@ class CORE_EXPORT QgsProviderSublayerProxyModel: public QSortFilterProxyModel
*/
void setFilterString( const QString &filter );

/**
* Returns TRUE if system and internal tables will be shown in the model.
*
* \see setIncludeSystemTables()
*/
bool includeSystemTables() const;

/**
* Sets whether system and internal tables will be shown in the model.
*
* \see includeSystemTables()
*/
void setIncludeSystemTables( bool include );

protected:
bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const override;
bool lessThan( const QModelIndex &source_left, const QModelIndex &source_right ) const override;

private:

QString mFilterString;
bool mIncludeSystemTables = false;

};

Expand Down
27 changes: 27 additions & 0 deletions tests/src/python/test_qgsprovidersublayermodel.py
Expand Up @@ -13,6 +13,7 @@
import qgis # NOQA

from qgis.core import (
Qgis,
QgsMapLayerType,
QgsWkbTypes,
QgsProviderSublayerDetails,
Expand Down Expand Up @@ -61,6 +62,7 @@ def test_model(self):
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Uri), 'uri 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Name), 'layer 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Description), 'description 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Flags), 0)

self.assertEqual(model.indexToSublayer(model.index(0, 0, QModelIndex())), layer1)
self.assertFalse(model.indexToSublayer(model.index(1, 0, QModelIndex())).name())
Expand All @@ -74,6 +76,7 @@ def test_model(self):
layer2.setUri('uri 2')
layer2.setFeatureCount(-1)
layer2.setWkbType(QgsWkbTypes.LineString)
layer2.setFlags(Qgis.SublayerFlags(Qgis.SublayerFlag.SystemTable))

model.setSublayerDetails([layer1, layer2])
self.assertEqual(model.rowCount(QModelIndex()), 2)
Expand All @@ -84,6 +87,7 @@ def test_model(self):
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Uri), 'uri 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Name), 'layer 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Description), 'description 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Flags), 0)

self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'layer 2')
self.assertEqual(model.data(model.index(1, 1), Qt.DisplayRole), 'description 2 - LineString (Uncounted)')
Expand All @@ -92,6 +96,7 @@ def test_model(self):
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.Uri), 'uri 2')
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.Name), 'layer 2')
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.Description), 'description 2')
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.Flags), 1)

self.assertEqual(model.indexToSublayer(model.index(0, 0, QModelIndex())), layer1)
self.assertEqual(model.indexToSublayer(model.index(1, 0, QModelIndex())), layer2)
Expand Down Expand Up @@ -224,6 +229,7 @@ def test_model_with_non_layer_items(self):
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Name), 'layer 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Description), 'description 1')
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.IsNonLayerItem), False)
self.assertEqual(model.data(model.index(0, 0), QgsProviderSublayerModel.Role.Flags), 0)

self.assertEqual(model.indexToSublayer(model.index(0, 0, QModelIndex())), layer1)
self.assertFalse(model.indexToSublayer(model.index(1, 0, QModelIndex())).name())
Expand Down Expand Up @@ -253,6 +259,7 @@ def test_model_with_non_layer_items(self):
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.Description), 'item desc 1')
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.IsNonLayerItem), True)
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.NonLayerItemType), 'item type 1')
self.assertEqual(model.data(model.index(1, 0), QgsProviderSublayerModel.Role.Flags), None)

self.assertEqual(model.indexToSublayer(model.index(0, 0, QModelIndex())), layer1)
self.assertFalse(model.indexToSublayer(model.index(1, 0, QModelIndex())).name())
Expand Down Expand Up @@ -391,6 +398,26 @@ def test_proxy(self):
self.assertEqual(proxy.data(proxy.index(1, 0), Qt.DisplayRole), 'another layer 2')
self.assertEqual(proxy.data(proxy.index(2, 0), Qt.DisplayRole), 'layer 1')

# add a system table
layer3 = QgsProviderSublayerDetails()
layer3.setType(QgsMapLayerType.VectorLayer)
layer3.setName('system table')
layer3.setFlags(Qgis.SublayerFlags(Qgis.SublayerFlag.SystemTable))

model.setSublayerDetails([layer1, layer2, layer3])
# system tables should be hidden by default
self.assertEqual(proxy.rowCount(QModelIndex()), 3)
self.assertEqual(proxy.data(proxy.index(0, 0), Qt.DisplayRole), 'item name 1')
self.assertEqual(proxy.data(proxy.index(1, 0), Qt.DisplayRole), 'another layer 2')
self.assertEqual(proxy.data(proxy.index(2, 0), Qt.DisplayRole), 'layer 1')

proxy.setIncludeSystemTables(True)
self.assertEqual(proxy.rowCount(QModelIndex()), 4)
self.assertEqual(proxy.data(proxy.index(0, 0), Qt.DisplayRole), 'item name 1')
self.assertEqual(proxy.data(proxy.index(1, 0), Qt.DisplayRole), 'another layer 2')
self.assertEqual(proxy.data(proxy.index(2, 0), Qt.DisplayRole), 'layer 1')
self.assertEqual(proxy.data(proxy.index(3, 0), Qt.DisplayRole), 'system table')


if __name__ == '__main__':
unittest.main()

0 comments on commit f2f4009

Please sign in to comment.