QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgslegendmodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslegendmodel.cpp - description
3  ------------------
4  begin : June 2008
5  copyright : (C) 2008 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgslegendmodel.h"
19 #include "qgscomposerlegenditem.h"
20 #include "qgsfield.h"
21 #include "qgsmaplayer.h"
22 #include "qgsmaplayerregistry.h"
23 #include "qgsrasterlayer.h"
24 #include "qgsrendererv2.h"
25 #include "qgssymbollayerv2utils.h"
26 #include "qgsvectordataprovider.h"
27 #include "qgsvectorlayer.h"
28 #include <QApplication>
29 #include <QDomDocument>
30 #include <QDomElement>
31 #include <QMimeData>
32 #include <QSettings>
33 #include <QMessageBox>
34 
35 QgsLegendModel::QgsLegendModel(): QStandardItemModel(), mAutoUpdate( true )
36 {
37  setColumnCount( 2 );
38 
40  {
41  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
42  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( addLayer( QgsMapLayer* ) ) );
43  }
44 
45  QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
46  mHasTopLevelWindow = ( topLevelWidgets.size() > 0 );
47 }
48 
50 {
51 }
52 
53 void QgsLegendModel::setLayerSetAndGroups( const QStringList& layerIds, const QList< GroupLayerInfo >& groupInfo )
54 {
55  setLayerSet( layerIds );
56 
57  QStandardItem* currentItem = 0;
58  QStandardItem* currentGroupItem = 0;
59  int i = 0;
60 
61  QList< GroupLayerInfo >::const_iterator infoIt = groupInfo.constBegin();
62  for ( ; infoIt != groupInfo.constEnd() && i < invisibleRootItem()->rowCount(); )
63  {
64  currentItem = invisibleRootItem()->child( i, 0 );
65  QString infoKey = infoIt->first;
66  if ( infoKey.isNull() ) //a toplevel layer
67  {
68  ++i;
69  }
70  else //a group
71  {
72  currentGroupItem = addGroup( infoKey, i );
73  ++i;
74  QList<QString> layerList = infoIt->second;
75  QList<QString>::const_iterator groupLayerIt = layerList.constBegin();
76  for ( ; currentItem && ( groupLayerIt != layerList.constEnd() ); ++groupLayerIt )
77  {
78  //check if current item is contained in this group
79  QgsComposerLayerItem* layerItem = dynamic_cast<QgsComposerLayerItem*>( currentItem );
80  if ( !layerItem )
81  {
82  return; //should never happen
83  }
84  QString layerID = layerItem->layerID();
85  if ( layerList.contains( layerID ) )
86  {
87  takeRow( i );
88  currentGroupItem->setChild( currentGroupItem->rowCount(), 0, currentItem );
89  }
90  else
91  {
92  ++i;
93  }
94  currentItem = invisibleRootItem()->child( i, 0 );
95  }
96  }
97  ++infoIt;
98  }
99 }
100 
101 void QgsLegendModel::setLayerSet( const QStringList& layerIds, double scaleDenominator, QString rule )
102 {
103  mLayerIds = layerIds;
104 
105  //for now clear the model and add the new entries
106  clear();
107 
108  QStringList::const_iterator idIter = mLayerIds.constBegin();
109  QgsMapLayer* currentLayer = 0;
110 
111  for ( ; idIter != mLayerIds.constEnd(); ++idIter )
112  {
113  currentLayer = QgsMapLayerRegistry::instance()->mapLayer( *idIter );
114  addLayer( currentLayer, scaleDenominator, rule );
115  }
116 }
117 
118 QStandardItem* QgsLegendModel::addGroup( QString text, int position )
119 {
120  if ( text.isNull() )
121  text = tr( "Group" );
122 
123  QgsComposerGroupItem* groupItem = new QgsComposerGroupItem( text );
124  groupItem->setUserText( text );
125 
126  if ( position == -1 )
127  {
128  position = invisibleRootItem()->rowCount();
129  }
130  QList<QStandardItem *> itemsList;
131  itemsList << groupItem << new QgsComposerStyleItem( groupItem );
132  invisibleRootItem()->insertRow( position, itemsList );
133 
134  emit layersChanged();
135  return groupItem;
136 }
137 
138 int QgsLegendModel::addVectorLayerItemsV2( QStandardItem* layerItem, QgsVectorLayer* vlayer, double scaleDenominator, QString rule )
139 {
140  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
141 
142  if ( !layerItem || !lItem || !vlayer )
143  {
144  return 1;
145  }
146 
147  QgsFeatureRendererV2* renderer = vlayer->rendererV2();
148  if ( !renderer )
149  {
150  return 2;
151  }
152 
153  if ( lItem->showFeatureCount() )
154  {
155  if ( !vlayer->countSymbolFeatures() )
156  {
157  QgsDebugMsg( "Cannot get feature counts" );
158  }
159  }
160 
161  QgsLegendSymbolList lst = renderer->legendSymbolItems( scaleDenominator, rule );
162  QgsLegendSymbolList::const_iterator symbolIt = lst.constBegin();
163  int row = 0;
164  for ( ; symbolIt != lst.constEnd(); ++symbolIt )
165  {
166  if ( scaleDenominator == -1 && rule.isEmpty() )
167  {
168  QgsComposerSymbolV2Item* currentSymbolItem = new QgsComposerSymbolV2Item( "" );
169 
170  // Get userText from old item if exists
171  QgsComposerSymbolV2Item* oldSymbolItem = dynamic_cast<QgsComposerSymbolV2Item*>( layerItem->child( row, 0 ) );
172  if ( oldSymbolItem )
173  {
174  currentSymbolItem->setUserText( oldSymbolItem->userText() );
175  }
176 
177  currentSymbolItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
178  if ( symbolIt->second )
179  {
180  if ( mHasTopLevelWindow ) //only use QIcon / QPixmap if we have a running x-server
181  {
182  currentSymbolItem->setIcon( QgsSymbolLayerV2Utils::symbolPreviewIcon( symbolIt->second, QSize( 30, 30 ) ) );
183  }
184  currentSymbolItem->setSymbolV2( symbolIt->second->clone() );
185  }
186  layerItem->setChild( row, 0, currentSymbolItem );
187 
188  // updateSymbolV2ItemText needs layer set
189  updateSymbolV2ItemText( currentSymbolItem );
190  }
191  else
192  {
193  QgsComposerSymbolV2Item* currentSymbolItem = new QgsComposerSymbolV2Item( "" );
194  if ( mHasTopLevelWindow ) //only use QIcon / QPixmap if we have a running x-server
195  {
196  currentSymbolItem->setIcon( QgsSymbolLayerV2Utils::symbolPreviewIcon( symbolIt->second, QSize( 30, 30 ) ) );
197  }
198  currentSymbolItem->setSymbolV2( symbolIt->second->clone() );
199  layerItem->setChild( row, 0, currentSymbolItem );
200  currentSymbolItem->setText( symbolIt->first );
201  }
202 
203  row++;
204  }
205 
206  // Don't remove row on getLegendGraphic (read only with filter)
207  if ( scaleDenominator == -1 && rule.isEmpty() )
208  {
209  // Delete following old items (if current number of items decreased)
210  for ( int i = layerItem->rowCount() - 1; i >= row; --i )
211  {
212  layerItem->removeRow( i );
213  }
214  }
215 
216  return 0;
217 }
218 
219 int QgsLegendModel::addRasterLayerItems( QStandardItem* layerItem, QgsMapLayer* rlayer )
220 {
221  if ( !layerItem || !rlayer )
222  {
223  return 1;
224  }
225 
226  QgsRasterLayer* rasterLayer = qobject_cast<QgsRasterLayer *>( rlayer );
227  if ( !rasterLayer )
228  {
229  return 2;
230  }
231 
232  QgsDebugMsg( QString( "layer providertype:: %1" ).arg( rasterLayer->providerType() ) );
233  if ( rasterLayer->providerType() == "wms" )
234  {
235  QgsComposerRasterSymbolItem* currentSymbolItem = new QgsComposerRasterSymbolItem( "" );
236  // GetLegendGraphics in case of WMS service... image can return null if GetLegendGraphics
237  // is not supported by the server
238  // double currentScale = legend()->canvas()->scale();
239  // BEWARE getLegendGraphic() COULD BE USED WITHOUT SCALE PARAMETER IF IT WAS ALREADY CALLED WITH
240  // THIS PARAMETER FROM A COMPONENT THAT CAN RECOVER CURRENT SCALE => LEGEND IN THE DESKTOP
241  // OTHERWISE IT RETURN A INVALID PIXMAP (QPixmap().isNull() == False)
242  QImage legendGraphic = rasterLayer->dataProvider()->getLegendGraphic();
243  if ( !legendGraphic.isNull() )
244  {
245  QgsDebugMsg( QString( "downloaded legend with dimension width:" ) + QString::number( legendGraphic.width() ) + QString( " and Height:" ) + QString::number( legendGraphic.height() ) );
246  if ( mHasTopLevelWindow )
247  {
248  currentSymbolItem->setIcon( QIcon( QPixmap::fromImage( legendGraphic ) ) );
249  }
250  }
251  else
252  {
253  currentSymbolItem->setText( tr( "No Legend Available" ) );
254  }
255 
256  currentSymbolItem->setLayerID( rasterLayer->id() );
257  currentSymbolItem->setColor( QColor() );
258  layerItem->removeRows( 0, layerItem->rowCount() );
259  layerItem->setChild( layerItem->rowCount(), 0, currentSymbolItem );
260  }
261  else
262  {
263  QList< QPair< QString, QColor > > rasterItemList = rasterLayer->legendSymbologyItems();
264  QList< QPair< QString, QColor > >::const_iterator itemIt = rasterItemList.constBegin();
265  int row = 0;
266  for ( ; itemIt != rasterItemList.constEnd(); ++itemIt )
267  {
268  QgsComposerRasterSymbolItem* currentSymbolItem = new QgsComposerRasterSymbolItem( itemIt->first );
269 
270  QgsComposerRasterSymbolItem* oldSymbolItem = dynamic_cast<QgsComposerRasterSymbolItem*>( layerItem->child( row, 0 ) );
271  if ( oldSymbolItem )
272  {
273  currentSymbolItem->setUserText( oldSymbolItem->userText() );
274  currentSymbolItem->setText( currentSymbolItem->userText() );
275  }
276 
277  if ( mHasTopLevelWindow )
278  {
279  QPixmap itemPixmap( 20, 20 );
280  itemPixmap.fill( itemIt->second );
281  currentSymbolItem->setIcon( QIcon( itemPixmap ) );
282  }
283  currentSymbolItem->setLayerID( rasterLayer->id() );
284 
285  QColor itemColor = itemIt->second;
286 
287  //determine raster layer opacity, and adjust item color opacity to match
288  QgsRasterRenderer* rasterRenderer = rasterLayer->renderer();
289  int opacity = 255;
290  if ( rasterRenderer )
291  {
292  opacity = rasterRenderer->opacity() * 255.0;
293  }
294  itemColor.setAlpha( opacity );
295 
296  currentSymbolItem->setColor( itemColor );
297 
298  int currentRowCount = layerItem->rowCount();
299  layerItem->setChild( currentRowCount, 0, currentSymbolItem );
300  row++;
301  }
302 
303  // Delete following old items (if current number of items decreased)
304  for ( int i = layerItem->rowCount() - 1; i >= row; --i )
305  {
306  layerItem->removeRow( i );
307  }
308  }
309 
310  return 0;
311 }
312 
313 void QgsLegendModel::updateSymbolV2ItemText( QStandardItem* symbolItem )
314 {
315  QgsComposerSymbolV2Item* sv2Item = dynamic_cast<QgsComposerSymbolV2Item*>( symbolItem );
316  if ( !sv2Item ) return;
317 
318  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( sv2Item->parent() );
319  if ( !lItem ) return;
320 
321  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
322  if ( !mapLayer ) return;
323 
324  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
325  if ( !vLayer ) return;
326 
327  QgsFeatureRendererV2* renderer = vLayer->rendererV2();
328  if ( !renderer ) return;
329 
330  if ( lItem->showFeatureCount() ) vLayer->countSymbolFeatures();
331 
332  QgsLegendSymbolList symbolList = renderer->legendSymbolItems();
333 
334  QPair<QString, QgsSymbolV2*> symbol = symbolList.value( symbolItem->row() );
335 
336  QString label = sv2Item->userText().isEmpty() ? symbol.first : sv2Item->userText();
337 
338  if ( renderer->type() == "singleSymbol" )
339  {
340  if ( !sv2Item->userText().isEmpty() )
341  {
342  label = sv2Item->userText();
343  }
344  else if ( !lItem->userText().isEmpty() )
345  {
346  label = lItem->userText();
347  }
348  else if ( !vLayer->title().isEmpty() )
349  {
350  label = vLayer->title();
351  }
352  else
353  {
354  label = vLayer->name();
355  }
356  }
357 
358  if ( lItem->showFeatureCount() )
359  {
360  // Add counts to multi symbols layers only or labeled single symbols,
361  // so that single symbol layers are still drawn on single line
362  if ( symbolList.size() > 1 || !label.isEmpty() )
363  {
364  label += QString( " [%1]" ).arg( vLayer->featureCount( symbol.second ) );
365  }
366  }
367  symbolItem->setText( label );
368 }
369 
370 void QgsLegendModel::updateRasterSymbolItemText( QStandardItem* symbolItem )
371 {
372  QgsComposerRasterSymbolItem* rItem = dynamic_cast<QgsComposerRasterSymbolItem*>( symbolItem );
373  if ( !rItem ) return;
374 
375  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( rItem->parent() );
376  if ( !lItem ) return;
377 
378  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
379  if ( !mapLayer ) return;
380 
381  QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( mapLayer );
382  if ( !rLayer ) return;
383 
384  QPair< QString, QColor> symbol = rLayer->legendSymbologyItems().value( symbolItem->row() );
385 
386  QString label = rItem->userText().isEmpty() ? symbol.first : rItem->userText();
387 
388  symbolItem->setText( label );
389 }
390 
391 void QgsLegendModel::updateItem( QStandardItem* item )
392 {
393  if ( !item )
394  {
395  return;
396  }
397 
398  //only layer items are supported for update
399  QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
400  if ( ! cItem )
401  {
402  return;
403  }
404 
406  if ( type == QgsComposerLegendItem::LayerItem )
407  {
408  updateLayer( cItem );
409  }
410 }
411 
412 void QgsLegendModel::updateItemText( QStandardItem* item )
413 {
414  if ( !item )
415  {
416  return;
417  }
418 
419  //only layer items are supported for update
420  QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
421  if ( ! cItem )
422  {
423  return;
424  }
425 
426  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( cItem );
427  if ( lItem )
428  {
429  updateLayerItemText( lItem );
430  return;
431  }
432 
433  QgsComposerSymbolV2Item* sv2Item = dynamic_cast<QgsComposerSymbolV2Item*>( cItem );
434  if ( sv2Item )
435  {
436  updateSymbolV2ItemText( sv2Item );
437  return;
438  }
439 
440  QgsComposerRasterSymbolItem* rItem = dynamic_cast<QgsComposerRasterSymbolItem*>( cItem );
441  if ( rItem )
442  {
444  return;
445  }
446 
447  // group
448  cItem->setText( cItem->userText() );
449 }
450 
451 void QgsLegendModel::updateLayer( QStandardItem* layerItem )
452 {
453  QgsDebugMsg( "Entered." );
454  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
455  if ( lItem )
456  {
457  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
458  if ( mapLayer )
459  {
460  updateLayerItemText( lItem );
461 
462  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
463  if ( vLayer )
464  {
465  addVectorLayerItemsV2( lItem, vLayer );
466  }
467 
468  QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( mapLayer );
469  if ( rLayer )
470  {
471  addRasterLayerItems( lItem, rLayer );
472  }
473  }
474  }
475 }
476 
477 void QgsLegendModel::updateLayerItemText( QStandardItem* layerItem )
478 {
479  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
480  if ( !lItem ) return;
481 
482  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
483  if ( !mapLayer ) return;
484 
485  QString label = lItem->userText().isEmpty() ? mapLayer->name() : lItem->userText();
486 
487  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
488  if ( vLayer )
489  {
490  addVectorLayerItemsV2( lItem, vLayer );
491  if ( lItem->showFeatureCount() )
492  {
493  label += QString( " [%1]" ).arg( vLayer->featureCount() );
494  }
495  }
496  lItem->setText( label );
497 }
498 
499 void QgsLegendModel::removeLayer( const QString& layerId )
500 {
501  int numRootItems = rowCount();
502  for ( int i = 0; i < numRootItems ; ++i )
503  {
504  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( item( i ) );
505  if ( !lItem )
506  {
507  continue;
508  }
509 
510  if ( layerId == lItem->layerID() )
511  {
513  {
515  if ( layer )
516  {
517  disconnect( layer, SIGNAL( rendererChanged() ), this, SLOT( updateLayer() ) );
518  }
519  }
520  removeRow( i ); //todo: also remove the subitems and their symbols...
521  emit layersChanged();
522  return;
523  }
524  }
525 }
526 
527 void QgsLegendModel::addLayer( QgsMapLayer* theMapLayer, double scaleDenominator, QString rule )
528 {
529  if ( !theMapLayer )
530  {
531  return;
532  }
533 
534  QgsComposerLayerItem* layerItem = new QgsComposerLayerItem( theMapLayer->name() );
535  if ( theMapLayer->title() != "" )
536  {
537  layerItem->setText( theMapLayer->title() );
538  layerItem->setUserText( theMapLayer->title() );
539  }
540  layerItem->setLayerID( theMapLayer->id() );
541  layerItem->setDefaultStyle( scaleDenominator, rule );
542  layerItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
543 
544  QList<QStandardItem *> itemsList;
545  itemsList << layerItem << new QgsComposerStyleItem( layerItem );
546  invisibleRootItem()->appendRow( itemsList );
547 
548  switch ( theMapLayer->type() )
549  {
551  {
552  QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( theMapLayer );
553  if ( vl )
554  {
555  addVectorLayerItemsV2( layerItem, vl, scaleDenominator, rule );
556  }
557  break;
558  }
560  addRasterLayerItems( layerItem, theMapLayer );
561  break;
562  default:
563  break;
564  }
565 
566  if ( mAutoUpdate )
567  {
568  connect( theMapLayer, SIGNAL( rendererChanged() ), this, SLOT( updateLayer() ) );
569  }
570 
571  emit layersChanged();
572 }
573 
575 {
576  QString layerId = qobject_cast<QgsMapLayer*>( QObject::sender() )->id();
577 
578  for ( int i = 0, n = rowCount(); i < n ; ++i )
579  {
580  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( item( i ) );
581  if ( lItem && layerId == lItem->layerID() )
582  {
583  updateLayer( lItem );
584  emit layersChanged();
585  return;
586  }
587  }
588 }
589 
590 bool QgsLegendModel::writeXML( QDomElement& composerLegendElem, QDomDocument& doc ) const
591 {
592  if ( composerLegendElem.isNull() )
593  {
594  return false;
595  }
596 
597  QDomElement legendModelElem = doc.createElement( "Model" );
598  legendModelElem.setAttribute( "autoUpdate", mAutoUpdate );
599  int nTopLevelItems = invisibleRootItem()->rowCount();
600  QStandardItem* currentItem = 0;
601  QgsComposerLegendItem* currentLegendItem = 0;
602 
603  for ( int i = 0; i < nTopLevelItems; ++i )
604  {
605  currentItem = invisibleRootItem()->child( i, 0 );
606  currentLegendItem = dynamic_cast<QgsComposerLegendItem*>( currentItem );
607  if ( currentLegendItem )
608  {
609  currentLegendItem->writeXML( legendModelElem, doc );
610  }
611  }
612 
613  composerLegendElem.appendChild( legendModelElem );
614  return true;
615 }
616 
617 bool QgsLegendModel::readXML( const QDomElement& legendModelElem, const QDomDocument& doc )
618 {
619  Q_UNUSED( doc );
620 
621  if ( legendModelElem.isNull() )
622  {
623  return false;
624  }
625 
626  clear();
627  //disable autoupdates here in order to have a setAutoUpdate(true)
628  //below connect the rendererChanged signals to the layers
629  setAutoUpdate( false );
630 
631  QDomNodeList topLevelItemList = legendModelElem.childNodes();
632  QDomElement currentElem;
633  QgsComposerLegendItem* currentItem = 0;
634 
635  int nTopLevelItems = topLevelItemList.size();
636  for ( int i = 0; i < nTopLevelItems; ++i )
637  {
638  currentElem = topLevelItemList.at( i ).toElement();
639  if ( currentElem.isNull() )
640  {
641  continue;
642  }
643 
644  //toplevel items can be groups or layers
645  if ( currentElem.tagName() == "LayerItem" )
646  {
647  currentItem = new QgsComposerLayerItem();
648  }
649  else if ( currentElem.tagName() == "GroupItem" )
650  {
651  currentItem = new QgsComposerGroupItem();
652  }
653  currentItem->readXML( currentElem, mHasTopLevelWindow );
654 
655  QList<QStandardItem *> itemsList;
656  itemsList << currentItem << new QgsComposerStyleItem( currentItem );
657  appendRow( itemsList );
658  }
659 
660  setAutoUpdate( legendModelElem.attribute( "autoUpdate", "1" ).toInt() );
661  return true;
662 }
663 
665 {
666  return Qt::MoveAction;
667 }
668 
669 Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
670 {
671  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
672  if ( !index.isValid() )
673  {
674  flags |= Qt::ItemIsDropEnabled;
675  return flags;
676  }
677 
678  QStandardItem* item = itemFromIndex( index );
679  QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
680 
681  if ( cItem )
682  {
684  if ( type == QgsComposerLegendItem::GroupItem )
685  {
686  flags |= Qt::ItemIsDragEnabled;
687  flags |= Qt::ItemIsDropEnabled;
688  }
689  else if ( type == QgsComposerLegendItem::LayerItem )
690  {
691  flags |= Qt::ItemIsDragEnabled;
692  }
693  }
694  if ( index.column() == 1 && item )
695  {
696  // Style
697  QStandardItem* firstColumnItem = 0;
698  if ( item->parent() )
699  {
700  firstColumnItem = item->parent()->child( index.row(), 0 );
701  }
702  else
703  {
704  firstColumnItem = QgsLegendModel::item( index.row(), 0 );
705  }
706  cItem = dynamic_cast<QgsComposerLegendItem*>( firstColumnItem );
707 
708  if ( cItem )
709  {
710  if ( cItem->itemType() == QgsComposerLegendItem::GroupItem ||
712  {
713  flags |= Qt::ItemIsEditable;
714  }
715  }
716  }
717  return flags;
718 }
719 
720 bool QgsLegendModel::removeRows( int row, int count, const QModelIndex & parent )
721 {
722  if ( count < 1 )
723  {
724  return false;
725  }
726 
727  if ( parent.isValid() )
728  {
729  for ( int i = row + count - 1; i >= row; --i )
730  {
731  QStandardItem* item = itemFromIndex( parent );
732  if ( item )
733  {
734  item->takeRow( i );
735  }
736  }
737  }
738  else
739  {
740  for ( int i = row + count - 1; i >= row; --i )
741  {
742  takeRow( i );
743  }
744  }
745  return true;
746 }
747 
748 QMimeData* QgsLegendModel::mimeData( const QModelIndexList &indexes ) const
749 {
750  QMimeData* mimeData = new QMimeData();
751  QByteArray encodedData;
752  QDomDocument xmlDoc;
753  QDomElement xmlRootElement = xmlDoc.createElement( "LegendModelDragData" );
754  xmlDoc.appendChild( xmlRootElement );
755 
756  QModelIndexList::const_iterator indexIt = indexes.constBegin();
757  for ( ; indexIt != indexes.constEnd(); ++indexIt )
758  {
759  QStandardItem* sItem = itemFromIndex( *indexIt );
760  if ( sItem )
761  {
762  QgsComposerLegendItem* mItem = dynamic_cast<QgsComposerLegendItem*>( sItem );
763  if ( mItem )
764  {
765  mItem->writeXML( xmlRootElement, xmlDoc );
766  }
767  }
768  }
769  mimeData->setData( "text/xml", xmlDoc.toByteArray() );
770  return mimeData;
771 }
772 
773 QStringList QgsLegendModel::mimeTypes() const
774 {
775  QStringList types;
776  types << "text/xml";
777  return types;
778 }
779 
780 bool QgsLegendModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
781 {
782  Q_UNUSED( action );
783  Q_UNUSED( column );
784 
785  if ( !data->hasFormat( "text/xml" ) )
786  {
787  return false;
788  }
789 
790  QStandardItem* dropIntoItem = 0;
791  if ( parent.isValid() )
792  {
793  dropIntoItem = itemFromIndex( parent );
794  }
795  else
796  {
797  dropIntoItem = invisibleRootItem();
798  }
799 
800  //get XML doc
801  QByteArray encodedData = data->data( "text/xml" );
802  QDomDocument xmlDoc;
803  xmlDoc.setContent( encodedData );
804 
805  QDomElement dragDataElem = xmlDoc.documentElement();
806  if ( dragDataElem.tagName() != "LegendModelDragData" )
807  {
808  return false;
809  }
810 
811  QDomNodeList nodeList = dragDataElem.childNodes();
812  int nChildNodes = nodeList.size();
813  QDomElement currentElem;
814  QString currentTagName;
815  QgsComposerLegendItem* currentItem = 0;
816 
817  for ( int i = 0; i < nChildNodes; ++i )
818  {
819  currentElem = nodeList.at( i ).toElement();
820  if ( currentElem.isNull() )
821  {
822  continue;
823  }
824  currentTagName = currentElem.tagName();
825  if ( currentTagName == "LayerItem" )
826  {
827  currentItem = new QgsComposerLayerItem();
828  }
829  else if ( currentTagName == "GroupItem" )
830  {
831  currentItem = new QgsComposerGroupItem();
832  }
833  else
834  {
835  continue;
836  }
837  currentItem->readXML( currentElem );
838  int index;
839  if ( row < 0 )
840  {
841  index = dropIntoItem->rowCount();
842  }
843  else
844  {
845  index = row + i;
846  }
847  QList<QStandardItem *> itemsList;
848  itemsList << currentItem << new QgsComposerStyleItem( currentItem );
849  dropIntoItem->insertRow( index, itemsList );
850  }
851  emit layersChanged();
852  return true;
853 }
854 
855 void QgsLegendModel::setAutoUpdate( bool autoUpdate )
856 {
857  if ( mAutoUpdate == autoUpdate ) //prevent multiple signal/slot connections
858  {
859  return;
860  }
861 
863  if ( autoUpdate )
864  {
866  {
867  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
868  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( addLayer( QgsMapLayer* ) ) );
869 
870  for ( int i = 0, n = rowCount(); i < n ; ++i )
871  {
872  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( item( i ) );
873  if ( lItem )
874  {
876  if ( layer )
877  {
878  connect( layer, SIGNAL( rendererChanged() ), this, SLOT( updateLayer() ) );
879  }
880  }
881  }
882  }
883  }
884  else
885  {
887  {
888  disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
889  disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( addLayer( QgsMapLayer* ) ) );
890 
891  for ( int i = 0, n = rowCount(); i < n ; ++i )
892  {
893  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( item( i ) );
894  if ( lItem )
895  {
897  if ( layer )
898  {
899  disconnect( layer, SIGNAL( rendererChanged() ), this, SLOT( updateLayer() ) );
900  }
901  }
902  }
903  }
904  }
905 }
void removeLayer(const QString &layerId)
virtual void readXML(const QDomElement &itemElem, bool xServerAvailable=true)=0
Read item content from xml.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
static unsigned index
Base class for all map layer types.
Definition: qgsmaplayer.h:47
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:86
void addLayer(QgsMapLayer *theMapLayer, double scaleDenominator=-1, QString rule="")
void setLayerID(const QString &id)
void updateItemText(QStandardItem *item)
Update single item text using item userText and other properties like showFeatureCount.
QStringList mLayerIds
bool mHasTopLevelWindow
True if this application has toplevel windows (normally true).
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void updateRasterSymbolItemText(QStandardItem *symbolItem)
Qt::DropActions supportedDropActions() const
void updateItem(QStandardItem *item)
Tries to automatically update a model entry (e.g.
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="")
return a list of item text / symbol
virtual QString userText() const
double opacity() const
int addRasterLayerItems(QStandardItem *layerItem, QgsMapLayer *rlayer)
Adds item of raster layer.
void setLayerID(const QString &id)
QString type() const
Definition: qgsrendererv2.h:77
const QString & name() const
Get the display name of the layer.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Implements the drop operation.
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
void updateLayerItemText(QStandardItem *layerItem)
void setDefaultStyle(double scaleDenominator=-1, QString rule="")
void setLayerSet(const QStringList &layerIds, double scaleDenominator=-1, QString rule="")
QgsRasterRenderer * renderer() const
void setAutoUpdate(bool autoUpdate)
void updateSymbolV2ItemText(QStandardItem *symbolItem)
virtual void writeXML(QDomElement &elem, QDomDocument &doc) const =0
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:92
int addVectorLayerItemsV2(QStandardItem *layerItem, QgsVectorLayer *vlayer, double scaleDenominator=-1, QString rule="")
Adds classification items of vector layers using new symbology.
bool writeXML(QDomElement &composerLegendElem, QDomDocument &doc) const
void setSymbolV2(QgsSymbolV2 *s)
Set symbol (takes ownership)
bool mAutoUpdate
True if the legend is auto updated when layers are added or removed from the map canvas.
Abstract base class for the legend item types.
bool readXML(const QDomElement &legendModelElem, const QDomDocument &doc)
bool countSymbolFeatures(bool showProgress=true)
Count features for symbols.
virtual QImage getLegendGraphic(double scale=0, bool forceRefresh=false)
Returns the legend rendered as pixmap useful for that layer that need to get legend layer remotly as ...
QStandardItem * addGroup(QString text=QString::null, int position=-1)
Adds a group.
void layersChanged()
virtual long featureCount() const
Number of features in the layer.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void setLayerSetAndGroups(const QStringList &layerIds, const QList< GroupLayerInfo > &groupInfo)
Sets layer set and groups.
QMimeData * mimeData(const QModelIndexList &indexes) const
For the drag operation.
virtual ItemType itemType() const =0
QStringList mimeTypes() const
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
QgsRasterDataProvider * dataProvider()
Returns the data provider.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color)
Represents a vector layer which manages a vector based data sets.
QList< QPair< QString, QgsSymbolV2 * > > QgsLegendSymbolList
Definition: qgsrendererv2.h:41
const QString & title() const
Definition: qgsmaplayer.h:96
virtual void setUserText(const QString &text)
Raster renderer pipe that applies colors to a raster.
Qt::ItemFlags flags(const QModelIndex &index) const
virtual bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex())
Implemented to support drag operations.
#define tr(sourceText)