20
20
#include " qgsproject.h"
21
21
#include " qgsmapsettings.h"
22
22
#include " qgsvectorlayer.h"
23
+ #include " qgslayertreelayer.h"
24
+ #include " qgssymbollayerutils.h"
23
25
24
26
QgsPropertyAssistantWidget::QgsPropertyAssistantWidget ( QWidget* parent ,
25
27
const QgsPropertyDefinition& definition, const QgsProperty& initialState,
@@ -53,6 +55,16 @@ QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget* parent ,
53
55
54
56
connect ( computeValuesButton, &QPushButton::clicked, this , &QgsPropertyAssistantWidget::computeValuesFromLayer );
55
57
58
+ if ( mLayer )
59
+ {
60
+ mLayerTreeLayer = new QgsLayerTreeLayer ( const_cast < QgsVectorLayer* >( mLayer ) );
61
+ mRoot .addChildNode ( mLayerTreeLayer ); // takes ownership
62
+ }
63
+ mLegendPreview ->setModel ( &mPreviewList );
64
+ mLegendPreview ->setItemDelegate ( new ItemDelegate ( &mPreviewList ) );
65
+ mLegendPreview ->setHeaderHidden ( true );
66
+ mLegendPreview ->expandAll ();
67
+
56
68
switch ( definition.standardTemplate () )
57
69
{
58
70
case QgsPropertyDefinition::Size :
@@ -72,6 +84,8 @@ QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget* parent ,
72
84
connect ( minValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this , &QgsPropertyAssistantWidget::widgetChanged );
73
85
connect ( maxValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this , &QgsPropertyAssistantWidget::widgetChanged );
74
86
connect ( mExpressionWidget , static_cast < void ( QgsFieldExpressionWidget::* )( const QString& ) > ( &QgsFieldExpressionWidget::fieldChanged ), this , &QgsPropertyAssistantWidget::widgetChanged );
87
+ connect ( this , &QgsPropertyAssistantWidget::widgetChanged, this , &QgsPropertyAssistantWidget::updatePreview );
88
+ updatePreview ();
75
89
}
76
90
77
91
void QgsPropertyAssistantWidget::registerExpressionContextGenerator ( QgsExpressionContextGenerator* generator )
@@ -116,6 +130,55 @@ void QgsPropertyAssistantWidget::computeValuesFromLayer()
116
130
emit widgetChanged ();
117
131
}
118
132
133
+ void QgsPropertyAssistantWidget::updatePreview ()
134
+ {
135
+ if ( !mTransformerWidget || !mSymbol )
136
+ return ;
137
+
138
+ if ( dockMode () )
139
+ return ;
140
+
141
+ mLegendPreview ->setIconSize ( QSize ( 512 , 512 ) );
142
+ mPreviewList .clear ();
143
+
144
+ QList<double > breaks = QgsSymbolLayerUtils::prettyBreaks ( minValueSpinBox->value (),
145
+ maxValueSpinBox->value (), 4 );
146
+
147
+ QList< QgsSymbolLegendNode* > nodes = mTransformerWidget ->generatePreviews ( breaks, mLayerTreeLayer , mLayer , mSymbol .get (), minValueSpinBox->value (),
148
+ maxValueSpinBox->value () );
149
+ if ( nodes.isEmpty () )
150
+ {
151
+ mLegendPreview ->show ();
152
+ return ;
153
+ }
154
+
155
+ int widthMax = 0 ;
156
+ int i = 0 ;
157
+ Q_FOREACH ( QgsSymbolLegendNode* node, nodes )
158
+ {
159
+ const QSize minSize ( node->minimumIconSize () );
160
+ node->setIconSize ( minSize );
161
+ widthMax = qMax ( minSize.width (), widthMax );
162
+ mPreviewList .appendRow ( new QStandardItem ( node->data ( Qt::DecorationRole ).value <QPixmap>(), QString::number ( breaks[i] ) ) );
163
+ delete node;
164
+ i++;
165
+ }
166
+ // center icon and align text left by giving icons the same width
167
+ // @todo maybe add some space so that icons don't touch
168
+ for ( int i = 0 ; i < breaks.length (); i++ )
169
+ {
170
+ QPixmap img ( mPreviewList .item ( i )->icon ().pixmap ( mPreviewList .item ( i )->icon ().actualSize ( QSize ( 512 , 512 ) ) ) );
171
+ QPixmap enlarged ( widthMax, img.height () );
172
+ // fill transparent and add original image
173
+ enlarged.fill ( Qt::transparent );
174
+ QPainter p ( &enlarged );
175
+ p.drawPixmap ( QPoint (( widthMax - img.width () ) / 2 , 0 ), img );
176
+ p.end ();
177
+ mPreviewList .item ( i )->setIcon ( enlarged );
178
+ }
179
+ mLegendPreview ->show ();
180
+ }
181
+
119
182
bool QgsPropertyAssistantWidget::computeValuesFromExpression ( const QString& expression, double & minValue, double & maxValue ) const
120
183
{
121
184
QgsExpression e ( expression );
@@ -236,7 +299,7 @@ QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget* parent,
236
299
);
237
300
}
238
301
239
- QgsPropertyTransformer * QgsPropertySizeAssistantWidget::createTransformer ( double minValue, double maxValue ) const
302
+ QgsSizeScaleTransformer * QgsPropertySizeAssistantWidget::createTransformer ( double minValue, double maxValue ) const
240
303
{
241
304
QgsSizeScaleTransformer* transformer = new QgsSizeScaleTransformer (
242
305
static_cast < QgsSizeScaleTransformer::ScaleType >( scaleMethodComboBox->currentData ().toInt () ),
@@ -248,3 +311,41 @@ QgsPropertyTransformer* QgsPropertySizeAssistantWidget::createTransformer( doubl
248
311
exponentSpinBox->value () );
249
312
return transformer;
250
313
}
314
+
315
+ QList< QgsSymbolLegendNode* > QgsPropertySizeAssistantWidget::generatePreviews ( const QList<double >& breaks, QgsLayerTreeLayer* parent, const QgsVectorLayer* layer, const QgsSymbol* symbol, double minValue, double maxValue ) const
316
+ {
317
+ QList< QgsSymbolLegendNode* > nodes;
318
+
319
+ if ( !symbol || !layer )
320
+ return nodes;
321
+
322
+ std::unique_ptr< QgsSizeScaleTransformer > t ( createTransformer ( minValue, maxValue ) );
323
+
324
+ for ( int i = 0 ; i < breaks.length (); i++ )
325
+ {
326
+ std::unique_ptr< QgsSymbolLegendNode > node;
327
+ if ( dynamic_cast <const QgsMarkerSymbol*>( symbol ) )
328
+ {
329
+ std::unique_ptr< QgsMarkerSymbol > symbolClone ( static_cast <QgsMarkerSymbol*>( symbol->clone () ) );
330
+ symbolClone->setDataDefinedSize ( QgsProperty () );
331
+ symbolClone->setDataDefinedAngle ( QgsProperty () ); // to avoid symbol not being drawn
332
+ symbolClone->setSize ( t->size ( breaks[i] ) );
333
+ node.reset ( new QgsSymbolLegendNode ( parent, QgsLegendSymbolItem ( symbolClone.get (), QString::number ( i ), QString () ) ) );
334
+ }
335
+ else if ( dynamic_cast <const QgsLineSymbol*>( symbol ) )
336
+ {
337
+ std::unique_ptr< QgsLineSymbol > symbolClone ( static_cast <QgsLineSymbol*>( symbol->clone () ) );
338
+ symbolClone->setDataDefinedWidth ( QgsProperty () );
339
+ symbolClone->setWidth ( t->size ( breaks[i] ) );
340
+ node.reset ( new QgsSymbolLegendNode ( parent, QgsLegendSymbolItem ( symbolClone.get (), QString::number ( i ), QString () ) ) );
341
+ }
342
+ if ( node )
343
+ nodes << node.release ();
344
+ }
345
+ return nodes;
346
+ }
347
+
348
+ QList<QgsSymbolLegendNode*> QgsPropertyAbstractTransformerWidget::generatePreviews ( const QList<double >& , QgsLayerTreeLayer* , const QgsVectorLayer*, const QgsSymbol*, double , double ) const
349
+ {
350
+ return QList< QgsSymbolLegendNode* >();
351
+ }
0 commit comments