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