QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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 <QString>
28
29#include "moc_qgsfieldconditionalformatwidget.cpp"
30
31using namespace Qt::StringLiterals;
32
33//
34// QgsFieldConditionalFormatWidget
35//
36
38 : QgsPanelWidget( parent )
39{
40 setupUi( this );
41 setPanelTitle( tr( "Conditional Styles" ) );
42 connect( mFieldCombo, &QgsFieldComboBox::fieldChanged, this, &QgsFieldConditionalFormatWidget::fieldChanged );
43 connect( fieldRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::typeChanged );
44 connect( rowRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::typeChanged );
45 connect( mNewButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::addNewRule );
46 connect( listView, &QAbstractItemView::clicked, this, &QgsFieldConditionalFormatWidget::ruleClicked );
47 mModel = new QStandardItemModel( listView );
48 listView->setModel( mModel );
49
50 connect( fieldRadio, &QRadioButton::toggled, mFieldCombo, &QWidget::setEnabled );
51
52 mPresets = defaultPresets();
53}
54
56{
57 mLayer = layer;
58 mFieldCombo->setLayer( layer );
59 mFieldCombo->setCurrentIndex( 0 );
60 fieldChanged( mFieldCombo->currentField() );
61}
62
63void QgsFieldConditionalFormatWidget::ruleClicked( const QModelIndex &index )
64{
65 const QList<QgsConditionalStyle> styles = getStyles();
66 const QgsConditionalStyle style = styles.at( index.row() );
67 editStyle( index.row(), style );
68}
69
71{
72 mEditIndex = editIndex;
73 mEditing = editIndex >= 0;
74 mPanelHandled = false;
75
77 ruleWidget->setLayer( mLayer );
78 ruleWidget->setPresets( mPresets );
79 ruleWidget->loadStyle( style );
80 ruleWidget->setDockMode( true );
81
82 if ( fieldRadio->isChecked() && style.rule().isEmpty() )
83 {
84 ruleWidget->setRule( u"@value "_s );
85 }
86
87 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::panelAccepted, this, [this, ruleWidget] {
88 if ( mPanelHandled )
89 {
90 // already handled the result of the panel, and the panel is being dismissed as a result
91 // of an already dealt with action
92 return;
93 }
94
95 QList<QgsConditionalStyle> styles = getStyles();
96 if ( mEditing )
97 {
98 styles.replace( mEditIndex, ruleWidget->currentStyle() );
99 }
100 else
101 {
102 styles.append( ruleWidget->currentStyle() );
103 }
104
105 QString fieldName;
106 if ( fieldRadio->isChecked() )
107 {
108 fieldName = mFieldCombo->currentField();
109 mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
110 }
111 else if ( rowRadio->isChecked() )
112 {
113 mLayer->conditionalStyles()->setRowStyles( styles );
114 }
115
116 reloadStyles();
117 emit rulesUpdated( fieldName );
118 } );
119
120 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleSaved, this, [ruleWidget] { ruleWidget->acceptPanel(); } );
121
122 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::canceled, this, [this, ruleWidget] {
123 mPanelHandled = true;
124 ruleWidget->acceptPanel();
125 } );
126
127 connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleDeleted, this, [this, ruleWidget] {
128 deleteCurrentRule();
129 mPanelHandled = true;
130 ruleWidget->acceptPanel();
131 } );
132 showPanel( ruleWidget );
133}
134
137
138QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
139{
140 QList<QgsConditionalStyle> styles;
141 if ( fieldRadio->isChecked() )
142 {
143 styles = mLayer->conditionalStyles()->fieldStyles( mFieldCombo->currentField() );
144 }
145 else if ( rowRadio->isChecked() )
146 {
147 styles = mLayer->conditionalStyles()->rowStyles();
148 }
149
150 return styles;
151}
152
153void QgsFieldConditionalFormatWidget::addNewRule()
154{
155 editStyle( -1, QgsConditionalStyle() );
156}
157
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
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( u"value"_s, 0, true ) );
342 context.setHighlightedVariables( QStringList() << u"value"_s );
343
344 QgsExpressionBuilderDialog dlg( mLayer, mRuleEdit->text(), this, u"generic"_s, 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( u"abc - 123"_s );
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}
@ Point
Points.
Definition qgis.h:380
@ Marker
Marker symbol.
Definition qgis.h:637
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6591
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.