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