QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgssymbolslistwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbolslist.cpp
3  ---------------------
4  begin : June 2012
5  copyright : (C) 2012 by Arunmozhi
6  email : aruntheguy at gmail.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 
17 #include "qgssymbolslistwidget.h"
18 
20 
21 #include "qgssymbolv2.h"
22 #include "qgsstylev2.h"
23 #include "qgssymbollayerv2utils.h"
24 
25 #include "qgsapplication.h"
26 
27 #include <QString>
28 #include <QStringList>
29 #include <QPainter>
30 #include <QIcon>
31 #include <QStandardItemModel>
32 #include <QColorDialog>
33 #include <QInputDialog>
34 #include <QMessageBox>
35 #include <QMenu>
36 
37 
38 QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* style, QMenu* menu, QWidget* parent )
39  : QWidget( parent )
40  , mAdvancedMenu( 0 )
41  , mClipFeaturesAction( 0 )
42 {
43  mSymbol = symbol;
44  mStyle = style;
45 
46  setupUi( this );
47 
48  mSymbolUnitWidget->setUnits( QgsSymbolV2::OutputUnitList() << QgsSymbolV2::MM << QgsSymbolV2::MapUnit );
49 
50  btnAdvanced->hide(); // advanced button is hidden by default
51  if ( menu ) // show it if there is a menu pointer
52  {
53  mAdvancedMenu = menu;
54  btnAdvanced->show();
55  btnAdvanced->setMenu( mAdvancedMenu );
56  }
57  else
58  {
59  btnAdvanced->setMenu( new QMenu( this ) );
60  }
61  mClipFeaturesAction = new QAction( tr( "Clip features to canvas extent" ), this );
62  mClipFeaturesAction->setCheckable( true );
63  connect( mClipFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( clipFeaturesToggled( bool ) ) );
64 
65  // populate the groups
66  groupsCombo->addItem( "" );
67  populateGroups();
68  QStringList groups = style->smartgroupNames();
69  foreach ( QString group, groups )
70  {
71  groupsCombo->addItem( group, QVariant( "smart" ) );
72  }
73 
74  QStandardItemModel* model = new QStandardItemModel( viewSymbols );
75  viewSymbols->setModel( model );
76  connect( viewSymbols->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( setSymbolFromStyle( const QModelIndex & ) ) );
77 
78  connect( mStyle, SIGNAL( symbolSaved( QString, QgsSymbolV2* ) ), this, SLOT( symbolAddedToStyle( QString, QgsSymbolV2* ) ) );
79  connect( openStyleManagerButton, SIGNAL( pressed() ), this, SLOT( openStyleManager() ) );
80 
81  lblSymbolName->setText( "" );
83 
84  if ( mSymbol )
85  {
87  }
88 
89  // select correct page in stacked widget
90  // there's a correspondence between symbol type number and page numbering => exploit it!
91  stackedWidget->setCurrentIndex( symbol->type() );
92  connect( btnColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setSymbolColor( const QColor& ) ) );
93  connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setMarkerAngle( double ) ) );
94  connect( spinSize, SIGNAL( valueChanged( double ) ), this, SLOT( setMarkerSize( double ) ) );
95  connect( spinWidth, SIGNAL( valueChanged( double ) ), this, SLOT( setLineWidth( double ) ) );
96 
97  // Live color updates are not undoable to child symbol layers
98  btnColor->setAcceptLiveUpdates( false );
99  btnColor->setAllowAlpha( true );
100  btnColor->setColorDialogTitle( tr( "Select color" ) );
101  btnColor->setContext( "symbology" );
102 }
103 
104 void QgsSymbolsListWidget::populateGroups( QString parent, QString prepend )
105 {
106  QgsSymbolGroupMap groups = mStyle->childGroupNames( parent );
107  QgsSymbolGroupMap::const_iterator i = groups.constBegin();
108  while ( i != groups.constEnd() )
109  {
110  QString text;
111  if ( !prepend.isEmpty() )
112  {
113  text = prepend + "/" + i.value();
114  }
115  else
116  {
117  text = i.value();
118  }
119  groupsCombo->addItem( text, QVariant( i.key() ) );
120  populateGroups( i.value(), text );
121  ++i;
122  }
123 }
124 
126 {
128 }
129 
130 void QgsSymbolsListWidget::populateSymbols( QStringList names )
131 {
132  QSize previewSize = viewSymbols->iconSize();
133  QPixmap p( previewSize );
134  QPainter painter;
135 
136  QStandardItemModel* model = qobject_cast<QStandardItemModel*>( viewSymbols->model() );
137  if ( !model )
138  {
139  return;
140  }
141  model->clear();
142 
143  for ( int i = 0; i < names.count(); i++ )
144  {
145  QgsSymbolV2* s = mStyle->symbol( names[i] );
146  if ( s->type() != mSymbol->type() )
147  {
148  delete s;
149  continue;
150  }
151  QStandardItem* item = new QStandardItem( names[i] );
152  item->setData( names[i], Qt::UserRole ); //so we can load symbol with that name
153  item->setText( names[i] );
154  item->setToolTip( names[i] );
155  item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
156  // Set font to 10points to show reasonable text
157  QFont itemFont = item->font();
158  itemFont.setPointSize( 10 );
159  item->setFont( itemFont );
160  // create preview icon
161  QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( s, previewSize );
162  item->setIcon( icon );
163  // add to model
164  model->appendRow( item );
165  delete s;
166  }
167 }
168 
170 {
171  QgsStyleV2ManagerDialog dlg( mStyle, this );
172  dlg.exec();
173 
175 }
176 
178 {
179  if ( !mSymbol )
180  return;
181 
182  mSymbol->setClipFeaturesToExtent( checked );
183  emit changed();
184 }
185 
186 void QgsSymbolsListWidget::setSymbolColor( const QColor& color )
187 {
188  mSymbol->setColor( color );
189  emit changed();
190 }
191 
193 {
194  QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mSymbol );
195  if ( markerSymbol->angle() == angle )
196  return;
197  markerSymbol->setAngle( angle );
198  emit changed();
199 }
200 
202 {
203  QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mSymbol );
204  if ( markerSymbol->size() == size )
205  return;
206  markerSymbol->setSize( size );
207  emit changed();
208 }
209 
211 {
212  QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( mSymbol );
213  if ( lineSymbol->width() == width )
214  return;
215  lineSymbol->setWidth( width );
216  emit changed();
217 }
218 
220 {
221  Q_UNUSED( name );
222  Q_UNUSED( symbol );
224 }
225 
227 {
228  bool ok;
229  QString name = QInputDialog::getText( this, tr( "Symbol name" ),
230  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
231  if ( !ok || name.isEmpty() )
232  return;
233 
234  // check if there is no symbol with same name
235  if ( mStyle->symbolNames().contains( name ) )
236  {
237  int res = QMessageBox::warning( this, tr( "Save symbol" ),
238  tr( "Symbol with name '%1' already exists. Overwrite?" )
239  .arg( name ),
240  QMessageBox::Yes | QMessageBox::No );
241  if ( res != QMessageBox::Yes )
242  {
243  return;
244  }
245  }
246 
247  // add new symbol to style and re-populate the list
248  mStyle->addSymbol( name, mSymbol->clone() );
249 
250  // make sure the symbol is stored
251  mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
253 }
254 
256 {
257  if ( mSymbol )
258  {
259 
260  mSymbol->setOutputUnit( mSymbolUnitWidget->unit() );
261  mSymbol->setMapUnitScale( mSymbolUnitWidget->getMapUnitScale() );
262 
263  emit changed();
264  }
265 }
266 
268 {
269  if ( mSymbol )
270  {
271  double alpha = 1 - ( value / 255.0 );
272  mSymbol->setAlpha( alpha );
273  displayTransparency( alpha );
274  emit changed();
275  }
276 }
277 
278 void QgsSymbolsListWidget::displayTransparency( double alpha )
279 {
280  double transparencyPercent = ( 1 - alpha ) * 100;
281  mTransparencyLabel->setText( tr( "Transparency %1%" ).arg(( int ) transparencyPercent ) );
282 }
283 
285 {
286  btnColor->blockSignals( true );
287  btnColor->setColor( mSymbol->color() );
288  btnColor->blockSignals( false );
289 }
290 
292 {
294 
295  if ( mSymbol->type() == QgsSymbolV2::Marker )
296  {
297  QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mSymbol );
298  spinSize->setValue( markerSymbol->size() );
299  spinAngle->setValue( markerSymbol->angle() );
300  }
301  else if ( mSymbol->type() == QgsSymbolV2::Line )
302  {
303  QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( mSymbol );
304  spinWidth->setValue( lineSymbol->width() );
305  }
306 
307  mSymbolUnitWidget->blockSignals( true );
308  mSymbolUnitWidget->setUnit( mSymbol->outputUnit() );
309  mSymbolUnitWidget->setMapUnitScale( mSymbol->mapUnitScale() );
310  mSymbolUnitWidget->blockSignals( false );
311 
312  mTransparencySlider->blockSignals( true );
313  double transparency = 1 - mSymbol->alpha();
314  mTransparencySlider->setValue( transparency * 255 );
315  displayTransparency( mSymbol->alpha() );
316  mTransparencySlider->blockSignals( false );
317 
319  {
320  //add clip features option for line or fill symbols
321  btnAdvanced->menu()->addAction( mClipFeaturesAction );
322  }
323  else
324  {
325  btnAdvanced->menu()->removeAction( mClipFeaturesAction );
326  }
327  btnAdvanced->setVisible( mAdvancedMenu || !btnAdvanced->menu()->isEmpty() );
328 
329  mClipFeaturesAction->blockSignals( true );
331  mClipFeaturesAction->blockSignals( false );
332 }
333 
335 {
336  QString symbolName = index.data( Qt::UserRole ).toString();
337  lblSymbolName->setText( symbolName );
338  // get new instance of symbol from style
339  QgsSymbolV2* s = mStyle->symbol( symbolName );
341  // remove all symbol layers from original symbol
342  while ( mSymbol->symbolLayerCount() )
344  // move all symbol layers to our symbol
345  while ( s->symbolLayerCount() )
346  {
347  QgsSymbolLayerV2* sl = s->takeSymbolLayer( 0 );
348  mSymbol->appendSymbolLayer( sl );
349  }
350  mSymbol->setAlpha( s->alpha() );
351  mSymbol->setOutputUnit( unit );
352  // delete the temporary symbol
353  delete s;
354 
356  emit changed();
357 }
358 
360 {
361  QStringList symbols;
362  QString text = groupsCombo->itemText( index );
363  // List all symbols when empty list item is selected
364  if ( text.isEmpty() )
365  {
366  symbols = mStyle->symbolNames();
367  }
368  else
369  {
370  int groupid;
371  if ( groupsCombo->itemData( index ).toString() == "smart" )
372  {
373  groupid = mStyle->smartgroupId( text );
374  symbols = mStyle->symbolsOfSmartgroup( QgsStyleV2::SymbolEntity, groupid );
375  }
376  else
377  {
378  groupid = groupsCombo->itemData( index ).toInt();
379  symbols = mStyle->symbolsOfGroup( QgsStyleV2::SymbolEntity, groupid );
380  }
381  }
382  populateSymbols( symbols );
383 }
384 
386 {
387  QStringList symbols = mStyle->findSymbols( QgsStyleV2::SymbolEntity, text );
388  populateSymbols( symbols );
389 }
void populateSymbols(QStringList symbols)
bool deleteSymbolLayer(int index)
delete symbol layer at specified index
static unsigned index
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent...
Definition: qgssymbolv2.h:172
void symbolAddedToStyle(QString name, QgsSymbolV2 *symbol)
void on_mTransparencySlider_valueChanged(int value)
void setLineWidth(double width)
bool saveSymbol(QString name, QgsSymbolV2 *symbol, int groupid, QStringList tags)
add the symbol to the DB with the tags
Definition: qgsstylev2.cpp:107
void setSymbolFromStyle(const QModelIndex &index)
SymbolType type() const
Definition: qgssymbolv2.h:85
virtual QgsSymbolV2 * clone() const =0
QList< OutputUnit > OutputUnitList
Definition: qgssymbolv2.h:59
QStringList symbolsOfGroup(StyleEntity type, int groupid)
returns the symbolnames of a given groupid
Definition: qgsstylev2.cpp:527
double clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent...
Definition: qgssymbolv2.h:182
QgsMapUnitScale mapUnitScale() const
Definition: qgssymbolv2.cpp:90
QgsSymbolV2 * symbol(QString name)
return a NEW copy of symbol
Definition: qgsstylev2.cpp:166
void setMarkerSize(double size)
void on_groupsCombo_editTextChanged(const QString &text)
void setWidth(double width)
void setMapUnitScale(const QgsMapUnitScale &scale)
QgsSymbolGroupMap childGroupNames(QString parent="")
return a map of groupid and names for the given parent group
Definition: qgsstylev2.cpp:480
bool addSymbol(QString name, QgsSymbolV2 *symbol, bool update=false)
add symbol to style. takes symbol's ownership
Definition: qgsstylev2.cpp:83
void setColor(const QColor &color)
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
bool appendSymbolLayer(QgsSymbolLayerV2 *layer)
append symbol layer at the end of the list
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:157
void setAngle(double angle)
void setSymbolColor(const QColor &color)
int symbolLayerCount()
Returns total number of symbol layers contained in the symbol.
Definition: qgssymbolv2.h:112
void setSize(double size)
void setMarkerAngle(double angle)
QStringList symbolsOfSmartgroup(StyleEntity type, int id)
returns the symbols for the smartgroup
QStringList symbolNames()
return a list of names of symbols
Definition: qgsstylev2.cpp:182
QMap< int, QString > QgsSymbolGroupMap
Definition: qgsstylev2.h:35
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
void on_groupsCombo_currentIndexChanged(int index)
void clipFeaturesToggled(bool checked)
QStringList smartgroupNames()
returns the smart groups list
QgsSymbolV2::OutputUnit outputUnit() const
Definition: qgssymbolv2.cpp:69
QgsSymbolsListWidget(QgsSymbolV2 *symbol, QgsStyleV2 *style, QMenu *menu, QWidget *parent)
QgsSymbolLayerV2 * takeSymbolLayer(int index)
remove symbol layer from the list and return pointer to it
QStringList findSymbols(StyleEntity type, QString qword)
return the names of the symbols which have a matching 'substring' in its defintion ...
Definition: qgsstylev2.cpp:764
double size
Definition: qgssvgcache.cpp:77
int smartgroupId(QString smartgroup)
return the DB id for the given smartgroup name
void setOutputUnit(QgsSymbolV2::OutputUnit u)
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:159
QColor color() const
#define tr(sourceText)