QGIS API Documentation 3.27.0-Master (f261cc1f8b)
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::reloadStyles );
38 connect( rowRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::reloadStyles );
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 if ( rowRadio->isChecked() )
107 {
108 mLayer->conditionalStyles()->setRowStyles( styles );
109 }
110 reloadStyles();
111 emit rulesUpdated( fieldName );
112 } );
113
114 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleSaved, this, [ = ]
115 {
116 ruleWidget->acceptPanel();
117 } );
118
119 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::canceled, this, [ = ]
120 {
121 mPanelHandled = true;
122 ruleWidget->acceptPanel();
123 } );
124
125 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleDeleted, this, [ = ]
126 {
127 deleteCurrentRule();
128 mPanelHandled = true;
129 ruleWidget->acceptPanel();
130 } );
131 showPanel( ruleWidget );
132}
133
135{
136}
137
138QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
139{
140 QList<QgsConditionalStyle> styles;
141 if ( fieldRadio->isChecked() )
142 {
143 styles = mLayer->conditionalStyles()->fieldStyles( mFieldCombo->currentField() );
144 }
145 if ( rowRadio->isChecked() )
146 {
147 styles = mLayer->conditionalStyles()->rowStyles();
148 }
149 return styles;
150}
151
152void QgsFieldConditionalFormatWidget::addNewRule()
153{
155}
156
158{
159}
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::reloadStyles()
191{
192 mModel->clear();
193
194 const auto constGetStyles = getStyles();
195
196 const QSize size( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 10, Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 2 );
197
198 listView->setIconSize( size );
199
200 for ( const QgsConditionalStyle &style : constGetStyles )
201 {
202 QStandardItem *item = new QStandardItem( style.displayText() );
203 item->setIcon( QIcon( style.renderPreview( size ) ) );
204 mModel->appendRow( item );
205 }
206}
207
208void QgsFieldConditionalFormatWidget::fieldChanged( const QString &fieldName )
209{
210 Q_UNUSED( fieldName )
211 reloadStyles();
212}
213
214void QgsFieldConditionalFormatWidget::deleteCurrentRule()
215{
216 if ( !mEditing )
217 return;
218
219 QList<QgsConditionalStyle> styles = getStyles();
220 styles.removeAt( mEditIndex );
221 QString fieldName;
222 if ( fieldRadio->isChecked() )
223 {
224 fieldName = mFieldCombo->currentField();
225 mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
226 }
227 if ( rowRadio->isChecked() )
228 {
229 mLayer->conditionalStyles()->setRowStyles( styles );
230 }
231
232 reloadStyles();
233 emit rulesUpdated( fieldName );
234}
235
237{
238}
239
240
241//
242// QgsEditConditionalFormatRuleWidget
243//
244
246 : QgsPanelWidget( parent )
247{
248 setupUi( this );
249
250 setPanelTitle( tr( "Edit Rule" ) );
251
252 btnBackgroundColor->setColor( QColor() );
253 btnTextColor->setColor( QColor() );
254 checkIcon->setChecked( false );
255 btnChangeIcon->setIcon( QIcon() );
256 btnBackgroundColor->setToNoColor();
257 btnTextColor->setToNoColor();
258
259 mFontBoldBtn->setChecked( false );
260 mFontItalicBtn->setChecked( false );
261 mFontStrikethroughBtn->setChecked( false );
262 mFontUnderlineBtn->setChecked( false );
263
264 const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
265 mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
266 mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
267 mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
268 mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
269 mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
270 mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
271 mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
272 mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
273
274 connect( mSaveRule, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleSaved );
275 connect( mCancelButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::canceled );
276 connect( mDeleteButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleDeleted );
277
278 connect( btnBuildExpression, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::setExpression );
279 connect( mPresetsList, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditConditionalFormatRuleWidget::presetSet );
280
281 btnBackgroundColor->setAllowOpacity( true );
282 btnBackgroundColor->setShowNoColor( true );
283 btnTextColor->setAllowOpacity( true );
284 btnTextColor->setShowNoColor( true );
285 mPresetsModel = new QStandardItemModel( mPresetsList );
286 mPresetsList->setModel( mPresetsModel );
287
288 btnChangeIcon->setSymbolType( Qgis::SymbolType::Marker );
289 btnChangeIcon->setSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
290 connect( checkIcon, &QCheckBox::toggled, btnChangeIcon, &QWidget::setEnabled );
291}
292
294{
295 mLayer = layer;
296}
297
299{
300 mRuleEdit->setText( style.rule() );
301 mNameEdit->setText( style.name() );
302 setFormattingFromStyle( style );
303}
304
306{
308
309 style.setRule( mRuleEdit->text() );
310 style.setName( mNameEdit->text() );
311
312 const QColor backColor = btnBackgroundColor->color();
313 const QColor fontColor = btnTextColor->color();
314
315 QFont font = mFontFamilyCmbBx->currentFont();
316 font.setBold( mFontBoldBtn->isChecked() );
317 font.setItalic( mFontItalicBtn->isChecked() );
318 font.setStrikeOut( mFontStrikethroughBtn->isChecked() );
319 font.setUnderline( mFontUnderlineBtn->isChecked() );
320 style.setFont( font );
321 style.setBackgroundColor( backColor );
322 style.setTextColor( fontColor );
323 if ( checkIcon->isChecked() )
324 {
325 style.setSymbol( btnChangeIcon->clonedSymbol< QgsMarkerSymbol >() );
326 }
327 else
328 {
329 style.setSymbol( nullptr );
330 }
331 return style;
332}
333
334void QgsEditConditionalFormatRuleWidget::setExpression()
335{
337 context.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "value" ), 0, true ) );
338 context.setHighlightedVariables( QStringList() << QStringLiteral( "value" ) );
339
340 QgsExpressionBuilderDialog dlg( mLayer, mRuleEdit->text(), this, QStringLiteral( "generic" ), context );
341 dlg.setWindowTitle( tr( "Conditional Style Rule Expression" ) );
342
343 if ( dlg.exec() )
344 {
345 const QString expression = dlg.expressionBuilder()->expressionText();
346 mRuleEdit->setText( expression );
347 }
348}
349
350void QgsEditConditionalFormatRuleWidget::presetSet( int index )
351{
352 if ( index == -1 || mPresets.isEmpty() )
353 return;
354
355 const int styleIndex = mPresetsList->currentData( Qt::UserRole + 1 ).toInt();
356 const QgsConditionalStyle style = mPresets.at( styleIndex );
357 setFormattingFromStyle( style );
358}
359
360void QgsEditConditionalFormatRuleWidget::setFormattingFromStyle( const QgsConditionalStyle &style )
361{
362 btnBackgroundColor->setColor( style.backgroundColor() );
363 btnTextColor->setColor( style.textColor() );
364 if ( auto *lSymbol = style.symbol() )
365 {
366 btnChangeIcon->setSymbol( lSymbol->clone() );
367 checkIcon->setChecked( true );
368 }
369 else
370 {
371 checkIcon->setChecked( false );
372 }
373 const QFont font = style.font();
374 mFontBoldBtn->setChecked( font.bold() );
375 mFontItalicBtn->setChecked( font.italic() );
376 mFontStrikethroughBtn->setChecked( font.strikeOut() );
377 mFontUnderlineBtn->setChecked( font.underline() );
378 mFontFamilyCmbBx->setCurrentFont( font );
379}
380
381void QgsEditConditionalFormatRuleWidget::setPresets( const QList<QgsConditionalStyle> &styles )
382{
383 mPresets.clear();
384 mPresetsModel->clear();
385 QStandardItem *item = new QStandardItem( QString() );
386 mPresetsModel->appendRow( item );
387 int i = 0;
388 for ( const QgsConditionalStyle &style : styles )
389 {
390 if ( style.isValid() )
391 {
392 QStandardItem *item = new QStandardItem( QStringLiteral( "abc - 123" ) );
393 if ( style.validBackgroundColor() )
394 item->setBackground( style.backgroundColor() );
395 if ( style.validTextColor() )
396 item->setForeground( style.textColor() );
397 if ( style.symbol() )
398 item->setIcon( style.icon() );
399 item->setFont( style.font() );
400 item->setData( i, Qt::UserRole + 1 );
401 mPresetsModel->appendRow( item );
402 mPresets.append( style );
403 i++;
404 }
405 }
406 mPresetsList->setCurrentIndex( 0 );
407}
408
410{
411 mRuleEdit->setText( rule );
412}
413
414bool QgsEditConditionalFormatRuleWidget::isCustomSet()
415{
416 return ( btnBackgroundColor->color().isValid()
417 || btnTextColor->color().isValid()
418 || mFontButtons->checkedId() != -1 );
419}
@ Marker
Marker symbol.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:2173
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.
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.
QgsEditConditionalFormatRuleWidget(QWidget *parent SIP_TRANSFERTHIS=nullptr)
Constructor for QgsFieldConditionalFormatWidget, with the specified parent widget.
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 SIP_TRANSFERTHIS=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 reset() SIP_DEPRECATED
Resets the formatting options to their default state.
Q_DECL_DEPRECATED void viewRules() SIP_DEPRECATED
Switches the widget to the rules page.
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.
Q_DECL_DEPRECATED void loadStyle(const QgsConditionalStyle &style) SIP_DEPRECATED
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(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:673
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.