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