QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgspointcloudattributemodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointcloudattributemodel.cpp
3 ---------------------
4 begin : November 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgspointcloudlayer.h"
20#include "qgspointcloudindex.h"
21#include "qgsapplication.h"
22#include "qgsvariantutils.h"
23
25 : QAbstractItemModel( parent )
26{
27
28}
29
31{
32 if ( layer )
33 {
34 mLayer = layer;
36 }
37 else
39}
40
42{
43 return mLayer;
44}
45
47{
48 beginResetModel();
49 mAttributes = attributes;
50 endResetModel();
51}
52
54{
55 if ( allowEmpty == mAllowEmpty )
56 return;
57
58 if ( allowEmpty )
59 {
60 beginInsertRows( QModelIndex(), 0, 0 );
61 mAllowEmpty = true;
62 endInsertRows();
63 }
64 else
65 {
66 beginRemoveRows( QModelIndex(), 0, 0 );
67 mAllowEmpty = false;
68 endRemoveRows();
69 }
70}
71
72QModelIndex QgsPointCloudAttributeModel::indexFromName( const QString &name )
73{
74 if ( !name.isEmpty() )
75 {
76 const int idx = mAttributes.indexOf( name );
77 if ( idx >= 0 )
78 {
79 if ( mAllowEmpty )
80 return index( 1 + idx, 0 );
81 else
82 return index( idx, 0 );
83 }
84 }
85
86 if ( mAllowEmpty && name.isEmpty() )
87 return index( 0, 0 );
88
89 return QModelIndex();
90}
91
92QModelIndex QgsPointCloudAttributeModel::index( int row, int column, const QModelIndex &parent ) const
93{
94 if ( hasIndex( row, column, parent ) )
95 {
96 return createIndex( row, column, row );
97 }
98
99 return QModelIndex();
100}
101
102QModelIndex QgsPointCloudAttributeModel::parent( const QModelIndex &child ) const
103{
104 Q_UNUSED( child )
105 return QModelIndex();
106}
107
108int QgsPointCloudAttributeModel::rowCount( const QModelIndex &parent ) const
109{
110 if ( parent.isValid() )
111 {
112 return 0;
113 }
114
115 return ( mAllowEmpty ? 1 : 0 ) + mAttributes.count();
116}
117
118int QgsPointCloudAttributeModel::columnCount( const QModelIndex &parent ) const
119{
120 Q_UNUSED( parent )
121 return 1;
122}
123
124QVariant QgsPointCloudAttributeModel::data( const QModelIndex &index, int role ) const
125{
126 if ( !index.isValid() )
127 return QVariant();
128
129 const bool isEmpty = mAllowEmpty && index.row() == 0;
130 const int fieldOffset = mAllowEmpty ? 1 : 0;
131
132 if ( !isEmpty && ( index.row() - fieldOffset >= mAttributes.count() ) )
133 return QVariant();
134
135 switch ( role )
136 {
138 {
139 if ( isEmpty )
140 {
141 return QVariant();
142 }
143 return mAttributes.at( index.row() - fieldOffset ).name();
144 }
145
147 {
148 if ( isEmpty )
149 {
150 return QVariant();
151 }
152 return index.row() - fieldOffset;
153 }
154
156 {
157 if ( isEmpty )
158 {
159 return QVariant();
160 }
161 return static_cast< int >( mAttributes.at( index.row() - fieldOffset ).size() );
162 }
163
165 {
166 if ( isEmpty )
167 {
168 return QVariant();
169 }
170 return static_cast< int >( mAttributes.at( index.row() - fieldOffset ).type() );
171 }
172
173 case IsEmptyRole:
174 {
175 return isEmpty;
176 }
177
178 case IsNumericRole:
179 {
180 if ( isEmpty )
181 {
182 return QVariant();
183 }
184 return QgsPointCloudAttribute::isNumeric( mAttributes.at( index.row() - fieldOffset ).type() );
185 }
186
187 case Qt::DisplayRole:
188 case Qt::EditRole:
189 case Qt::ToolTipRole:
190 {
191 if ( isEmpty )
192 {
193 return QVariant();
194 }
195 else if ( role == Qt::ToolTipRole )
196 {
197 return attributeToolTip( mAttributes.at( index.row() - fieldOffset ) );
198 }
199 else
200 return mAttributes.at( index.row() - fieldOffset ).name();
201 }
202
203 case Qt::DecorationRole:
204 {
205 if ( !isEmpty )
206 {
207 return iconForAttributeType( mAttributes.at( index.row() - fieldOffset ).type() );
208 }
209 return QIcon();
210 }
211
212 default:
213 return QVariant();
214 }
215}
216
218{
219 QString toolTip = QStringLiteral( "<b>%1</b>" ).arg( attribute.name() );
220
221 toolTip += QStringLiteral( "<br><font style='font-family:monospace; white-space: nowrap;'>%3</font>" ).arg( attribute.displayType() );
222
223 return toolTip;
224}
225
227{
228 switch ( type )
229 {
238 {
239 return QgsApplication::getThemeIcon( "/mIconFieldInteger.svg" );
240 }
243 {
244 return QgsApplication::getThemeIcon( "/mIconFieldFloat.svg" );
245 }
246
247 }
248 return QIcon();
249}
250
251//
252// QgsPointCloudAttributeProxyModel
253//
254
256 : QSortFilterProxyModel( parent )
257 , mModel( source )
258{
259 setSourceModel( mModel );
260}
261
262QgsPointCloudAttributeProxyModel *QgsPointCloudAttributeProxyModel::setFilters( QgsPointCloudAttributeProxyModel::Filters filters )
263{
264 mFilters = filters;
265 invalidateFilter();
266 return this;
267}
268
269bool QgsPointCloudAttributeProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
270{
271 const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
272
273 if ( mFilters.testFlag( AllTypes ) )
274 return true;
275
276 const QVariant typeVar = mModel->data( index, QgsPointCloudAttributeModel::AttributeTypeRole );
277 if ( QgsVariantUtils::isNull( typeVar ) )
278 return true;
279
280 bool ok;
281 const QgsPointCloudAttribute::DataType type = static_cast< QgsPointCloudAttribute::DataType >( typeVar.toInt( &ok ) );
282 if ( !ok )
283 return true;
284
285 if ( ( mFilters.testFlag( Char ) && type == QgsPointCloudAttribute::Char ) ||
286 ( mFilters.testFlag( Char ) && type == QgsPointCloudAttribute::UChar ) ||
287 ( mFilters.testFlag( Short ) && type == QgsPointCloudAttribute::Short ) ||
288 ( mFilters.testFlag( Short ) && type == QgsPointCloudAttribute::UShort ) ||
289 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::Int32 ) ||
290 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::UInt32 ) ||
291 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::Int64 ) ||
292 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::UInt64 ) ||
293 ( mFilters.testFlag( Float ) && type == QgsPointCloudAttribute::Float ) ||
294 ( mFilters.testFlag( Double ) && type == QgsPointCloudAttribute::Double ) )
295 return true;
296
297 return false;
298}
299
300bool QgsPointCloudAttributeProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
301{
302 // empty field is always first
303 if ( sourceModel()->data( left, QgsPointCloudAttributeModel::IsEmptyRole ).toBool() )
304 return true;
305 else if ( sourceModel()->data( right, QgsPointCloudAttributeModel::IsEmptyRole ).toBool() )
306 return false;
307
308 // order is attribute order
309 bool lok, rok;
310 const int leftId = sourceModel()->data( left, QgsPointCloudAttributeModel::AttributeIndexRole ).toInt( &lok );
311 const int rightId = sourceModel()->data( right, QgsPointCloudAttributeModel::AttributeIndexRole ).toInt( &rok );
312
313 if ( !lok )
314 return false;
315 if ( !rok )
316 return true;
317
318 return leftId < rightId;
319}
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Collection of point cloud attributes.
const QgsPointCloudAttribute & at(int index) const
Returns the attribute at the specified index.
int count() const
Returns the number of attributes present in the collection.
int indexOf(const QString &name) const
Returns the index of the attribute with the specified name.
A model for display of available attributes from a point cloud.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the model.
QModelIndex parent(const QModelIndex &child) const override
void setAllowEmptyAttributeName(bool allowEmpty)
Sets whether an optional empty attribute ("not set") option is present in the model.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
int columnCount(const QModelIndex &parent) const override
void setLayer(QgsPointCloudLayer *layer)
Sets the layer associated with the model.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
QgsPointCloudAttributeModel(QObject *parent=nullptr)
Constructor for QgsPointCloudAttributeModel, with the specified parent object.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Sets the attributes to include in the model.
static QString attributeToolTip(const QgsPointCloudAttribute &attribute)
Returns a HTML formatted tooltip string for a attribute, containing details like the attribute name a...
QModelIndex indexFromName(const QString &name)
Returns the index corresponding to a given attribute name.
@ AttributeTypeRole
Attribute type, see QgsPointCloudAttribute::DataType.
@ IsEmptyRole
true if the index corresponds to the empty value
@ AttributeIndexRole
Attribute index if index corresponds to an attribute.
@ IsNumericRole
true if the index corresponds to a numeric attributre
QgsPointCloudLayer * layer()
Returns the layer associated with the model.
static QIcon iconForAttributeType(QgsPointCloudAttribute::DataType type)
Returns an icon corresponding to an attribute type.
A proxy model for filtering available attributes from a point cloud attribute model.
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Filters filters() const
Returns the filters controlling displayed attributes.
QgsPointCloudAttributeProxyModel * setFilters(QgsPointCloudAttributeProxyModel::Filters filters)
Set flags that affect how fields are filtered in the model.
QgsPointCloudAttributeProxyModel(QgsPointCloudAttributeModel *source, QObject *parent=nullptr)
Constructor for QgsPointCloudAttributeProxyModel, with the specified source model and parent object.
Attribute for point cloud data pair of name and size in bytes.
DataType
Systems of unit measurement.
@ UShort
Unsigned short int 2 bytes.
@ UChar
Unsigned char 1 byte.
@ UInt32
Unsigned int32 4 bytes.
@ UInt64
Unsigned int64 8 bytes.
static bool isNumeric(DataType type)
Returns true if the specified data type is numeric.
QString displayType() const
Returns the type to use when displaying this field.
int size() const
Returns size of the attribute in bytes.
QString name() const
Returns name of the attribute.
DataType type() const
Returns the data type.
Represents a map layer supporting display of point clouds.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes available from the layer.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.