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