QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 
26  : QWidget( parent )
27 {
28  setupUi( this );
29  mDeleteButton->hide();
30  connect( mFieldCombo, &QgsFieldComboBox::fieldChanged, this, &QgsFieldConditionalFormatWidget::fieldChanged );
31  connect( fieldRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::reloadStyles );
32  connect( rowRadio, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::reloadStyles );
33  connect( mNewButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::addNewRule );
34  connect( mSaveRule, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::saveRule );
35  connect( mCancelButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::cancelRule );
36  connect( mDeleteButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::deleteRule );
37  connect( listView, &QAbstractItemView::clicked, this, &QgsFieldConditionalFormatWidget::ruleClicked );
38  connect( btnBuildExpression, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::setExpression );
39  connect( mPresetsList, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFieldConditionalFormatWidget::presetSet );
40  btnBackgroundColor->setAllowOpacity( true );
41  btnBackgroundColor->setShowNoColor( true );
42  btnTextColor->setAllowOpacity( true );
43  btnTextColor->setShowNoColor( true );
44  mPresetsModel = new QStandardItemModel( listView );
45  mModel = new QStandardItemModel( listView );
46  listView->setModel( mModel );
47  mPresetsList->setModel( mPresetsModel );
48  btnChangeIcon->setSymbolType( QgsSymbol::Marker );
49  btnChangeIcon->setSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
50 
52 }
53 
54 void QgsFieldConditionalFormatWidget::setExpression()
55 {
57  context.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "value" ), 0, true ) );
58  context.setHighlightedVariables( QStringList() << QStringLiteral( "value" ) );
59 
60  QgsExpressionBuilderDialog dlg( mLayer, mRuleEdit->text(), this, QStringLiteral( "generic" ), context );
61  dlg.setWindowTitle( tr( "Conditional Style Rule Expression" ) );
62 
63  if ( dlg.exec() )
64  {
65  QString expression = dlg.expressionBuilder()->expressionText();
66  mRuleEdit->setText( expression );
67  }
68 }
69 
70 void QgsFieldConditionalFormatWidget::presetSet( int index )
71 {
72  if ( index == -1 || mPresets.isEmpty() )
73  return;
74 
75  QgsConditionalStyle style = mPresets.at( index );
76  setFormattingFromStyle( style );
77 }
78 
80 {
81  mLayer = layer;
82  mFieldCombo->setLayer( layer );
83  mFieldCombo->setCurrentIndex( 0 );
84 }
85 
86 void QgsFieldConditionalFormatWidget::ruleClicked( const QModelIndex &index )
87 {
88  QList<QgsConditionalStyle> styles = getStyles();
89  QgsConditionalStyle style = styles.at( index.row() );
90  editStyle( index.row(), style );
91 }
92 
94 {
95  pages->setCurrentIndex( 1 );
96  mEditIndex = editIndex;
97  mEditing = true;
98  mDeleteButton->show();
99  loadStyle( style );
100 }
101 
103 {
104  mRuleEdit->setText( style.rule() );
105  mNameEdit->setText( style.name() );
106  setFormattingFromStyle( style );
107 }
108 void QgsFieldConditionalFormatWidget::setFormattingFromStyle( const QgsConditionalStyle &style )
109 {
110  btnBackgroundColor->setColor( style.backgroundColor() );
111  btnTextColor->setColor( style.textColor() );
112  if ( style.symbol() )
113  {
114  btnChangeIcon->setSymbol( style.symbol()->clone() );
115  checkIcon->setChecked( true );
116  }
117  else
118  {
119  checkIcon->setChecked( false );
120  }
121  QFont font = style.font();
122  mFontBoldBtn->setChecked( font.bold() );
123  mFontItalicBtn->setChecked( font.italic() );
124  mFontStrikethroughBtn->setChecked( font.strikeOut() );
125  mFontUnderlineBtn->setChecked( font.underline() );
126  mFontFamilyCmbBx->setFont( font );
127 }
128 
129 QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::getStyles()
130 {
131  QList<QgsConditionalStyle> styles;
132  if ( fieldRadio->isChecked() )
133  {
134  styles = mLayer->conditionalStyles()->fieldStyles( mFieldCombo->currentField() );
135  }
136  if ( rowRadio->isChecked() )
137  {
138  styles = mLayer->conditionalStyles()->rowStyles();
139  }
140  return styles;
141 }
142 
143 void QgsFieldConditionalFormatWidget::deleteRule()
144 {
145  QList<QgsConditionalStyle> styles = getStyles();
146  styles.removeAt( mEditIndex );
147  QString fieldName;
148  if ( fieldRadio->isChecked() )
149  {
150  fieldName = mFieldCombo->currentField();
151  mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
152  }
153  if ( rowRadio->isChecked() )
154  {
155  mLayer->conditionalStyles()->setRowStyles( styles );
156  }
157 
158  pages->setCurrentIndex( 0 );
159  reloadStyles();
160  emit rulesUpdated( fieldName );
161 }
162 
163 void QgsFieldConditionalFormatWidget::cancelRule()
164 {
165  pages->setCurrentIndex( 0 );
166  reloadStyles();
167  reset();
168 }
169 
170 void QgsFieldConditionalFormatWidget::addNewRule()
171 {
172  pages->setCurrentIndex( 1 );
173  reset();
174 }
175 
177 {
178  mNameEdit->clear();
179  mRuleEdit->clear();
180  if ( fieldRadio->isChecked() )
181  {
182  mRuleEdit->setText( QStringLiteral( "@value " ) );
183  }
184  btnBackgroundColor->setColor( QColor() );
185  btnTextColor->setColor( QColor() );
186  mPresetsList->setCurrentIndex( 0 );
187  mDeleteButton->hide();
188  mEditing = false;
189  checkIcon->setChecked( false );
190  btnChangeIcon->setIcon( QIcon() );
191  btnBackgroundColor->setToNoColor();
192  btnTextColor->setToNoColor();
193 
194  mFontBoldBtn->setChecked( false );
195  mFontItalicBtn->setChecked( false );
196  mFontStrikethroughBtn->setChecked( false );
197  mFontUnderlineBtn->setChecked( false );
198 }
199 
200 
201 void QgsFieldConditionalFormatWidget::setPresets( const QList<QgsConditionalStyle> &styles )
202 {
203  mPresets.clear();
204  mPresetsModel->clear();
205  const auto constStyles = styles;
206  for ( const QgsConditionalStyle &style : constStyles )
207  {
208  if ( style.isValid() )
209  {
210  QStandardItem *item = new QStandardItem( QStringLiteral( "abc - 123" ) );
211  if ( style.validBackgroundColor() )
212  item->setBackground( style.backgroundColor() );
213  if ( style.validTextColor() )
214  item->setForeground( style.textColor() );
215  if ( style.symbol() )
216  item->setIcon( style.icon() );
217  item->setFont( style.font() );
218  mPresetsModel->appendRow( item );
219  mPresets.append( style );
220  }
221  }
222  mPresetsList->setCurrentIndex( 0 );
223 }
224 
225 QList<QgsConditionalStyle> QgsFieldConditionalFormatWidget::defaultPresets() const
226 {
227  QList<QgsConditionalStyle> styles;
229  style.setBackgroundColor( QColor( 154, 216, 113 ) );
230  styles.append( style );
231  style = QgsConditionalStyle();
232  style.setBackgroundColor( QColor( 251, 193, 78 ) );
233  styles.append( style );
234  style = QgsConditionalStyle();
235  style.setBackgroundColor( QColor( 251, 154, 153 ) );
236  styles.append( style );
237  style = QgsConditionalStyle();
238  style.setTextColor( QColor( 154, 216, 113 ) );
239  styles.append( style );
240  style = QgsConditionalStyle();
241  style.setTextColor( QColor( 251, 193, 78 ) );
242  styles.append( style );
243  style = QgsConditionalStyle();
244  style.setTextColor( QColor( 251, 154, 153 ) );
245  styles.append( style );
246  return styles;
247 }
248 
249 void QgsFieldConditionalFormatWidget::saveRule()
250 {
251  QList<QgsConditionalStyle> styles = getStyles();
252 
254 
255  style.setRule( mRuleEdit->text() );
256  style.setName( mNameEdit->text() );
257 
258  QColor backColor = btnBackgroundColor->color();
259  QColor fontColor = btnTextColor->color();
260 
261  QFont font = mFontFamilyCmbBx->currentFont();
262  font.setBold( mFontBoldBtn->isChecked() );
263  font.setItalic( mFontItalicBtn->isChecked() );
264  font.setStrikeOut( mFontStrikethroughBtn->isChecked() );
265  font.setUnderline( mFontUnderlineBtn->isChecked() );
266  style.setFont( font );
267  style.setBackgroundColor( backColor );
268  style.setTextColor( fontColor );
269  if ( checkIcon->isChecked() )
270  {
271  style.setSymbol( btnChangeIcon->clonedSymbol< QgsMarkerSymbol >() );
272  }
273  else
274  {
275  style.setSymbol( nullptr );
276  }
277  if ( mEditing )
278  {
279  styles.replace( mEditIndex, style );
280  }
281  else
282  {
283  styles.append( style );
284  }
285 
286  QString fieldName;
287  if ( fieldRadio->isChecked() )
288  {
289  fieldName = mFieldCombo->currentField();
290  mLayer->conditionalStyles()->setFieldStyles( fieldName, styles );
291  }
292  if ( rowRadio->isChecked() )
293  {
294  mLayer->conditionalStyles()->setRowStyles( styles );
295  }
296  pages->setCurrentIndex( 0 );
297  reloadStyles();
298  emit rulesUpdated( fieldName );
299  reset();
300 }
301 
302 void QgsFieldConditionalFormatWidget::reloadStyles()
303 {
304  mModel->clear();
305 
306  const auto constGetStyles = getStyles();
307  for ( const QgsConditionalStyle &style : constGetStyles )
308  {
309  QStandardItem *item = new QStandardItem( style.displayText() );
310  item->setIcon( QIcon( style.renderPreview() ) );
311  mModel->appendRow( item );
312  }
313 }
314 
315 void QgsFieldConditionalFormatWidget::fieldChanged( const QString &fieldName )
316 {
317  Q_UNUSED( fieldName )
318  reloadStyles();
319 }
320 
322 {
323  pages->setCurrentIndex( 0 );
324 }
325 
326 bool QgsFieldConditionalFormatWidget::isCustomSet()
327 {
328  return ( btnBackgroundColor->color().isValid()
329  || btnTextColor->color().isValid()
330  || mFontButtons->checkedId() != -1 );
331 }
QString name() const
The name of the style.
void setName(const QString &value)
Set the name of the style.
Single variable definition for use within a QgsExpressionContextScope.
void setPresets(const QList< QgsConditionalStyle > &styles)
Set the presets that can be used for quick pick.
QList< QgsConditionalStyle > defaultPresets() const
The default presets for the widget.
void setRule(const QString &value)
Set the rule for the style.
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName)
Returns the conditional styles set for the field UI properties.
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.
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:766
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
QList< QgsConditionalStyle > rowStyles()
void viewRules()
Switches the widget to the rules page.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void reset()
Resets the formatting options to their default state.
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:293
Conditional styling for a rule.
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 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.
void setFont(const QFont &value)
Set the font for the style.
Marker symbol.
Definition: qgssymbol.h:85
void setRowStyles(const QList< QgsConditionalStyle > &styles)
Set the conditional styles that apply to full rows of data in the attribute table.
QColor textColor() const
The text color set for style.
QPixmap renderPreview() const
Render a preview icon of the rule.
void setSymbol(QgsSymbol *value)
Set the icon for the style.
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.
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.
QString displayText() const
The name of 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 setFieldStyles(const QString &fieldName, const QList< QgsConditionalStyle > &styles)
Set the conditional styles for the field UI properties.
Represents a vector layer which manages a vector based data sets.
QString rule() const
The condition rule set for the style.
A generic dialog for building expression strings.
void loadStyle(const QgsConditionalStyle &style)
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.