QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 ) : QWidget( parent )
39 {
40  mSymbol = symbol;
41  mStyle = style;
42 
43  setupUi( this );
44 
45  mSymbolUnitWidget->setUnits( QStringList() << tr( "Millimeter" ) << tr( "Map unit" ), 1 );
46 
47  btnAdvanced->hide(); // advanced button is hidden by default
48  if ( menu ) // show it if there is a menu pointer
49  {
50  btnAdvanced->setMenu( menu );
51  btnAdvanced->show();
52  }
53 
54  // populate the groups
55  groupsCombo->addItem( "" );
56  populateGroups();
57  QStringList groups = style->smartgroupNames();
58  foreach ( QString group, groups )
59  {
60  groupsCombo->addItem( group, QVariant( "smart" ) );
61  }
62 
63  QStandardItemModel* model = new QStandardItemModel( viewSymbols );
64  viewSymbols->setModel( model );
65  connect( viewSymbols->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( setSymbolFromStyle( const QModelIndex & ) ) );
66 
67  connect( mStyle, SIGNAL( symbolSaved( QString, QgsSymbolV2* ) ), this, SLOT( symbolAddedToStyle( QString, QgsSymbolV2* ) ) );
68  connect( openStyleManagerButton, SIGNAL( pressed() ), this, SLOT( openStyleManager() ) );
69 
70  lblSymbolName->setText( "" );
72 
73  if ( mSymbol )
74  {
76  }
77 
78  // select correct page in stacked widget
79  // there's a correspondence between symbol type number and page numbering => exploit it!
80  stackedWidget->setCurrentIndex( symbol->type() );
81  connect( btnColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setSymbolColor( const QColor& ) ) );
82  connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setMarkerAngle( double ) ) );
83  connect( spinSize, SIGNAL( valueChanged( double ) ), this, SLOT( setMarkerSize( double ) ) );
84  connect( spinWidth, SIGNAL( valueChanged( double ) ), this, SLOT( setLineWidth( double ) ) );
85 
86  // Live color updates are not undoable to child symbol layers
87  btnColor->setAcceptLiveUpdates( false );
88  btnColor->setAllowAlpha( true );
89  btnColor->setColorDialogTitle( tr( "Select color" ) );
90  btnColor->setContext( "symbology" );
91 }
92 
93 void QgsSymbolsListWidget::populateGroups( QString parent, QString prepend )
94 {
95  QgsSymbolGroupMap groups = mStyle->childGroupNames( parent );
96  QgsSymbolGroupMap::const_iterator i = groups.constBegin();
97  while ( i != groups.constEnd() )
98  {
99  QString text;
100  if ( !prepend.isEmpty() )
101  {
102  text = prepend + "/" + i.value();
103  }
104  else
105  {
106  text = i.value();
107  }
108  groupsCombo->addItem( text, QVariant( i.key() ) );
109  populateGroups( i.value(), text );
110  ++i;
111  }
112 }
113 
115 {
117 }
118 
119 void QgsSymbolsListWidget::populateSymbols( QStringList names )
120 {
121  QSize previewSize = viewSymbols->iconSize();
122  QPixmap p( previewSize );
123  QPainter painter;
124 
125  QStandardItemModel* model = qobject_cast<QStandardItemModel*>( viewSymbols->model() );
126  if ( !model )
127  {
128  return;
129  }
130  model->clear();
131 
132  for ( int i = 0; i < names.count(); i++ )
133  {
134  QgsSymbolV2* s = mStyle->symbol( names[i] );
135  if ( s->type() != mSymbol->type() )
136  {
137  delete s;
138  continue;
139  }
140  QStandardItem* item = new QStandardItem( names[i] );
141  item->setData( names[i], Qt::UserRole ); //so we can load symbol with that name
142  item->setText( names[i] );
143  item->setToolTip( names[i] );
144  item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
145  // Set font to 10points to show reasonable text
146  QFont itemFont = item->font();
147  itemFont.setPointSize( 10 );
148  item->setFont( itemFont );
149  // create preview icon
150  QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( s, previewSize );
151  item->setIcon( icon );
152  // add to model
153  model->appendRow( item );
154  delete s;
155  }
156 }
157 
159 {
160  QgsStyleV2ManagerDialog dlg( mStyle, this );
161  dlg.exec();
162 
164 }
165 
166 void QgsSymbolsListWidget::setSymbolColor( const QColor& color )
167 {
168  mSymbol->setColor( color );
169  emit changed();
170 }
171 
173 {
174  QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mSymbol );
175  if ( markerSymbol->angle() == angle )
176  return;
177  markerSymbol->setAngle( angle );
178  emit changed();
179 }
180 
182 {
183  QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mSymbol );
184  if ( markerSymbol->size() == size )
185  return;
186  markerSymbol->setSize( size );
187  emit changed();
188 }
189 
191 {
192  QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( mSymbol );
193  if ( lineSymbol->width() == width )
194  return;
195  lineSymbol->setWidth( width );
196  emit changed();
197 }
198 
200 {
201  Q_UNUSED( name );
202  Q_UNUSED( symbol );
204 }
205 
207 {
208  bool ok;
209  QString name = QInputDialog::getText( this, tr( "Symbol name" ),
210  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
211  if ( !ok || name.isEmpty() )
212  return;
213 
214  // check if there is no symbol with same name
215  if ( mStyle->symbolNames().contains( name ) )
216  {
217  int res = QMessageBox::warning( this, tr( "Save symbol" ),
218  tr( "Symbol with name '%1' already exists. Overwrite?" )
219  .arg( name ),
220  QMessageBox::Yes | QMessageBox::No );
221  if ( res != QMessageBox::Yes )
222  {
223  return;
224  }
225  }
226 
227  // add new symbol to style and re-populate the list
228  mStyle->addSymbol( name, mSymbol->clone() );
229 
230  // make sure the symbol is stored
231  mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
233 }
234 
236 {
237  if ( mSymbol )
238  {
239  QgsSymbolV2::OutputUnit unit = static_cast<QgsSymbolV2::OutputUnit>( mSymbolUnitWidget->getUnit() );
240  mSymbol->setOutputUnit( unit );
241  mSymbol->setMapUnitScale( mSymbolUnitWidget->getMapUnitScale() );
242 
243  emit changed();
244  }
245 }
246 
248 {
249  if ( mSymbol )
250  {
251  double alpha = 1 - ( value / 255.0 );
252  mSymbol->setAlpha( alpha );
253  displayTransparency( alpha );
254  emit changed();
255  }
256 }
257 
258 void QgsSymbolsListWidget::displayTransparency( double alpha )
259 {
260  double transparencyPercent = ( 1 - alpha ) * 100;
261  mTransparencyLabel->setText( tr( "Transparency %1%" ).arg(( int ) transparencyPercent ) );
262 }
263 
265 {
266  btnColor->blockSignals( true );
267  btnColor->setColor( mSymbol->color() );
268  btnColor->blockSignals( false );
269 }
270 
272 {
274 
275  if ( mSymbol->type() == QgsSymbolV2::Marker )
276  {
277  QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mSymbol );
278  spinSize->setValue( markerSymbol->size() );
279  spinAngle->setValue( markerSymbol->angle() );
280  }
281  else if ( mSymbol->type() == QgsSymbolV2::Line )
282  {
283  QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( mSymbol );
284  spinWidth->setValue( lineSymbol->width() );
285  }
286 
287  mSymbolUnitWidget->blockSignals( true );
288  mSymbolUnitWidget->setUnit( mSymbol->outputUnit() );
289  mSymbolUnitWidget->setMapUnitScale( mSymbol->mapUnitScale() );
290  mSymbolUnitWidget->blockSignals( false );
291 
292  mTransparencySlider->blockSignals( true );
293  double transparency = 1 - mSymbol->alpha();
294  mTransparencySlider->setValue( transparency * 255 );
295  displayTransparency( mSymbol->alpha() );
296  mTransparencySlider->blockSignals( false );
297 }
298 
300 {
301  QString symbolName = index.data( Qt::UserRole ).toString();
302  lblSymbolName->setText( symbolName );
303  // get new instance of symbol from style
304  QgsSymbolV2* s = mStyle->symbol( symbolName );
306  // remove all symbol layers from original symbol
307  while ( mSymbol->symbolLayerCount() )
309  // move all symbol layers to our symbol
310  while ( s->symbolLayerCount() )
311  {
312  QgsSymbolLayerV2* sl = s->takeSymbolLayer( 0 );
313  mSymbol->appendSymbolLayer( sl );
314  }
315  mSymbol->setAlpha( s->alpha() );
316  mSymbol->setOutputUnit( unit );
317  // delete the temporary symbol
318  delete s;
319 
321  emit changed();
322 }
323 
325 {
326  QStringList symbols;
327  QString text = groupsCombo->itemText( index );
328  // List all symbols when empty list item is selected
329  if ( text.isEmpty() )
330  {
331  symbols = mStyle->symbolNames();
332  }
333  else
334  {
335  int groupid;
336  if ( groupsCombo->itemData( index ).toString() == "smart" )
337  {
338  groupid = mStyle->smartgroupId( text );
339  symbols = mStyle->symbolsOfSmartgroup( QgsStyleV2::SymbolEntity, groupid );
340  }
341  else
342  {
343  groupid = groupsCombo->itemData( index ).toInt();
344  symbols = mStyle->symbolsOfGroup( QgsStyleV2::SymbolEntity, groupid );
345  }
346  }
347  populateSymbols( symbols );
348 }
349 
351 {
352  QStringList symbols = mStyle->findSymbols( QgsStyleV2::SymbolEntity, text );
353  populateSymbols( symbols );
354 }