QGIS API Documentation  2.99.0-Master (d55fa22)
qgspalettedrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspalettedrendererwidget.cpp
3  -----------------------------
4  begin : February 2012
5  copyright : (C) 2012 by Marco Hugentobler
6  email : marco at sourcepole dot ch
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 
20 #include "qgsrasterdataprovider.h"
21 #include "qgsrasterlayer.h"
22 #include "qgscolordialog.h"
23 #include "qgssettings.h"
24 #include "qgsproject.h"
25 
26 #include <QColorDialog>
27 #include <QInputDialog>
28 #include <QFileDialog>
29 #include <QMessageBox>
30 #include <QMenu>
31 
32 #ifdef ENABLE_MODELTEST
33 #include "modeltest.h"
34 #endif
35 
37 {
38  setupUi( this );
39 
40  mCalculatingProgressBar->hide();
41  mCancelButton->hide();
42 
43  contextMenu = new QMenu( tr( "Options" ), this );
44  contextMenu->addAction( tr( "Change color" ), this, SLOT( changeColor() ) );
45  contextMenu->addAction( tr( "Change opacity" ), this, SLOT( changeOpacity() ) );
46  contextMenu->addAction( tr( "Change label" ), this, SLOT( changeLabel() ) );
47 
48  mModel = new QgsPalettedRendererModel( this );
49  mTreeView->setSortingEnabled( false );
50  mTreeView->setModel( mModel );
51 
52 #ifdef ENABLE_MODELTEST
53  new ModelTest( mModel, this );
54 #endif
55 
56  mSwatchDelegate = new QgsColorSwatchDelegate( this );
57  mTreeView->setItemDelegateForColumn( QgsPalettedRendererModel::ColorColumn, mSwatchDelegate );
58  mTreeView->setColumnWidth( QgsPalettedRendererModel::ColorColumn, 50 );
59  mTreeView->setContextMenuPolicy( Qt::CustomContextMenu );
60  mTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
61  mTreeView->setDragEnabled( true );
62  mTreeView->setAcceptDrops( true );
63  mTreeView->setDropIndicatorShown( true );
64  mTreeView->setDragDropMode( QAbstractItemView::InternalMove );
65  mTreeView->setSelectionBehavior( QAbstractItemView::SelectRows );
66  mTreeView->setDefaultDropAction( Qt::MoveAction );
67 
68  connect( mTreeView, &QTreeView::customContextMenuRequested, [ = ]( const QPoint & ) { contextMenu->exec( QCursor::pos() ); }
69  );
70 
71  btnColorRamp->setShowRandomColorRamp( true );
72 
73  connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsPalettedRendererWidget::applyColorRamp );
74 
75  mBandComboBox->setLayer( mRasterLayer );
76 
77  if ( mRasterLayer )
78  {
80  if ( !provider )
81  {
82  return;
83  }
85  }
86 
88  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
89  connect( mDeleteEntryButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::deleteEntry );
90  connect( mAddEntryButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::addEntry );
91  connect( mLoadFromFileButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::loadColorTable );
92  connect( mExportToFileButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::saveColorTable );
93  connect( mClassifyButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::classify );
94  connect( mButtonLoadFromLayer, &QPushButton::clicked, this, &QgsPalettedRendererWidget::loadFromLayer );
95 
97  if ( provider )
98  {
99  mButtonLoadFromLayer->setEnabled( !provider->colorTable( mBandComboBox->currentBand() ).isEmpty() );
100  }
101  else
102  {
103  mButtonLoadFromLayer->setEnabled( false );
104  }
105 
106  connect( QgsProject::instance(), static_cast < void ( QgsProject::* )( QgsMapLayer * ) >( &QgsProject::layerWillBeRemoved ), this, &QgsPalettedRendererWidget::layerWillBeRemoved );
107  connect( mBandComboBox, &QgsRasterBandComboBox::bandChanged, this, &QgsPalettedRendererWidget::loadFromLayer );
108 }
109 
111 {
112  if ( mGatherer )
113  {
114  mGatherer->stop();
115  mGatherer->wait(); // mGatherer is deleted when wait completes
116  }
117 }
118 
120 {
121  QgsPalettedRasterRenderer::ClassData classes = mModel->classData();
122  int bandNumber = mBandComboBox->currentBand();
123 
125  if ( !btnColorRamp->isNull() )
126  {
127  r->setSourceColorRamp( btnColorRamp->colorRamp() );
128  }
129  return r;
130 }
131 
133 {
134  const QgsPalettedRasterRenderer *pr = dynamic_cast<const QgsPalettedRasterRenderer *>( r );
135  if ( pr )
136  {
137  //read values and colors and fill into tree widget
138  mModel->setClassData( pr->classes() );
139 
140  if ( pr->sourceColorRamp() )
141  {
142  whileBlocking( btnColorRamp )->setColorRamp( pr->sourceColorRamp() );
143  }
144  else
145  {
146  std::unique_ptr< QgsColorRamp > ramp( new QgsRandomColorRamp() );
147  whileBlocking( btnColorRamp )->setColorRamp( ramp.get() );
148  }
149  }
150  else
151  {
152  loadFromLayer();
153  std::unique_ptr< QgsColorRamp > ramp( new QgsRandomColorRamp() );
154  whileBlocking( btnColorRamp )->setColorRamp( ramp.get() );
155  }
156 }
157 
158 void QgsPalettedRendererWidget::setSelectionColor( const QItemSelection &selection, const QColor &color )
159 {
160  // don't want to emit widgetChanged multiple times
161  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
162 
163  QModelIndex colorIndex;
164  Q_FOREACH ( const QItemSelectionRange &range, selection )
165  {
166  Q_FOREACH ( const QModelIndex &index, range.indexes() )
167  {
168  colorIndex = mModel->index( index.row(), QgsPalettedRendererModel::ColorColumn );
169  mModel->setData( colorIndex, color, Qt::EditRole );
170  }
171  }
172  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
173 
174  emit widgetChanged();
175 }
176 
177 void QgsPalettedRendererWidget::deleteEntry()
178 {
179  // don't want to emit widgetChanged multiple times
180  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
181 
182  QItemSelection sel = mTreeView->selectionModel()->selection();
183  Q_FOREACH ( const QItemSelectionRange &range, sel )
184  {
185  if ( range.isValid() )
186  mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
187  }
188 
189  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
190 
191  emit widgetChanged();
192 }
193 
194 void QgsPalettedRendererWidget::addEntry()
195 {
196  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
197 
198  QColor color( 150, 150, 150 );
199  std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
200  if ( ramp )
201  {
202  color = ramp->color( 1.0 );
203  }
204  mModel->addEntry( color );
205  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
206  emit widgetChanged();
207 }
208 
209 void QgsPalettedRendererWidget::changeColor()
210 {
211  QItemSelection sel = mTreeView->selectionModel()->selection();
212 
213  QModelIndex colorIndex = mModel->index( sel.first().top(), QgsPalettedRendererModel::ColorColumn );
214  QColor currentColor = mModel->data( colorIndex, Qt::DisplayRole ).value<QColor>();
215 
216  QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( qobject_cast< QWidget * >( parent() ) );
217  if ( panel && panel->dockMode() )
218  {
220  colorWidget->setPanelTitle( tr( "Select color" ) );
221  colorWidget->setAllowAlpha( true );
222  connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, [ = ]( const QColor & color ) { setSelectionColor( sel, color ); } );
223  panel->openPanel( colorWidget );
224  }
225  else
226  {
227  // modal dialog version... yuck
228  QColor newColor = QgsColorDialog::getColor( currentColor, this, QStringLiteral( "Change color" ), true );
229  if ( newColor.isValid() )
230  {
231  setSelectionColor( sel, newColor );
232  }
233  }
234 }
235 
236 void QgsPalettedRendererWidget::changeOpacity()
237 {
238  QItemSelection sel = mTreeView->selectionModel()->selection();
239 
240  QModelIndex colorIndex = mModel->index( sel.first().top(), QgsPalettedRendererModel::ColorColumn );
241  QColor currentColor = mModel->data( colorIndex, Qt::DisplayRole ).value<QColor>();
242 
243  bool ok;
244  double oldOpacity = ( currentColor.alpha() / 255.0 ) * 100.0;
245  double opacity = QInputDialog::getDouble( this, tr( "Opacity" ), tr( "Change color opacity [%]" ), oldOpacity, 0.0, 100.0, 0, &ok );
246  if ( ok )
247  {
248  int newOpacity = opacity / 100 * 255;
249 
250  // don't want to emit widgetChanged multiple times
251  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
252 
253  Q_FOREACH ( const QItemSelectionRange &range, sel )
254  {
255  Q_FOREACH ( const QModelIndex &index, range.indexes() )
256  {
257  colorIndex = mModel->index( index.row(), QgsPalettedRendererModel::ColorColumn );
258 
259  QColor newColor = mModel->data( colorIndex, Qt::DisplayRole ).value<QColor>();
260  newColor.setAlpha( newOpacity );
261  mModel->setData( colorIndex, newColor, Qt::EditRole );
262  }
263  }
264  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
265 
266  emit widgetChanged();
267  }
268 }
269 
270 void QgsPalettedRendererWidget::changeLabel()
271 {
272  QItemSelection sel = mTreeView->selectionModel()->selection();
273 
274  QModelIndex labelIndex = mModel->index( sel.first().top(), QgsPalettedRendererModel::LabelColumn );
275  QString currentLabel = mModel->data( labelIndex, Qt::DisplayRole ).toString();
276 
277  bool ok;
278  QString newLabel = QInputDialog::getText( this, tr( "Label" ), tr( "Change label" ), QLineEdit::Normal, currentLabel, &ok );
279  if ( ok )
280  {
281  // don't want to emit widgetChanged multiple times
282  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
283 
284  Q_FOREACH ( const QItemSelectionRange &range, sel )
285  {
286  Q_FOREACH ( const QModelIndex &index, range.indexes() )
287  {
288  labelIndex = mModel->index( index.row(), QgsPalettedRendererModel::LabelColumn );
289  mModel->setData( labelIndex, newLabel, Qt::EditRole );
290  }
291  }
292  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
293 
294  emit widgetChanged();
295  }
296 }
297 
298 void QgsPalettedRendererWidget::applyColorRamp()
299 {
300  std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
301  if ( !ramp )
302  {
303  return;
304  }
305 
306  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
307 
308  QgsPalettedRasterRenderer::ClassData data = mModel->classData();
309  QgsPalettedRasterRenderer::ClassData::iterator cIt = data.begin();
310 
311  double numberOfEntries = data.count();
312  int i = 0;
313 
314  if ( QgsRandomColorRamp *randomRamp = dynamic_cast<QgsRandomColorRamp *>( ramp.get() ) )
315  {
316  //ramp is a random colors ramp, so inform it of the total number of required colors
317  //this allows the ramp to pregenerate a set of visually distinctive colors
318  randomRamp->setTotalColorCount( numberOfEntries );
319  }
320 
321  if ( numberOfEntries > 1 )
322  numberOfEntries -= 1; //avoid duplicate first color
323 
324  for ( ; cIt != data.end(); ++cIt )
325  {
326  cIt->color = ramp->color( i / numberOfEntries );
327  i++;
328  }
329  mModel->setClassData( data );
330 
331  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
332  emit widgetChanged();
333 }
334 
335 void QgsPalettedRendererWidget::loadColorTable()
336 {
337  QgsSettings settings;
338  QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
339  QString fileName = QFileDialog::getOpenFileName( this, tr( "Open file" ), lastDir );
340  if ( !fileName.isEmpty() )
341  {
343  if ( !classes.isEmpty() )
344  {
345  disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
346  mModel->setClassData( classes );
347  emit widgetChanged();
348  connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
349  }
350  else
351  {
352  QMessageBox::critical( nullptr, tr( "Invalid file" ), tr( "Could not interpret file as a raster color table." ) );
353  }
354  }
355 }
356 
357 void QgsPalettedRendererWidget::saveColorTable()
358 {
359  QgsSettings settings;
360  QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
361  QString fileName = QFileDialog::getSaveFileName( this, tr( "Save file" ), lastDir, tr( "Text (*.clr)" ) );
362  if ( !fileName.isEmpty() )
363  {
364  if ( !fileName.endsWith( QLatin1String( ".clr" ), Qt::CaseInsensitive ) )
365  {
366  fileName = fileName + ".clr";
367  }
368 
369  QFile outputFile( fileName );
370  if ( outputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
371  {
372  QTextStream outputStream( &outputFile );
373  outputStream << QgsPalettedRasterRenderer::classDataToString( mModel->classData() );
374  outputStream.flush();
375  outputFile.close();
376 
377  QFileInfo fileInfo( fileName );
378  settings.setValue( QStringLiteral( "lastColorMapDir" ), fileInfo.absoluteDir().absolutePath() );
379  }
380  else
381  {
382  QMessageBox::warning( this, tr( "Write access denied" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
383  }
384  }
385 }
386 
387 void QgsPalettedRendererWidget::classify()
388 {
389  if ( mRasterLayer )
390  {
392  if ( !provider )
393  {
394  return;
395  }
396 
397  if ( mGatherer )
398  {
399  mGatherer->stop();
400  return;
401  }
402 
403  mGatherer = new QgsPalettedRendererClassGatherer( mRasterLayer, mBandComboBox->currentBand(), mModel->classData(), btnColorRamp->colorRamp() );
404 
405  connect( mGatherer, &QgsPalettedRendererClassGatherer::progressChanged, mCalculatingProgressBar, &QProgressBar::setValue );
406  mCalculatingProgressBar->show();
407  mCancelButton->show();
408  connect( mCancelButton, &QPushButton::clicked, mGatherer, &QgsPalettedRendererClassGatherer::stop );
409 
410  connect( mGatherer, &QgsPalettedRendererClassGatherer::collectedClasses, this, &QgsPalettedRendererWidget::gatheredClasses );
411  connect( mGatherer, &QgsPalettedRendererClassGatherer::finished, this, &QgsPalettedRendererWidget::gathererThreadFinished );
412  mClassifyButton->setText( tr( "Calculating..." ) );
413  mClassifyButton->setEnabled( false );
414  mGatherer->start();
415  }
416 }
417 
418 void QgsPalettedRendererWidget::loadFromLayer()
419 {
420  //read default palette settings from layer
422  if ( provider )
423  {
424  QList<QgsColorRampShader::ColorRampItem> table = provider->colorTable( mBandComboBox->currentBand() );
425  if ( !table.isEmpty() )
426  {
427  QgsPalettedRasterRenderer::ClassData classes = QgsPalettedRasterRenderer::colorTableToClassData( provider->colorTable( mBandComboBox->currentBand() ) );
428  mModel->setClassData( classes );
429  emit widgetChanged();
430  }
431  }
432 }
433 
434 void QgsPalettedRendererWidget::gatheredClasses()
435 {
436  if ( !mGatherer || mGatherer->wasCanceled() )
437  return;
438 
439  mModel->setClassData( mGatherer->classes() );
440  emit widgetChanged();
441 }
442 
443 void QgsPalettedRendererWidget::gathererThreadFinished()
444 {
445  mGatherer->deleteLater();
446  mGatherer = nullptr;
447  mClassifyButton->setText( tr( "Add Unique Values" ) );
448  mClassifyButton->setEnabled( true );
449  mCalculatingProgressBar->hide();
450  mCancelButton->hide();
451 }
452 
453 void QgsPalettedRendererWidget::layerWillBeRemoved( QgsMapLayer *layer )
454 {
455  if ( mGatherer && mRasterLayer == layer )
456  {
457  mGatherer->stop();
458  mGatherer->wait();
459  }
460 }
461 
462 //
463 // QgsPalettedRendererModel
464 //
465 
467 QgsPalettedRendererModel::QgsPalettedRendererModel( QObject *parent )
468  : QAbstractItemModel( parent )
469 {
470 
471 }
472 
473 void QgsPalettedRendererModel::setClassData( const QgsPalettedRasterRenderer::ClassData &data )
474 {
475  beginResetModel();
476  mData = data;
477  endResetModel();
478 }
479 
480 QModelIndex QgsPalettedRendererModel::index( int row, int column, const QModelIndex &parent ) const
481 {
482  if ( column < 0 || column >= columnCount() )
483  {
484  //column out of bounds
485  return QModelIndex();
486  }
487 
488  if ( !parent.isValid() && row >= 0 && row < mData.size() )
489  {
490  //return an index for the item at this position
491  return createIndex( row, column );
492  }
493 
494  //only top level supported
495  return QModelIndex();
496 }
497 
498 QModelIndex QgsPalettedRendererModel::parent( const QModelIndex &index ) const
499 {
500  Q_UNUSED( index );
501 
502  //all items are top level
503  return QModelIndex();
504 }
505 
506 int QgsPalettedRendererModel::columnCount( const QModelIndex &parent ) const
507 {
508  if ( parent.isValid() )
509  return 0;
510 
511  return 3;
512 }
513 
514 int QgsPalettedRendererModel::rowCount( const QModelIndex &parent ) const
515 {
516  if ( parent.isValid() )
517  return 0;
518 
519  return mData.count();
520 }
521 
522 QVariant QgsPalettedRendererModel::data( const QModelIndex &index, int role ) const
523 {
524  if ( !index.isValid() )
525  return QVariant();
526 
527  switch ( role )
528  {
529  case Qt::DisplayRole:
530  case Qt::EditRole:
531  {
532  switch ( index.column() )
533  {
534  case ValueColumn:
535  return mData.at( index.row() ).value;
536 
537  case ColorColumn:
538  return mData.at( index.row() ).color;
539 
540  case LabelColumn:
541  return mData.at( index.row() ).label;
542  }
543  }
544 
545  default:
546  return QVariant();
547  }
548 
549  return QVariant();
550 }
551 
552 QVariant QgsPalettedRendererModel::headerData( int section, Qt::Orientation orientation, int role ) const
553 {
554  switch ( orientation )
555  {
556  case Qt::Vertical:
557  return QVariant();
558 
559  case Qt::Horizontal:
560  {
561  switch ( role )
562  {
563  case Qt::DisplayRole:
564  {
565  switch ( section )
566  {
567  case ValueColumn:
568  return tr( "Value" );
569 
570  case ColorColumn:
571  return tr( "Color" );
572 
573  case LabelColumn:
574  return tr( "Label" );
575  }
576  }
577 
578  }
579  break;
580  }
581 
582  default:
583  return QAbstractItemModel::headerData( section, orientation, role );
584  }
585  return QAbstractItemModel::headerData( section, orientation, role );
586 }
587 
588 bool QgsPalettedRendererModel::setData( const QModelIndex &index, const QVariant &value, int )
589 {
590  if ( !index.isValid() )
591  return false;
592  if ( index.row() >= mData.length() )
593  return false;
594 
595  switch ( index.column() )
596  {
597  case ValueColumn:
598  {
599  bool ok = false;
600  int newValue = value.toInt( &ok );
601  if ( !ok )
602  return false;
603 
604  mData[ index.row() ].value = newValue;
605  emit dataChanged( index, index );
606  emit classesChanged();
607  return true;
608  }
609 
610  case ColorColumn:
611  {
612  mData[ index.row() ].color = value.value<QColor>();
613  emit dataChanged( index, index );
614  emit classesChanged();
615  return true;
616  }
617 
618  case LabelColumn:
619  {
620  mData[ index.row() ].label = value.toString();
621  emit dataChanged( index, index );
622  emit classesChanged();
623  return true;
624  }
625  }
626 
627  return false;
628 }
629 
630 Qt::ItemFlags QgsPalettedRendererModel::flags( const QModelIndex &index ) const
631 {
632  if ( !index.isValid() )
633  return QAbstractItemModel::flags( index ) | Qt::ItemIsDropEnabled;
634 
635  Qt::ItemFlags f = QAbstractItemModel::flags( index );
636  switch ( index.column() )
637  {
638  case ValueColumn:
639  case LabelColumn:
640  case ColorColumn:
641  f = f | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
642  break;
643  }
644  return f | Qt::ItemIsEnabled | Qt::ItemIsSelectable;;
645 }
646 
647 bool QgsPalettedRendererModel::removeRows( int row, int count, const QModelIndex &parent )
648 {
649  if ( row < 0 || row >= mData.count() )
650  return false;
651  if ( parent.isValid() )
652  return false;
653 
654  for ( int i = row + count - 1; i >= row; --i )
655  {
656  beginRemoveRows( parent, i, i );
657  mData.removeAt( i );
658  endRemoveRows();
659  }
660  emit classesChanged();
661  return true;
662 }
663 
664 bool QgsPalettedRendererModel::insertRows( int row, int count, const QModelIndex & )
665 {
666  QgsPalettedRasterRenderer::ClassData::const_iterator cIt = mData.constBegin();
667  int currentMaxValue = -INT_MAX;
668  for ( ; cIt != mData.constEnd(); ++cIt )
669  {
670  int value = cIt->value;
671  currentMaxValue = qMax( value, currentMaxValue );
672  }
673  int nextValue = qMax( 0, currentMaxValue + 1 );
674 
675  beginInsertRows( QModelIndex(), row, row + count - 1 );
676  for ( int i = row; i < row + count; ++i, ++nextValue )
677  {
678  mData.insert( i, QgsPalettedRasterRenderer::Class( nextValue, QColor( 200, 200, 200 ), QString::number( nextValue ) ) );
679  }
680  endInsertRows();
681  emit classesChanged();
682  return true;
683 }
684 
685 Qt::DropActions QgsPalettedRendererModel::supportedDropActions() const
686 {
687  return Qt::MoveAction;
688 }
689 
690 QStringList QgsPalettedRendererModel::mimeTypes() const
691 {
692  QStringList types;
693  types << QStringLiteral( "application/x-qgspalettedrenderermodel" );
694  return types;
695 }
696 
697 QMimeData *QgsPalettedRendererModel::mimeData( const QModelIndexList &indexes ) const
698 {
699  QMimeData *mimeData = new QMimeData();
700  QByteArray encodedData;
701 
702  QDataStream stream( &encodedData, QIODevice::WriteOnly );
703 
704  // Create list of rows
705  Q_FOREACH ( const QModelIndex &index, indexes )
706  {
707  if ( !index.isValid() || index.column() != 0 )
708  continue;
709 
710  stream << index.row();
711  }
712  mimeData->setData( QStringLiteral( "application/x-qgspalettedrenderermodel" ), encodedData );
713  return mimeData;
714 }
715 
716 bool QgsPalettedRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex & )
717 {
718  Q_UNUSED( column );
719  if ( action != Qt::MoveAction ) return true;
720 
721  if ( !data->hasFormat( QStringLiteral( "application/x-qgspalettedrenderermodel" ) ) )
722  return false;
723 
724  QByteArray encodedData = data->data( QStringLiteral( "application/x-qgspalettedrenderermodel" ) );
725  QDataStream stream( &encodedData, QIODevice::ReadOnly );
726 
727  QVector<int> rows;
728  while ( !stream.atEnd() )
729  {
730  int r;
731  stream >> r;
732  rows.append( r );
733  }
734 
736  for ( int i = 0; i < rows.count(); ++i )
737  newData << mData.at( rows.at( i ) );
738 
739  if ( row < 0 )
740  row = mData.count();
741 
742  beginInsertRows( QModelIndex(), row, row + rows.count() - 1 );
743  for ( int i = 0; i < rows.count(); ++i )
744  mData.insert( row + i, newData.at( i ) );
745  endInsertRows();
746  emit classesChanged();
747  return true;
748 }
749 
750 void QgsPalettedRendererModel::addEntry( const QColor &color )
751 {
752  insertRow( rowCount() );
753  setData( index( mData.count() - 1, 1 ), color );
754 }
755 
757 
void setSourceColorRamp(QgsColorRamp *ramp)
Set the source color ramp.
QgsPalettedRendererWidget(QgsRasterLayer *layer, const QgsRectangle &extent=QgsRectangle())
static QString classDataToString(const QgsPalettedRasterRenderer::ClassData &classes)
Converts classes to a string representation, using the .clr/gdal color table file format...
A rectangle specified with double values.
Definition: qgsrectangle.h:38
Base class for all map layer types.
Definition: qgsmaplayer.h:54
Renderer for paletted raster images.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
ClassData classes() const
Returns a map of value to classes (colors) used by the renderer.
Properties of a single value class.
Base class for any widget that can be shown as a inline panel.
QgsRasterRenderer * renderer() const
QgsRasterDataProvider * dataProvider() override
void setFromRenderer(const QgsRasterRenderer *r)
void setValue(const QString &key, const QVariant &value, const QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget...
A custom QGIS widget for selecting a color, including options for selecting colors via hue wheel...
void bandChanged(int band)
This signal is emitted when the currently selected band changes.
Reads and writes project states.
Definition: qgsproject.h:78
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), const bool allowAlpha=false)
Return a color selection from a color dialog.
void setAllowAlpha(const bool allowAlpha)
Sets whether alpha modification (transparency) is permitted for the color dialog. ...
Totally random color ramp.
Definition: qgscolorramp.h:382
QgsColorRamp * sourceColorRamp() const
Get the source color ramp.
QgsRasterRenderer * renderer() override
void layerWillBeRemoved(const QString &layerId)
Emitted when a layer is about to be removed from the registry.
static QgsPalettedRasterRenderer::ClassData classDataFromFile(const QString &path)
Opens a color table file and returns corresponding paletted renderer class data.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:170
void currentColorChanged(const QColor &color)
Emitted when the dialog&#39;s color changes.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:377
QList< Class > ClassData
Map of value to class properties.
void widgetChanged()
Emitted when something on the widget has changed.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
static QgsPalettedRasterRenderer::ClassData colorTableToClassData(const QList< QgsColorRampShader::ColorRampItem > &table)
Converts a raster color table to paletted renderer class data.
Raster renderer pipe that applies colors to a raster.
Use a narrower, vertically stacked layout.
A delegate for showing a color swatch in a list.
Base class for raster data providers.