QGIS API Documentation  2.3.0-Master
 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 }
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
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="")
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?
void updateLayer(QStandardItem *layerItem)
Updates the whole symbology of a layer.
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)
QList< QPair< QString, QColor > > legendSymbologyItems() const
Returns a list with classification items (Text and color)
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)