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