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