QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsgradientcolorrampdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgradientcolorrampdialog.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include "qgscolorramp.h"
19 #include "qgsdialog.h"
20 #include "qgscolordialog.h"
21 #include "qgscptcityarchive.h"
22 #include "qgssettings.h"
23 #include "qgsgui.h"
24 
25 #include <QColorDialog>
26 #include <QHeaderView>
27 #include <QInputDialog>
28 #include <QPainter>
29 #include <QTableWidget>
30 #include <QTextEdit>
31 
32 // QWT Charting widget
33 #include <qwt_global.h>
34 #include <qwt_plot_canvas.h>
35 #include <qwt_plot.h>
36 #include <qwt_plot_curve.h>
37 #include <qwt_plot_grid.h>
38 #include <qwt_plot_marker.h>
39 #include <qwt_plot_picker.h>
40 #include <qwt_picker_machine.h>
41 #include <qwt_plot_layout.h>
42 #include <qwt_symbol.h>
43 #include <qwt_legend.h>
44 
46  : QDialog( parent )
47  , mRamp( ramp )
48  , mCurrentPlotColorComponent( -1 )
49  , mCurrentPlotMarkerIndex( 0 )
50 {
51  setupUi( this );
53  connect( cboType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientColorRampDialog::cboType_currentIndexChanged );
54  connect( btnInformation, &QPushButton::pressed, this, &QgsGradientColorRampDialog::btnInformation_pressed );
55  connect( mPositionSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientColorRampDialog::mPositionSpinBox_valueChanged );
56  connect( mPlotHueCheckbox, &QCheckBox::toggled, this, &QgsGradientColorRampDialog::mPlotHueCheckbox_toggled );
57  connect( mPlotLightnessCheckbox, &QCheckBox::toggled, this, &QgsGradientColorRampDialog::mPlotLightnessCheckbox_toggled );
58  connect( mPlotSaturationCheckbox, &QCheckBox::toggled, this, &QgsGradientColorRampDialog::mPlotSaturationCheckbox_toggled );
59  connect( mPlotAlphaCheckbox, &QCheckBox::toggled, this, &QgsGradientColorRampDialog::mPlotAlphaCheckbox_toggled );
60 #ifdef Q_OS_MAC
61  setWindowModality( Qt::WindowModal );
62 #endif
63 
64  mPositionSpinBox->setShowClearButton( false );
65  btnColor1->setAllowOpacity( true );
66  btnColor1->setColorDialogTitle( tr( "Select Ramp Color" ) );
67  btnColor1->setContext( QStringLiteral( "symbology" ) );
68  btnColor1->setShowNoColor( true );
69  btnColor1->setNoColorString( tr( "Transparent" ) );
70  btnColor2->setAllowOpacity( true );
71  btnColor2->setColorDialogTitle( tr( "Select Ramp Color" ) );
72  btnColor2->setContext( QStringLiteral( "symbology" ) );
73  btnColor2->setShowNoColor( true );
74  btnColor2->setNoColorString( tr( "Transparent" ) );
75  updateColorButtons();
78 
79  // fill type combobox
80  cboType->blockSignals( true );
81  cboType->addItem( tr( "Discrete" ) );
82  cboType->addItem( tr( "Continuous" ) );
83  if ( mRamp.isDiscrete() )
84  cboType->setCurrentIndex( 0 );
85  else
86  cboType->setCurrentIndex( 1 );
87  cboType->blockSignals( false );
88 
89  if ( mRamp.info().isEmpty() )
90  btnInformation->setEnabled( false );
91 
92  mStopEditor->setGradientRamp( mRamp );
93  connect( mStopEditor, &QgsGradientStopEditor::changed, this, &QgsGradientColorRampDialog::updateRampFromStopEditor );
94 
95  connect( mColorWidget, &QgsCompoundColorWidget::currentColorChanged, this, &QgsGradientColorRampDialog::colorWidgetChanged );
96  connect( mDeleteStopButton, &QAbstractButton::clicked, mStopEditor, &QgsGradientStopEditor::deleteSelectedStop );
97 
98  // hide the ugly canvas frame
99  mPlot->setFrameStyle( QFrame::NoFrame );
100  QFrame *plotCanvasFrame = dynamic_cast<QFrame *>( mPlot->canvas() );
101  if ( plotCanvasFrame )
102  plotCanvasFrame->setFrameStyle( QFrame::NoFrame );
103 
104  mPlot->setAxisScale( QwtPlot::yLeft, 0.0, 1.0 );
105  mPlot->enableAxis( QwtPlot::yLeft, false );
106 
107  // add a grid
108  QwtPlotGrid *grid = new QwtPlotGrid();
109  QwtScaleDiv gridDiv( 0.0, 1.0, QList<double>(), QList<double>(), QList<double>() << 0.2 << 0.4 << 0.6 << 0.8 );
110  grid->setXDiv( gridDiv );
111  grid->setYDiv( gridDiv );
112  grid->setPen( QPen( QColor( 0, 0, 0, 50 ) ) );
113  grid->attach( mPlot );
114 
115  mLightnessCurve = new QwtPlotCurve();
116  mLightnessCurve->setTitle( tr( "Lightness" ) );
117  mLightnessCurve->setPen( QPen( QColor( 70, 150, 255 ), 0.0 ) ),
118  mLightnessCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
119  mLightnessCurve->attach( mPlot );
120 
121  mHueCurve = new QwtPlotCurve();
122  mHueCurve->setTitle( tr( "Hue" ) );
123  mHueCurve->setPen( QPen( QColor( 255, 215, 70 ), 0.0 ) ),
124  mHueCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
125  mHueCurve->attach( mPlot );
126 
127  mSaturationCurve = new QwtPlotCurve();
128  mSaturationCurve->setTitle( tr( "Saturation" ) );
129  mSaturationCurve->setPen( QPen( QColor( 255, 70, 150 ), 0.0 ) ),
130  mSaturationCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
131  mSaturationCurve->attach( mPlot );
132 
133  mAlphaCurve = new QwtPlotCurve();
134  mAlphaCurve->setTitle( tr( "Opacity" ) );
135  mAlphaCurve->setPen( QPen( QColor( 50, 50, 50 ), 0.0 ) ),
136  mAlphaCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
137  mAlphaCurve->attach( mPlot );
138 
139  mPlotFilter = new QgsGradientPlotEventFilter( mPlot );
140  connect( mPlotFilter, &QgsGradientPlotEventFilter::mousePress, this, &QgsGradientColorRampDialog::plotMousePress );
141  connect( mPlotFilter, &QgsGradientPlotEventFilter::mouseRelease, this, &QgsGradientColorRampDialog::plotMouseRelease );
142  connect( mPlotFilter, &QgsGradientPlotEventFilter::mouseMove, this, &QgsGradientColorRampDialog::plotMouseMove );
143 
144  QgsSettings settings;
145  mPlotHueCheckbox->setChecked( settings.value( QStringLiteral( "GradientEditor/plotHue" ), false ).toBool() );
146  mPlotLightnessCheckbox->setChecked( settings.value( QStringLiteral( "GradientEditor/plotLightness" ), true ).toBool() );
147  mPlotSaturationCheckbox->setChecked( settings.value( QStringLiteral( "GradientEditor/plotSaturation" ), false ).toBool() );
148  mPlotAlphaCheckbox->setChecked( settings.value( QStringLiteral( "GradientEditor/plotAlpha" ), false ).toBool() );
149 
150  mHueCurve->setVisible( mPlotHueCheckbox->isChecked() );
151  mLightnessCurve->setVisible( mPlotLightnessCheckbox->isChecked() );
152  mSaturationCurve->setVisible( mPlotSaturationCheckbox->isChecked() );
153  mAlphaCurve->setVisible( mPlotAlphaCheckbox->isChecked() );
154 
155  connect( mStopEditor, &QgsGradientStopEditor::selectedStopChanged, this, &QgsGradientColorRampDialog::selectedStopChanged );
156  mStopEditor->selectStop( 0 );
157 
158  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsGradientColorRampDialog::showHelp );
159 }
160 
162 {
163  QgsSettings settings;
164  settings.setValue( QStringLiteral( "GradientEditor/plotHue" ), mPlotHueCheckbox->isChecked() );
165  settings.setValue( QStringLiteral( "GradientEditor/plotLightness" ), mPlotLightnessCheckbox->isChecked() );
166  settings.setValue( QStringLiteral( "GradientEditor/plotSaturation" ), mPlotSaturationCheckbox->isChecked() );
167  settings.setValue( QStringLiteral( "GradientEditor/plotAlpha" ), mPlotAlphaCheckbox->isChecked() );
168 
169 }
170 
172 {
173  mRamp = ramp;
174 
175  updateColorButtons();
176  updateStopEditor();
177  updatePlot();
178 
179  emit changed();
180 }
181 
182 QDialogButtonBox *QgsGradientColorRampDialog::buttonBox() const
183 {
184  return mButtonBox;
185 }
186 
187 void QgsGradientColorRampDialog::cboType_currentIndexChanged( int index )
188 {
189  if ( ( index == 0 && mRamp.isDiscrete() ) ||
190  ( index == 1 && !mRamp.isDiscrete() ) )
191  return;
192  mRamp.convertToDiscrete( index == 0 );
193  updateColorButtons();
194  updateStopEditor();
195  updatePlot();
196 
197  emit changed();
198 }
199 
200 void QgsGradientColorRampDialog::btnInformation_pressed()
201 {
202  if ( mRamp.info().isEmpty() )
203  return;
204 
205  QgsDialog *dlg = new QgsDialog( this );
206  QLabel *label = nullptr;
207 
208  // information table
209  QTableWidget *tableInfo = new QTableWidget( dlg );
210  tableInfo->verticalHeader()->hide();
211  tableInfo->horizontalHeader()->hide();
212  tableInfo->setRowCount( mRamp.info().count() );
213  tableInfo->setColumnCount( 2 );
214  int i = 0;
215  QgsStringMap rampInfo = mRamp.info();
216  for ( QgsStringMap::const_iterator it = rampInfo.constBegin();
217  it != rampInfo.constEnd(); ++it )
218  {
219  if ( it.key().startsWith( QLatin1String( "cpt-city" ) ) )
220  continue;
221  tableInfo->setItem( i, 0, new QTableWidgetItem( it.key() ) );
222  tableInfo->setItem( i, 1, new QTableWidgetItem( it.value() ) );
223  tableInfo->resizeRowToContents( i );
224  i++;
225  }
226  tableInfo->resizeColumnToContents( 0 );
227  tableInfo->horizontalHeader()->setStretchLastSection( true );
228  tableInfo->setRowCount( i );
229  tableInfo->setFixedHeight( tableInfo->rowHeight( 0 ) * i + 5 );
230  dlg->layout()->addWidget( tableInfo );
231  dlg->resize( 600, 250 );
232 
233  dlg->layout()->addSpacing( 5 );
234 
235  // gradient file
236  QString gradientFile = mRamp.info().value( QStringLiteral( "cpt-city-gradient" ) );
237  if ( ! gradientFile.isNull() )
238  {
239  QString fileName = gradientFile;
240  fileName.replace( QLatin1String( "<cpt-city>" ), QgsCptCityArchive::defaultBaseDir() );
241  if ( ! QFile::exists( fileName ) )
242  {
243  fileName = gradientFile;
244  fileName.replace( QLatin1String( "<cpt-city>" ), QLatin1String( "http://soliton.vm.bytemark.co.uk/pub/cpt-city" ) );
245  }
246  label = new QLabel( tr( "Gradient file : %1" ).arg( fileName ), dlg );
247  label->setTextInteractionFlags( Qt::TextBrowserInteraction );
248  dlg->layout()->addSpacing( 5 );
249  dlg->layout()->addWidget( label );
250  }
251 
252  // license file
253  QString licenseFile = mRamp.info().value( QStringLiteral( "cpt-city-license" ) );
254  if ( !licenseFile.isNull() )
255  {
256  QString fileName = licenseFile;
257  fileName.replace( QLatin1String( "<cpt-city>" ), QgsCptCityArchive::defaultBaseDir() );
258  if ( ! QFile::exists( fileName ) )
259  {
260  fileName = licenseFile;
261  fileName.replace( QLatin1String( "<cpt-city>" ), QLatin1String( "http://soliton.vm.bytemark.co.uk/pub/cpt-city" ) );
262  }
263  label = new QLabel( tr( "License file : %1" ).arg( fileName ), dlg );
264  label->setTextInteractionFlags( Qt::TextBrowserInteraction );
265  dlg->layout()->addSpacing( 5 );
266  dlg->layout()->addWidget( label );
267  if ( QFile::exists( fileName ) )
268  {
269  QTextEdit *textEdit = new QTextEdit( dlg );
270  textEdit->setReadOnly( true );
271  QFile file( fileName );
272  if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
273  {
274  textEdit->setText( file.readAll() );
275  file.close();
276  dlg->layout()->addSpacing( 5 );
277  dlg->layout()->addWidget( textEdit );
278  dlg->resize( 600, 500 );
279  }
280  }
281  }
282 
283  dlg->show(); //non modal
284 }
285 
286 void QgsGradientColorRampDialog::updateColorButtons()
287 {
288  btnColor1->blockSignals( true );
289  btnColor1->setColor( mRamp.color1() );
290  btnColor1->blockSignals( false );
291  btnColor2->blockSignals( true );
292  btnColor2->setColor( mRamp.color2() );
293  btnColor2->blockSignals( false );
294 }
295 
296 void QgsGradientColorRampDialog::updateStopEditor()
297 {
298  mStopEditor->blockSignals( true );
299  mStopEditor->setGradientRamp( mRamp );
300  mStopEditor->blockSignals( false );
301 }
302 
303 void QgsGradientColorRampDialog::selectedStopChanged( const QgsGradientStop &stop )
304 {
305  mColorWidget->blockSignals( true );
306  mColorWidget->setColor( stop.color );
307  mColorWidget->blockSignals( false );
308  mPositionSpinBox->blockSignals( true );
309  mPositionSpinBox->setValue( stop.offset * 100 );
310  mPositionSpinBox->blockSignals( false );
311 
312  if ( ( stop.offset == 0 && stop.color == mRamp.color1() ) || ( stop.offset == 1.0 && stop.color == mRamp.color2() ) )
313  {
314  //first/last stop can't be repositioned
315  mPositionSpinBox->setDisabled( true );
316  mDeleteStopButton->setDisabled( true );
317  }
318  else
319  {
320  mPositionSpinBox->setDisabled( false );
321  mDeleteStopButton->setDisabled( false );
322  }
323 
324  updatePlot();
325 }
326 
327 void QgsGradientColorRampDialog::colorWidgetChanged( const QColor &color )
328 {
329  mStopEditor->setSelectedStopColor( color );
330 }
331 
332 void QgsGradientColorRampDialog::mPositionSpinBox_valueChanged( double val )
333 {
334  mStopEditor->setSelectedStopOffset( val / 100.0 );
335 }
336 
337 void QgsGradientColorRampDialog::mPlotHueCheckbox_toggled( bool checked )
338 {
339  mHueCurve->setVisible( checked );
340  updatePlot();
341 }
342 
343 void QgsGradientColorRampDialog::mPlotLightnessCheckbox_toggled( bool checked )
344 {
345  mLightnessCurve->setVisible( checked );
346  updatePlot();
347 }
348 
349 void QgsGradientColorRampDialog::mPlotSaturationCheckbox_toggled( bool checked )
350 {
351  mSaturationCurve->setVisible( checked );
352  updatePlot();
353 }
354 
355 void QgsGradientColorRampDialog::mPlotAlphaCheckbox_toggled( bool checked )
356 {
357  mAlphaCurve->setVisible( checked );
358  updatePlot();
359 }
360 
361 void QgsGradientColorRampDialog::plotMousePress( QPointF point )
362 {
363  //find closest part
364 
365  double minDist = 1;
366  mCurrentPlotColorComponent = -1;
367  mCurrentPlotMarkerIndex = -1;
368  // first color
369 
370  for ( int i = 0; i < mRamp.count(); ++i )
371  {
372  QColor currentCol;
373  double currentOff = 0.0;
374  if ( i == 0 )
375  {
376  currentOff = 0.0;
377  currentCol = mRamp.color1();
378  }
379  else if ( i == mRamp.count() - 1 )
380  {
381  currentOff = 1.0;
382  currentCol = mRamp.color2();
383  }
384  else
385  {
386  currentOff = mRamp.stops().at( i - 1 ).offset;
387  currentCol = mRamp.stops().at( i - 1 ).color;
388  }
389 
390  double currentDist;
391  if ( mPlotHueCheckbox->isChecked() )
392  {
393  currentDist = std::pow( point.x() - currentOff, 2.0 ) + std::pow( point.y() - currentCol.hslHueF(), 2.0 );
394  if ( currentDist < minDist )
395  {
396  minDist = currentDist;
397  mCurrentPlotColorComponent = 0;
398  mCurrentPlotMarkerIndex = i;
399  }
400  }
401  if ( mPlotLightnessCheckbox->isChecked() )
402  {
403  currentDist = std::pow( point.x() - currentOff, 2.0 ) + std::pow( point.y() - currentCol.lightnessF(), 2.0 );
404  if ( currentDist < minDist )
405  {
406  minDist = currentDist;
407  mCurrentPlotColorComponent = 1;
408  mCurrentPlotMarkerIndex = i;
409  }
410  }
411  if ( mPlotSaturationCheckbox->isChecked() )
412  {
413  currentDist = std::pow( point.x() - currentOff, 2.0 ) + std::pow( point.y() - currentCol.hslSaturationF(), 2.0 );
414  if ( currentDist < minDist )
415  {
416  minDist = currentDist;
417  mCurrentPlotColorComponent = 2;
418  mCurrentPlotMarkerIndex = i;
419  }
420  }
421  if ( mPlotAlphaCheckbox->isChecked() )
422  {
423  currentDist = std::pow( point.x() - currentOff, 2.0 ) + std::pow( point.y() - currentCol.alphaF(), 2.0 );
424  if ( currentDist < minDist )
425  {
426  minDist = currentDist;
427  mCurrentPlotColorComponent = 3;
428  mCurrentPlotMarkerIndex = i;
429  }
430  }
431  }
432 
433  // watch out - selected stop index may differ if stops in editor are out of order!!!
434  if ( mCurrentPlotMarkerIndex >= 0 )
435  mStopEditor->selectStop( mCurrentPlotMarkerIndex );
436 }
437 
438 void QgsGradientColorRampDialog::plotMouseRelease( QPointF )
439 {
440  mCurrentPlotColorComponent = -1;
441 }
442 
443 void QgsGradientColorRampDialog::plotMouseMove( QPointF point )
444 {
445  QColor newColor = mStopEditor->selectedStop().color;
446 
447  if ( mCurrentPlotColorComponent == 0 )
448  newColor = QColor::fromHslF( std::clamp( point.y(), qreal( 0.0 ), qreal( 1.0 ) ), newColor.hslSaturationF(), newColor.lightnessF(), newColor.alphaF() );
449  else if ( mCurrentPlotColorComponent == 1 )
450  newColor = QColor::fromHslF( newColor.hslHueF(), newColor.hslSaturationF(), std::clamp( point.y(), qreal( 0.0 ), qreal( 1.0 ) ), newColor.alphaF() );
451  else if ( mCurrentPlotColorComponent == 2 )
452  newColor = QColor::fromHslF( newColor.hslHueF(), std::clamp( point.y(), qreal( 0.0 ), qreal( 1.0 ) ), newColor.lightnessF(), newColor.alphaF() );
453  else if ( mCurrentPlotColorComponent == 3 )
454  newColor = QColor::fromHslF( newColor.hslHueF(), newColor.hslSaturationF(), newColor.lightnessF(), std::clamp( point.y(), qreal( 0.0 ), qreal( 1.0 ) ) );
455 
456  mStopEditor->setSelectedStopDetails( newColor, std::clamp( point.x(), qreal( 0.0 ), qreal( 1.0 ) ) );
457 }
458 
459 bool byX( QPointF p1, QPointF p2 )
460 {
461  return p1.x() < p2.x();
462 }
463 
464 void QgsGradientColorRampDialog::addPlotMarker( double x, double y, const QColor &color, bool isSelected )
465 {
466  QColor borderColor = color.darker( 200 );
467  borderColor.setAlpha( 255 );
468 
469  QColor brushColor = color;
470  brushColor.setAlpha( 255 );
471 
472  QwtPlotMarker *marker = new QwtPlotMarker();
473  marker->setSymbol( new QwtSymbol( QwtSymbol::Ellipse, QBrush( brushColor ), QPen( borderColor, isSelected ? 2 : 1 ), QSize( 8, 8 ) ) );
474  marker->setValue( x, y );
475  marker->attach( mPlot );
476  marker->setRenderHint( QwtPlotItem::RenderAntialiased, true );
477  mMarkers << marker;
478 }
479 
480 void QgsGradientColorRampDialog::addMarkersForColor( double x, const QColor &color, bool isSelected )
481 {
482  if ( mPlotHueCheckbox->isChecked() )
483  addPlotMarker( x, color.hslHueF(), color, isSelected && mCurrentPlotColorComponent == 0 );
484  if ( mPlotLightnessCheckbox->isChecked() )
485  addPlotMarker( x, color.lightnessF(), color, isSelected && mCurrentPlotColorComponent == 1 );
486  if ( mPlotSaturationCheckbox->isChecked() )
487  addPlotMarker( x, color.hslSaturationF(), color, isSelected && mCurrentPlotColorComponent == 2 );
488  if ( mPlotAlphaCheckbox->isChecked() )
489  addPlotMarker( x, color.alphaF(), color, isSelected && mCurrentPlotColorComponent == 3 );
490 }
491 
492 void QgsGradientColorRampDialog::updatePlot()
493 {
494  // remove existing markers
495  const auto constMMarkers = mMarkers;
496  for ( QwtPlotMarker *marker : constMMarkers )
497  {
498  marker->detach();
499  delete marker;
500  }
501  mMarkers.clear();
502 
503  QPolygonF lightnessPoints;
504  QPolygonF huePoints;
505  QPolygonF saturationPoints;
506  QPolygonF alphaPoints;
507  lightnessPoints << QPointF( 0.0, mRamp.color1().lightnessF() );
508  huePoints << QPointF( 0.0, mRamp.color1().hslHueF() );
509  saturationPoints << QPointF( 0.0, mRamp.color1().hslSaturationF() );
510  alphaPoints << QPointF( 0.0, mRamp.color1().alphaF() );
511  addMarkersForColor( 0, mRamp.color1(), mCurrentPlotMarkerIndex == 0 );
512 
513  int i = 1;
514  const auto constStops = mRamp.stops();
515  for ( const QgsGradientStop &stop : constStops )
516  {
517  lightnessPoints << QPointF( stop.offset, stop.color.lightnessF() );
518  huePoints << QPointF( stop.offset, stop.color.hslHueF() );
519  saturationPoints << QPointF( stop.offset, stop.color.hslSaturationF() );
520  alphaPoints << QPointF( stop.offset, stop.color.alphaF() );
521 
522  addMarkersForColor( stop.offset, stop.color, mCurrentPlotMarkerIndex == i );
523  i++;
524  }
525 
526  //add extra intermediate points
527  for ( double p = 0.001; p < 1.0; p += 0.001 )
528  {
529  QColor c = mRamp.color( p );
530  lightnessPoints << QPointF( p, c.lightnessF() );
531  huePoints << QPointF( p, c.hslHueF() );
532  saturationPoints << QPointF( p, c.hslSaturationF() );
533  alphaPoints << QPointF( p, c.alphaF() );
534  }
535 
536  lightnessPoints << QPointF( 1.0, mRamp.color2().lightnessF() );
537  huePoints << QPointF( 1.0, mRamp.color2().hslHueF() );
538  saturationPoints << QPointF( 1.0, mRamp.color2().hslSaturationF() );
539  alphaPoints << QPointF( 1.0, mRamp.color2().alphaF() );
540  addMarkersForColor( 1.0, mRamp.color2(), mCurrentPlotMarkerIndex == i );
541 
542  std::sort( lightnessPoints.begin(), lightnessPoints.end(), byX );
543  std::sort( huePoints.begin(), huePoints.end(), byX );
544  std::sort( saturationPoints.begin(), saturationPoints.end(), byX );
545  std::sort( alphaPoints.begin(), alphaPoints.end(), byX );
546 
547  mLightnessCurve->setSamples( lightnessPoints );
548  mHueCurve->setSamples( huePoints );
549  mSaturationCurve->setSamples( saturationPoints );
550  mAlphaCurve->setSamples( alphaPoints );
551  mPlot->replot();
552 }
553 
554 void QgsGradientColorRampDialog::updateRampFromStopEditor()
555 {
556  mRamp = mStopEditor->gradientRamp();
557  mPositionSpinBox->blockSignals( true );
558  mPositionSpinBox->setValue( mStopEditor->selectedStop().offset * 100 );
559  mPositionSpinBox->blockSignals( false );
560  mColorWidget->blockSignals( true );
561  mColorWidget->setColor( mStopEditor->selectedStop().color );
562  mColorWidget->blockSignals( false );
563 
564  updateColorButtons();
565  updatePlot();
566 
567  emit changed();
568 }
569 
570 void QgsGradientColorRampDialog::setColor1( const QColor &color )
571 {
572  mStopEditor->setColor1( color );
573  updateColorButtons();
574 }
575 
576 void QgsGradientColorRampDialog::setColor2( const QColor &color )
577 {
578  mStopEditor->setColor2( color );
579  updateColorButtons();
580 }
581 
582 void QgsGradientColorRampDialog::showHelp()
583 {
584  QgsHelp::openHelp( QStringLiteral( "style_library/style_manager.html#setting-a-color-ramp" ) );
585 }
586 
587 
589 
590 QgsGradientPlotEventFilter::QgsGradientPlotEventFilter( QwtPlot *plot )
591  : QObject( plot )
592  , mPlot( plot )
593 {
594  mPlot->canvas()->installEventFilter( this );
595 }
596 
597 bool QgsGradientPlotEventFilter::eventFilter( QObject *object, QEvent *event )
598 {
599  if ( !mPlot->isEnabled() )
600  return QObject::eventFilter( object, event );
601 
602  switch ( event->type() )
603  {
604  case QEvent::MouseButtonPress:
605  {
606  const QMouseEvent *mouseEvent = static_cast<QMouseEvent * >( event );
607  if ( mouseEvent->button() == Qt::LeftButton )
608  {
609  emit mousePress( mapPoint( mouseEvent->pos() ) );
610  }
611  break;
612  }
613  case QEvent::MouseMove:
614  {
615  const QMouseEvent *mouseEvent = static_cast<QMouseEvent * >( event );
616  if ( mouseEvent->buttons() & Qt::LeftButton )
617  {
618  // only emit when button pressed
619  emit mouseMove( mapPoint( mouseEvent->pos() ) );
620  }
621  break;
622  }
623  case QEvent::MouseButtonRelease:
624  {
625  const QMouseEvent *mouseEvent = static_cast<QMouseEvent * >( event );
626  if ( mouseEvent->button() == Qt::LeftButton )
627  {
628  emit mouseRelease( mapPoint( mouseEvent->pos() ) );
629  }
630  break;
631  }
632  default:
633  break;
634  }
635 
636  return QObject::eventFilter( object, event );
637 }
638 
639 QPointF QgsGradientPlotEventFilter::mapPoint( QPointF point ) const
640 {
641  if ( !mPlot )
642  return QPointF();
643 
644  return QPointF( mPlot->canvasMap( QwtPlot::xBottom ).invTransform( point.x() ),
645  mPlot->canvasMap( QwtPlot::yLeft ).invTransform( point.y() ) );
646 }
647 
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
void currentColorChanged(const QColor &color)
Emitted when the dialog's color changes.
static QString defaultBaseDir()
A generic dialog with layout and button box.
Definition: qgsdialog.h:34
QVBoxLayout * layout()
Returns the central layout. Widgets added to it must have this dialog as parent.
Definition: qgsdialog.h:46
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
void setColor2(const QColor &color)
Sets the end color for the gradient ramp.
void setRamp(const QgsGradientColorRamp &ramp)
Sets the color ramp to show in the dialog.
QgsGradientColorRampDialog(const QgsGradientColorRamp &ramp, QWidget *parent=nullptr)
Constructor for QgsGradientColorRampDialog.
void setColor1(const QColor &color)
Sets the start color for the gradient ramp.
void changed()
Emitted when the dialog settings change.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorramp.h:151
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
Definition: qgscolorramp.h:221
int count() const override
Returns number of defined colors, or -1 if undefined.
Definition: qgscolorramp.h:170
QgsStringMap info() const
Returns any additional info attached to the gradient ramp (e.g., authorship notes)
Definition: qgscolorramp.h:260
void convertToDiscrete(bool discrete)
Converts a gradient with existing color stops to or from discrete interpolation.
QColor color(double value) const override
Returns the color corresponding to a specified value.
QColor color1() const
Returns the gradient start color.
Definition: qgscolorramp.h:191
QgsGradientStopsList stops() const
Returns the list of intermediate gradient stops for the ramp.
Definition: qgscolorramp.h:254
QColor color2() const
Returns the gradient end color.
Definition: qgscolorramp.h:198
void changed()
Emitted when the gradient ramp is changed by a user.
void deleteSelectedStop()
Deletes the current selected stop.
void selectedStopChanged(const QgsGradientStop &stop)
Emitted when the current selected stop changes.
Represents a color stop within a QgsGradientColorRamp color ramp.
Definition: qgscolorramp.h:113
double offset
Relative positional offset, between 0 and 1.
Definition: qgscolorramp.h:127
QColor color
Gradient color at stop.
Definition: qgscolorramp.h:129
static QgsGui * instance()
Returns a pointer to the singleton instance.
Definition: qgsgui.cpp:65
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:156
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
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
QMap< QString, QString > QgsStringMap
Definition: qgis.h:1041
bool byX(QPointF p1, QPointF p2)