34 QgsPointCloudClassifiedRendererModel::QgsPointCloudClassifiedRendererModel( QObject *parent )
35 : QAbstractItemModel( parent )
36 , mMimeFormat( QStringLiteral(
"application/x-qgspointcloudclassifiedrenderermodel" ) )
42 if ( !mCategories.empty() )
44 beginRemoveRows( QModelIndex(), 0, std::max< int >( mCategories.size() - 1, 0 ) );
48 if ( categories.size() > 0 )
50 beginInsertRows( QModelIndex(), 0, categories.size() - 1 );
51 mCategories = categories;
58 const int idx = mCategories.size();
59 beginInsertRows( QModelIndex(), idx, idx );
60 mCategories.append( cat );
63 emit categoriesChanged();
68 const int row = index.row();
69 if ( row >= mCategories.size() )
73 return mCategories.at( row );
76 Qt::ItemFlags QgsPointCloudClassifiedRendererModel::flags(
const QModelIndex &index )
const
78 if ( !index.isValid() || mCategories.empty() )
80 return Qt::ItemIsDropEnabled;
83 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
84 if ( index.column() == 1 )
86 flags |= Qt::ItemIsEditable;
88 else if ( index.column() == 2 )
90 flags |= Qt::ItemIsEditable;
95 Qt::DropActions QgsPointCloudClassifiedRendererModel::supportedDropActions()
const
97 return Qt::MoveAction;
100 QVariant QgsPointCloudClassifiedRendererModel::data(
const QModelIndex &index,
int role )
const
102 if ( !index.isValid() || mCategories.empty() )
109 case Qt::CheckStateRole:
111 if ( index.column() == 0 )
113 return category.
renderState() ? Qt::Checked : Qt::Unchecked;
118 case Qt::DisplayRole:
119 case Qt::ToolTipRole:
121 switch ( index.column() )
125 return QString::number( category.
value() );
128 return category.
label();
133 case Qt::DecorationRole:
135 if ( index.column() == 0 )
139 pix.fill( category.
color() );
145 case Qt::TextAlignmentRole:
147 return ( index.column() == 0 ) ?
static_cast<Qt::Alignment::Int
>( Qt::AlignHCenter ) :
static_cast<Qt::Alignment::Int
>( Qt::AlignLeft );
152 switch ( index.column() )
156 return QString::number( category.
value() );
160 return category.
label();
169 bool QgsPointCloudClassifiedRendererModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
171 if ( !index.isValid() )
174 if ( index.column() == 0 && role == Qt::CheckStateRole )
176 mCategories[ index.row() ].setRenderState( value == Qt::Checked );
177 emit dataChanged( index, index );
178 emit categoriesChanged();
182 if ( role != Qt::EditRole )
185 switch ( index.column() )
189 const int val = value.toInt();
190 mCategories[ index.row() ].setValue( val );
195 mCategories[ index.row() ].setLabel( value.toString() );
202 emit dataChanged( index, index );
203 emit categoriesChanged();
207 QVariant QgsPointCloudClassifiedRendererModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
209 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
212 lst << tr(
"Color" ) << tr(
"Value" ) << tr(
"Legend" );
213 return lst.value( section );
218 int QgsPointCloudClassifiedRendererModel::rowCount(
const QModelIndex &parent )
const
220 if ( parent.isValid() )
224 return mCategories.size();
227 int QgsPointCloudClassifiedRendererModel::columnCount(
const QModelIndex &index )
const
233 QModelIndex QgsPointCloudClassifiedRendererModel::index(
int row,
int column,
const QModelIndex &parent )
const
235 if ( hasIndex( row, column, parent ) )
237 return createIndex( row, column );
239 return QModelIndex();
242 QModelIndex QgsPointCloudClassifiedRendererModel::parent(
const QModelIndex &index )
const
245 return QModelIndex();
248 QStringList QgsPointCloudClassifiedRendererModel::mimeTypes()
const
251 types << mMimeFormat;
255 QMimeData *QgsPointCloudClassifiedRendererModel::mimeData(
const QModelIndexList &indexes )
const
257 QMimeData *mimeData =
new QMimeData();
258 QByteArray encodedData;
260 QDataStream stream( &encodedData, QIODevice::WriteOnly );
263 const auto constIndexes = indexes;
264 for (
const QModelIndex &index : constIndexes )
266 if ( !index.isValid() || index.column() != 0 )
269 stream << index.row();
271 mimeData->setData( mMimeFormat, encodedData );
275 bool QgsPointCloudClassifiedRendererModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
279 if ( action != Qt::MoveAction )
282 if ( !data->hasFormat( mMimeFormat ) )
285 QByteArray encodedData = data->data( mMimeFormat );
286 QDataStream stream( &encodedData, QIODevice::ReadOnly );
289 while ( !stream.atEnd() )
296 int to = parent.row();
300 to = mCategories.size();
301 for (
int i = rows.size() - 1; i >= 0; i-- )
307 if ( !( rows[i] < 0 || rows[i] >= mCategories.size() || t < 0 || t >= mCategories.size() ) )
309 mCategories.move( rows[i], t );
313 for (
int j = 0; j < i; j++ )
315 if ( to < rows[j] && rows[i] > rows[j] )
322 emit dataChanged( createIndex( 0, 0 ), createIndex( mCategories.size(), 0 ) );
323 emit categoriesChanged();
327 void QgsPointCloudClassifiedRendererModel::deleteRows( QList<int> rows )
329 std::sort( rows.begin(), rows.end() );
330 for (
int i = rows.size() - 1; i >= 0; i-- )
332 beginRemoveRows( QModelIndex(), rows[i], rows[i] );
333 mCategories.removeAt( rows[i] );
336 emit categoriesChanged();
339 void QgsPointCloudClassifiedRendererModel::removeAllRows()
341 beginRemoveRows( QModelIndex(), 0, mCategories.size() - 1 );
344 emit categoriesChanged();
347 void QgsPointCloudClassifiedRendererModel::setCategoryColor(
int row,
const QColor &color )
349 mCategories[row].setColor( color );
350 emit dataChanged( createIndex( row, 0 ), createIndex( row, 0 ) );
351 emit categoriesChanged();
355 QgsPointCloudClassifiedRendererViewStyle::QgsPointCloudClassifiedRendererViewStyle( QWidget *parent )
359 void QgsPointCloudClassifiedRendererViewStyle::drawPrimitive( PrimitiveElement element,
const QStyleOption *option, QPainter *painter,
const QWidget *widget )
const
361 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
363 QStyleOption opt( *option );
364 opt.rect.setLeft( 0 );
366 opt.rect.setHeight( 0 );
368 opt.rect.setRight( widget->width() );
369 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
372 QProxyStyle::drawPrimitive( element, option, painter, widget );
381 mAttributeComboBox->setAllowEmptyAttributeName(
true );
384 mModel =
new QgsPointCloudClassifiedRendererModel(
this );
389 mAttributeComboBox->setLayer( layer );
391 setFromRenderer( layer->
renderer() );
394 viewCategories->setModel( mModel );
395 viewCategories->resizeColumnToContents( 0 );
396 viewCategories->resizeColumnToContents( 1 );
397 viewCategories->resizeColumnToContents( 2 );
399 viewCategories->setStyle(
new QgsPointCloudClassifiedRendererViewStyle( viewCategories ) );
402 this, &QgsPointCloudClassifiedRendererWidget::emitWidgetChanged );
403 connect( mModel, &QgsPointCloudClassifiedRendererModel::categoriesChanged,
this, &QgsPointCloudClassifiedRendererWidget::emitWidgetChanged );
405 connect( viewCategories, &QAbstractItemView::doubleClicked,
this, &QgsPointCloudClassifiedRendererWidget::categoriesDoubleClicked );
406 connect( btnAddCategories, &QAbstractButton::clicked,
this, &QgsPointCloudClassifiedRendererWidget::addCategories );
407 connect( btnDeleteCategories, &QAbstractButton::clicked,
this, &QgsPointCloudClassifiedRendererWidget::deleteCategories );
408 connect( btnDeleteAllCategories, &QAbstractButton::clicked,
this, &QgsPointCloudClassifiedRendererWidget::deleteAllCategories );
409 connect( btnAddCategory, &QAbstractButton::clicked,
this, &QgsPointCloudClassifiedRendererWidget::addCategory );
415 return new QgsPointCloudClassifiedRendererWidget( layer, style );
425 std::unique_ptr< QgsPointCloudClassifiedRenderer > renderer = std::make_unique< QgsPointCloudClassifiedRenderer >();
426 renderer->setAttribute( mAttributeComboBox->currentAttribute() );
427 renderer->setCategories( mModel->categories() );
429 return renderer.release();
434 return mModel->categories();
437 QString QgsPointCloudClassifiedRendererWidget::attribute()
439 return mAttributeComboBox->currentAttribute();
442 void QgsPointCloudClassifiedRendererWidget::emitWidgetChanged()
444 if ( !mBlockChangedSignal )
445 emit widgetChanged();
448 void QgsPointCloudClassifiedRendererWidget::categoriesDoubleClicked(
const QModelIndex &idx )
450 if ( idx.isValid() && idx.column() == 0 )
451 changeCategorySymbol();
454 void QgsPointCloudClassifiedRendererWidget::addCategories()
456 if ( !mLayer || !mLayer->dataProvider() )
459 const QVariantList providerCategories = mLayer->dataProvider()->metadataClasses( mAttributeComboBox->currentAttribute() );
462 for (
const QVariant &providerCategory : providerCategories )
464 const int newValue = providerCategory.toInt();
469 if (
c.value() == newValue )
483 void QgsPointCloudClassifiedRendererWidget::addCategory()
489 mModel->addCategory( cat );
490 emit widgetChanged();
493 void QgsPointCloudClassifiedRendererWidget::deleteCategories()
495 const QList<int> categoryIndexes = selectedCategories();
496 mModel->deleteRows( categoryIndexes );
497 emit widgetChanged();
500 void QgsPointCloudClassifiedRendererWidget::deleteAllCategories()
502 mModel->removeAllRows();
503 emit widgetChanged();
508 mBlockChangedSignal =
true;
511 mModel->setRendererCategories( classifiedRenderer->categories() );
512 mAttributeComboBox->setAttribute( classifiedRenderer->attribute() );
516 if ( mAttributeComboBox->findText( QStringLiteral(
"Classification" ) ) > -1 )
518 mAttributeComboBox->setAttribute( QStringLiteral(
"Classification" ) );
522 mAttributeComboBox->setCurrentIndex( mAttributeComboBox->count() > 1 ? 1 : 0 );
525 mBlockChangedSignal =
false;
528 void QgsPointCloudClassifiedRendererWidget::setFromCategories(
QgsPointCloudCategoryList categories,
const QString &attribute )
530 mBlockChangedSignal =
false;
531 mModel->setRendererCategories( categories );
532 if ( !attribute.isEmpty() )
534 mAttributeComboBox->setAttribute( attribute );
538 if ( mAttributeComboBox->findText( QStringLiteral(
"Classification" ) ) > -1 )
540 mAttributeComboBox->setAttribute( QStringLiteral(
"Classification" ) );
544 mAttributeComboBox->setCurrentIndex( mAttributeComboBox->count() > 1 ? 1 : 0 );
547 mBlockChangedSignal =
false;
550 void QgsPointCloudClassifiedRendererWidget::changeCategorySymbol()
552 const int row = currentCategoryRow();
568 mModel->setCategoryColor( row, newColor );
575 if ( newColor.isValid() )
577 mModel->setCategoryColor( row, newColor );
582 QList<int> QgsPointCloudClassifiedRendererWidget::selectedCategories()
585 const QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows();
586 for (
const QModelIndex &r : selectedRows )
590 rows.append( r.row() );
596 int QgsPointCloudClassifiedRendererWidget::currentCategoryRow()
598 const QModelIndex idx = viewCategories->selectionModel()->currentIndex();
599 if ( !idx.isValid() )
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), bool allowOpacity=false)
Returns a color selection from a color dialog.
QColor fetchRandomStyleColor() const
Returns a random color for use with a new symbol style (e.g.
void attributeChanged(const QString &name)
Emitted when the currently selected attribute changes.
@ Char
Character attributes.
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
int value() const
Returns the value corresponding to this category.
bool renderState() const
Returns true if the category is currently enabled and should be rendered.
QColor color() const
Returns the color which will be used to render this category.
QString label() const
Returns the label for this category, which is used to represent the category within legends and the l...
Renders point clouds by a classification attribute.
static QgsPointCloudCategoryList defaultCategories()
Returns the default list of categories.
static QMap< int, QString > translatedLasClassificationCodes()
Returns the map of LAS classification code to translated string value, corresponding to the ASPRS Sta...
Represents a map layer supporting display of point clouds.
QgsPointCloudRenderer * renderer()
Returns the 2D renderer for the point cloud.
Abstract base class for 2d point cloud renderers.
A QProxyStyle subclass which correctly sets the base style to match the QGIS application style,...
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QList< QgsPointCloudCategory > QgsPointCloudCategoryList