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