QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
26 //
27 // QgsFieldConditionalFormatWidget
28 //
29 
31  : QgsPanelWidget( parent )
32 {
33  setupUi( this );
34  setPanelTitle( tr( "Conditional Styles" ) );
35  connect( mFieldCombo, &QgsFieldComboBox::fieldChanged, this, &QgsFieldConditionalFormatWidget::fieldChanged );
36  connect( fieldRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::reloadStyles );
37  connect( rowRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::reloadStyles );
38  connect( mNewButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::addNewRule );
39  connect( listView, &QAbstractItemView::clicked, this, &QgsFieldConditionalFormatWidget::ruleClicked );
40  mModel = new QStandardItemModel( listView );
41  listView->setModel( mModel );
42 
43  connect( fieldRadio, &QRadioButton::toggled, mFieldCombo, &QWidget::setEnabled );
44 
45  mPresets = defaultPresets();
46 }
47 
49 {
50  mLayer = layer;
51  mFieldCombo->setLayer( layer );
52  mFieldCombo->setCurrentIndex( 0 );
53 }
54 
55 void QgsFieldConditionalFormatWidget::ruleClicked( const QModelIndex &index )
56 {
57  QList<QgsConditionalStyle> styles = getStyles();
58  QgsConditionalStyle style = styles.at( index.row() );
59  editStyle( index.row(), style );
60 }
61 
63 {
64  mEditIndex = editIndex;
65  mEditing = editIndex >= 0;
66  mPanelHandled = false;
67 
69  ruleWidget->setLayer( mLayer );
70  ruleWidget->setPresets( mPresets );
71  ruleWidget->loadStyle( style );
72  ruleWidget->setDockMode( true );
73 
74  if ( fieldRadio->isChecked() )
75  {
76  ruleWidget->setRule( QStringLiteral( "@value " ) );
77  }
78 
79  connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::panelAccepted, this, [ = ]
80  {
81  if ( mPanelHandled )
82  {
83  // already handled the result of the panel, and the panel is being dismissed as a result
84  // of an already dealt with action
85  return;
86  }
87 
88  QList<QgsConditionalStyle> styles = getStyles();
89  if ( mEditing )
90  {
91  styles.replace( mEditIndex, ruleWidget->currentStyle() );
92  }
93  else
94  {
95  styles.append( ruleWidget->currentStyle() );
96  }
97 
98  QString fieldName;
99  if ( fieldRadio->isChecked() )
100  {
101  fieldName = mFieldCombo->currentField();
102  mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
103  }
104  if ( rowRadio->isChecked() )
105  {
106  mLayer->conditionalStyles()->setRowStyles( styles );
107  }
108  reloadStyles();
109  emit rulesUpdated( fieldName );
110  } );
111 
112  connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleSaved, this, [ = ]
113  {
114  ruleWidget->acceptPanel();
115  } );
116 
117  connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::canceled, this, [ = ]
118  {
119  mPanelHandled = true;
120  ruleWidget->acceptPanel();
121  } );
122 
123  connect( ruleWidget, &QgsEditConditionalFormatRuleWidget::ruleDeleted, this, [ = ]
124  {
125  deleteCurrentRule();
126  mPanelHandled = true;
127  ruleWidget->acceptPanel();
128  } );
129  showPanel( ruleWidget );
130 }
131 
133 {
134 }
135 
136 QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
137 {
138  QList<QgsConditionalStyle> styles;
139  if ( fieldRadio->isChecked() )
140  {
141  styles = mLayer->conditionalStyles()->fieldStyles( mFieldCombo->currentField() );
142  }
143  if ( rowRadio->isChecked() )
144  {
145  styles = mLayer->conditionalStyles()->rowStyles();
146  }
147  return styles;
148 }
149 
150 void QgsFieldConditionalFormatWidget::addNewRule()
151 {
153 }
154 
156 {
157 }
158 
159 void QgsFieldConditionalFormatWidget::setPresets( const QList<QgsConditionalStyle> &styles )
160 {
161  mPresets = styles;
162 }
163 
165 {
166  QList<QgsConditionalStyle> styles;
168  style.setBackgroundColor( QColor( 154, 216, 113 ) );
169  styles.append( style );
170  style = QgsConditionalStyle();
171  style.setBackgroundColor( QColor( 251, 193, 78 ) );
172  styles.append( style );
173  style = QgsConditionalStyle();
174  style.setBackgroundColor( QColor( 251, 154, 153 ) );
175  styles.append( style );
176  style = QgsConditionalStyle();
177  style.setTextColor( QColor( 154, 216, 113 ) );
178  styles.append( style );
179  style = QgsConditionalStyle();
180  style.setTextColor( QColor( 251, 193, 78 ) );
181  styles.append( style );
182  style = QgsConditionalStyle();
183  style.setTextColor( QColor( 251, 154, 153 ) );
184  styles.append( style );
185  return styles;
186 }
187 
188 void QgsFieldConditionalFormatWidget::reloadStyles()
189 {
190  mModel->clear();
191 
192  const auto constGetStyles = getStyles();
193 
194  const QSize size( Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 10, Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 2 );
195  listView->setIconSize( size );
196 
197  for ( const QgsConditionalStyle &style : constGetStyles )
198  {
199  QStandardItem *item = new QStandardItem( style.displayText() );
200  item->setIcon( QIcon( style.renderPreview( size ) ) );
201  mModel->appendRow( item );
202  }
203 }
204 
205 void QgsFieldConditionalFormatWidget::fieldChanged( const QString &fieldName )
206 {
207  Q_UNUSED( fieldName )
208  reloadStyles();
209 }
210 
211 void QgsFieldConditionalFormatWidget::deleteCurrentRule()
212 {
213  if ( !mEditing )
214  return;
215 
216  QList<QgsConditionalStyle> styles = getStyles();
217  styles.removeAt( mEditIndex );
218  QString fieldName;
219  if ( fieldRadio->isChecked() )
220  {
221  fieldName = mFieldCombo->currentField();
222  mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
223  }
224  if ( rowRadio->isChecked() )
225  {
226  mLayer->conditionalStyles()->setRowStyles( styles );
227  }
228 
229  reloadStyles();
230  emit rulesUpdated( fieldName );
231 }
232 
234 {
235 }
236 
237 
238 //
239 // QgsEditConditionalFormatRuleWidget
240 //
241 
243  : QgsPanelWidget( parent )
244 {
245  setupUi( this );
246 
247  setPanelTitle( tr( "Edit Rule" ) );
248 
249  btnBackgroundColor->setColor( QColor() );
250  btnTextColor->setColor( QColor() );
251  checkIcon->setChecked( false );
252  btnChangeIcon->setIcon( QIcon() );
253  btnBackgroundColor->setToNoColor();
254  btnTextColor->setToNoColor();
255 
256  mFontBoldBtn->setChecked( false );
257  mFontItalicBtn->setChecked( false );
258  mFontStrikethroughBtn->setChecked( false );
259  mFontUnderlineBtn->setChecked( false );
260 
261  const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
262  mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
263  mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
264  mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
265  mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
266  mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
267  mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
268  mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
269  mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
270 
271  connect( mSaveRule, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleSaved );
272  connect( mCancelButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::canceled );
273  connect( mDeleteButton, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::ruleDeleted );
274 
275  connect( btnBuildExpression, &QAbstractButton::clicked, this, &QgsEditConditionalFormatRuleWidget::setExpression );
276  connect( mPresetsList, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditConditionalFormatRuleWidget::presetSet );
277 
278  btnBackgroundColor->setAllowOpacity( true );
279  btnBackgroundColor->setShowNoColor( true );
280  btnTextColor->setAllowOpacity( true );
281  btnTextColor->setShowNoColor( true );
282  mPresetsModel = new QStandardItemModel( mPresetsList );
283  mPresetsList->setModel( mPresetsModel );
284 
285  btnChangeIcon->setSymbolType( QgsSymbol::Marker );
286  btnChangeIcon->setSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
287  connect( checkIcon, &QCheckBox::toggled, btnChangeIcon, &QWidget::setEnabled );
288 }
289 
291 {
292  mLayer = layer;
293 }
294 
296 {
297  mRuleEdit->setText( style.rule() );
298  mNameEdit->setText( style.name() );
299  setFormattingFromStyle( style );
300 }
301 
303 {
304  QgsConditionalStyle style;
305 
306  style.setRule( mRuleEdit->text() );
307  style.setName( mNameEdit->text() );
308 
309  QColor backColor = btnBackgroundColor->color();
310  QColor fontColor = btnTextColor->color();
311 
312  QFont font = mFontFamilyCmbBx->currentFont();
313  font.setBold( mFontBoldBtn->isChecked() );
314  font.setItalic( mFontItalicBtn->isChecked() );
315  font.setStrikeOut( mFontStrikethroughBtn->isChecked() );
316  font.setUnderline( mFontUnderlineBtn->isChecked() );
317  style.setFont( font );
318  style.setBackgroundColor( backColor );
319  style.setTextColor( fontColor );
320  if ( checkIcon->isChecked() )
321  {
322  style.setSymbol( btnChangeIcon->clonedSymbol< QgsMarkerSymbol >() );
323  }
324  else
325  {
326  style.setSymbol( nullptr );
327  }
328  return style;
329 }
330 
331 void QgsEditConditionalFormatRuleWidget::setExpression()
332 {
334  context.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "value" ), 0, true ) );
335  context.setHighlightedVariables( QStringList() << QStringLiteral( "value" ) );
336 
337  QgsExpressionBuilderDialog dlg( mLayer, mRuleEdit->text(), this, QStringLiteral( "generic" ), context );
338  dlg.setWindowTitle( tr( "Conditional Style Rule Expression" ) );
339 
340  if ( dlg.exec() )
341  {
342  QString expression = dlg.expressionBuilder()->expressionText();
343  mRuleEdit->setText( expression );
344  }
345 }
346 
347 void QgsEditConditionalFormatRuleWidget::presetSet( int index )
348 {
349  if ( index == -1 || mPresets.isEmpty() )
350  return;
351 
352  const int styleIndex = mPresetsList->currentData( Qt::UserRole + 1 ).toInt();
353  QgsConditionalStyle style = mPresets.at( styleIndex );
354  setFormattingFromStyle( style );
355 }
356 
357 void QgsEditConditionalFormatRuleWidget::setFormattingFromStyle( const QgsConditionalStyle &style )
358 {
359  btnBackgroundColor->setColor( style.backgroundColor() );
360  btnTextColor->setColor( style.textColor() );
361  if ( style.symbol() )
362  {
363  btnChangeIcon->setSymbol( style.symbol()->clone() );
364  checkIcon->setChecked( true );
365  }
366  else
367  {
368  checkIcon->setChecked( false );
369  }
370  QFont font = style.font();
371  mFontBoldBtn->setChecked( font.bold() );
372  mFontItalicBtn->setChecked( font.italic() );
373  mFontStrikethroughBtn->setChecked( font.strikeOut() );
374  mFontUnderlineBtn->setChecked( font.underline() );
375  mFontFamilyCmbBx->setCurrentFont( font );
376 }
377 
378 void QgsEditConditionalFormatRuleWidget::setPresets( const QList<QgsConditionalStyle> &styles )
379 {
380  mPresets.clear();
381  mPresetsModel->clear();
382  QStandardItem *item = new QStandardItem( QString() );
383  mPresetsModel->appendRow( item );
384  int i = 0;
385  for ( const QgsConditionalStyle &style : styles )
386  {
387  if ( style.isValid() )
388  {
389  QStandardItem *item = new QStandardItem( QStringLiteral( "abc - 123" ) );
390  if ( style.validBackgroundColor() )
391  item->setBackground( style.backgroundColor() );
392  if ( style.validTextColor() )
393  item->setForeground( style.textColor() );
394  if ( style.symbol() )
395  item->setIcon( style.icon() );
396  item->setFont( style.font() );
397  item->setData( i, Qt::UserRole + 1 );
398  mPresetsModel->appendRow( item );
399  mPresets.append( style );
400  i++;
401  }
402  }
403  mPresetsList->setCurrentIndex( 0 );
404 }
405 
407 {
408  mRuleEdit->setText( rule );
409 }
410 
411 bool QgsEditConditionalFormatRuleWidget::isCustomSet()
412 {
413  return ( btnBackgroundColor->color().isValid()
414  || btnTextColor->color().isValid()
415  || mFontButtons->checkedId() != -1 );
416 }
QString name() const
The name of the style.
static QList< QgsConditionalStyle > defaultPresets()
Returns a list of the default presets.
void setName(const QString &value)
Set the name of the style.
A widget for customizing an individual conditional formatting rule.
Single variable definition for use within a QgsExpressionContextScope.
void setPresets(const QList< QgsConditionalStyle > &styles)
Sets the preset styles that can be used for quick pick.
Q_DECL_DEPRECATED void reset() SIP_DEPRECATED
Resets the formatting options to their default state.
void setPresets(const QList< QgsConditionalStyle > &styles)
Sets the preset styles that can be used for quick pick.
Q_DECL_DEPRECATED void viewRules() SIP_DEPRECATED
Switches the widget to the rules page.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:154
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly...
void setRule(const QString &rule)
Sets the current expression rule to show in the widget.
void setRule(const QString &value)
Set the rule for the style.
QgsExpressionBuilderWidget * expressionBuilder()
The builder widget that is used by the dialog.
void setLayer(QgsVectorLayer *layer)
Sets the vector layer associated with the widget.
bool validBackgroundColor() const
Check if the background color is valid for render.
QPixmap icon() const
The icon set for style generated from the set symbol.
Base class for any widget that can be shown as a inline panel.
void canceled()
Emitted when a user has opted to cancel the rule modification.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:860
QgsConditionalStyle currentStyle() const
Returns the current style defined by the widget.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void ruleSaved()
Emitted when a user has opted to save the current rule.
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:297
Conditional styling for a rule.
void acceptPanel()
Accept the panel.
void loadStyle(const QgsConditionalStyle &style)
Sets the widget to match the settings from the specified style.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool isValid() const
isValid Check if this rule is valid.
void setLayer(QgsVectorLayer *layer)
Sets the vector layer associated with the widget.
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QColor backgroundColor() const
The background color for style.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
void setBackgroundColor(const QColor &value)
Set the background color for the style.
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName) const
Returns the conditional styles set for the field with matching fieldName.
void setFont(const QFont &value)
Set the font for the style.
Marker symbol.
Definition: qgssymbol.h:85
QColor textColor() const
The text color set for style.
void setSymbol(QgsSymbol *value)
Set the icon for the style.
QgsEditConditionalFormatRuleWidget(QWidget *parent SIP_TRANSFERTHIS=nullptr)
Constructor for QgsFieldConditionalFormatWidget, with the specified parent widget.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
bool validTextColor() const
Check if the text color is valid for render.
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 ruleDeleted()
Emitted when a user has opted to deleted the current rule.
Q_DECL_DEPRECATED void loadStyle(const QgsConditionalStyle &style) SIP_DEPRECATED
QString expressionText()
Gets the expression string that has been set in the expression area.
QgsSymbol * symbol() const
The symbol used to generate the icon for the style.
QgsFieldConditionalFormatWidget(QWidget *parent SIP_TRANSFERTHIS=nullptr)
Constructor for QgsFieldConditionalFormatWidget.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user...
QFont font() const
The font for the style.
void setRowStyles(const QgsConditionalStyles &styles)
Sets the conditional styles that apply to full rows of data in the attribute table.
void setFieldStyles(const QString &fieldName, const QList< QgsConditionalStyle > &styles)
Set the conditional styles for a field, with the specified fieldName.
Represents a vector layer which manages a vector based data sets.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QString rule() const
The condition rule set for the style.
A generic dialog for building expression strings.
QgsConditionalStyles rowStyles() const
Returns a list of row styles associated with the layer.
void rulesUpdated(const QString &fieldName)
Emitted when the conditional styling rules are updated.
void setTextColor(const QColor &value)
Set the text color for the style.