Skip to content
Permalink
Browse files

Add proxy model for filtering QgsPointCloudAttributeModel by attribut…

…e type
  • Loading branch information
nyalldawson committed Nov 12, 2020
1 parent d8f6a2e commit 38e6b6b93e93bb5ef08d2d08b67e160ec33a0a47
@@ -114,6 +114,67 @@ Returns an icon corresponding to an attribute ``type``
};


class QgsPointCloudAttributeProxyModel : QSortFilterProxyModel
{
%Docstring

A proxy model for filtering available attributes from a point cloud attribute model.

.. versionadded:: 3.18
%End

%TypeHeaderCode
#include "qgspointcloudattributemodel.h"
%End
public:

enum Filter
{
Char,
Short,
Int32,
Float,
Double,
Numeric,
AllTypes,
};
typedef QFlags<QgsPointCloudAttributeProxyModel::Filter> Filters;


explicit QgsPointCloudAttributeProxyModel( QgsPointCloudAttributeModel *source, QObject *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsPointCloudAttributeProxyModel, with the specified ``source``
model and ``parent`` object.
%End

QgsPointCloudAttributeModel *sourceAttributeModel();
%Docstring
Returns the QgsPointCloudAttributeModel used in this QSortFilterProxyModel.
%End

QgsPointCloudAttributeProxyModel *setFilters( QgsPointCloudAttributeProxyModel::Filters filters );
%Docstring
Set flags that affect how fields are filtered in the model.

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

Filters filters() const;
%Docstring
Returns the filters controlling displayed attributes.

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

public:
virtual bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const;

virtual bool lessThan( const QModelIndex &left, const QModelIndex &right ) const;

};
QFlags<QgsPointCloudAttributeProxyModel::Filter> operator|(QgsPointCloudAttributeProxyModel::Filter f1, QFlags<QgsPointCloudAttributeProxyModel::Filter> f2);



/************************************************************************
* This file has been generated automatically from *
@@ -244,3 +244,68 @@ QIcon QgsPointCloudAttributeModel::iconForAttributeType( QgsPointCloudAttribute:
}
return QIcon();
}

//
// QgsPointCloudAttributeProxyModel
//

QgsPointCloudAttributeProxyModel::QgsPointCloudAttributeProxyModel( QgsPointCloudAttributeModel *source, QObject *parent )
: QSortFilterProxyModel( parent )
, mModel( source )
{
setSourceModel( mModel );
}

QgsPointCloudAttributeProxyModel *QgsPointCloudAttributeProxyModel::setFilters( QgsPointCloudAttributeProxyModel::Filters filters )
{
mFilters = filters;
invalidateFilter();
return this;
}

bool QgsPointCloudAttributeProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
{
QModelIndex index = sourceModel()->index( source_row, 0, source_parent );

if ( mFilters.testFlag( AllTypes ) )
return true;

const QVariant typeVar = mModel->data( index, QgsPointCloudAttributeModel::AttributeTypeRole );
if ( typeVar.isNull() )
return true;

bool ok;
const QgsPointCloudAttribute::DataType type = static_cast< QgsPointCloudAttribute::DataType >( typeVar.toInt( &ok ) );
if ( !ok )
return true;

if ( ( mFilters.testFlag( Char ) && type == QgsPointCloudAttribute::Char ) ||
( mFilters.testFlag( Short ) && type == QgsPointCloudAttribute::Short ) ||
( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::Int32 ) ||
( mFilters.testFlag( Float ) && type == QgsPointCloudAttribute::Float ) ||
( mFilters.testFlag( Double ) && type == QgsPointCloudAttribute::Double ) )
return true;

return false;
}

bool QgsPointCloudAttributeProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
{
// empty field is always first
if ( sourceModel()->data( left, QgsPointCloudAttributeModel::IsEmptyRole ).toBool() )
return true;
else if ( sourceModel()->data( right, QgsPointCloudAttributeModel::IsEmptyRole ).toBool() )
return false;

// order is attribute order
bool lok, rok;
int leftId = sourceModel()->data( left, QgsPointCloudAttributeModel::AttributeIndexRole ).toInt( &lok );
int rightId = sourceModel()->data( right, QgsPointCloudAttributeModel::AttributeIndexRole ).toInt( &rok );

if ( !lok )
return false;
if ( !rok )
return true;

return leftId < rightId;
}
@@ -22,6 +22,7 @@

#include <QAbstractItemModel>
#include <QPointer>
#include <QSortFilterProxyModel>

class QgsPointCloudLayer;

@@ -126,5 +127,66 @@ class CORE_EXPORT QgsPointCloudAttributeModel : public QAbstractItemModel
};


/**
* \ingroup core
*
* A proxy model for filtering available attributes from a point cloud attribute model.
*
* \since QGIS 3.18
*/
class CORE_EXPORT QgsPointCloudAttributeProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:

//! Attribute type filters
enum Filter
{
Char = 1 << 0, //!< Character attributes
Short = 1 << 1, //!< Short attributes
Int32 = 1 << 2, //!< Int32 attributes
Float = 1 << 3, //!< Float attributes
Double = 1 << 4, //!< Double attributes
Numeric = Short | Int32 | Float | Double, //!< All numeric attributes
AllTypes = Numeric | Char, //!< All attribute types
};
Q_DECLARE_FLAGS( Filters, Filter )
Q_FLAG( Filters )

/**
* Constructor for QgsPointCloudAttributeProxyModel, with the specified \a source
* model and \a parent object.
*/
explicit QgsPointCloudAttributeProxyModel( QgsPointCloudAttributeModel *source, QObject *parent SIP_TRANSFERTHIS = nullptr );

/**
* Returns the QgsPointCloudAttributeModel used in this QSortFilterProxyModel.
*/
QgsPointCloudAttributeModel *sourceAttributeModel() { return mModel; }

/**
* Set flags that affect how fields are filtered in the model.
* \see filters()
*/
QgsPointCloudAttributeProxyModel *setFilters( QgsPointCloudAttributeProxyModel::Filters filters );

/**
* Returns the filters controlling displayed attributes.
* \see setFilters()
*/
Filters filters() const { return mFilters; }

private:

QgsPointCloudAttributeModel *mModel = nullptr;
Filters mFilters = AllTypes;

// QSortFilterProxyModel interface
public:
bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const override;
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsPointCloudAttributeProxyModel::Filters )


#endif // QGSPOINTCLOUDATTRIBUTEMODEL_H
@@ -15,6 +15,7 @@
from qgis.core import (QgsPointCloudAttribute,
QgsPointCloudAttributeCollection,
QgsPointCloudAttributeModel,
QgsPointCloudAttributeProxyModel,
QgsProviderRegistry,
QgsPointCloudLayer)
from qgis.PyQt.QtCore import QVariant, Qt, QModelIndex
@@ -224,6 +225,116 @@ def testSetLayer(self):
self.assertEqual(m.layer(), layer)
self.assertEqual([a.name() for a in m.attributes().attributes()], ['X', 'Y', 'Z', 'Intensity', 'ReturnNumber', 'NumberOfReturns', 'ScanDirectionFlag', 'EdgeOfFlightLine', 'Classification', 'ScanAngleRank', 'UserData', 'PointSourceId', 'GpsTime', 'Red', 'Green', 'Blue'])

def testProxyModel(self):
m = QgsPointCloudAttributeModel()
attributes = create_attributes()
attributes.push_back(QgsPointCloudAttribute('green', QgsPointCloudAttribute.Short))
attributes.push_back(QgsPointCloudAttribute('intensity', QgsPointCloudAttribute.Double))
m.setAttributes(attributes)
proxy = QgsPointCloudAttributeProxyModel(m)

self.assertEqual(proxy.rowCount(), 7)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'x')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'y')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'z')
self.assertEqual(proxy.data(proxy.index(3, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'cat')
self.assertEqual(proxy.data(proxy.index(4, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')
self.assertEqual(proxy.data(proxy.index(5, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'green')
self.assertEqual(proxy.data(proxy.index(6, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')
self.assertEqual(proxy.data(proxy.index(7, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 8)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'x')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'y')
self.assertEqual(proxy.data(proxy.index(7, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Char)
self.assertEqual(proxy.rowCount(), 1)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'cat')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 2)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'cat')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Short)
self.assertEqual(proxy.rowCount(), 1)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'green')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 2)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'green')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Int32)
self.assertEqual(proxy.rowCount(), 1)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 2)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Float)
self.assertEqual(proxy.rowCount(), 3)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'x')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'y')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'z')
self.assertEqual(proxy.data(proxy.index(3, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 4)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'x')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'y')
self.assertEqual(proxy.data(proxy.index(3, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'z')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Double)
self.assertEqual(proxy.rowCount(), 1)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 2)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Double | QgsPointCloudAttributeProxyModel.Int32)
self.assertEqual(proxy.rowCount(), 2)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 3)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')

m.setAllowEmptyAttributeName(False)
proxy.setFilters(QgsPointCloudAttributeProxyModel.Numeric)
self.assertEqual(proxy.rowCount(), 6)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'x')
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'y')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'z')
self.assertEqual(proxy.data(proxy.index(3, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')
self.assertEqual(proxy.data(proxy.index(4, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'green')
self.assertEqual(proxy.data(proxy.index(5, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')
self.assertEqual(proxy.data(proxy.index(6, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
m.setAllowEmptyAttributeName(True)
self.assertEqual(proxy.rowCount(), 7)
self.assertEqual(proxy.data(proxy.index(0, 0), QgsPointCloudAttributeModel.AttributeNameRole), None)
self.assertEqual(proxy.data(proxy.index(1, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'x')
self.assertEqual(proxy.data(proxy.index(2, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'y')
self.assertEqual(proxy.data(proxy.index(3, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'z')
self.assertEqual(proxy.data(proxy.index(4, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'red')
self.assertEqual(proxy.data(proxy.index(5, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'green')
self.assertEqual(proxy.data(proxy.index(6, 0), QgsPointCloudAttributeModel.AttributeNameRole), 'intensity')


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

0 comments on commit 38e6b6b

Please sign in to comment.
You can’t perform that action at this time.