QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
38 {
39 mLayer = nullptr;
41 }
42}
43
45{
46 return mLayer;
47}
48
50{
51 beginResetModel();
52 mAttributes = attributes;
53 endResetModel();
54}
55
57{
58 if ( allowEmpty == mAllowEmpty )
59 return;
60
61 if ( allowEmpty )
62 {
63 beginInsertRows( QModelIndex(), 0, 0 );
64 mAllowEmpty = true;
65 endInsertRows();
66 }
67 else
68 {
69 beginRemoveRows( QModelIndex(), 0, 0 );
70 mAllowEmpty = false;
71 endRemoveRows();
72 }
73}
74
75QModelIndex QgsPointCloudAttributeModel::indexFromName( const QString &name )
76{
77 if ( !name.isEmpty() )
78 {
79 const int idx = mAttributes.indexOf( name );
80 if ( idx >= 0 )
81 {
82 if ( mAllowEmpty )
83 return index( 1 + idx, 0 );
84 else
85 return index( idx, 0 );
86 }
87 }
88
89 if ( mAllowEmpty && name.isEmpty() )
90 return index( 0, 0 );
91
92 return QModelIndex();
93}
94
95QModelIndex QgsPointCloudAttributeModel::index( int row, int column, const QModelIndex &parent ) const
96{
97 if ( hasIndex( row, column, parent ) )
98 {
99 return createIndex( row, column, row );
100 }
101
102 return QModelIndex();
103}
104
105QModelIndex QgsPointCloudAttributeModel::parent( const QModelIndex &child ) const
106{
107 Q_UNUSED( child )
108 return QModelIndex();
109}
110
111int QgsPointCloudAttributeModel::rowCount( const QModelIndex &parent ) const
112{
113 if ( parent.isValid() )
114 {
115 return 0;
116 }
117
118 return ( mAllowEmpty ? 1 : 0 ) + mAttributes.count();
119}
120
121int QgsPointCloudAttributeModel::columnCount( const QModelIndex &parent ) const
122{
123 Q_UNUSED( parent )
124 return 1;
125}
126
127QVariant QgsPointCloudAttributeModel::data( const QModelIndex &index, int role ) const
128{
129 if ( !index.isValid() )
130 return QVariant();
131
132 const bool isEmpty = mAllowEmpty && index.row() == 0;
133 const int fieldOffset = mAllowEmpty ? 1 : 0;
134
135 if ( !isEmpty && ( index.row() - fieldOffset >= mAttributes.count() ) )
136 return QVariant();
137
138 switch ( role )
139 {
140 case static_cast< int >( CustomRole::AttributeName ):
141 {
142 if ( isEmpty )
143 {
144 return QVariant();
145 }
146 return mAttributes.at( index.row() - fieldOffset ).name();
147 }
148
149 case static_cast< int >( CustomRole::AttributeIndex ):
150 {
151 if ( isEmpty )
152 {
153 return QVariant();
154 }
155 return index.row() - fieldOffset;
156 }
157
158 case static_cast< int >( CustomRole::AttributeSize ):
159 {
160 if ( isEmpty )
161 {
162 return QVariant();
163 }
164 return static_cast< int >( mAttributes.at( index.row() - fieldOffset ).size() );
165 }
166
167 case static_cast< int >( CustomRole::AttributeType ):
168 {
169 if ( isEmpty )
170 {
171 return QVariant();
172 }
173 return static_cast< int >( mAttributes.at( index.row() - fieldOffset ).type() );
174 }
175
176 case static_cast< int >( CustomRole::IsEmpty ):
177 {
178 return isEmpty;
179 }
180
181 case static_cast< int >( CustomRole::IsNumeric ):
182 {
183 if ( isEmpty )
184 {
185 return QVariant();
186 }
187 return QgsPointCloudAttribute::isNumeric( mAttributes.at( index.row() - fieldOffset ).type() );
188 }
189
190 case Qt::DisplayRole:
191 case Qt::EditRole:
192 case Qt::ToolTipRole:
193 {
194 if ( isEmpty )
195 {
196 return QVariant();
197 }
198 else if ( role == Qt::ToolTipRole )
199 {
200 return attributeToolTip( mAttributes.at( index.row() - fieldOffset ) );
201 }
202 else
203 return mAttributes.at( index.row() - fieldOffset ).name();
204 }
205
206 case Qt::DecorationRole:
207 {
208 if ( !isEmpty )
209 {
210 return iconForAttributeType( mAttributes.at( index.row() - fieldOffset ).type() );
211 }
212 return QIcon();
213 }
214
215 default:
216 return QVariant();
217 }
218}
219
221{
222 QString toolTip = QStringLiteral( "<b>%1</b>" ).arg( attribute.name() );
223
224 toolTip += QStringLiteral( "<br><font style='font-family:monospace; white-space: nowrap;'>%3</font>" ).arg( attribute.displayType() );
225
226 return toolTip;
227}
228
230{
231 switch ( type )
232 {
241 {
242 return QgsApplication::getThemeIcon( "/mIconFieldInteger.svg" );
243 }
246 {
247 return QgsApplication::getThemeIcon( "/mIconFieldFloat.svg" );
248 }
249
250 }
251 return QIcon();
252}
253
254//
255// QgsPointCloudAttributeProxyModel
256//
257
259 : QSortFilterProxyModel( parent )
260 , mModel( source )
261{
262 setSourceModel( mModel );
263}
264
266{
267 mFilters = filters;
268 invalidateFilter();
269 return this;
270}
271
272bool QgsPointCloudAttributeProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
273{
274 const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
275
276 if ( mFilters.testFlag( AllTypes ) )
277 return true;
278
279 const QVariant typeVar = mModel->data( index, static_cast< int >( QgsPointCloudAttributeModel::CustomRole::AttributeType ) );
280 if ( QgsVariantUtils::isNull( typeVar ) )
281 return true;
282
283 bool ok;
284 const QgsPointCloudAttribute::DataType type = static_cast< QgsPointCloudAttribute::DataType >( typeVar.toInt( &ok ) );
285 if ( !ok )
286 return true;
287
288 if ( ( mFilters.testFlag( Char ) && type == QgsPointCloudAttribute::Char ) ||
289 ( mFilters.testFlag( Char ) && type == QgsPointCloudAttribute::UChar ) ||
290 ( mFilters.testFlag( Short ) && type == QgsPointCloudAttribute::Short ) ||
291 ( mFilters.testFlag( Short ) && type == QgsPointCloudAttribute::UShort ) ||
292 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::Int32 ) ||
293 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::UInt32 ) ||
294 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::Int64 ) ||
295 ( mFilters.testFlag( Int32 ) && type == QgsPointCloudAttribute::UInt64 ) ||
296 ( mFilters.testFlag( Float ) && type == QgsPointCloudAttribute::Float ) ||
297 ( mFilters.testFlag( Double ) && type == QgsPointCloudAttribute::Double ) )
298 return true;
299
300 return false;
301}
302
303bool QgsPointCloudAttributeProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
304{
305 // empty field is always first
306 if ( sourceModel()->data( left, static_cast< int >( QgsPointCloudAttributeModel::CustomRole::IsEmpty ) ).toBool() )
307 return true;
308 else if ( sourceModel()->data( right, static_cast< int >( QgsPointCloudAttributeModel::CustomRole::IsEmpty ) ).toBool() )
309 return false;
310
311 // order is attribute order
312 bool lok, rok;
313 const int leftId = sourceModel()->data( left, static_cast< int >( QgsPointCloudAttributeModel::CustomRole::AttributeIndex ) ).toInt( &lok );
314 const int rightId = sourceModel()->data( right, static_cast< int >( QgsPointCloudAttributeModel::CustomRole::AttributeIndex ) ).toInt( &rok );
315
316 if ( !lok )
317 return false;
318 if ( !rok )
319 return true;
320
321 return leftId < rightId;
322}
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
@ IsNumeric
true if the index corresponds to a numeric attributre
@ AttributeIndex
Attribute index if index corresponds to an attribute.
@ AttributeType
Attribute type, see QgsPointCloudAttribute::DataType.
@ IsEmpty
true if the index corresponds to the empty value
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.
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, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.