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