Skip to content

Commit cc9b5a4

Browse files
committedFeb 22, 2017
[FEATURE] Interactive curve editing for property overrides
This adds a new interactive "curve" to the assistant widgets. It allows you to fine tune exactly how input values get mapped to output sizes/colors/etc. Think GIMP or Photoshop curves, but for your data...
1 parent 45861d3 commit cc9b5a4

8 files changed

+566
-28
lines changed
 

‎python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
%Include qgsconfigureshortcutsdialog.sip
5252
%Include qgscredentialdialog.sip
5353
%Include qgscustomdrophandler.sip
54+
%Include qgscurveeditorwidget.sip
5455
%Include qgsdetaileditemdata.sip
5556
%Include qgsdetaileditemdelegate.sip
5657
%Include qgsdetaileditemwidget.sip

‎python/gui/qgscurveeditorwidget.sip

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class QgsCurveEditorWidget : QWidget
2+
{
3+
%TypeHeaderCode
4+
#include <qgscurveeditorwidget.h>
5+
%End
6+
7+
public:
8+
9+
QgsCurveEditorWidget( QWidget* parent /TransferThis/ = 0, const QgsCurveTransform& curve = QgsCurveTransform() );
10+
11+
QgsCurveTransform curve() const;
12+
13+
void setCurve( const QgsCurveTransform& curve );
14+
15+
signals:
16+
17+
void changed();
18+
19+
protected:
20+
21+
virtual void keyPressEvent( QKeyEvent *event );
22+
23+
};

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ SET(QGIS_GUI_SRCS
193193
qgscredentialdialog.cpp
194194
qgscursors.cpp
195195
qgscustomdrophandler.cpp
196+
qgscurveeditorwidget.cpp
196197
qgsdatumtransformdialog.cpp
197198
qgsdetaileditemdata.cpp
198199
qgsdetaileditemdelegate.cpp
@@ -345,6 +346,7 @@ SET(QGIS_GUI_MOC_HDRS
345346
qgscompoundcolorwidget.h
346347
qgsconfigureshortcutsdialog.h
347348
qgscredentialdialog.h
349+
qgscurveeditorwidget.h
348350
qgsdatumtransformdialog.h
349351
qgsdetaileditemdelegate.h
350352
qgsdetaileditemwidget.h

‎src/gui/qgscurveeditorwidget.cpp

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
/***************************************************************************
2+
qgscurveeditorwidget.cpp
3+
------------------------
4+
begin : February 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson 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+
16+
17+
#include "qgscurveeditorwidget.h"
18+
19+
#include <qmath.h>
20+
#include <QPainter>
21+
#include <QVBoxLayout>
22+
#include <QMouseEvent>
23+
24+
// QWT Charting widget
25+
#include <qwt_global.h>
26+
#include <qwt_plot_canvas.h>
27+
#include <qwt_plot.h>
28+
#include <qwt_plot_curve.h>
29+
#include <qwt_plot_grid.h>
30+
#include <qwt_plot_marker.h>
31+
#include <qwt_plot_picker.h>
32+
#include <qwt_picker_machine.h>
33+
#include <qwt_plot_layout.h>
34+
#include <qwt_symbol.h>
35+
#include <qwt_legend.h>
36+
37+
QgsCurveEditorWidget::QgsCurveEditorWidget( QWidget* parent, const QgsCurveTransform& transform )
38+
: QWidget( parent )
39+
, mCurve( transform )
40+
, mCurrentPlotMarkerIndex( -1 )
41+
{
42+
mPlot = new QwtPlot();
43+
mPlot->setMinimumSize( QSize( 0, 100 ) );
44+
mPlot->setAxisScale( QwtPlot::yLeft, 0, 1 );
45+
mPlot->setAxisScale( QwtPlot::yRight, 0, 1 );
46+
mPlot->setAxisScale( QwtPlot::xBottom, 0, 1 );
47+
mPlot->setAxisScale( QwtPlot::xTop, 0, 1 );
48+
49+
QVBoxLayout* vlayout = new QVBoxLayout();
50+
vlayout->addWidget( mPlot );
51+
setLayout( vlayout );
52+
53+
// hide the ugly canvas frame
54+
mPlot->setFrameStyle( QFrame::NoFrame );
55+
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
56+
QFrame* plotCanvasFrame = dynamic_cast<QFrame*>( mPlot->canvas() );
57+
if ( plotCanvasFrame )
58+
plotCanvasFrame->setFrameStyle( QFrame::NoFrame );
59+
#else
60+
mPlot->canvas()->setFrameStyle( QFrame::NoFrame );
61+
#endif
62+
63+
mPlot->enableAxis( QwtPlot::yLeft, false );
64+
mPlot->enableAxis( QwtPlot::xBottom, false );
65+
66+
// add a grid
67+
QwtPlotGrid * grid = new QwtPlotGrid();
68+
QwtScaleDiv gridDiv( 0.0, 1.0, QList<double>(), QList<double>(), QList<double>() << 0.2 << 0.4 << 0.6 << 0.8 );
69+
grid->setXDiv( gridDiv );
70+
grid->setYDiv( gridDiv );
71+
grid->setPen( QPen( QColor( 0, 0, 0, 50 ) ) );
72+
grid->attach( mPlot );
73+
74+
mPlotCurve = new QwtPlotCurve();
75+
mPlotCurve->setTitle( QStringLiteral( "Curve" ) );
76+
mPlotCurve->setPen( QPen( QColor( 30, 30, 30 ), 0.0 ) ),
77+
mPlotCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
78+
mPlotCurve->attach( mPlot );
79+
80+
mPlotFilter = new QgsCurveEditorPlotEventFilter( mPlot );
81+
connect( mPlotFilter, &QgsCurveEditorPlotEventFilter::mousePress, this, &QgsCurveEditorWidget::plotMousePress );
82+
connect( mPlotFilter, &QgsCurveEditorPlotEventFilter::mouseRelease, this, &QgsCurveEditorWidget::plotMouseRelease );
83+
connect( mPlotFilter, &QgsCurveEditorPlotEventFilter::mouseMove, this, &QgsCurveEditorWidget::plotMouseMove );
84+
85+
mPlotCurve->setVisible( true );
86+
updatePlot();
87+
}
88+
89+
void QgsCurveEditorWidget::setCurve( const QgsCurveTransform& curve )
90+
{
91+
mCurve = curve;
92+
updatePlot();
93+
emit changed();
94+
}
95+
96+
void QgsCurveEditorWidget::keyPressEvent( QKeyEvent* event )
97+
{
98+
if ( event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace )
99+
{
100+
QList< QgsPoint > cp = mCurve.controlPoints();
101+
if ( mCurrentPlotMarkerIndex > 0 && mCurrentPlotMarkerIndex < cp.count() - 1 )
102+
{
103+
cp.removeAt( mCurrentPlotMarkerIndex );
104+
mCurve.setControlPoints( cp );
105+
updatePlot();
106+
emit changed();
107+
}
108+
}
109+
}
110+
111+
void QgsCurveEditorWidget::plotMousePress( QPointF point )
112+
{
113+
mCurrentPlotMarkerIndex = findNearestControlPoint( point );
114+
if ( mCurrentPlotMarkerIndex < 0 )
115+
{
116+
// add a new point
117+
mCurve.addControlPoint( point.x(), point.y() );
118+
mCurrentPlotMarkerIndex = findNearestControlPoint( point );
119+
emit changed();
120+
}
121+
updatePlot();
122+
}
123+
124+
125+
int QgsCurveEditorWidget::findNearestControlPoint( QPointF point ) const
126+
{
127+
double minDist = 3.0 / mPlot->width();
128+
int currentPlotMarkerIndex = -1;
129+
130+
QList< QgsPoint > controlPoints = mCurve.controlPoints();
131+
132+
for ( int i = 0; i < controlPoints.count(); ++i )
133+
{
134+
QgsPoint currentPoint = controlPoints.at( i );
135+
double currentDist;
136+
currentDist = qPow( point.x() - currentPoint.x(), 2.0 ) + qPow( point.y() - currentPoint.y(), 2.0 );
137+
if ( currentDist < minDist )
138+
{
139+
minDist = currentDist;
140+
currentPlotMarkerIndex = i;
141+
}
142+
}
143+
return currentPlotMarkerIndex;
144+
}
145+
146+
147+
void QgsCurveEditorWidget::plotMouseRelease( QPointF )
148+
{
149+
}
150+
151+
void QgsCurveEditorWidget::plotMouseMove( QPointF point )
152+
{
153+
if ( mCurrentPlotMarkerIndex < 0 )
154+
return;
155+
156+
QList< QgsPoint > cp = mCurve.controlPoints();
157+
bool removePoint = false;
158+
if ( mCurrentPlotMarkerIndex == 0 )
159+
{
160+
point.setX( qMin( point.x(), cp.at( 1 ).x() - 0.01 ) );
161+
}
162+
else
163+
{
164+
removePoint = point.x() <= cp.at( mCurrentPlotMarkerIndex - 1 ).x();
165+
}
166+
if ( mCurrentPlotMarkerIndex == cp.count() - 1 )
167+
{
168+
point.setX( qMax( point.x(), cp.at( mCurrentPlotMarkerIndex - 1 ).x() + 0.01 ) );
169+
removePoint = false;
170+
}
171+
else
172+
{
173+
removePoint = removePoint || point.x() >= cp.at( mCurrentPlotMarkerIndex + 1 ).x();
174+
}
175+
176+
if ( removePoint )
177+
{
178+
cp.removeAt( mCurrentPlotMarkerIndex );
179+
mCurrentPlotMarkerIndex = -1;
180+
}
181+
else
182+
{
183+
cp[ mCurrentPlotMarkerIndex ] = QgsPoint( point.x(), point.y() );
184+
}
185+
mCurve.setControlPoints( cp );
186+
updatePlot();
187+
emit changed();
188+
}
189+
190+
void QgsCurveEditorWidget::addPlotMarker( double x, double y, bool isSelected )
191+
{
192+
QColor borderColor( 0, 0, 0 );
193+
194+
QColor brushColor = isSelected ? borderColor : QColor( 255, 255, 255, 0 );
195+
196+
QwtPlotMarker *marker = new QwtPlotMarker();
197+
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
198+
marker->setSymbol( new QwtSymbol( QwtSymbol::Ellipse, QBrush( brushColor ), QPen( borderColor, isSelected ? 2 : 1 ), QSize( 6, 6 ) ) );
199+
#else
200+
marker->setSymbol( QwtSymbol( QwtSymbol::Ellipse, QBrush( brushColor ), QPen( borderColor, isSelected ? 2 : 1 ), QSize( 6, 6 ) ) );
201+
#endif
202+
marker->setValue( x, y );
203+
marker->attach( mPlot );
204+
marker->setRenderHint( QwtPlotItem::RenderAntialiased, true );
205+
mMarkers << marker;
206+
}
207+
208+
void QgsCurveEditorWidget::updatePlot()
209+
{
210+
// remove existing markers
211+
Q_FOREACH ( QwtPlotMarker* marker, mMarkers )
212+
{
213+
marker->detach();
214+
delete marker;
215+
}
216+
mMarkers.clear();
217+
218+
QPolygonF curvePoints;
219+
QVector< double > x;
220+
221+
int i = 0;
222+
Q_FOREACH ( const QgsPoint& point, mCurve.controlPoints() )
223+
{
224+
x << point.x();
225+
addPlotMarker( point.x(), point.y(), mCurrentPlotMarkerIndex == i );
226+
i++;
227+
}
228+
229+
//add extra intermediate points
230+
231+
for ( double p = 0; p <= 1.0; p += 0.01 )
232+
{
233+
x << p;
234+
}
235+
std::sort( x.begin(), x.end() );
236+
QVector< double > y = mCurve.y( x );
237+
238+
for ( int j = 0; j < x.count(); ++j )
239+
{
240+
curvePoints << QPointF( x.at( j ), y.at( j ) );
241+
}
242+
243+
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
244+
mPlotCurve->setSamples( curvePoints );
245+
#else
246+
mPlotCurve->setData( curvePoints );
247+
#endif
248+
mPlot->replot();
249+
}
250+
251+
252+
/// @cond PRIVATE
253+
254+
QgsCurveEditorPlotEventFilter::QgsCurveEditorPlotEventFilter( QwtPlot *plot )
255+
: QObject( plot )
256+
, mPlot( plot )
257+
{
258+
mPlot->canvas()->installEventFilter( this );
259+
}
260+
261+
bool QgsCurveEditorPlotEventFilter::eventFilter( QObject *object, QEvent *event )
262+
{
263+
if ( !mPlot->isEnabled() )
264+
return QObject::eventFilter( object, event );
265+
266+
switch ( event->type() )
267+
{
268+
case QEvent::MouseButtonPress:
269+
{
270+
const QMouseEvent* mouseEvent = static_cast<QMouseEvent* >( event );
271+
if ( mouseEvent->button() == Qt::LeftButton )
272+
{
273+
emit mousePress( mapPoint( mouseEvent->pos() ) );
274+
}
275+
break;
276+
}
277+
case QEvent::MouseMove:
278+
{
279+
const QMouseEvent* mouseEvent = static_cast<QMouseEvent* >( event );
280+
if ( mouseEvent->buttons() & Qt::LeftButton )
281+
{
282+
// only emit when button pressed
283+
emit mouseMove( mapPoint( mouseEvent->pos() ) );
284+
}
285+
break;
286+
}
287+
case QEvent::MouseButtonRelease:
288+
{
289+
const QMouseEvent* mouseEvent = static_cast<QMouseEvent* >( event );
290+
if ( mouseEvent->button() == Qt::LeftButton )
291+
{
292+
emit mouseRelease( mapPoint( mouseEvent->pos() ) );
293+
}
294+
break;
295+
}
296+
default:
297+
break;
298+
}
299+
300+
return QObject::eventFilter( object, event );
301+
}
302+
303+
QPointF QgsCurveEditorPlotEventFilter::mapPoint( QPointF point ) const
304+
{
305+
if ( !mPlot )
306+
return QPointF();
307+
308+
return QPointF( mPlot->canvasMap( QwtPlot::xBottom ).invTransform( point.x() ),
309+
mPlot->canvasMap( QwtPlot::yLeft ).invTransform( point.y() ) );
310+
}
311+
312+
///@endcond

‎src/gui/qgscurveeditorwidget.h

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/***************************************************************************
2+
qgscurveeditorwidget.h
3+
----------------------
4+
begin : February 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson 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+
16+
#ifndef QGSCURVEEDITORWIDGET_H
17+
#define QGSCURVEEDITORWIDGET_H
18+
19+
#include <QWidget>
20+
#include "qgis_gui.h"
21+
#include "qgspropertytransformer.h"
22+
23+
class QwtPlot;
24+
class QwtPlotCurve;
25+
class QwtPlotMarker;
26+
class QgsCurveEditorPlotEventFilter;
27+
28+
/** \ingroup gui
29+
* \class QgsCurveEditorWidget
30+
* A widget for manipulating QgsCurveTransform curves.
31+
* \note added in QGIS 3.0
32+
*/
33+
class GUI_EXPORT QgsCurveEditorWidget : public QWidget
34+
{
35+
Q_OBJECT
36+
37+
public:
38+
39+
/**
40+
* Constructor for QgsCurveEditorWidget.
41+
*/
42+
QgsCurveEditorWidget( QWidget* parent = nullptr, const QgsCurveTransform& curve = QgsCurveTransform() );
43+
44+
/**
45+
* Returns a curve representing the current curve from the widget.
46+
* @see setCurve()
47+
*/
48+
QgsCurveTransform curve() const { return mCurve; }
49+
50+
/**
51+
* Sets the \a curve to show in the widget.
52+
* @see curve()
53+
*/
54+
void setCurve( const QgsCurveTransform& curve );
55+
56+
signals:
57+
58+
//! Emitted when the widget curve changes
59+
void changed();
60+
61+
protected:
62+
63+
virtual void keyPressEvent( QKeyEvent *event ) override ;
64+
65+
private slots:
66+
67+
void plotMousePress( QPointF point );
68+
void plotMouseRelease( QPointF point );
69+
void plotMouseMove( QPointF point );
70+
71+
private:
72+
73+
QgsCurveTransform mCurve;
74+
75+
QwtPlot* mPlot = nullptr;
76+
77+
QwtPlotCurve* mPlotCurve = nullptr;
78+
79+
QList< QwtPlotMarker* > mMarkers;
80+
QgsCurveEditorPlotEventFilter* mPlotFilter = nullptr;
81+
int mCurrentPlotMarkerIndex;
82+
83+
void updatePlot();
84+
void addPlotMarker( double x, double y, bool isSelected = false );
85+
86+
int findNearestControlPoint( QPointF point ) const;
87+
};
88+
89+
90+
//
91+
// NOTE:
92+
// For private only, not part of stable api or exposed to Python bindings
93+
//
94+
/// @cond PRIVATE
95+
class GUI_EXPORT QgsCurveEditorPlotEventFilter: public QObject
96+
{
97+
Q_OBJECT
98+
99+
public:
100+
101+
QgsCurveEditorPlotEventFilter( QwtPlot *plot );
102+
103+
virtual bool eventFilter( QObject* object, QEvent* event ) override;
104+
105+
signals:
106+
107+
void mousePress( QPointF );
108+
void mouseRelease( QPointF );
109+
void mouseMove( QPointF );
110+
111+
private:
112+
113+
QwtPlot* mPlot;
114+
QPointF mapPoint( QPointF point ) const;
115+
};
116+
///@endcond
117+
118+
#endif // QGSCURVEEDITORWIDGET_H

‎src/gui/qgspropertyassistantwidget.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget* parent ,
5151
{
5252
minValueSpinBox->setValue( initialState.transformer()->minValue() );
5353
maxValueSpinBox->setValue( initialState.transformer()->maxValue() );
54+
55+
if ( initialState.transformer()->curveTransform() )
56+
{
57+
mTransformCurveCheckBox->setChecked( true );
58+
mCurveEditor->setCurve( *initialState.transformer()->curveTransform() );
59+
}
5460
}
5561

5662
connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
@@ -108,10 +114,12 @@ QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget* parent ,
108114
mOutputWidget->layout()->addWidget( mTransformerWidget );
109115
connect( mTransformerWidget, &QgsPropertyAbstractTransformerWidget::widgetChanged, this, &QgsPropertyAssistantWidget::widgetChanged );
110116
}
117+
mTransformCurveCheckBox->setVisible( mTransformerWidget );
111118

112119
connect( minValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
113120
connect( maxValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
114121
connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString& ) > ( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
122+
connect( mCurveEditor, &QgsCurveEditorWidget::changed, this, &QgsPropertyAssistantWidget::widgetChanged );
115123
connect( this, &QgsPropertyAssistantWidget::widgetChanged, this, &QgsPropertyAssistantWidget::updatePreview );
116124
updatePreview();
117125
}
@@ -131,7 +139,18 @@ void QgsPropertyAssistantWidget::updateProperty( QgsProperty& property )
131139
property.setField( mExpressionWidget->currentField() );
132140

133141
if ( mTransformerWidget )
134-
property.setTransformer( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
142+
{
143+
std::unique_ptr< QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
144+
if ( mTransformCurveCheckBox->isChecked() )
145+
{
146+
t->setCurveTransform( new QgsCurveTransform( mCurveEditor->curve() ) );
147+
}
148+
else
149+
{
150+
t->setCurveTransform( nullptr );
151+
}
152+
property.setTransformer( t.release() );
153+
}
135154
}
136155

137156
void QgsPropertyAssistantWidget::setDockMode( bool dockMode )
@@ -180,8 +199,9 @@ void QgsPropertyAssistantWidget::updatePreview()
180199
QList<double> breaks = QgsSymbolLayerUtils::prettyBreaks( minValueSpinBox->value(),
181200
maxValueSpinBox->value(), 8 );
182201

202+
QgsCurveTransform curve = mCurveEditor->curve();
183203
QList< QgsSymbolLegendNode* > nodes = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(),
184-
maxValueSpinBox->value() );
204+
maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve : nullptr );
185205

186206
int widthMax = 0;
187207
int i = 0;
@@ -353,7 +373,7 @@ QgsSizeScaleTransformer* QgsPropertySizeAssistantWidget::createTransformer( doub
353373
return transformer;
354374
}
355375

356-
QList< QgsSymbolLegendNode* > QgsPropertySizeAssistantWidget::generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue ) const
376+
QList< QgsSymbolLegendNode* > QgsPropertySizeAssistantWidget::generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue, QgsCurveTransform* curve ) const
357377
{
358378
QList< QgsSymbolLegendNode* > nodes;
359379

@@ -376,6 +396,8 @@ QList< QgsSymbolLegendNode* > QgsPropertySizeAssistantWidget::generatePreviews(
376396
return nodes;
377397

378398
std::unique_ptr< QgsSizeScaleTransformer > t( createTransformer( minValue, maxValue ) );
399+
if ( curve )
400+
t->setCurveTransform( new QgsCurveTransform( *curve ) );
379401

380402
for ( int i = 0; i < breaks.length(); i++ )
381403
{
@@ -401,7 +423,7 @@ QList< QgsSymbolLegendNode* > QgsPropertySizeAssistantWidget::generatePreviews(
401423
return nodes;
402424
}
403425

404-
QList<QgsSymbolLegendNode*> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double>& , QgsLayerTreeLayer* , const QgsSymbol*, double, double ) const
426+
QList<QgsSymbolLegendNode*> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double>& , QgsLayerTreeLayer* , const QgsSymbol*, double, double, QgsCurveTransform* ) const
405427
{
406428
return QList< QgsSymbolLegendNode* >();
407429
}
@@ -451,7 +473,7 @@ QgsColorRampTransformer* QgsPropertyColorAssistantWidget::createTransformer( dou
451473
return transformer;
452474
}
453475

454-
QList<QgsSymbolLegendNode*> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue ) const
476+
QList<QgsSymbolLegendNode*> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue , QgsCurveTransform* curve ) const
455477
{
456478
QList< QgsSymbolLegendNode* > nodes;
457479

@@ -467,6 +489,8 @@ QList<QgsSymbolLegendNode*> QgsPropertyColorAssistantWidget::generatePreviews( c
467489
return nodes;
468490

469491
std::unique_ptr< QgsColorRampTransformer > t( createTransformer( minValue, maxValue ) );
492+
if ( curve )
493+
t->setCurveTransform( new QgsCurveTransform( *curve ) );
470494

471495
for ( int i = 0; i < breaks.length(); i++ )
472496
{

‎src/gui/qgspropertyassistantwidget.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class GUI_EXPORT QgsPropertyAbstractTransformerWidget : public QWidget
4848

4949
virtual QgsPropertyTransformer* createTransformer( double minValue, double maxValue ) const = 0;
5050

51-
virtual QList< QgsSymbolLegendNode* > generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue ) const;
51+
virtual QList< QgsSymbolLegendNode* > generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue, QgsCurveTransform* curve ) const;
5252

5353
signals:
5454

@@ -82,7 +82,7 @@ class GUI_EXPORT QgsPropertySizeAssistantWidget : public QgsPropertyAbstractTran
8282

8383
virtual QgsSizeScaleTransformer* createTransformer( double minValue, double maxValue ) const override;
8484

85-
QList< QgsSymbolLegendNode* > generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue ) const override;
85+
QList< QgsSymbolLegendNode* > generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue, QgsCurveTransform* curve ) const override;
8686
};
8787

8888
class GUI_EXPORT QgsPropertyColorAssistantWidget : public QgsPropertyAbstractTransformerWidget, private Ui::PropertyColorAssistant
@@ -95,7 +95,7 @@ class GUI_EXPORT QgsPropertyColorAssistantWidget : public QgsPropertyAbstractTra
9595

9696
virtual QgsColorRampTransformer* createTransformer( double minValue, double maxValue ) const override;
9797

98-
QList< QgsSymbolLegendNode* > generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue ) const override;
98+
QList< QgsSymbolLegendNode* > generatePreviews( const QList<double>& breaks, QgsLayerTreeLayer* parent, const QgsSymbol* symbol, double minValue, double maxValue, QgsCurveTransform* curve ) const override;
9999
};
100100

101101
///@endcond PRIVATE

‎src/ui/qgspropertyassistantwidgetbase.ui

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,12 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>522</width>
10-
<height>332</height>
9+
<width>525</width>
10+
<height>426</height>
1111
</rect>
1212
</property>
13-
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0">
14-
<item row="0" column="1" rowspan="2">
15-
<widget class="QTreeView" name="mLegendPreview">
16-
<property name="minimumSize">
17-
<size>
18-
<width>200</width>
19-
<height>0</height>
20-
</size>
21-
</property>
22-
</widget>
23-
</item>
24-
<item row="1" column="0">
13+
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0">
14+
<item row="2" column="0">
2515
<widget class="QGroupBox" name="groupBox_2">
2616
<property name="title">
2717
<string>Output</string>
@@ -60,6 +50,16 @@
6050
</layout>
6151
</widget>
6252
</item>
53+
<item row="3" column="0">
54+
<widget class="QFrame" name="mLegendVerticalFrame">
55+
<property name="frameShape">
56+
<enum>QFrame::NoFrame</enum>
57+
</property>
58+
<property name="frameShadow">
59+
<enum>QFrame::Plain</enum>
60+
</property>
61+
</widget>
62+
</item>
6363
<item row="0" column="0">
6464
<widget class="QGroupBox" name="groupBox">
6565
<property name="title">
@@ -153,14 +153,60 @@
153153
</layout>
154154
</widget>
155155
</item>
156-
<item row="2" column="0">
157-
<widget class="QFrame" name="mLegendVerticalFrame">
158-
<property name="frameShape">
159-
<enum>QFrame::NoFrame</enum>
156+
<item row="0" column="1" rowspan="3">
157+
<widget class="QTreeView" name="mLegendPreview">
158+
<property name="minimumSize">
159+
<size>
160+
<width>200</width>
161+
<height>0</height>
162+
</size>
160163
</property>
161-
<property name="frameShadow">
162-
<enum>QFrame::Plain</enum>
164+
</widget>
165+
</item>
166+
<item row="1" column="0">
167+
<widget class="QgsCollapsibleGroupBoxBasic" name="mTransformCurveCheckBox">
168+
<property name="title">
169+
<string>Apply transform curve</string>
170+
</property>
171+
<property name="checkable">
172+
<bool>true</bool>
173+
</property>
174+
<property name="checked">
175+
<bool>false</bool>
163176
</property>
177+
<property name="collapsed" stdset="0">
178+
<bool>true</bool>
179+
</property>
180+
<property name="syncGroup" stdset="0">
181+
<string notr="true">composeritem</string>
182+
</property>
183+
<layout class="QVBoxLayout" name="verticalLayout_2">
184+
<property name="leftMargin">
185+
<number>0</number>
186+
</property>
187+
<property name="topMargin">
188+
<number>0</number>
189+
</property>
190+
<property name="rightMargin">
191+
<number>0</number>
192+
</property>
193+
<property name="bottomMargin">
194+
<number>0</number>
195+
</property>
196+
<item>
197+
<widget class="QgsCurveEditorWidget" name="mCurveEditor" native="true">
198+
<property name="minimumSize">
199+
<size>
200+
<width>0</width>
201+
<height>100</height>
202+
</size>
203+
</property>
204+
<property name="focusPolicy">
205+
<enum>Qt::StrongFocus</enum>
206+
</property>
207+
</widget>
208+
</item>
209+
</layout>
164210
</widget>
165211
</item>
166212
</layout>
@@ -183,6 +229,18 @@
183229
<header>qgspanelwidget.h</header>
184230
<container>1</container>
185231
</customwidget>
232+
<customwidget>
233+
<class>QgsCollapsibleGroupBoxBasic</class>
234+
<extends>QGroupBox</extends>
235+
<header location="global">qgscollapsiblegroupbox.h</header>
236+
<container>1</container>
237+
</customwidget>
238+
<customwidget>
239+
<class>QgsCurveEditorWidget</class>
240+
<extends>QWidget</extends>
241+
<header location="global">qgscurveeditorwidget.h</header>
242+
<container>1</container>
243+
</customwidget>
186244
</customwidgets>
187245
<tabstops>
188246
<tabstop>mExpressionWidget</tabstop>

0 commit comments

Comments
 (0)
Please sign in to comment.