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