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