Skip to content
Permalink
Browse files
Add support for filtering system tables in QgsProviderSublayerProxyModel
  • Loading branch information
nyalldawson committed Aug 26, 2021
1 parent 7f090f6 commit f2f40096ab2eabacc502ae48a04db741723e2af4
@@ -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"
@@ -46,6 +46,7 @@ embedded project items. The non-sublayer items can be added by calling
LayerNumber,
IsNonLayerItem,
NonLayerItemType,
Flags,
};

enum class Column
@@ -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:
@@ -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 );
}
@@ -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();
}
@@ -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;

@@ -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;
@@ -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
@@ -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;

};

@@ -13,6 +13,7 @@
import qgis # NOQA

from qgis.core import (
Qgis,
QgsMapLayerType,
QgsWkbTypes,
QgsProviderSublayerDetails,
@@ -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())
@@ -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)
@@ -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)')
@@ -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)
@@ -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())
@@ -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())
@@ -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.