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