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