QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
18#include "qgssymbol.h"
20#include "qgssymbollayerutils.h"
21#include "qgsstyle.h"
22#include "qgsvectorlayer.h"
24#include "qgsguiutils.h"
25#include "qgsmarkersymbol.h"
26
27//
28// QgsFieldConditionalFormatWidget
29//
30
32 : QgsPanelWidget( parent )
33{
34 setupUi( this );
35 setPanelTitle( tr( "Conditional Styles" ) );
36 connect( mFieldCombo, &QgsFieldComboBox::fieldChanged, this, &QgsFieldConditionalFormatWidget::fieldChanged );
37 connect( fieldRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::typeChanged );
38 connect( rowRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::typeChanged );
39 connect( mNewButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::addNewRule );
40 connect( listView, &QAbstractItemView::clicked, this, &QgsFieldConditionalFormatWidget::ruleClicked );
41 mModel = new QStandardItemModel( listView );
42 listView->setModel( mModel );
43
44 connect( fieldRadio, &QRadioButton::toggled, mFieldCombo, &QWidget::setEnabled );
45
46 mPresets = defaultPresets();
47}
48
50{
51 mLayer = layer;
52 mFieldCombo->setLayer( layer );
53 mFieldCombo->setCurrentIndex( 0 );
54 fieldChanged( mFieldCombo->currentField() );
55}
56
57void QgsFieldConditionalFormatWidget::ruleClicked( const QModelIndex &index )
58{
59 const QList<QgsConditionalStyle> styles = getStyles();
60 const QgsConditionalStyle style = styles.at( index.row() );
61 editStyle( index.row(), style );
62}
63
65{
66 mEditIndex = editIndex;
67 mEditing = editIndex >= 0;
68 mPanelHandled = false;
69
71 ruleWidget->setLayer( mLayer );
72 ruleWidget->setPresets( mPresets );
73 ruleWidget->loadStyle( style );
74 ruleWidget->setDockMode( true );
75
76 if ( fieldRadio->isChecked() && style.rule().isEmpty() )
77 {
78 ruleWidget->setRule( QStringLiteral( "@value " ) );
79 }
80
81 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::panelAccepted, this, [ = ]
82 {
83 if ( mPanelHandled )
84 {
85 // already handled the result of the panel, and the panel is being dismissed as a result
86 // of an already dealt with action
87 return;
88 }
89
90 QList<QgsConditionalStyle> styles = getStyles();
91 if ( mEditing )
92 {
93 styles.replace( mEditIndex, ruleWidget->currentStyle() );
94 }
95 else
96 {
97 styles.append( ruleWidget->currentStyle() );
98 }
99
100 QString fieldName;
101 if ( fieldRadio->isChecked() )
102 {
103 fieldName = mFieldCombo->currentField();
104 mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
105 }
106 else if ( rowRadio->isChecked() )
107 {
108 mLayer->conditionalStyles()->setRowStyles( styles );
109 }
110
111 reloadStyles();
112 emit rulesUpdated( fieldName );
113 } );
114
115 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleSaved, this, [ = ]
116 {
117 ruleWidget->acceptPanel();
118 } );
119
120 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::canceled, this, [ = ]
121 {
122 mPanelHandled = true;
123 ruleWidget->acceptPanel();
124 } );
125
126 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleDeleted, this, [ = ]
127 {
128 deleteCurrentRule();
129 mPanelHandled = true;
130 ruleWidget->acceptPanel();
131 } );
132 showPanel( ruleWidget );
133}
134
136{
137}
138
139QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
140{
141 QList<QgsConditionalStyle> styles;
142 if ( fieldRadio->isChecked() )
143 {
144 styles = mLayer->conditionalStyles()->fieldStyles( mFieldCombo->currentField() );
145 }
146 else if ( rowRadio->isChecked() )
147 {
148 styles = mLayer->conditionalStyles()->rowStyles();
149 }
150
151 return styles;
152}
153
154void QgsFieldConditionalFormatWidget::addNewRule()
155{
157}
158
160{
161}
162
163void QgsFieldConditionalFormatWidget::setPresets( const QList<QgsConditionalStyle> &styles )
164{
165 mPresets = styles;
166}
167
169{
170 QList<QgsConditionalStyle> styles;
172 style.setBackgroundColor( QColor( 154, 216, 113 ) );
173 styles.append( style );
174 style = QgsConditionalStyle();
175 style.setBackgroundColor( QColor( 251, 193, 78 ) );
176 styles.append( style );
177 style = QgsConditionalStyle();
178 style.setBackgroundColor( QColor( 251, 154, 153 ) );
179 styles.append( style );
180 style = QgsConditionalStyle();
181 style.setTextColor( QColor( 154, 216, 113 ) );
182 styles.append( style );
183 style = QgsConditionalStyle();
184 style.setTextColor( QColor( 251, 193, 78 ) );
185 styles.append( style );
186 style = QgsConditionalStyle();
187 style.setTextColor( QColor( 251, 154, 153 ) );
188 styles.append( style );
189 return styles;
190}
191
192void QgsFieldConditionalFormatWidget::typeChanged()
193{
194 reloadStyles();
195}
196
197void QgsFieldConditionalFormatWidget::reloadStyles()
198{
199 mModel->clear();
200
201 const auto constGetStyles = getStyles();
202
203 const QSize size( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 10, Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 2 );
204
205 listView->setIconSize( size );
206
207 for ( const QgsConditionalStyle &style : constGetStyles )
208 {
209 QStandardItem *item = new QStandardItem( style.displayText() );
210 item->setIcon( QIcon( style.renderPreview( size ) ) );
211 mModel->appendRow( item );
212 }
213}
214
215void QgsFieldConditionalFormatWidget::fieldChanged( const QString &fieldName )
216{
217 Q_UNUSED( fieldName )
218 reloadStyles();
219}
220
221void QgsFieldConditionalFormatWidget::deleteCurrentRule()
222{
223 if ( !mEditing )
224 return;
225
226 QList<QgsConditionalStyle> styles = getStyles();
227 styles.removeAt( mEditIndex );
228 QString fieldName;
229 if ( fieldRadio->isChecked() )
230 {
231 fieldName = mFieldCombo->currentField();
232 mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
233 }
234 else if ( rowRadio->isChecked() )
235 {
236 mLayer->conditionalStyles()->setRowStyles( styles );
237 }
238
239 reloadStyles();
240 emit rulesUpdated( fieldName );
241}
242
244{
245}
246
247
248//
249// QgsEditConditionalFormatRuleWidget
250//
251
253 : QgsPanelWidget( parent )
254{
255 setupUi( this );
256
257 setPanelTitle( tr( "Edit Rule" ) );
258
259 btnBackgroundColor->setColor( QColor() );
260 btnTextColor->setColor( QColor() );
261 checkIcon->setChecked( false );
262 btnChangeIcon->setIcon( QIcon() );
263 btnBackgroundColor->setToNoColor();
264 btnTextColor->setToNoColor();
265
266 mFontBoldBtn->setChecked( false );
267 mFontItalicBtn->setChecked( false );
268 mFontStrikethroughBtn->setChecked( false );
269 mFontUnderlineBtn->setChecked( false );
270
271 const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
272 mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
273 mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
274 mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
275 mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
276 mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
277 mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
278 mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
279 mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
280
281 connect( mSaveRule, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleSaved );
282 connect( mCancelButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::canceled );
283 connect( mDeleteButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleDeleted );
284
285 connect( btnBuildExpression, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::setExpression );
286 connect( mPresetsList, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditConditionalFormatRuleWidget::presetSet );
287
288 btnBackgroundColor->setAllowOpacity( true );
289 btnBackgroundColor->setShowNoColor( true );
290 btnTextColor->setAllowOpacity( true );
291 btnTextColor->setShowNoColor( true );
292 mPresetsModel = new QStandardItemModel( mPresetsList );
293 mPresetsList->setModel( mPresetsModel );
294
295 btnChangeIcon->setSymbolType( Qgis::SymbolType::Marker );
296 btnChangeIcon->setSymbol( QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) );
297 connect( checkIcon, &QCheckBox::toggled, btnChangeIcon, &QWidget::setEnabled );
298}
299
301{
302 mLayer = layer;
303}
304
306{
307 mRuleEdit->setText( style.rule() );
308 mNameEdit->setText( style.name() );
309 setFormattingFromStyle( style );
310}
311
313{
315
316 style.setRule( mRuleEdit->text() );
317 style.setName( mNameEdit->text() );
318
319 const QColor backColor = btnBackgroundColor->color();
320 const QColor fontColor = btnTextColor->color();
321
322 QFont font = mFontFamilyCmbBx->currentFont();
323 font.setBold( mFontBoldBtn->isChecked() );
324 font.setItalic( mFontItalicBtn->isChecked() );
325 font.setStrikeOut( mFontStrikethroughBtn->isChecked() );
326 font.setUnderline( mFontUnderlineBtn->isChecked() );
327 style.setFont( font );
328 style.setBackgroundColor( backColor );
329 style.setTextColor( fontColor );
330 if ( checkIcon->isChecked() )
331 {
332 style.setSymbol( btnChangeIcon->clonedSymbol< QgsMarkerSymbol >() );
333 }
334 else
335 {
336 style.setSymbol( nullptr );
337 }
338 return style;
339}
340
341void QgsEditConditionalFormatRuleWidget::setExpression()
342{
344 context.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "value" ), 0, true ) );
345 context.setHighlightedVariables( QStringList() << QStringLiteral( "value" ) );
346
347 QgsExpressionBuilderDialog dlg( mLayer, mRuleEdit->text(), this, QStringLiteral( "generic" ), context );
348 dlg.setWindowTitle( tr( "Conditional Style Rule Expression" ) );
349
350 if ( dlg.exec() )
351 {
352 const QString expression = dlg.expressionBuilder()->expressionText();
353 mRuleEdit->setText( expression );
354 }
355}
356
357void QgsEditConditionalFormatRuleWidget::presetSet( int index )
358{
359 if ( index == -1 || mPresets.isEmpty() )
360 return;
361
362 const int styleIndex = mPresetsList->currentData( Qt::UserRole + 1 ).toInt();
363 const QgsConditionalStyle style = mPresets.at( styleIndex );
364 setFormattingFromStyle( style );
365}
366
367void QgsEditConditionalFormatRuleWidget::setFormattingFromStyle( const QgsConditionalStyle &style )
368{
369 btnBackgroundColor->setColor( style.backgroundColor() );
370 btnTextColor->setColor( style.textColor() );
371 if ( auto *lSymbol = style.symbol() )
372 {
373 btnChangeIcon->setSymbol( lSymbol->clone() );
374 checkIcon->setChecked( true );
375 }
376 else
377 {
378 checkIcon->setChecked( false );
379 }
380 const QFont font = style.font();
381 mFontBoldBtn->setChecked( font.bold() );
382 mFontItalicBtn->setChecked( font.italic() );
383 mFontStrikethroughBtn->setChecked( font.strikeOut() );
384 mFontUnderlineBtn->setChecked( font.underline() );
385 mFontFamilyCmbBx->setCurrentFont( font );
386}
387
388void QgsEditConditionalFormatRuleWidget::setPresets( const QList<QgsConditionalStyle> &styles )
389{
390 mPresets.clear();
391 mPresetsModel->clear();
392 QStandardItem *item = new QStandardItem( QString() );
393 mPresetsModel->appendRow( item );
394 int i = 0;
395 for ( const QgsConditionalStyle &style : styles )
396 {
397 if ( style.isValid() )
398 {
399 QStandardItem *item = new QStandardItem( QStringLiteral( "abc - 123" ) );
400 if ( style.validBackgroundColor() )
401 item->setBackground( style.backgroundColor() );
402 if ( style.validTextColor() )
403 item->setForeground( style.textColor() );
404 if ( style.symbol() )
405 item->setIcon( style.icon() );
406 item->setFont( style.font() );
407 item->setData( i, Qt::UserRole + 1 );
408 mPresetsModel->appendRow( item );
409 mPresets.append( style );
410 i++;
411 }
412 }
413 mPresetsList->setCurrentIndex( 0 );
414}
415
417{
418 mRuleEdit->setText( rule );
419}
420
421bool QgsEditConditionalFormatRuleWidget::isCustomSet()
422{
423 return ( btnBackgroundColor->color().isValid()
424 || btnTextColor->color().isValid()
425 || mFontButtons->checkedId() != -1 );
426}
@ Marker
Marker symbol.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:4927
QgsConditionalStyles rowStyles() const
Returns a list of row styles associated with the layer.
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName) const
Returns the conditional styles set for the field with matching fieldName.
void setFieldStyles(const QString &fieldName, const QList< QgsConditionalStyle > &styles)
Set the conditional styles for a field, with the specified fieldName.
void setRowStyles(const QgsConditionalStyles &styles)
Sets the conditional styles that apply to full rows of data in the attribute table.
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.
Base class for any widget that can be shown as a inline panel.
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.
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.
Definition: qgssymbol.cpp:705
Represents a vector layer which manages a vector based data sets.
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.