QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsfieldconditionalformatwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfieldconditionalformatwidget.cpp
3 ---------------------
4 begin : August 2015
5 copyright : (C) 2015 by Nathan Woodrow
6 email : woodrow dot nathan 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 ***************************************************************************/
16
19#include "qgsguiutils.h"
20#include "qgsmarkersymbol.h"
21#include "qgsstyle.h"
22#include "qgssymbol.h"
23#include "qgssymbollayerutils.h"
25#include "qgsvectorlayer.h"
26
27#include "moc_qgsfieldconditionalformatwidget.cpp"
28
29//
30// QgsFieldConditionalFormatWidget
31//
32
34 : QgsPanelWidget( parent )
35{
36 setupUi( this );
37 setPanelTitle( tr( "Conditional Styles" ) );
38 connect( mFieldCombo, &QgsFieldComboBox::fieldChanged, this, &QgsFieldConditionalFormatWidget::fieldChanged );
39 connect( fieldRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::typeChanged );
40 connect( rowRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::typeChanged );
41 connect( mNewButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::addNewRule );
42 connect( listView, &QAbstractItemView::clicked, this, &QgsFieldConditionalFormatWidget::ruleClicked );
43 mModel = new QStandardItemModel( listView );
44 listView->setModel( mModel );
45
46 connect( fieldRadio, &QRadioButton::toggled, mFieldCombo, &QWidget::setEnabled );
47
48 mPresets = defaultPresets();
49}
50
52{
53 mLayer = layer;
54 mFieldCombo->setLayer( layer );
55 mFieldCombo->setCurrentIndex( 0 );
56 fieldChanged( mFieldCombo->currentField() );
57}
58
59void QgsFieldConditionalFormatWidget::ruleClicked( const QModelIndex &index )
60{
61 const QList<QgsConditionalStyle> styles = getStyles();
62 const QgsConditionalStyle style = styles.at( index.row() );
63 editStyle( index.row(), style );
64}
65
67{
68 mEditIndex = editIndex;
69 mEditing = editIndex >= 0;
70 mPanelHandled = false;
71
73 ruleWidget->setLayer( mLayer );
74 ruleWidget->setPresets( mPresets );
75 ruleWidget->loadStyle( style );
76 ruleWidget->setDockMode( true );
77
78 if ( fieldRadio->isChecked() && style.rule().isEmpty() )
79 {
80 ruleWidget->setRule( QStringLiteral( "@value " ) );
81 }
82
83 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::panelAccepted, this, [this, ruleWidget] {
84 if ( mPanelHandled )
85 {
86 // already handled the result of the panel, and the panel is being dismissed as a result
87 // of an already dealt with action
88 return;
89 }
90
91 QList<QgsConditionalStyle> styles = getStyles();
92 if ( mEditing )
93 {
94 styles.replace( mEditIndex, ruleWidget->currentStyle() );
95 }
96 else
97 {
98 styles.append( ruleWidget->currentStyle() );
99 }
100
101 QString fieldName;
102 if ( fieldRadio->isChecked() )
103 {
104 fieldName = mFieldCombo->currentField();
105 mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
106 }
107 else if ( rowRadio->isChecked() )
108 {
109 mLayer->conditionalStyles()->setRowStyles( styles );
110 }
111
112 reloadStyles();
113 emit rulesUpdated( fieldName );
114 } );
115
116 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleSaved, this, [ruleWidget] {
117 ruleWidget->acceptPanel();
118 } );
119
120 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::canceled, this, [this, ruleWidget] {
121 mPanelHandled = true;
122 ruleWidget->acceptPanel();
123 } );
124
125 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleDeleted, this, [this, ruleWidget] {
126 deleteCurrentRule();
127 mPanelHandled = true;
128 ruleWidget->acceptPanel();
129 } );
130 showPanel( ruleWidget );
131}
132
136
137QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
138{
139 QList<QgsConditionalStyle> styles;
140 if ( fieldRadio->isChecked() )
141 {
142 styles = mLayer->conditionalStyles()->fieldStyles( mFieldCombo->currentField() );
143 }
144 else if ( rowRadio->isChecked() )
145 {
146 styles = mLayer->conditionalStyles()->rowStyles();
147 }
148
149 return styles;
150}
151
152void QgsFieldConditionalFormatWidget::addNewRule()
153{
154 editStyle( -1, QgsConditionalStyle() );
155}
156
160
161void QgsFieldConditionalFormatWidget::setPresets( const QList<QgsConditionalStyle> &styles )
162{
163 mPresets = styles;
164}
165
167{
168 QList<QgsConditionalStyle> styles;
170 style.setBackgroundColor( QColor( 154, 216, 113 ) );
171 styles.append( style );
172 style = QgsConditionalStyle();
173 style.setBackgroundColor( QColor( 251, 193, 78 ) );
174 styles.append( style );
175 style = QgsConditionalStyle();
176 style.setBackgroundColor( QColor( 251, 154, 153 ) );
177 styles.append( style );
178 style = QgsConditionalStyle();
179 style.setTextColor( QColor( 154, 216, 113 ) );
180 styles.append( style );
181 style = QgsConditionalStyle();
182 style.setTextColor( QColor( 251, 193, 78 ) );
183 styles.append( style );
184 style = QgsConditionalStyle();
185 style.setTextColor( QColor( 251, 154, 153 ) );
186 styles.append( style );
187 return styles;
188}
189
190void QgsFieldConditionalFormatWidget::typeChanged()
191{
192 reloadStyles();
193}
194
195void QgsFieldConditionalFormatWidget::reloadStyles()
196{
197 mModel->clear();
198
199 const auto constGetStyles = getStyles();
200
201 const QSize size( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 10, Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 2 );
202
203 listView->setIconSize( size );
204
205 for ( const QgsConditionalStyle &style : constGetStyles )
206 {
207 QStandardItem *item = new QStandardItem( style.displayText() );
208 item->setIcon( QIcon( style.renderPreview( size ) ) );
209 mModel->appendRow( item );
210 }
211}
212
213void QgsFieldConditionalFormatWidget::fieldChanged( const QString &fieldName )
214{
215 Q_UNUSED( fieldName )
216 reloadStyles();
217}
218
219void QgsFieldConditionalFormatWidget::deleteCurrentRule()
220{
221 if ( !mEditing )
222 return;
223
224 QList<QgsConditionalStyle> styles = getStyles();
225 styles.removeAt( mEditIndex );
226 QString fieldName;
227 if ( fieldRadio->isChecked() )
228 {
229 fieldName = mFieldCombo->currentField();
230 mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
231 }
232 else if ( rowRadio->isChecked() )
233 {
234 mLayer->conditionalStyles()->setRowStyles( styles );
235 }
236
237 reloadStyles();
238 emit rulesUpdated( fieldName );
239}
240
244
245
246//
247// QgsEditConditionalFormatRuleWidget
248//
249
251 : QgsPanelWidget( parent )
252{
253 setupUi( this );
254
255 setPanelTitle( tr( "Edit Rule" ) );
256
257 btnBackgroundColor->setColor( QColor() );
258 btnTextColor->setColor( QColor() );
259 checkIcon->setChecked( false );
260 btnChangeIcon->setIcon( QIcon() );
261 btnBackgroundColor->setToNoColor();
262 btnTextColor->setToNoColor();
263
264 mFontBoldBtn->setChecked( false );
265 mFontItalicBtn->setChecked( false );
266 mFontStrikethroughBtn->setChecked( false );
267 mFontUnderlineBtn->setChecked( false );
268
269 const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
270 mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
271 mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
272 mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
273 mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
274 mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
275 mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
276 mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
277 mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
278
279 connect( mSaveRule, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleSaved );
280 connect( mCancelButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::canceled );
281 connect( mDeleteButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleDeleted );
282
283 connect( btnBuildExpression, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::setExpression );
284 connect( mPresetsList, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditConditionalFormatRuleWidget::presetSet );
285
286 btnBackgroundColor->setAllowOpacity( true );
287 btnBackgroundColor->setShowNoColor( true );
288 btnTextColor->setAllowOpacity( true );
289 btnTextColor->setShowNoColor( true );
290 mPresetsModel = new QStandardItemModel( mPresetsList );
291 mPresetsList->setModel( mPresetsModel );
292
293 btnChangeIcon->setSymbolType( Qgis::SymbolType::Marker );
294 btnChangeIcon->setSymbol( QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) );
295 connect( checkIcon, &QCheckBox::toggled, btnChangeIcon, &QWidget::setEnabled );
296}
297
299{
300 mLayer = layer;
301}
302
304{
305 mRuleEdit->setText( style.rule() );
306 mNameEdit->setText( style.name() );
307 setFormattingFromStyle( style );
308}
309
311{
313
314 style.setRule( mRuleEdit->text() );
315 style.setName( mNameEdit->text() );
316
317 const QColor backColor = btnBackgroundColor->color();
318 const QColor fontColor = btnTextColor->color();
319
320 QFont font = mFontFamilyCmbBx->currentFont();
321 font.setBold( mFontBoldBtn->isChecked() );
322 font.setItalic( mFontItalicBtn->isChecked() );
323 font.setStrikeOut( mFontStrikethroughBtn->isChecked() );
324 font.setUnderline( mFontUnderlineBtn->isChecked() );
325 style.setFont( font );
326 style.setBackgroundColor( backColor );
327 style.setTextColor( fontColor );
328 if ( checkIcon->isChecked() )
329 {
330 style.setSymbol( btnChangeIcon->clonedSymbol<QgsMarkerSymbol>() );
331 }
332 else
333 {
334 style.setSymbol( nullptr );
335 }
336 return style;
337}
338
339void QgsEditConditionalFormatRuleWidget::setExpression()
340{
342 context.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "value" ), 0, true ) );
343 context.setHighlightedVariables( QStringList() << QStringLiteral( "value" ) );
344
345 QgsExpressionBuilderDialog dlg( mLayer, mRuleEdit->text(), this, QStringLiteral( "generic" ), context );
346 dlg.setWindowTitle( tr( "Conditional Style Rule Expression" ) );
347
348 if ( dlg.exec() )
349 {
350 const QString expression = dlg.expressionBuilder()->expressionText();
351 mRuleEdit->setText( expression );
352 }
353}
354
355void QgsEditConditionalFormatRuleWidget::presetSet( int index )
356{
357 if ( index == -1 || mPresets.isEmpty() )
358 return;
359
360 const int styleIndex = mPresetsList->currentData( Qt::UserRole + 1 ).toInt();
361 const QgsConditionalStyle style = mPresets.at( styleIndex );
362 setFormattingFromStyle( style );
363}
364
365void QgsEditConditionalFormatRuleWidget::setFormattingFromStyle( const QgsConditionalStyle &style )
366{
367 btnBackgroundColor->setColor( style.backgroundColor() );
368 btnTextColor->setColor( style.textColor() );
369 if ( auto *lSymbol = style.symbol() )
370 {
371 btnChangeIcon->setSymbol( lSymbol->clone() );
372 checkIcon->setChecked( true );
373 }
374 else
375 {
376 checkIcon->setChecked( false );
377 }
378 const QFont font = style.font();
379 mFontBoldBtn->setChecked( font.bold() );
380 mFontItalicBtn->setChecked( font.italic() );
381 mFontStrikethroughBtn->setChecked( font.strikeOut() );
382 mFontUnderlineBtn->setChecked( font.underline() );
383 mFontFamilyCmbBx->setCurrentFont( font );
384}
385
386void QgsEditConditionalFormatRuleWidget::setPresets( const QList<QgsConditionalStyle> &styles )
387{
388 mPresets.clear();
389 mPresetsModel->clear();
390 QStandardItem *item = new QStandardItem( QString() );
391 mPresetsModel->appendRow( item );
392 int i = 0;
393 for ( const QgsConditionalStyle &style : styles )
394 {
395 if ( style.isValid() )
396 {
397 QStandardItem *item = new QStandardItem( QStringLiteral( "abc - 123" ) );
398 if ( style.validBackgroundColor() )
399 item->setBackground( style.backgroundColor() );
400 if ( style.validTextColor() )
401 item->setForeground( style.textColor() );
402 if ( style.symbol() )
403 item->setIcon( style.icon() );
404 item->setFont( style.font() );
405 item->setData( i, Qt::UserRole + 1 );
406 mPresetsModel->appendRow( item );
407 mPresets.append( style );
408 i++;
409 }
410 }
411 mPresetsList->setCurrentIndex( 0 );
412}
413
415{
416 mRuleEdit->setText( rule );
417}
418
419bool QgsEditConditionalFormatRuleWidget::isCustomSet()
420{
421 return ( btnBackgroundColor->color().isValid() || btnTextColor->color().isValid() || mFontButtons->checkedId() != -1 );
422}
@ Point
Points.
Definition qgis.h:359
@ Marker
Marker symbol.
Definition qgis.h:611
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6222
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName) const
Returns the conditional styles set for the field with matching fieldName.
Conditional styling for a rule.
QString displayText() const
The name of the style.
QString name() const
The name of the style.
void setSymbol(QgsSymbol *value)
Set the icon for the style.
void setName(const QString &value)
Set the name of the style.
QPixmap renderPreview(const QSize &size=QSize()) const
Render a preview icon of the rule, at the specified size.
void setTextColor(const QColor &value)
Set the text color for the style.
void setRule(const QString &value)
Set the rule for the style.
void setBackgroundColor(const QColor &value)
Set the background color for the style.
void setFont(const QFont &value)
Set the font for the style.
QColor backgroundColor() const
The background color for style.
QColor textColor() const
The text color set for style.
QString rule() const
The condition rule set for the style.
QFont font() const
The font for the style.
bool validTextColor() const
Check if the text color is valid for render.
QgsSymbol * symbol() const
The symbol used to generate the icon for the style.
bool isValid() const
isValid Check if this rule is valid.
QPixmap icon() const
The icon set for style generated from the set symbol.
bool validBackgroundColor() const
Check if the background color is valid for render.
A widget for customizing an individual conditional formatting rule.
QgsEditConditionalFormatRuleWidget(QWidget *parent=nullptr)
Constructor for QgsFieldConditionalFormatWidget, with the specified parent widget.
void setPresets(const QList< QgsConditionalStyle > &styles)
Sets the preset styles that can be used for quick pick.
void loadStyle(const QgsConditionalStyle &style)
Sets the widget to match the settings from the specified style.
void setLayer(QgsVectorLayer *layer)
Sets the vector layer associated with the widget.
void setRule(const QString &rule)
Sets the current expression rule to show in the widget.
QgsConditionalStyle currentStyle() const
Returns the current style defined by the widget.
void canceled()
Emitted when a user has opted to cancel the rule modification.
void ruleDeleted()
Emitted when a user has opted to deleted the current rule.
void ruleSaved()
Emitted when a user has opted to save the current rule.
A generic dialog for building expression strings.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QgsFieldConditionalFormatWidget(QWidget *parent=nullptr)
Constructor for QgsFieldConditionalFormatWidget.
void rulesUpdated(const QString &fieldName)
Emitted when the conditional styling rules are updated.
static QList< QgsConditionalStyle > defaultPresets()
Returns a list of the default presets.
Q_DECL_DEPRECATED void viewRules()
Switches the widget to the rules page.
Q_DECL_DEPRECATED void loadStyle(const QgsConditionalStyle &style)
Q_DECL_DEPRECATED void reset()
Resets the formatting options to their default state.
void editStyle(int index, const QgsConditionalStyle &style)
Switches the widget to the edit style mode for the specified style, where index is the index of the c...
void setPresets(const QList< QgsConditionalStyle > &styles)
Sets the preset styles that can be used for quick pick.
void setLayer(QgsVectorLayer *layer)
Sets the vector layer associated with the widget.
A marker symbol type, for rendering Point and MultiPoint geometries.
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
QgsPanelWidget(QWidget *parent=nullptr)
Base class for any widget that can be shown as an inline panel.
void acceptPanel()
Accept the panel.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Represents a vector layer which manages a vector based dataset.
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Single variable definition for use within a QgsExpressionContextScope.