QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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  Q_FOREACH ( const QgsLegendSymbolItem &item, mRenderer->legendSymbolItems() )
49  {
50  if ( item.symbol() )
51  mList << item;
52  }
53  }
54 
55  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
56  int maxLayers = 0;
57  tableLevels->setRowCount( mList.count() );
58  for ( int i = 0; i < mList.count(); i++ )
59  {
60  QgsSymbol *sym = mList.at( i ).symbol();
61 
62  // set icons for the rows
63  QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( sym, QSize( iconSize, iconSize ) );
64  tableLevels->setVerticalHeaderItem( i, new QTableWidgetItem( icon, QString() ) );
65 
66  // find out max. number of layers per symbol
67  int layers = sym->symbolLayerCount();
68  if ( layers > maxLayers )
69  maxLayers = layers;
70  }
71 
72  tableLevels->setColumnCount( maxLayers + 1 );
73  tableLevels->setHorizontalHeaderItem( 0, new QTableWidgetItem( QString() ) );
74  for ( int i = 0; i < maxLayers; i++ )
75  {
76  QString name = tr( "Layer %1" ).arg( i );
77  tableLevels->setHorizontalHeaderItem( i + 1, new QTableWidgetItem( name ) );
78  }
79 
80  mMaxLayers = maxLayers;
81 
82  updateUi();
83 
84  if ( !usingSymbolLevels )
86 
87  populateTable();
88 
89  connect( tableLevels, &QTableWidget::cellChanged, this, &QgsSymbolLevelsWidget::renderingPassChanged );
90 }
91 
93 {
94  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
95  for ( int row = 0; row < mList.count(); row++ )
96  {
97  QgsSymbol *sym = mList.at( row ).symbol();
98  QString label = mList.at( row ).label();
99  QTableWidgetItem *itemLabel = new QTableWidgetItem( label );
100  itemLabel->setFlags( itemLabel->flags() ^ Qt::ItemIsEditable );
101  tableLevels->setItem( row, 0, itemLabel );
102  for ( int layer = 0; layer < mMaxLayers; layer++ )
103  {
104  QTableWidgetItem *item = nullptr;
105  if ( layer >= sym->symbolLayerCount() )
106  {
107  item = new QTableWidgetItem();
108  item->setFlags( Qt::ItemFlags() );
109  }
110  else
111  {
112  QgsSymbolLayer *sl = sym->symbolLayer( layer );
113  QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, QgsUnitTypes::RenderMillimeters, QSize( iconSize, iconSize ) );
114  item = new QTableWidgetItem( icon, QString::number( sl->renderingPass() ) );
115  }
116  tableLevels->setItem( row, layer + 1, item );
117  tableLevels->resizeColumnToContents( 0 );
118  }
119  }
120 
121 }
122 
123 void QgsSymbolLevelsWidget::updateUi()
124 {
125  tableLevels->setEnabled( chkEnable->isChecked() );
126  emit widgetChanged();
127 }
128 
130 {
131  for ( int i = 0; i < mList.count(); i++ )
132  {
133  QgsSymbol *sym = mList.at( i ).symbol();
134  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
135  {
136  mRenderer->setLegendSymbolItem( mList.at( i ).ruleKey(), sym->clone() );
137  }
138  }
139 
141 }
142 
144 {
145  for ( int i = 0; i < mList.count(); i++ )
146  {
147  QgsSymbol *sym = mList.at( i ).symbol();
148  for ( int layer = 0; layer < sym->symbolLayerCount(); layer++ )
149  {
150  sym->symbolLayer( layer )->setRenderingPass( layer );
151  }
152  }
153 }
154 
156 {
157  return chkEnable->isChecked();
158 }
159 
160 void QgsSymbolLevelsWidget::renderingPassChanged( int row, int column )
161 {
162  if ( row < 0 || row >= mList.count() )
163  return;
164  QgsSymbol *sym = mList.at( row ).symbol();
165  if ( column < 0 || column > sym->symbolLayerCount() )
166  return;
167  sym->symbolLayer( column - 1 )->setRenderingPass( tableLevels->item( row, column )->text().toInt() );
168 
169  emit widgetChanged();
170 }
171 
173 {
174  mForceOrderingEnabled = enabled;
175  if ( enabled )
176  {
177  chkEnable->setChecked( true );
178  chkEnable->hide();
179  }
180  else
181  chkEnable->show();
182 }
183 
184 QgsSymbolLevelsDialog::QgsSymbolLevelsDialog( QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent )
185  : QDialog( parent )
186 {
187  QVBoxLayout *vLayout = new QVBoxLayout();
188  mWidget = new QgsSymbolLevelsWidget( renderer, usingSymbolLevels );
189  vLayout->addWidget( mWidget );
190  QDialogButtonBox *bbox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
191  connect( bbox, &QDialogButtonBox::accepted, mWidget, &QgsSymbolLevelsWidget::apply );
192  connect( bbox, &QDialogButtonBox::accepted, this, &QgsSymbolLevelsDialog::accept );
193  connect( bbox, &QDialogButtonBox::rejected, this, &QgsSymbolLevelsDialog::reject );
194  connect( bbox, &QDialogButtonBox::helpRequested, this, &QgsSymbolLevelsDialog::showHelp );
195  vLayout->addWidget( bbox );
196  setLayout( vLayout );
197  setWindowTitle( tr( "Symbol Levels" ) );
198 }
199 
201 {
202  mWidget->setForceOrderingEnabled( enabled );
203 }
204 
205 void QgsSymbolLevelsDialog::showHelp()
206 {
207  QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#symbols-levels" ) );
208 }
209 
211 
212 QWidget *SpinBoxDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
213 {
214  QSpinBox *editor = new QSpinBox( parent );
215  editor->setMinimum( 0 );
216  editor->setMaximum( 999 );
217  return editor;
218 }
219 
220 void SpinBoxDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
221 {
222  int value = index.model()->data( index, Qt::EditRole ).toInt();
223  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
224  spinBox->setValue( value );
225 }
226 
227 void SpinBoxDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
228 {
229  QSpinBox *spinBox = static_cast<QSpinBox *>( editor );
230  spinBox->interpretText();
231  int value = spinBox->value();
232 
233  model->setData( index, value, Qt::EditRole );
234 }
235 
236 void SpinBoxDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & ) const
237 {
238  editor->setGeometry( option.rect );
239 }
240 
241 
QgsLegendSymbolList mList
void setRenderingPass(int renderingPass)
bool usingLevels() const
Returns whether the level ordering is enabled.
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 symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:150
int mMaxLayers
maximal number of layers from all symbols
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
void setForceOrderingEnabled(bool enabled)
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:272
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.
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.
int renderingPass() const
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:340
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:35
QgsSymbol * symbol() const
Returns associated symbol. May be null.
QgsSymbolLevelsDialog(QgsFeatureRenderer *renderer, bool usingSymbolLevels, QWidget *parent=nullptr)
Constructor for QgsSymbolLevelsDialog.