Skip to content

Commit 32b63f2

Browse files
author
mhugent
committed
Legend update function for composer on item level
git-svn-id: http://svn.osgeo.org/qgis/trunk@9228 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent edbdba1 commit 32b63f2

File tree

3 files changed

+219
-86
lines changed

3 files changed

+219
-86
lines changed

src/app/composer/qgscomposerlegendwidget.cpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,11 @@ void QgsComposerLegendWidget::on_mUpdatePushButton_clicked()
363363
return;
364364
}
365365

366-
QModelIndex parentIndex = currentIndex.parent();
367-
if ( !parentIndex.isValid() ) // a layer item
368-
{
369-
QString mapLayerId = currentItem->data().toString();
370-
mLegend->model()->updateLayer( mapLayerId );
371-
mLegend->update();
372-
}
366+
if(mLegend->model())
367+
{
368+
mLegend->model()->updateItem(currentItem);
369+
}
370+
mLegend->update();
373371
}
374372

375373
void QgsComposerLegendWidget::on_mUpdateAllPushButton_clicked()

src/core/composer/qgslegendmodel.cpp

+204-75
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ int QgsLegendModel::addVectorLayerItems( QStandardItem* layerItem, QgsMapLayer*
134134
continue;
135135
}
136136

137+
#if 0
137138
//label
138139
QString label;
139140
QString lowerValue = ( *symbolIt )->lowerValue();
@@ -170,12 +171,14 @@ int QgsLegendModel::addVectorLayerItems( QStandardItem* layerItem, QgsMapLayer*
170171
currentSymbolItem->setData( QVariant::fromValue(( void* )symbolCopy ) );
171172
insertSymbol( symbolCopy );
172173

173-
if ( !currentSymbolItem )
174-
{
175-
continue;
176-
}
177-
178174
currentSymbolItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
175+
#endif //0
176+
177+
QStandardItem* currentSymbolItem = itemFromSymbol(*symbolIt);
178+
if(!currentSymbolItem)
179+
{
180+
continue;
181+
}
179182

180183
layerItem->setChild( layerItem->rowCount(), 0, currentSymbolItem );
181184

@@ -230,103 +233,180 @@ void QgsLegendModel::removeAllSymbols()
230233
mSymbols.clear();
231234
}
232235

233-
#if 0
234-
void QgsLegendModel::updateLayerEntries( const QStringList& newLayerIds )
236+
void QgsLegendModel::updateItem(QStandardItem* item)
235237
{
236-
if ( !invisibleRootItem() )
237-
{
238-
return;
239-
}
238+
if(!item)
239+
{
240+
return;
241+
}
240242

241-
//check for layers to remove
242-
QStandardItem* currentLayerItem = 0;
243-
QSet<int> rowsToRemove;
243+
//is it a toplevel layer item?
244+
QModelIndex itemIndex = indexFromItem(item);
245+
QModelIndex parentIndex = itemIndex.parent();
246+
if ( !parentIndex.isValid() ) // a layer item?
247+
{
248+
updateLayer(item);
249+
}
244250

245-
int numRootItems = rowCount();
246-
for ( int i = 0; i < numRootItems ; ++i )
247-
{
248-
currentLayerItem = item( i );
249-
if ( !currentLayerItem )
251+
//take QgsSymbol* from user data
252+
QVariant symbolVariant = item->data();
253+
QgsSymbol* symbol = 0;
254+
if ( symbolVariant.canConvert<void*>() )
250255
{
251-
continue;
256+
void* symbolData = symbolVariant.value<void*>();
257+
symbol = ( QgsSymbol* )( symbolData );
252258
}
253259

254-
QString layerId = currentLayerItem->data().toString();
260+
if ( symbol ) //vector classification item
261+
{
262+
updateVectorClassificationItem(item, symbol, item->text());
263+
}
264+
else if(!item->icon().isNull()) //raster classification item
265+
{
266+
updateRasterClassificationItem(item);
267+
}
268+
}
255269

256-
if ( !newLayerIds.contains( layerId ) ) //layer has been removed
270+
void QgsLegendModel::updateLayer(QStandardItem* layerItem)
271+
{
272+
if(!layerItem)
257273
{
258-
rowsToRemove.insert( i );
274+
return;
259275
}
260-
}
261276

262-
//remove layers in reverse order
263-
if ( rowsToRemove.size() > 0 )
277+
QString layerId = layerItem->data().toString();
278+
QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer(layerId);
279+
if(mapLayer)
280+
{
281+
//delete all the entries under layer item
282+
for(int i = rowCount() - 1; i >= 0; --i)
283+
{
284+
layerItem->removeRow(i);
285+
}
286+
287+
//and add the new ones...
288+
switch(mapLayer->type())
289+
{
290+
case QgsMapLayer::VECTOR:
291+
addVectorLayerItems(layerItem, mapLayer);
292+
break;
293+
case QgsMapLayer::RASTER:
294+
addRasterLayerItem(layerItem, mapLayer);
295+
break;
296+
default:
297+
break;
298+
}
299+
}
300+
}
301+
302+
void QgsLegendModel::updateVectorClassificationItem(QStandardItem* classificationItem, QgsSymbol* symbol, QString itemText)
303+
{
304+
//this function uses the following logic to find a classification match:
305+
//first test if there is a symbol where lowerbound - upperbound equels itemText
306+
//if no match found, test if there is a symbol where label equals itemText
307+
//still no match found. Test, if there is a symbol with same pen/brush/point symbol
308+
309+
//get parent item
310+
QStandardItem* parentItem = classificationItem->parent();
311+
if(!parentItem)
264312
{
265-
QSet<int>::const_iterator delete_it = --rowsToRemove.constEnd();
266-
for ( ;; --delete_it )
313+
return;
314+
}
315+
316+
//get maplayer object from parent item
317+
QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer(parentItem->data().toString());
318+
if(!ml)
267319
{
268-
removeRow( *delete_it );
269-
if ( delete_it == rowsToRemove.constBegin() )
270-
{
271-
break;
272-
}
320+
return;
321+
}
322+
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>(ml);
323+
if(!vl)
324+
{
325+
return;
326+
}
327+
328+
const QgsRenderer* layerRenderer = vl->renderer();
329+
if(!layerRenderer)
330+
{
331+
return;
273332
}
274333

275-
}
334+
QList<QgsSymbol*> symbolList = layerRenderer->symbols();
335+
QList<QgsSymbol*>::iterator symbolIt;
336+
QgsSymbol* currentSymbol = 0;
276337

338+
//try to find a symbol where lowerbound - upperbound matches item text
339+
symbolIt = symbolList.begin();
340+
for(; symbolIt != symbolList.end(); ++symbolIt)
341+
{
342+
currentSymbol = *symbolIt;
343+
if(currentSymbol->lowerValue() + " - " + currentSymbol->upperValue() == itemText)
344+
{
345+
removeSymbol(symbol);
346+
parentItem->insertRow(classificationItem->row(), itemFromSymbol(currentSymbol));
347+
parentItem->removeRow(classificationItem->row());
348+
return;
349+
}
350+
}
277351

278-
mLayerIds = newLayerIds;
279-
}
280-
#endif //0
352+
//try to find a symbol where lower value matches item text (non-numeric classifications)
353+
symbolIt = symbolList.begin();
354+
for(; symbolIt != symbolList.end(); ++symbolIt)
355+
{
356+
currentSymbol = *symbolIt;
357+
if(currentSymbol->lowerValue() == itemText)
358+
{
359+
removeSymbol(symbol);
360+
parentItem->insertRow(classificationItem->row(), itemFromSymbol(currentSymbol));
361+
parentItem->removeRow(classificationItem->row());
362+
return;
363+
}
364+
}
281365

282-
void QgsLegendModel::updateLayer( const QString& layerId )
283-
{
284-
//find layer item
285-
QStandardItem* layerItem = 0;
286-
QStandardItem* currentLayerItem = 0;
366+
//try to find a symbol where label matches item text
367+
symbolIt = symbolList.begin();
368+
for(; symbolIt != symbolList.end(); ++symbolIt)
369+
{
370+
currentSymbol = *symbolIt;
371+
if(currentSymbol->label() == itemText)
372+
{
373+
removeSymbol(symbol);
374+
parentItem->insertRow(classificationItem->row(), itemFromSymbol(currentSymbol));
375+
parentItem->removeRow(classificationItem->row());
376+
return;
377+
}
378+
}
379+
}
380+
287381

288-
int numRootItems = rowCount();
289-
for ( int i = 0; i < numRootItems ; ++i )
290-
{
291-
currentLayerItem = item( i );
292-
if ( !currentLayerItem )
382+
void QgsLegendModel::updateRasterClassificationItem(QStandardItem* classificationItem)
383+
{
384+
if(!classificationItem)
293385
{
294-
continue;
386+
return;
295387
}
296388

297-
QString currentId = currentLayerItem->data().toString();
298-
if ( currentId == layerId )
389+
QStandardItem* parentItem = classificationItem->parent();
390+
if(!parentItem)
299391
{
300-
layerItem = currentLayerItem;
301-
break;
392+
return;
302393
}
303-
}
304394

305-
if ( layerItem )
306-
{
307-
QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
308-
if ( mapLayer )
395+
QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer(parentItem->data().toString());
396+
if(!ml)
309397
{
310-
//delete all the entries under layer item
311-
for ( int i = rowCount() - 1; i >= 0; --i )
312-
{
313-
layerItem->removeRow( i );
314-
}
398+
return;
399+
}
315400

316-
//and add the new ones...
317-
switch ( mapLayer->type() )
318-
{
319-
case QgsMapLayer::VECTOR:
320-
addVectorLayerItems( layerItem, mapLayer );
321-
break;
322-
case QgsMapLayer::RASTER:
323-
addRasterLayerItem( layerItem, mapLayer );
324-
break;
325-
default:
326-
break;
327-
}
401+
QgsRasterLayer* rl = dynamic_cast<QgsRasterLayer*>(ml);
402+
if(!rl)
403+
{
404+
return;
328405
}
329-
}
406+
407+
QStandardItem* currentSymbolItem = new QStandardItem( QIcon( rl->getLegendQPixmap( true ) ), "" );
408+
parentItem->insertRow(0, currentSymbolItem);
409+
parentItem->removeRow(1);
330410
}
331411

332412
void QgsLegendModel::removeLayer( const QString& layerId )
@@ -380,6 +460,55 @@ void QgsLegendModel::addLayer( QgsMapLayer* theMapLayer )
380460
}
381461
emit layersChanged();
382462
}
463+
464+
QStandardItem* QgsLegendModel::itemFromSymbol(QgsSymbol* s)
465+
{
466+
QStandardItem* currentSymbolItem = 0;
467+
468+
//label
469+
QString label;
470+
QString lowerValue = s->lowerValue();
471+
QString upperValue = s->upperValue();
472+
473+
if ( lowerValue == upperValue || upperValue.isEmpty() )
474+
{
475+
label = lowerValue;
476+
}
477+
else
478+
{
479+
label = lowerValue + " - " + upperValue;
480+
}
481+
482+
//icon item
483+
switch (s->type())
484+
{
485+
case QGis::Point:
486+
currentSymbolItem = new QStandardItem( QIcon( QPixmap::fromImage(s->getPointSymbolAsImage() ) ), label );
487+
break;
488+
case QGis::Line:
489+
currentSymbolItem = new QStandardItem( QIcon( QPixmap::fromImage(s->getLineSymbolAsImage() ) ), label );
490+
break;
491+
case QGis::Polygon:
492+
currentSymbolItem = new QStandardItem( QIcon( QPixmap::fromImage(s->getPolygonSymbolAsImage() ) ), label );
493+
break;
494+
default:
495+
currentSymbolItem = 0;
496+
break;
497+
}
498+
499+
if(!currentSymbolItem)
500+
{
501+
return 0;
502+
}
503+
504+
//Pass deep copy of QgsSymbol as user data. Cast to void* necessary such that QMetaType handles it
505+
QgsSymbol* symbolCopy = new QgsSymbol(*s);
506+
currentSymbolItem->setData( QVariant::fromValue(( void* )symbolCopy ) );
507+
insertSymbol( symbolCopy );
508+
509+
currentSymbolItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
510+
return currentSymbolItem;
511+
}
383512

384513
bool QgsLegendModel::writeXML( QDomElement& composerLegendElem, QDomDocument& doc )
385514
{

src/core/composer/qgslegendmodel.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@ class CORE_EXPORT QgsLegendModel: public QStandardItemModel
4040
~QgsLegendModel();
4141

4242
void setLayerSet( const QStringList& layerIds );
43-
/**Apply added or removed layers to the model*/
44-
//void updateLayerEntries( const QStringList& newLayerIds );
4543

46-
/**Updates the symbology of a single layer*/
47-
void updateLayer( const QString& layerId );
44+
/**Tries to automatically update a model entry (e.g. a whole layer or only a single item)*/
45+
void updateItem(QStandardItem* item);
46+
/**Updates the whole symbology of a layer*/
47+
void updateLayer(QStandardItem* layerItem);
48+
/**Tries to update a single classification item*/
49+
void updateVectorClassificationItem(QStandardItem* classificationItem, QgsSymbol* symbol, QString itemText);
50+
void updateRasterClassificationItem(QStandardItem* classificationItem);
4851

4952
bool writeXML( QDomElement& composerLegendElem, QDomDocument& doc );
5053
bool readXML( const QDomElement& legendModelElem, const QDomDocument& doc );
@@ -72,6 +75,9 @@ class CORE_EXPORT QgsLegendModel: public QStandardItemModel
7275
/**Removes and deletes all stored symbols*/
7376
void removeAllSymbols();
7477

78+
/**Creates a model item for a vector symbol. The calling function takes ownership*/
79+
QStandardItem* itemFromSymbol(QgsSymbol* s);
80+
7581
/**Keep track of copied symbols to delete them if not used anymore*/
7682
QSet<QgsSymbol*> mSymbols;
7783

0 commit comments

Comments
 (0)