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