QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 #include "qgsguiutils.h"
23 
24 #include <QTableWidgetItem>
25 #include <QItemDelegate>
26 #include <QSpinBox>
27 #include <QDialogButtonBox>
28 
29 
31 
32 QgsSymbolLevelsWidget::QgsSymbolLevelsWidget( QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent )
33  : QgsSymbolLevelsWidget( renderer->legendSymbolItems(), usingSymbolLevels, parent )
34 {
35  mRenderer = renderer;
36 }
37 
38 QgsSymbolLevelsWidget::QgsSymbolLevelsWidget( const QgsLegendSymbolList &symbols, bool usingSymbolLevels, QWidget *parent )
39  : QgsPanelWidget( parent )
40 {
41  setupUi( this );
42 
43  tableLevels->setItemDelegate( new SpinBoxDelegate( this ) );
44 
45  chkEnable->setChecked( usingSymbolLevels );
46 
47  connect( chkEnable, &QAbstractButton::clicked, this, &QgsSymbolLevelsWidget::updateUi );
48 
49  // only consider entries with symbols
50  for ( const QgsLegendSymbolItem &item : symbols )
51  {
52  if ( item.symbol() )
53  mLegendSymbols << item;
54  }
55 
56  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
57  int maxLayers = 0;
58  tableLevels->setRowCount( mLegendSymbols.count() );
59  for ( int i = 0; i < mLegendSymbols.count(); i++ )
60  {
61  QgsSymbol *sym = mLegendSymbols.at( i ).symbol();
62 
63  // set icons for the rows
64  QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( sym, QSize( iconSize, iconSize ) );
65  tableLevels->setVerticalHeaderItem( i, new QTableWidgetItem( icon, QString() ) );
66 
67  // find out max. number of layers per symbol
68  int layers = sym->symbolLayerCount();
69  if ( layers > maxLayers )
70  maxLayers = layers;
71  }
72 
73  tableLevels->setColumnCount( maxLayers + 1 );
74  tableLevels->setHorizontalHeaderItem( 0, new QTableWidgetItem( QString() ) );
75  for ( int i = 0; i < maxLayers; i++ )
76  {
77  QString name = tr( "Layer %1" ).arg( i );
78  tableLevels->setHorizontalHeaderItem( i + 1, new QTableWidgetItem( name ) );
79  }
80 
81  mMaxLayers = maxLayers;
82 
83  updateUi();
84 
85  if ( !usingSymbolLevels )
86  setDefaultLevels();
87 
88  populateTable();
89 
90  connect( tableLevels, &QTableWidget::cellChanged, this, &QgsSymbolLevelsWidget::renderingPassChanged );
91 }
92 
93 
94 void QgsSymbolLevelsWidget::populateTable()
95 {
96  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
97  for ( int row = 0; row < mLegendSymbols.count(); row++ )
98  {
99  QgsSymbol *sym = mLegendSymbols.at( row ).symbol();
100  const QString label = mLegendSymbols.at( row ).label();
101  QTableWidgetItem *itemLabel = new QTableWidgetItem( label );
102  itemLabel->setFlags( itemLabel->flags() ^ Qt::ItemIsEditable );
103  tableLevels->setItem( row, 0, itemLabel );
104  for ( int layer = 0; layer < mMaxLayers; layer++ )
105  {
106  QTableWidgetItem *item = nullptr;
107  if ( layer >= sym->symbolLayerCount() )
108  {
109  item = new QTableWidgetItem();
110  item->setFlags( Qt::ItemFlags() );
111  }
112  else
113  {
114  const QgsSymbolLayer *sl = sym->symbolLayer( layer );
116  item = new QTableWidgetItem( icon, QString::number( sl->renderingPass() ) );
117  }
118  tableLevels->setItem( row, layer + 1, item );
119  tableLevels->resizeColumnToContents( 0 );
120  }
121  }
122 }
123 
124 void QgsSymbolLevelsWidget::updateUi()
125 {
126  tableLevels->setEnabled( chkEnable->isChecked() );
127  emit widgetChanged();
128 }
129 
131 {
132  if ( !mRenderer )
133  return;
134 
135  for ( const QgsLegendSymbolItem &legendSymbol : std::as_const( mLegendSymbols ) )
136  {
137  QgsSymbol *sym = legendSymbol.symbol();
138  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
139  {
140  mRenderer->setLegendSymbolItem( legendSymbol.ruleKey(), sym->clone() );
141  }
142  }
143 
144  mRenderer->setUsingSymbolLevels( usingLevels() );
145 }
146 
147 void QgsSymbolLevelsWidget::setDefaultLevels()
148 {
149  for ( const QgsLegendSymbolItem &item : std::as_const( mLegendSymbols ) )
150  {
151  QgsSymbol *sym = item.symbol();
152  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
153  {
154  sym->symbolLayer( layer )->setRenderingPass( layer );
155  }
156  }
157 }
158 
160 {
161  return chkEnable->isChecked();
162 }
163 
165 {
166  return mLegendSymbols;
167 }
168 
169 void QgsSymbolLevelsWidget::renderingPassChanged( int row, int column )
170 {
171  if ( row < 0 || row >= mLegendSymbols.count() )
172  return;
173  QgsSymbol *sym = mLegendSymbols.at( row ).symbol();
174  if ( column < 0 || column > sym->symbolLayerCount() )
175  return;
176  sym->symbolLayer( column - 1 )->setRenderingPass( tableLevels->item( row, column )->text().toInt() );
177 
178  emit widgetChanged();
179 }
180 
182 {
183  mForceOrderingEnabled = enabled;
184  if ( enabled )
185  {
186  chkEnable->setChecked( true );
187  chkEnable->hide();
188  }
189  else
190  chkEnable->show();
191 }
192 
193 
194 //
195 // QgsSymbolLevelsDialog
196 //
197 
198 QgsSymbolLevelsDialog::QgsSymbolLevelsDialog( QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent )
199  : QDialog( parent )
200 {
201  QVBoxLayout *vLayout = new QVBoxLayout();
202  mWidget = new QgsSymbolLevelsWidget( renderer, usingSymbolLevels );
203  vLayout->addWidget( mWidget );
204  QDialogButtonBox *bbox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
205  connect( bbox, &QDialogButtonBox::accepted, this, &QgsSymbolLevelsDialog::accept );
206  connect( bbox, &QDialogButtonBox::rejected, this, &QgsSymbolLevelsDialog::reject );
207  connect( bbox, &QDialogButtonBox::helpRequested, this, &QgsSymbolLevelsDialog::showHelp );
208  vLayout->addWidget( bbox );
209  setLayout( vLayout );
210  setWindowTitle( tr( "Symbol Levels" ) );
211 }
212 
214 {
215  mWidget->setForceOrderingEnabled( enabled );
216 }
217 
219 {
220  return mWidget->usingLevels();
221 }
222 
224 {
225  return mWidget->symbolLevels();
226 }
227 
228 void QgsSymbolLevelsDialog::showHelp()
229 {
230  QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#symbols-levels" ) );
231 }
232 
234 
235 QWidget *SpinBoxDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
236 {
237  QSpinBox *editor = new QSpinBox( parent );
238  editor->setMinimum( 0 );
239  editor->setMaximum( 999 );
240  return editor;
241 }
242 
243 void SpinBoxDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
244 {
245  int value = index.model()->data( index, Qt::EditRole ).toInt();
246  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
247  spinBox->setValue( value );
248 }
249 
250 void SpinBoxDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
251 {
252  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
253  spinBox->interpretText();
254  int value = spinBox->value();
255 
256  model->setData( index, value, Qt::EditRole );
257 }
258 
259 void SpinBoxDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & ) const
260 {
261  editor->setGeometry( option.rect );
262 }
263 
264 
virtual void setLegendSymbolItem(const QString &key, QgsSymbol *symbol)
Sets the symbol to be used for a legend symbol item.
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:292
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Base class for any widget that can be shown as a inline panel.
void widgetChanged()
Emitted when the widget state changes.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
Draws a symbol layer preview to an icon.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QgsLegendSymbolList symbolLevels() const
Returns the current legend symbols with rendering passes set, as defined in the widget.
QgsSymbolLevelsDialog(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsDialog.
bool usingLevels() const
Returns whether the level ordering is enabled.
void setForceOrderingEnabled(bool enabled)
A widget which allows the user to modify the rendering order of symbol layers.
QgsSymbolLevelsWidget(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsWidget.
void setForceOrderingEnabled(bool enabled)
Sets whether the level ordering is always forced on and hide the checkbox (used by rule-based rendere...
bool usingLevels() const
Returns whether the level ordering is enabled.
Q_DECL_DEPRECATED void apply()
Apply button.
QgsLegendSymbolList symbolLevels() const
Returns the current legend symbols with rendering passes set, as defined in the widget.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:38
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:420
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:160
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QList< QgsLegendSymbolItem > QgsLegendSymbolList