00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "qgslegendmodel.h"
00019 #include "qgscomposerlegenditem.h"
00020 #include "qgsfield.h"
00021 #include "qgsmaplayer.h"
00022 #include "qgsmaplayerregistry.h"
00023 #include "qgsrasterlayer.h"
00024 #include "qgsrenderer.h"
00025 #include "qgsrendererv2.h"
00026 #include "qgssymbollayerv2utils.h"
00027 #include "qgssymbol.h"
00028 #include "qgsvectordataprovider.h"
00029 #include "qgsvectorlayer.h"
00030 #include <QApplication>
00031 #include <QDomDocument>
00032 #include <QDomElement>
00033 #include <QMimeData>
00034 #include <QSettings>
00035
00036 QgsLegendModel::QgsLegendModel(): QStandardItemModel()
00037 {
00038 if ( QgsMapLayerRegistry::instance() )
00039 {
00040 connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
00041 connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( addLayer( QgsMapLayer* ) ) );
00042 }
00043 setItemPrototype( new QgsComposerSymbolItem() );
00044
00045 QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
00046 mHasTopLevelWindow = ( topLevelWidgets.size() > 0 );
00047 }
00048
00049 QgsLegendModel::~QgsLegendModel()
00050 {
00051 }
00052
00053 void QgsLegendModel::setLayerSetAndGroups( const QStringList& layerIds, const QList< GroupLayerInfo >& groupInfo )
00054 {
00055 setLayerSet( layerIds );
00056
00057 QStandardItem* currentItem = 0;
00058 QStandardItem* currentGroupItem = 0;
00059 int i = 0;
00060
00061 QList< GroupLayerInfo >::const_iterator infoIt = groupInfo.constBegin();
00062 for ( ; infoIt != groupInfo.constEnd() && i < invisibleRootItem()->rowCount(); )
00063 {
00064 currentItem = invisibleRootItem()->child( i, 0 );
00065 QString infoKey = infoIt->first;
00066 if ( infoKey.isNull() )
00067 {
00068 ++i;
00069 }
00070 else
00071 {
00072 currentGroupItem = addGroup( infoKey, i );
00073 ++i;
00074 QList<QString> layerList = infoIt->second;
00075 QList<QString>::const_iterator groupLayerIt = layerList.constBegin();
00076 for ( ; currentItem && ( groupLayerIt != layerList.constEnd() ); ++groupLayerIt )
00077 {
00078
00079 QgsComposerLayerItem* layerItem = dynamic_cast<QgsComposerLayerItem*>( currentItem );
00080 if ( !layerItem )
00081 {
00082 return;
00083 }
00084
00085 QString layerID = layerItem->layerID();
00086 if ( layerList.contains( layerID ) )
00087 {
00088 takeRow( i );
00089 currentGroupItem->setChild( currentGroupItem->rowCount(), 0, currentItem );
00090 }
00091 else
00092 {
00093 ++i;
00094 }
00095 currentItem = invisibleRootItem()->child( i, 0 );
00096 }
00097 }
00098 ++infoIt;
00099 }
00100 }
00101
00102 void QgsLegendModel::setLayerSet( const QStringList& layerIds )
00103 {
00104 mLayerIds = layerIds;
00105
00106
00107 clear();
00108
00109 QStringList::const_iterator idIter = mLayerIds.constBegin();
00110 QgsMapLayer* currentLayer = 0;
00111
00112 for ( ; idIter != mLayerIds.constEnd(); ++idIter )
00113 {
00114 currentLayer = QgsMapLayerRegistry::instance()->mapLayer( *idIter );
00115 addLayer( currentLayer );
00116 }
00117 }
00118
00119 QStandardItem* QgsLegendModel::addGroup( QString text, int position )
00120 {
00121 QgsComposerGroupItem* groupItem = new QgsComposerGroupItem( text );
00122 if ( position == -1 )
00123 {
00124 invisibleRootItem()->insertRow( invisibleRootItem()->rowCount(), groupItem );
00125 }
00126 else
00127 {
00128 invisibleRootItem()->insertRow( position, groupItem );
00129 }
00130 return groupItem;
00131 }
00132
00133 int QgsLegendModel::addVectorLayerItemsV2( QStandardItem* layerItem, QgsVectorLayer* vlayer )
00134 {
00135 if ( !layerItem || !vlayer )
00136 {
00137 return 1;
00138 }
00139
00140 QgsFeatureRendererV2* renderer = vlayer->rendererV2();
00141 if ( !renderer )
00142 {
00143 return 2;
00144 }
00145
00146 QgsLegendSymbolList lst = renderer->legendSymbolItems();
00147 QgsLegendSymbolList::const_iterator symbolIt = lst.constBegin();
00148 for ( ; symbolIt != lst.constEnd(); ++symbolIt )
00149 {
00150 QgsComposerSymbolV2Item* currentSymbolItem = new QgsComposerSymbolV2Item( symbolIt->first );
00151 currentSymbolItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
00152 if ( symbolIt->second )
00153 {
00154 if ( mHasTopLevelWindow )
00155 {
00156 currentSymbolItem->setIcon( QgsSymbolLayerV2Utils::symbolPreviewIcon( symbolIt->second, QSize( 30, 30 ) ) );
00157 }
00158 currentSymbolItem->setSymbolV2( symbolIt->second->clone() );
00159 }
00160 layerItem->setChild( layerItem->rowCount(), 0, currentSymbolItem );
00161 }
00162
00163 return 0;
00164 }
00165
00166 int QgsLegendModel::addVectorLayerItems( QStandardItem* layerItem, QgsVectorLayer* vlayer )
00167 {
00168 if ( !layerItem || !vlayer )
00169 {
00170 return 1;
00171 }
00172
00173 int opacity = vlayer->getTransparency();
00174
00175 const QgsRenderer* vectorRenderer = vlayer->renderer();
00176 if ( !vectorRenderer )
00177 {
00178 return 3;
00179 }
00180
00181
00182 QSettings settings;
00183 if ( settings.value( "/qgis/showLegendClassifiers", false ).toBool() )
00184 {
00185 QgsFieldMap layerFields = vlayer->pendingFields();
00186 QgsAttributeList attributes = vectorRenderer->classificationAttributes();
00187 QgsAttributeList::const_iterator att_it = attributes.constBegin();
00188 for ( ; att_it != attributes.constEnd(); ++att_it )
00189 {
00190 QgsFieldMap::const_iterator fieldIt = layerFields.find( *att_it );
00191 if ( fieldIt != layerFields.constEnd() )
00192 {
00193 QString attributeName = vlayer->attributeDisplayName( fieldIt.key() );
00194 QStandardItem* attributeItem = new QStandardItem( attributeName );
00195 attributeItem->setData( QgsLegendModel::ClassificationItem, Qt::UserRole + 1 );
00196 attributeItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
00197 layerItem->setChild( layerItem->rowCount(), 0, attributeItem );
00198 }
00199 }
00200 }
00201
00202 const QList<QgsSymbol*> vectorSymbols = vectorRenderer->symbols();
00203 QList<QgsSymbol*>::const_iterator symbolIt = vectorSymbols.constBegin();
00204
00205 for ( ; symbolIt != vectorSymbols.constEnd(); ++symbolIt )
00206 {
00207 if ( !( *symbolIt ) )
00208 {
00209 continue;
00210 }
00211
00212 QStandardItem* currentSymbolItem = itemFromSymbol( *symbolIt, opacity, vlayer->getLayerID() );
00213 if ( !currentSymbolItem )
00214 {
00215 continue;
00216 }
00217
00218 layerItem->setChild( layerItem->rowCount(), 0, currentSymbolItem );
00219
00220 }
00221
00222 return 0;
00223 }
00224
00225 int QgsLegendModel::addRasterLayerItem( QStandardItem* layerItem, QgsMapLayer* rlayer )
00226 {
00227 if ( !layerItem || !rlayer )
00228 {
00229 return 1;
00230 }
00231
00232 QgsRasterLayer* rasterLayer = qobject_cast<QgsRasterLayer *>( rlayer );
00233 if ( !rasterLayer )
00234 {
00235 return 2;
00236 }
00237
00238 QgsComposerRasterSymbolItem* currentSymbolItem = new QgsComposerRasterSymbolItem();
00239
00240 if ( mHasTopLevelWindow )
00241 {
00242 currentSymbolItem->setIcon( QIcon( rasterLayer->legendAsPixmap( true ) ) );
00243 }
00244 currentSymbolItem->setLayerID( rasterLayer->getLayerID() );
00245 int currentRowCount = layerItem->rowCount();
00246 layerItem->setChild( currentRowCount, 0, currentSymbolItem );
00247
00248 return 0;
00249 }
00250
00251 void QgsLegendModel::updateItem( QStandardItem* item )
00252 {
00253 if ( !item )
00254 {
00255 return;
00256 }
00257
00258
00259 QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
00260 if ( ! cItem )
00261 {
00262 return;
00263 }
00264
00265 QgsComposerLegendItem::ItemType type = cItem->itemType();
00266 if ( type == QgsComposerLegendItem::LayerItem )
00267 {
00268 updateLayer( cItem );
00269 }
00270 }
00271
00272 void QgsLegendModel::updateLayer( QStandardItem* layerItem )
00273 {
00274 QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
00275 if ( lItem )
00276 {
00277 QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( lItem->layerID() );
00278 if ( mapLayer )
00279 {
00280
00281 int currentRowCount = lItem->rowCount();
00282 for ( int i = currentRowCount - 1; i >= 0; --i )
00283 {
00284 lItem->removeRow( i );
00285 }
00286
00287
00288 layerItem->setText( mapLayer->name() );
00289
00290 QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
00291 if ( vLayer )
00292 {
00293 if ( vLayer->isUsingRendererV2() )
00294 {
00295 addVectorLayerItemsV2( lItem, vLayer );
00296 }
00297 else
00298 {
00299 addVectorLayerItems( lItem, vLayer );
00300 }
00301 }
00302
00303 QgsRasterLayer* rLayer = qobject_cast<QgsRasterLayer*>( mapLayer );
00304 if ( rLayer )
00305 {
00306 addRasterLayerItem( lItem, rLayer );
00307 }
00308 }
00309 }
00310 }
00311
00312 void QgsLegendModel::removeLayer( const QString& layerId )
00313 {
00314 QStandardItem* currentLayerItem = 0;
00315
00316 int numRootItems = rowCount();
00317 for ( int i = 0; i < numRootItems ; ++i )
00318 {
00319 currentLayerItem = item( i );
00320 if ( !currentLayerItem )
00321 {
00322 continue;
00323 }
00324
00325 QString currentId = currentLayerItem->data( Qt::UserRole + 2 ).toString();
00326 if ( currentId == layerId )
00327 {
00328 removeRow( i );
00329 emit layersChanged();
00330 return;
00331 }
00332 }
00333 }
00334
00335 void QgsLegendModel::addLayer( QgsMapLayer* theMapLayer )
00336 {
00337 if ( !theMapLayer )
00338 {
00339 return;
00340 }
00341
00342 QgsComposerLayerItem* layerItem = new QgsComposerLayerItem( theMapLayer->name() );
00343 layerItem->setLayerID( theMapLayer->getLayerID() );
00344 layerItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
00345
00346 invisibleRootItem()->setChild( invisibleRootItem()->rowCount(), layerItem );
00347
00348 switch ( theMapLayer->type() )
00349 {
00350 case QgsMapLayer::VectorLayer:
00351 {
00352 QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( theMapLayer );
00353 if ( vl )
00354 {
00355 if ( vl->isUsingRendererV2() )
00356 {
00357 addVectorLayerItemsV2( layerItem, vl );
00358 }
00359 else
00360 {
00361 addVectorLayerItems( layerItem, vl );
00362 }
00363 }
00364 break;
00365 }
00366 case QgsMapLayer::RasterLayer:
00367 addRasterLayerItem( layerItem, theMapLayer );
00368 break;
00369 default:
00370 break;
00371 }
00372 emit layersChanged();
00373 }
00374
00375 QStandardItem* QgsLegendModel::itemFromSymbol( QgsSymbol* s, int opacity, const QString& layerID )
00376 {
00377 QgsComposerSymbolItem* currentSymbolItem = 0;
00378
00379
00380 QString itemText;
00381 QString label;
00382
00383 QString lowerValue = s->lowerValue();
00384 QString upperValue = s->upperValue();
00385
00386 label = s->label();
00387
00388
00389 if ( !label.isEmpty() )
00390 {
00391 itemText = label;
00392 }
00393
00394 else if ( lowerValue == upperValue || upperValue.isEmpty() )
00395 {
00396 itemText = lowerValue;
00397 }
00398 else
00399 {
00400 itemText = lowerValue + " - " + upperValue;
00401 }
00402
00403
00404 QImage symbolImage;
00405 switch ( s->type() )
00406 {
00407 case QGis::Point:
00408 symbolImage = s->getPointSymbolAsImage();
00409 break;
00410 case QGis::Line:
00411 symbolImage = s->getLineSymbolAsImage();
00412 break;
00413 case QGis::Polygon:
00414 symbolImage = s->getPolygonSymbolAsImage();
00415 break;
00416 default:
00417 return 0;
00418 }
00419
00420 if ( opacity != 255 )
00421 {
00422
00423 QRgb oldColor;
00424 for ( int i = 0; i < symbolImage.height(); ++i )
00425 {
00426 QRgb* scanLineBuffer = ( QRgb* ) symbolImage.scanLine( i );
00427 for ( int j = 0; j < symbolImage.width(); ++j )
00428 {
00429 oldColor = symbolImage.pixel( j, i );
00430 scanLineBuffer[j] = qRgba( qRed( oldColor ), qGreen( oldColor ), qBlue( oldColor ), opacity );
00431 }
00432 }
00433 }
00434
00435 currentSymbolItem = new QgsComposerSymbolItem( itemText );
00436 if ( mHasTopLevelWindow )
00437 {
00438 currentSymbolItem->setIcon( QIcon( QPixmap::fromImage( symbolImage ) ) );
00439 }
00440
00441 if ( !currentSymbolItem )
00442 {
00443 return 0;
00444 }
00445
00446
00447 QgsSymbol* symbolCopy = new QgsSymbol( *s );
00448 currentSymbolItem->setSymbol( symbolCopy );
00449 currentSymbolItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
00450 currentSymbolItem ->setLayerID( layerID );
00451 return currentSymbolItem;
00452 }
00453
00454 bool QgsLegendModel::writeXML( QDomElement& composerLegendElem, QDomDocument& doc ) const
00455 {
00456 if ( composerLegendElem.isNull() )
00457 {
00458 return false;
00459 }
00460
00461 QDomElement legendModelElem = doc.createElement( "Model" );
00462 int nTopLevelItems = invisibleRootItem()->rowCount();
00463 QStandardItem* currentItem = 0;
00464 QgsComposerLegendItem* currentLegendItem = 0;
00465
00466 for ( int i = 0; i < nTopLevelItems; ++i )
00467 {
00468 currentItem = invisibleRootItem()->child( i, 0 );
00469 currentLegendItem = dynamic_cast<QgsComposerLegendItem*>( currentItem );
00470 if ( currentLegendItem )
00471 {
00472 currentLegendItem->writeXML( legendModelElem, doc );
00473 }
00474 }
00475
00476 composerLegendElem.appendChild( legendModelElem );
00477 return true;
00478 }
00479
00480 bool QgsLegendModel::readXML( const QDomElement& legendModelElem, const QDomDocument& doc )
00481 {
00482 if ( legendModelElem.isNull() )
00483 {
00484 return false;
00485 }
00486
00487 clear();
00488
00489 QDomNodeList topLevelItemList = legendModelElem.childNodes();
00490 QDomElement currentElem;
00491 QgsComposerLegendItem* currentItem = 0;
00492
00493 int nTopLevelItems = topLevelItemList.size();
00494 for ( int i = 0; i < nTopLevelItems; ++i )
00495 {
00496 currentElem = topLevelItemList.at( i ).toElement();
00497 if ( currentElem.isNull() )
00498 {
00499 continue;
00500 }
00501
00502
00503 if ( currentElem.tagName() == "LayerItem" )
00504 {
00505 currentItem = new QgsComposerLayerItem();
00506 }
00507 else if ( currentElem.tagName() == "GroupItem" )
00508 {
00509 currentItem = new QgsComposerGroupItem();
00510 }
00511 currentItem->readXML( currentElem );
00512 appendRow( currentItem );
00513 }
00514 return true;
00515 }
00516
00517 Qt::DropActions QgsLegendModel::supportedDropActions() const
00518 {
00519 return Qt::MoveAction;
00520 }
00521
00522 Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
00523 {
00524 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
00525 if ( !index.isValid() )
00526 {
00527 flags |= Qt::ItemIsDropEnabled;
00528 return flags;
00529 }
00530
00531 QStandardItem* item = itemFromIndex( index );
00532 QgsComposerLegendItem* cItem = dynamic_cast<QgsComposerLegendItem*>( item );
00533
00534 if ( cItem )
00535 {
00536 QgsComposerLegendItem::ItemType type = cItem->itemType();
00537 if ( type == QgsComposerLegendItem::GroupItem )
00538 {
00539 flags |= Qt::ItemIsDragEnabled;
00540 flags |= Qt::ItemIsDropEnabled;
00541 }
00542 else if ( type == QgsComposerLegendItem::LayerItem )
00543 {
00544 flags |= Qt::ItemIsDragEnabled;
00545 }
00546 }
00547 return flags;
00548 }
00549
00550 bool QgsLegendModel::removeRows( int row, int count, const QModelIndex & parent )
00551 {
00552 if ( count < 1 )
00553 {
00554 return false;
00555 }
00556
00557 if ( parent.isValid() )
00558 {
00559 for ( int i = row + count - 1; i >= row; --i )
00560 {
00561 QStandardItem* item = itemFromIndex( parent );
00562 if ( item )
00563 {
00564 item->takeRow( i );
00565 }
00566 }
00567 }
00568 else
00569 {
00570 for ( int i = row + count - 1; i >= row; --i )
00571 {
00572 takeRow( i );
00573 }
00574 }
00575 return true;
00576 }
00577
00578 QMimeData* QgsLegendModel::mimeData( const QModelIndexList &indexes ) const
00579 {
00580 QMimeData* mimeData = new QMimeData();
00581 QByteArray encodedData;
00582 QDomDocument xmlDoc;
00583 QDomElement xmlRootElement = xmlDoc.createElement( "LegendModelDragData" );
00584 xmlDoc.appendChild( xmlRootElement );
00585
00586 QModelIndexList::const_iterator indexIt = indexes.constBegin();
00587 for ( ; indexIt != indexes.constEnd(); ++indexIt )
00588 {
00589 QStandardItem* sItem = itemFromIndex( *indexIt );
00590 if ( sItem )
00591 {
00592 QgsComposerLegendItem* mItem = dynamic_cast<QgsComposerLegendItem*>( sItem );
00593 if ( mItem )
00594 {
00595 mItem->writeXML( xmlRootElement, xmlDoc );
00596 }
00597 }
00598 }
00599 mimeData->setData( "text/xml", xmlDoc.toByteArray() );
00600 return mimeData;
00601 }
00602
00603 QStringList QgsLegendModel::mimeTypes() const
00604 {
00605 QStringList types;
00606 types << "text/xml";
00607 return types;
00608 }
00609
00610 bool QgsLegendModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
00611 {
00612 if ( !data->hasFormat( "text/xml" ) )
00613 {
00614 return false;
00615 }
00616
00617 QStandardItem* dropIntoItem = 0;
00618 if ( parent.isValid() )
00619 {
00620 dropIntoItem = itemFromIndex( parent );
00621 }
00622 else
00623 {
00624 dropIntoItem = invisibleRootItem();
00625 }
00626
00627
00628 QByteArray encodedData = data->data( "text/xml" );
00629 QDomDocument xmlDoc;
00630 xmlDoc.setContent( encodedData );
00631
00632 QDomElement dragDataElem = xmlDoc.documentElement();
00633 if ( dragDataElem.tagName() != "LegendModelDragData" )
00634 {
00635 return false;
00636 }
00637
00638 QDomNodeList nodeList = dragDataElem.childNodes();
00639 int nChildNodes = nodeList.size();
00640 QDomElement currentElem;
00641 QString currentTagName;
00642 QgsComposerLegendItem* currentItem = 0;
00643
00644 for ( int i = 0; i < nChildNodes; ++i )
00645 {
00646 currentElem = nodeList.at( i ).toElement();
00647 if ( currentElem.isNull() )
00648 {
00649 continue;
00650 }
00651 currentTagName = currentElem.tagName();
00652 if ( currentTagName == "LayerItem" )
00653 {
00654 currentItem = new QgsComposerLayerItem();
00655 }
00656 else if ( currentTagName == "GroupItem" )
00657 {
00658 currentItem = new QgsComposerGroupItem();
00659 }
00660 else
00661 {
00662 continue;
00663 }
00664 currentItem->readXML( currentElem );
00665 if ( row < 0 )
00666 {
00667 dropIntoItem->insertRow( dropIntoItem->rowCount(), currentItem );
00668 }
00669 else
00670 {
00671 dropIntoItem->insertRow( row + i, currentItem );
00672 }
00673 }
00674 emit layersChanged();
00675 return true;
00676 }