QGIS API Documentation  3.2.0-Bonn (bc43194)
qgssymbollevelsdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbollevelsdialog.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk 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  ***************************************************************************/
15 
16 #include "qgssymbollevelsdialog.h"
17 
18 #include "qgssymbollayerutils.h"
19 #include "qgssymbollayer.h"
20 #include "qgssymbol.h"
21 #include "qgssettings.h"
22 
23 #include <QTableWidgetItem>
24 #include <QItemDelegate>
25 #include <QSpinBox>
26 #include <QDialogButtonBox>
27 
28 
30 
31 QgsSymbolLevelsWidget::QgsSymbolLevelsWidget( QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent )
32  : QgsPanelWidget( parent )
33  , mRenderer( renderer )
34  , mForceOrderingEnabled( false )
35 {
36  setupUi( this );
37 
38  tableLevels->setItemDelegate( new SpinBoxDelegate( this ) );
39 
40  chkEnable->setChecked( usingSymbolLevels );
41 
42  connect( chkEnable, &QAbstractButton::clicked, this, &QgsSymbolLevelsWidget::updateUi );
43 
44  if ( mRenderer )
45  {
46  // only consider entries with symbols
47  Q_FOREACH ( const QgsLegendSymbolItem &item, mRenderer->legendSymbolItems() )
48  {
49  if ( item.symbol() )
50  mList << item;
51  }
52  }
53 
54  int maxLayers = 0;
55  tableLevels->setRowCount( mList.count() );
56  for ( int i = 0; i < mList.count(); i++ )
57  {
58  QgsSymbol *sym = mList.at( i ).symbol();
59 
60  // set icons for the rows
61  QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( sym, QSize( 16, 16 ) );
62  tableLevels->setVerticalHeaderItem( i, new QTableWidgetItem( icon, QString() ) );
63 
64  // find out max. number of layers per symbol
65  int layers = sym->symbolLayerCount();
66  if ( layers > maxLayers )
67  maxLayers = layers;
68  }
69 
70  tableLevels->setColumnCount( maxLayers + 1 );
71  tableLevels->setHorizontalHeaderItem( 0, new QTableWidgetItem( QString() ) );
72  for ( int i = 0; i < maxLayers; i++ )
73  {
74  QString name = tr( "Layer %1" ).arg( i );
75  tableLevels->setHorizontalHeaderItem( i + 1, new QTableWidgetItem( name ) );
76  }
77 
78  mMaxLayers = maxLayers;
79 
80  updateUi();
81 
82  if ( !usingSymbolLevels )
84 
85  populateTable();
86 
87  connect( tableLevels, &QTableWidget::cellChanged, this, &QgsSymbolLevelsWidget::renderingPassChanged );
88 }
89 
91 {
92  for ( int row = 0; row < mList.count(); row++ )
93  {
94  QgsSymbol *sym = mList.at( row ).symbol();
95  QString label = mList.at( row ).label();
96  QTableWidgetItem *itemLabel = new QTableWidgetItem( label );
97  itemLabel->setFlags( itemLabel->flags() ^ Qt::ItemIsEditable );
98  tableLevels->setItem( row, 0, itemLabel );
99  for ( int layer = 0; layer < mMaxLayers; layer++ )
100  {
101  QTableWidgetItem *item = nullptr;
102  if ( layer >= sym->symbolLayerCount() )
103  {
104  item = new QTableWidgetItem();
105  item->setFlags( Qt::ItemFlags() );
106  }
107  else
108  {
109  QgsSymbolLayer *sl = sym->symbolLayer( layer );
111  item = new QTableWidgetItem( icon, QString::number( sl->renderingPass() ) );
112  }
113  tableLevels->setItem( row, layer + 1, item );
114  tableLevels->resizeColumnToContents( 0 );
115  }
116  }
117 
118 }
119 
120 void QgsSymbolLevelsWidget::updateUi()
121 {
122  tableLevels->setEnabled( chkEnable->isChecked() );
123  emit widgetChanged();
124 }
125 
127 {
128  for ( int i = 0; i < mList.count(); i++ )
129  {
130  QgsSymbol *sym = mList.at( i ).symbol();
131  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
132  {
133  mRenderer->setLegendSymbolItem( mList.at( i ).ruleKey(), sym->clone() );
134  }
135  }
136 
138 }
139 
141 {
142  for ( int i = 0; i < mList.count(); i++ )
143  {
144  QgsSymbol *sym = mList.at( i ).symbol();
145  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
146  {
147  sym->symbolLayer( layer )->setRenderingPass( layer );
148  }
149  }
150 }
151 
153 {
154  return chkEnable->isChecked();
155 }
156 
157 void QgsSymbolLevelsWidget::renderingPassChanged( int row, int column )
158 {
159  if ( row < 0 || row >= mList.count() )
160  return;
161  QgsSymbol *sym = mList.at( row ).symbol();
162  if ( column < 0 || column > sym->symbolLayerCount() )
163  return;
164  sym->symbolLayer( column - 1 )->setRenderingPass( tableLevels->item( row, column )->text().toInt() );
165 
166  emit widgetChanged();
167 }
168 
170 {
171  mForceOrderingEnabled = enabled;
172  if ( enabled )
173  {
174  chkEnable->setChecked( true );
175  chkEnable->hide();
176  }
177  else
178  chkEnable->show();
179 }
180 
181 QgsSymbolLevelsDialog::QgsSymbolLevelsDialog( QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent )
182  : QDialog( parent )
183 {
184  QVBoxLayout *vLayout = new QVBoxLayout();
185  mWidget = new QgsSymbolLevelsWidget( renderer, usingSymbolLevels );
186  vLayout->addWidget( mWidget );
187  QDialogButtonBox *bbox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
188  connect( bbox, &QDialogButtonBox::accepted, mWidget, &QgsSymbolLevelsWidget::apply );
189  connect( bbox, &QDialogButtonBox::accepted, this, &QgsSymbolLevelsDialog::accept );
190  connect( bbox, &QDialogButtonBox::rejected, this, &QgsSymbolLevelsDialog::reject );
191  connect( bbox, &QDialogButtonBox::helpRequested, this, &QgsSymbolLevelsDialog::showHelp );
192  vLayout->addWidget( bbox );
193  setLayout( vLayout );
194  setWindowTitle( tr( "Symbol Levels" ) );
195 }
196 
198 {
199  mWidget->setForceOrderingEnabled( enabled );
200 }
201 
202 void QgsSymbolLevelsDialog::showHelp()
203 {
204  QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#symbols-levels" ) );
205 }
206 
208 
209 QWidget *SpinBoxDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
210 {
211  QSpinBox *editor = new QSpinBox( parent );
212  editor->setMinimum( 0 );
213  editor->setMaximum( 999 );
214  return editor;
215 }
216 
217 void SpinBoxDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
218 {
219  int value = index.model()->data( index, Qt::EditRole ).toInt();
220  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
221  spinBox->setValue( value );
222 }
223 
224 void SpinBoxDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
225 {
226  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
227  spinBox->interpretText();
228  int value = spinBox->value();
229 
230  model->setData( index, value, Qt::EditRole );
231 }
232 
233 void SpinBoxDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & ) const
234 {
235  editor->setGeometry( option.rect );
236 }
237 
238 
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
QgsLegendSymbolList mList
void setRenderingPass(int renderingPass)
QgsSymbol * symbol() const
Returns associated symbol. May be null.
QgsSymbolLevelsWidget(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsWidget.
int mMaxLayers
maximal number of layers from all symbols
void setForceOrderingEnabled(bool enabled)
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:272
int symbolLayerCount() const
Returns total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:143
Base class for any widget that can be shown as a inline panel.
static QIcon symbolLayerPreviewIcon(QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
Draws a symbol layer preview to an icon.
int renderingPass() const
static QIcon symbolPreviewIcon(QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
A widget which allows the user to modify the rendering order of symbol layers.
void setForceOrderingEnabled(bool enabled)
Sets whether the level ordering is always forced on and hide the checkbox (used by rule-based rendere...
QgsSymbolLayer * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
Definition: qgssymbol.cpp:332
void widgetChanged()
Emitted when the widget state changes.
virtual void setLegendSymbolItem(const QString &key, QgsSymbol *symbol)
Sets the symbol to be used for a legend symbol item.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
void apply()
Apply button.
QgsFeatureRenderer * mRenderer
bool mForceOrderingEnabled
whether symbol layers always should be used (default false)
virtual QgsSymbol * clone() const =0
Gets a deep copy of this symbol.
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:35
QgsSymbolLevelsDialog(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsDialog.
bool usingLevels() const
Returns whether the level ordering is enabled.