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