QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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  : QgsPanelWidget( parent )
34  , mRenderer( renderer )
35  , mForceOrderingEnabled( false )
36 {
37  setupUi( this );
38 
39  tableLevels->setItemDelegate( new SpinBoxDelegate( this ) );
40 
41  chkEnable->setChecked( usingSymbolLevels );
42 
43  connect( chkEnable, &QAbstractButton::clicked, this, &QgsSymbolLevelsWidget::updateUi );
44 
45  if ( mRenderer )
46  {
47  // only consider entries with symbols
48  const auto constLegendSymbolItems = mRenderer->legendSymbolItems();
49  for ( const QgsLegendSymbolItem &item : constLegendSymbolItems )
50  {
51  if ( item.symbol() )
52  mList << item;
53  }
54  }
55 
56  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
57  int maxLayers = 0;
58  tableLevels->setRowCount( mList.count() );
59  for ( int i = 0; i < mList.count(); i++ )
60  {
61  QgsSymbol *sym = mList.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 )
87 
88  populateTable();
89 
90  connect( tableLevels, &QTableWidget::cellChanged, this, &QgsSymbolLevelsWidget::renderingPassChanged );
91 }
92 
94 {
95  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
96  for ( int row = 0; row < mList.count(); row++ )
97  {
98  QgsSymbol *sym = mList.at( row ).symbol();
99  QString label = mList.at( row ).label();
100  QTableWidgetItem *itemLabel = new QTableWidgetItem( label );
101  itemLabel->setFlags( itemLabel->flags() ^ Qt::ItemIsEditable );
102  tableLevels->setItem( row, 0, itemLabel );
103  for ( int layer = 0; layer < mMaxLayers; layer++ )
104  {
105  QTableWidgetItem *item = nullptr;
106  if ( layer >= sym->symbolLayerCount() )
107  {
108  item = new QTableWidgetItem();
109  item->setFlags( Qt::ItemFlags() );
110  }
111  else
112  {
113  QgsSymbolLayer *sl = sym->symbolLayer( layer );
114  QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, QgsUnitTypes::RenderMillimeters, QSize( iconSize, iconSize ) );
115  item = new QTableWidgetItem( icon, QString::number( sl->renderingPass() ) );
116  }
117  tableLevels->setItem( row, layer + 1, item );
118  tableLevels->resizeColumnToContents( 0 );
119  }
120  }
121 
122 }
123 
124 void QgsSymbolLevelsWidget::updateUi()
125 {
126  tableLevels->setEnabled( chkEnable->isChecked() );
127  emit widgetChanged();
128 }
129 
131 {
132  for ( int i = 0; i < mList.count(); i++ )
133  {
134  QgsSymbol *sym = mList.at( i ).symbol();
135  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
136  {
137  mRenderer->setLegendSymbolItem( mList.at( i ).ruleKey(), sym->clone() );
138  }
139  }
140 
142 }
143 
145 {
146  for ( int i = 0; i < mList.count(); i++ )
147  {
148  QgsSymbol *sym = mList.at( i ).symbol();
149  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
150  {
151  sym->symbolLayer( layer )->setRenderingPass( layer );
152  }
153  }
154 }
155 
157 {
158  return chkEnable->isChecked();
159 }
160 
161 void QgsSymbolLevelsWidget::renderingPassChanged( int row, int column )
162 {
163  if ( row < 0 || row >= mList.count() )
164  return;
165  QgsSymbol *sym = mList.at( row ).symbol();
166  if ( column < 0 || column > sym->symbolLayerCount() )
167  return;
168  sym->symbolLayer( column - 1 )->setRenderingPass( tableLevels->item( row, column )->text().toInt() );
169 
170  emit widgetChanged();
171 }
172 
174 {
175  mForceOrderingEnabled = enabled;
176  if ( enabled )
177  {
178  chkEnable->setChecked( true );
179  chkEnable->hide();
180  }
181  else
182  chkEnable->show();
183 }
184 
185 QgsSymbolLevelsDialog::QgsSymbolLevelsDialog( QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent )
186  : QDialog( parent )
187 {
188  QVBoxLayout *vLayout = new QVBoxLayout();
189  mWidget = new QgsSymbolLevelsWidget( renderer, usingSymbolLevels );
190  vLayout->addWidget( mWidget );
191  QDialogButtonBox *bbox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
192  connect( bbox, &QDialogButtonBox::accepted, mWidget, &QgsSymbolLevelsWidget::apply );
193  connect( bbox, &QDialogButtonBox::accepted, this, &QgsSymbolLevelsDialog::accept );
194  connect( bbox, &QDialogButtonBox::rejected, this, &QgsSymbolLevelsDialog::reject );
195  connect( bbox, &QDialogButtonBox::helpRequested, this, &QgsSymbolLevelsDialog::showHelp );
196  vLayout->addWidget( bbox );
197  setLayout( vLayout );
198  setWindowTitle( tr( "Symbol Levels" ) );
199 }
200 
202 {
203  mWidget->setForceOrderingEnabled( enabled );
204 }
205 
206 void QgsSymbolLevelsDialog::showHelp()
207 {
208  QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#symbols-levels" ) );
209 }
210 
212 
213 QWidget *SpinBoxDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
214 {
215  QSpinBox *editor = new QSpinBox( parent );
216  editor->setMinimum( 0 );
217  editor->setMaximum( 999 );
218  return editor;
219 }
220 
221 void SpinBoxDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
222 {
223  int value = index.model()->data( index, Qt::EditRole ).toInt();
224  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
225  spinBox->setValue( value );
226 }
227 
228 void SpinBoxDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
229 {
230  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
231  spinBox->interpretText();
232  int value = spinBox->value();
233 
234  model->setData( index, value, Qt::EditRole );
235 }
236 
237 void SpinBoxDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & ) const
238 {
239  editor->setGeometry( option.rect );
240 }
241 
242 
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
QgsLegendSymbolList mList
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.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
QgsSymbolLevelsWidget(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsWidget.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly...
int mMaxLayers
maximal number of layers from all symbols
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
void setForceOrderingEnabled(bool enabled)
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:272
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:150
Base class for any widget that can be shown as a inline panel.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
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 layer contained in the symbol.
Definition: qgssymbol.cpp:358
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window&#39;s toolbar icons.
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
Returns 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:36
QgsSymbolLevelsDialog(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsDialog.
bool usingLevels() const
Returns whether the level ordering is enabled.