34 QgsPointCloudClassifiedRendererModel::QgsPointCloudClassifiedRendererModel( QObject *parent )
 
   35   : QAbstractItemModel( parent )
 
   36   , mMimeFormat( QStringLiteral( 
"application/x-qgspointcloudclassifiedrenderermodel" ) )
 
   42   if ( !mCategories.empty() )
 
   44     beginRemoveRows( QModelIndex(), 0, std::max( mCategories.size() - 1, 0 ) );
 
   48   if ( categories.size() > 0 )
 
   50     beginInsertRows( QModelIndex(), 0, categories.size() - 1 );
 
   51     mCategories = categories;
 
   58   int idx = mCategories.size();
 
   59   beginInsertRows( QModelIndex(), idx, idx );
 
   60   mCategories.append( cat );
 
   63   emit categoriesChanged();
 
   68   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 ) ? Qt::AlignHCenter : 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   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   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