QGIS API Documentation  2.2.0-Valmiera
 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 );
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  currentSymbolItem->setColor( itemIt->second );
285  int currentRowCount = layerItem->rowCount();
286  layerItem->setChild( currentRowCount, 0, currentSymbolItem );
287  row++;
288  }
289 
290  // Delete following old items (if current number of items decreased)
291  for ( int i = layerItem->rowCount() - 1; i >= row; --i )
292  {
293  layerItem->removeRow( i );
294  }
295  }
296 
297  return 0;
298 }
299 
300 void QgsLegendModel::updateSymbolV2ItemText( QStandardItem* symbolItem )
301 {
302  QgsComposerSymbolV2Item* sv2Item = dynamic_cast<QgsComposerSymbolV2Item*>( symbolItem );
303  if ( !sv2Item ) return;
304 
305  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( sv2Item->parent() );
306  if ( !lItem ) return;
307 
308  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
309  if ( !mapLayer ) return;
310 
311  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
312  if ( !vLayer ) return;
313 
314  QgsFeatureRendererV2* renderer = vLayer->rendererV2();
315  if ( !renderer ) return;
316 
317  if ( lItem->showFeatureCount() ) vLayer->countSymbolFeatures();
318 
319  QgsLegendSymbolList symbolList = renderer->legendSymbolItems();
320 
321  QPair<QString, QgsSymbolV2*> symbol = symbolList.value( symbolItem->row() );
322 
323  QString label = sv2Item->userText().isEmpty() ? symbol.first : sv2Item->userText();
324 
325  if ( renderer->type() == "singleSymbol" )
326  {
327  if ( !sv2Item->userText().isEmpty() )
328  {
329  label = sv2Item->userText();
330  }
331  else if ( !lItem->userText().isEmpty() )
332  {
333  label = lItem->userText();
334  }
335  else if ( !vLayer->title().isEmpty() )
336  {
337  label = vLayer->title();
338  }
339  else
340  {
341  label = vLayer->name();
342  }
343  }
344 
345  if ( lItem->showFeatureCount() )
346  {
347  // Add counts to multi symbols layers only or labeled single symbols,
348  // so that single symbol layers are still drawn on single line
349  if ( symbolList.size() > 1 || !label.isEmpty() )
350  {
351  label += QString( " [%1]" ).arg( vLayer->featureCount( symbol.second ) );
352  }
353  }
354  symbolItem->setText( label );
355 }
356 
357 void QgsLegendModel::updateRasterSymbolItemText( QStandardItem* symbolItem )
358 {
359  QgsComposerRasterSymbolItem* rItem = dynamic_cast<QgsComposerRasterSymbolItem*>( symbolItem );
360  if ( !rItem ) return;
361 
362  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( rItem->parent() );
363  if ( !lItem ) return;
364 
365  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
366  if ( !mapLayer ) return;
367 
368  QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( mapLayer );
369  if ( !rLayer ) return;
370 
371  QPair< QString, QColor> symbol = rLayer->legendSymbologyItems().value( symbolItem->row() );
372 
373  QString label = rItem->userText().isEmpty() ? symbol.first : rItem->userText();
374 
375  symbolItem->setText( label );
376 }
377 
378 void QgsLegendModel::updateItem( QStandardItem* item )
379 {
380  if ( !item )
381  {
382  return;
383  }
384 
385  //only layer items are supported for update
386  QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
387  if ( ! cItem )
388  {
389  return;
390  }
391 
393  if ( type == QgsComposerLegendItem::LayerItem )
394  {
395  updateLayer( cItem );
396  }
397 }
398 
399 void QgsLegendModel::updateItemText( QStandardItem* item )
400 {
401  if ( !item )
402  {
403  return;
404  }
405 
406  //only layer items are supported for update
407  QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
408  if ( ! cItem )
409  {
410  return;
411  }
412 
413  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( cItem );
414  if ( lItem )
415  {
416  updateLayerItemText( lItem );
417  return;
418  }
419 
420  QgsComposerSymbolV2Item* sv2Item = dynamic_cast<QgsComposerSymbolV2Item*>( cItem );
421  if ( sv2Item )
422  {
423  updateSymbolV2ItemText( sv2Item );
424  return;
425  }
426 
427  QgsComposerRasterSymbolItem* rItem = dynamic_cast<QgsComposerRasterSymbolItem*>( cItem );
428  if ( rItem )
429  {
431  return;
432  }
433 
434  // group
435  cItem->setText( cItem->userText() );
436 }
437 
438 void QgsLegendModel::updateLayer( QStandardItem* layerItem )
439 {
440  QgsDebugMsg( "Entered." );
441  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
442  if ( lItem )
443  {
444  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
445  if ( mapLayer )
446  {
447  updateLayerItemText( lItem );
448 
449  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
450  if ( vLayer )
451  {
452  addVectorLayerItemsV2( lItem, vLayer );
453  }
454 
455  QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( mapLayer );
456  if ( rLayer )
457  {
458  addRasterLayerItems( lItem, rLayer );
459  }
460  }
461  }
462 }
463 
464 void QgsLegendModel::updateLayerItemText( QStandardItem* layerItem )
465 {
466  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
467  if ( !lItem ) return;
468 
469  QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
470  if ( !mapLayer ) return;
471 
472  QString label = lItem->userText().isEmpty() ? mapLayer->name() : lItem->userText();
473 
474  QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
475  if ( vLayer )
476  {
477  addVectorLayerItemsV2( lItem, vLayer );
478  if ( lItem->showFeatureCount() )
479  {
480  label += QString( " [%1]" ).arg( vLayer->featureCount() );
481  }
482  }
483  lItem->setText( label );
484 }
485 
486 void QgsLegendModel::removeLayer( const QString& layerId )
487 {
488  int numRootItems = rowCount();
489  for ( int i = 0; i < numRootItems ; ++i )
490  {
491  QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( item( i ) );
492  if ( !lItem )
493  {
494  continue;
495  }
496 
497  if ( layerId == lItem->layerID() )
498  {
499  removeRow( i ); //todo: also remove the subitems and their symbols...
500  emit layersChanged();
501  return;
502  }
503  }
504 }
505 
506 void QgsLegendModel::addLayer( QgsMapLayer* theMapLayer, double scaleDenominator, QString rule )
507 {
508  if ( !theMapLayer )
509  {
510  return;
511  }
512 
513  QgsComposerLayerItem* layerItem = new QgsComposerLayerItem( theMapLayer->name() );
514  if ( theMapLayer->title() != "" )
515  {
516  layerItem->setText( theMapLayer->title() );
517  layerItem->setUserText( theMapLayer->title() );
518  }
519  layerItem->setLayerID( theMapLayer->id() );
520  layerItem->setDefaultStyle( scaleDenominator, rule );
521  layerItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
522 
523  QList<QStandardItem *> itemsList;
524  itemsList << layerItem << new QgsComposerStyleItem( layerItem );
525  invisibleRootItem()->appendRow( itemsList );
526 
527  switch ( theMapLayer->type() )
528  {
530  {
531  QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( theMapLayer );
532  if ( vl )
533  {
534  addVectorLayerItemsV2( layerItem, vl, scaleDenominator, rule );
535  }
536  break;
537  }
539  addRasterLayerItems( layerItem, theMapLayer );
540  break;
541  default:
542  break;
543  }
544  emit layersChanged();
545 }
546 
547 
548 bool QgsLegendModel::writeXML( QDomElement& composerLegendElem, QDomDocument& doc ) const
549 {
550  if ( composerLegendElem.isNull() )
551  {
552  return false;
553  }
554 
555  QDomElement legendModelElem = doc.createElement( "Model" );
556  legendModelElem.setAttribute( "autoUpdate", mAutoUpdate );
557  int nTopLevelItems = invisibleRootItem()->rowCount();
558  QStandardItem* currentItem = 0;
559  QgsComposerLegendItem* currentLegendItem = 0;
560 
561  for ( int i = 0; i < nTopLevelItems; ++i )
562  {
563  currentItem = invisibleRootItem()->child( i, 0 );
564  currentLegendItem = dynamic_cast<QgsComposerLegendItem*>( currentItem );
565  if ( currentLegendItem )
566  {
567  currentLegendItem->writeXML( legendModelElem, doc );
568  }
569  }
570 
571  composerLegendElem.appendChild( legendModelElem );
572  return true;
573 }
574 
575 bool QgsLegendModel::readXML( const QDomElement& legendModelElem, const QDomDocument& doc )
576 {
577  Q_UNUSED( doc );
578 
579  if ( legendModelElem.isNull() )
580  {
581  return false;
582  }
583 
584  clear();
585 
586  QDomNodeList topLevelItemList = legendModelElem.childNodes();
587  QDomElement currentElem;
588  QgsComposerLegendItem* currentItem = 0;
589 
590  int nTopLevelItems = topLevelItemList.size();
591  for ( int i = 0; i < nTopLevelItems; ++i )
592  {
593  currentElem = topLevelItemList.at( i ).toElement();
594  if ( currentElem.isNull() )
595  {
596  continue;
597  }
598 
599  //toplevel items can be groups or layers
600  if ( currentElem.tagName() == "LayerItem" )
601  {
602  currentItem = new QgsComposerLayerItem();
603  }
604  else if ( currentElem.tagName() == "GroupItem" )
605  {
606  currentItem = new QgsComposerGroupItem();
607  }
608  currentItem->readXML( currentElem, mHasTopLevelWindow );
609 
610  QList<QStandardItem *> itemsList;
611  itemsList << currentItem << new QgsComposerStyleItem( currentItem );
612  appendRow( itemsList );
613  }
614 
615  setAutoUpdate( legendModelElem.attribute( "autoUpdate", "1" ).toInt() );
616  return true;
617 }
618 
620 {
621  return Qt::MoveAction;
622 }
623 
624 Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
625 {
626  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
627  if ( !index.isValid() )
628  {
629  flags |= Qt::ItemIsDropEnabled;
630  return flags;
631  }
632 
633  QStandardItem* item = itemFromIndex( index );
634  QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
635 
636  if ( cItem )
637  {
639  if ( type == QgsComposerLegendItem::GroupItem )
640  {
641  flags |= Qt::ItemIsDragEnabled;
642  flags |= Qt::ItemIsDropEnabled;
643  }
644  else if ( type == QgsComposerLegendItem::LayerItem )
645  {
646  flags |= Qt::ItemIsDragEnabled;
647  }
648  }
649  if ( index.column() == 1 && item )
650  {
651  // Style
652  QStandardItem* firstColumnItem = 0;
653  if ( item->parent() )
654  {
655  firstColumnItem = item->parent()->child( index.row(), 0 );
656  }
657  else
658  {
659  firstColumnItem = QgsLegendModel::item( index.row(), 0 );
660  }
661  cItem = dynamic_cast<QgsComposerLegendItem*>( firstColumnItem );
662 
663  if ( cItem )
664  {
665  if ( cItem->itemType() == QgsComposerLegendItem::GroupItem ||
667  {
668  flags |= Qt::ItemIsEditable;
669  }
670  }
671  }
672  return flags;
673 }
674 
675 bool QgsLegendModel::removeRows( int row, int count, const QModelIndex & parent )
676 {
677  if ( count < 1 )
678  {
679  return false;
680  }
681 
682  if ( parent.isValid() )
683  {
684  for ( int i = row + count - 1; i >= row; --i )
685  {
686  QStandardItem* item = itemFromIndex( parent );
687  if ( item )
688  {
689  item->takeRow( i );
690  }
691  }
692  }
693  else
694  {
695  for ( int i = row + count - 1; i >= row; --i )
696  {
697  takeRow( i );
698  }
699  }
700  return true;
701 }
702 
703 QMimeData* QgsLegendModel::mimeData( const QModelIndexList &indexes ) const
704 {
705  QMimeData* mimeData = new QMimeData();
706  QByteArray encodedData;
707  QDomDocument xmlDoc;
708  QDomElement xmlRootElement = xmlDoc.createElement( "LegendModelDragData" );
709  xmlDoc.appendChild( xmlRootElement );
710 
711  QModelIndexList::const_iterator indexIt = indexes.constBegin();
712  for ( ; indexIt != indexes.constEnd(); ++indexIt )
713  {
714  QStandardItem* sItem = itemFromIndex( *indexIt );
715  if ( sItem )
716  {
717  QgsComposerLegendItem* mItem = dynamic_cast<QgsComposerLegendItem*>( sItem );
718  if ( mItem )
719  {
720  mItem->writeXML( xmlRootElement, xmlDoc );
721  }
722  }
723  }
724  mimeData->setData( "text/xml", xmlDoc.toByteArray() );
725  return mimeData;
726 }
727 
728 QStringList QgsLegendModel::mimeTypes() const
729 {
730  QStringList types;
731  types << "text/xml";
732  return types;
733 }
734 
735 bool QgsLegendModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
736 {
737  Q_UNUSED( action );
738  Q_UNUSED( column );
739 
740  if ( !data->hasFormat( "text/xml" ) )
741  {
742  return false;
743  }
744 
745  QStandardItem* dropIntoItem = 0;
746  if ( parent.isValid() )
747  {
748  dropIntoItem = itemFromIndex( parent );
749  }
750  else
751  {
752  dropIntoItem = invisibleRootItem();
753  }
754 
755  //get XML doc
756  QByteArray encodedData = data->data( "text/xml" );
757  QDomDocument xmlDoc;
758  xmlDoc.setContent( encodedData );
759 
760  QDomElement dragDataElem = xmlDoc.documentElement();
761  if ( dragDataElem.tagName() != "LegendModelDragData" )
762  {
763  return false;
764  }
765 
766  QDomNodeList nodeList = dragDataElem.childNodes();
767  int nChildNodes = nodeList.size();
768  QDomElement currentElem;
769  QString currentTagName;
770  QgsComposerLegendItem* currentItem = 0;
771 
772  for ( int i = 0; i < nChildNodes; ++i )
773  {
774  currentElem = nodeList.at( i ).toElement();
775  if ( currentElem.isNull() )
776  {
777  continue;
778  }
779  currentTagName = currentElem.tagName();
780  if ( currentTagName == "LayerItem" )
781  {
782  currentItem = new QgsComposerLayerItem();
783  }
784  else if ( currentTagName == "GroupItem" )
785  {
786  currentItem = new QgsComposerGroupItem();
787  }
788  else
789  {
790  continue;
791  }
792  currentItem->readXML( currentElem );
793  int index;
794  if ( row < 0 )
795  {
796  index = dropIntoItem->rowCount();
797  }
798  else
799  {
800  index = row + i;
801  }
802  QList<QStandardItem *> itemsList;
803  itemsList << currentItem << new QgsComposerStyleItem( currentItem );
804  dropIntoItem->insertRow( index, itemsList );
805  }
806  emit layersChanged();
807  return true;
808 }
809 
810 void QgsLegendModel::setAutoUpdate( bool autoUpdate )
811 {
812  if ( mAutoUpdate == autoUpdate ) //prevent multiple signal/slot connections
813  {
814  return;
815  }
816 
818  if ( autoUpdate )
819  {
821  {
822  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
823  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( addLayer( QgsMapLayer* ) ) );
824  }
825  }
826  else
827  {
829  {
830  disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
831  disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( addLayer( QgsMapLayer* ) ) );
832  }
833  }
834 }