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