QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
QgsFeatureRenderer::setLegendSymbolItem
virtual void setLegendSymbolItem(const QString &key, QgsSymbol *symbol)
Sets the symbol to be used for a legend symbol item.
Definition: qgsrenderer.cpp:365
QgsSymbolLevelsWidget::symbolLevels
QgsLegendSymbolList symbolLevels() const
Returns the current legend symbols with rendering passes set, as defined in the widget.
Definition: qgssymbollevelsdialog.cpp:164
QgsSymbolLevelsDialog::symbolLevels
QgsLegendSymbolList symbolLevels() const
Returns the current legend symbols with rendering passes set, as defined in the widget.
Definition: qgssymbollevelsdialog.cpp:223
QgsSymbolLevelsWidget::usingLevels
bool usingLevels() const
Returns whether the level ordering is enabled.
Definition: qgssymbollevelsdialog.cpp:159
qgssymbollayerutils.h
QgsSymbolLayer::setRenderingPass
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
Definition: qgssymbollayer.cpp:318
QgsSymbolLayerUtils::symbolLayerPreviewIcon
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to an icon.
Definition: qgssymbollayerutils.cpp:983
QgsSymbolLevelsWidget::apply
Q_DECL_DEPRECATED void apply()
Apply button.
Definition: qgssymbollevelsdialog.cpp:130
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
QgsSymbol::symbolLayer
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:725
qgssymbollevelsdialog.h
QgsSymbolLevelsWidget
A widget which allows the user to modify the rendering order of symbol layers.
Definition: qgssymbollevelsdialog.h:37
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:264
QgsSymbolLayerUtils::symbolPreviewIcon
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
Definition: qgssymbollayerutils.cpp:871
QgsLegendSymbolItem
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Definition: qgslegendsymbolitem.h:36
QgsSymbolLayer
Definition: qgssymbollayer.h:54
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:29
QgsSymbolLayer::renderingPass
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
Definition: qgssymbollayer.cpp:323
QgsFeatureRenderer::setUsingSymbolLevels
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:293
QgsSymbol::type
Qgis::SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:152
QgsSymbolLevelsDialog::usingLevels
bool usingLevels() const
Returns whether the level ordering is enabled.
Definition: qgssymbollevelsdialog.cpp:218
QgsSymbolLevelsWidget::QgsSymbolLevelsWidget
QgsSymbolLevelsWidget(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsWidget.
Definition: qgssymbollevelsdialog.cpp:32
QgsSymbolLevelsWidget::setForceOrderingEnabled
void setForceOrderingEnabled(bool enabled)
Sets whether the level ordering is always forced on and hide the checkbox (used by rule-based rendere...
Definition: qgssymbollevelsdialog.cpp:181
QgsSymbolLevelsDialog::QgsSymbolLevelsDialog
QgsSymbolLevelsDialog(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsDialog.
Definition: qgssymbollevelsdialog.cpp:198
QgsPanelWidget::widgetChanged
void widgetChanged()
Emitted when the widget state changes.
QgsSymbolLevelsDialog::setForceOrderingEnabled
void setForceOrderingEnabled(bool enabled)
Definition: qgssymbollevelsdialog.cpp:213
qgssymbollayer.h
QgsMapUnitScale
Struct for storing maximum and minimum scales for measurements in map units.
Definition: qgsmapunitscale.h:36
QgsSymbol::clone
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
QgsFeatureRenderer
Definition: qgsrenderer.h:101
QgsHelp::openHelp
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
qgssettings.h
qgsguiutils.h
QgsGuiUtils::scaleIconSize
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Definition: qgsguiutils.cpp:259
QgsLegendSymbolList
QList< QgsLegendSymbolItem > QgsLegendSymbolList
Definition: qgslegendsymbolitem.h:144
qgssymbol.h
QgsSymbol::symbolLayerCount
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:215