30 #include <QDomDocument>
31 #include <QDomElement>
36 , mTitle(
tr(
"Legend" ) )
37 , mFontColor( QColor( 0, 0, 0 ) )
40 , mTitleAlignment( Qt::AlignLeft )
43 , mSplitLayer( false )
44 , mEqualColumnWidth( false )
80 Q_UNUSED( itemStyle );
88 QStandardItem* rootItem =
mLegendModel.invisibleRootItem();
89 if ( !rootItem )
return size;
95 painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
102 qreal maxColumnWidth = 0;
105 foreach (
Atom atom, atomList )
107 maxColumnWidth = qMax( atom.
size.width(), maxColumnWidth );
118 bool firstInColumn =
true;
119 double columnMaxHeight = 0;
120 qreal columnWidth = 0;
122 foreach (
Atom atom, atomList )
124 if ( atom.
column > column )
135 point.ry() = columnTop;
138 firstInColumn =
true;
140 if ( !firstInColumn )
145 QSizeF atomSize =
drawAtom( atom, painter, point );
146 columnWidth = qMax( atomSize.width(), columnWidth );
148 point.ry() += atom.
size.height();
149 columnMaxHeight = qMax( point.y() - columnTop, columnMaxHeight );
151 firstInColumn =
false;
155 size.rheight() = columnTop + columnMaxHeight +
mBoxSpace;
156 size.rwidth() = point.x();
159 size.rwidth() = qMax( titleSize.width(), size.width() );
163 if ( painter && size.height() > rect().height() )
165 setSceneRect( QRectF( pos().x(), pos().y(), rect().width(), size.height() ) );
167 if ( painter && size.width() > rect().width() )
169 setSceneRect( QRectF( pos().x(), pos().y(), size.width(), rect().height() ) );
181 point.rx() = rect().width() / 2;
215 double y = point.y();
225 switch ( halignment )
227 case Qt::AlignHCenter:
228 textBoxWidth = ( qMin( point.x(), rect().width() - point.x() ) -
mBoxSpace ) * 2.0;
229 textBoxLeft = point.x() - textBoxWidth / 2.;
237 textBoxLeft = point.x();
238 textBoxWidth = rect().width() - point.x() -
mBoxSpace;
242 for ( QStringList::Iterator titlePart = lines.begin(); titlePart != lines.end(); ++titlePart )
249 QRectF r( textBoxLeft, y, textBoxWidth, height );
257 size.rwidth() = qMax( width, size.rwidth() );
260 if ( titlePart != lines.end() )
265 size.rheight() = y - point.y();
274 if ( !groupItem )
return size;
276 double y = point.y();
281 for ( QStringList::Iterator groupPart = lines.begin(); groupPart != lines.end(); ++groupPart )
286 size.rwidth() = qMax( width, size.width() );
287 if ( groupPart != lines.end() )
292 size.rheight() = y - point.y();
299 if ( !layerItem )
return size;
302 if ( layerItem->text().isEmpty() )
return size;
304 double y = point.y();
309 for ( QStringList::Iterator layerItemPart = lines.begin(); layerItemPart != lines.end(); ++layerItemPart )
314 size.rwidth() = qMax( width, size.width() );
315 if ( layerItemPart != lines.end() )
320 size.rheight() = y - point.y();
328 QgsDebugMsg( QString(
"width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
329 if ( size.isValid() )
331 setSceneRect( QRectF( pos().x(), pos().y(), size.width(), size.height() ) );
337 QSizeF symbolSize( 0, 0 );
338 QSizeF labelSize( 0, 0 );
339 if ( !symbolItem )
return Nucleon();
348 double realSymbolHeight;
367 QString text = symbolItem->text();
375 symbolNg = symbolV2Item->
symbolV2();
379 double x = point.x();
384 symbolSize.rwidth() = qMax( x - point.x(),
mSymbolWidth );
385 symbolSize.rheight() = qMax( realSymbolHeight,
mSymbolHeight );
387 else if ( rasterItem )
391 QIcon symbolIcon = symbolItem->icon();
392 if ( !symbolIcon.isNull() && symbolItem->text().isEmpty() )
395 QList<QSize> sizes = symbolIcon.availableSizes();
397 double maxHeight = 0;
398 foreach ( QSize
size, sizes )
400 if ( maxWidth < size.width() ) maxWidth = size.width();
401 if ( maxHeight < size.height() ) maxHeight = size.height();
403 QSize maxSize( maxWidth, maxHeight );
406 QImage legend = symbolIcon.pixmap( maxWidth, maxHeight ).toImage();
418 painter->setBrush( rasterItem->
color() );
427 QIcon symbolIcon = symbolItem->icon();
428 if ( !symbolIcon.isNull() )
439 double labelX = point.x() + qMax((
double ) symbolSize.width(), labelXOffset );
445 labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) *
mlineSpacing;
448 if ( labelSize.height() < symbolSize.height() )
450 labelY = point.y() + symbolSize.height() / 2 + textHeight / 2;
454 labelY = point.y() + textHeight;
457 for ( QStringList::Iterator itemPart = lines.begin(); itemPart != lines.end(); ++itemPart )
461 if ( itemPart != lines.end() )
468 nucleon.
item = symbolItem;
472 double width = qMax((
double ) symbolSize.width(), labelXOffset ) + labelSize.width();
473 double height = qMax( symbolSize.height(), labelSize.height() );
474 nucleon.
size = QSizeF( width, height );
487 double dotsPerMM = 1.0;
490 QPaintDevice* paintDevice = p->device();
495 dotsPerMM = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4;
500 double mmPerMapUnit = 1;
512 double widthOffset = 0;
513 double heightOffset = 0;
517 size = markerSymbol->
size();
522 height *= mmPerMapUnit;
523 width *= mmPerMapUnit;
524 markerSymbol->
setSize( width );
538 if ( markerSymbol && sizeInMapUnits )
544 p->setRenderHint( QPainter::Antialiasing );
549 QImage tempImage = QImage( QSize( rect().width() * dotsPerMM, rect().height() * dotsPerMM ), QImage::Format_ARGB32 );
550 QPainter imagePainter( &tempImage );
551 tempImage.fill( Qt::transparent );
552 imagePainter.translate( dotsPerMM * ( currentXPosition + widthOffset ),
553 dotsPerMM * ( currentYCoord + heightOffset ) );
554 s->
drawPreviewIcon( &imagePainter, QSize( width * dotsPerMM, height * dotsPerMM ) );
556 imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
557 imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
559 p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
560 p->drawImage( 0, 0, tempImage );
564 p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
565 p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
566 s->
drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ) );
570 if ( markerSymbol && sizeInMapUnits )
576 currentXPosition += width;
577 currentXPosition += 2 * widthOffset;
578 symbolHeight = height + 2 * heightOffset;
589 return QStringList();
628 QDomElement composerLegendElem = doc.createElement(
"ComposerLegend" );
629 elem.appendChild( composerLegendElem );
632 composerLegendElem.setAttribute(
"title",
mTitle );
633 composerLegendElem.setAttribute(
"titleAlignment", QString::number((
int )
mTitleAlignment ) );
634 composerLegendElem.setAttribute(
"columnCount", QString::number(
mColumnCount ) );
635 composerLegendElem.setAttribute(
"splitLayer", QString::number(
mSplitLayer ) );
636 composerLegendElem.setAttribute(
"equalColumnWidth", QString::number(
mEqualColumnWidth ) );
638 composerLegendElem.setAttribute(
"boxSpace", QString::number(
mBoxSpace ) );
639 composerLegendElem.setAttribute(
"columnSpace", QString::number(
mColumnSpace ) );
641 composerLegendElem.setAttribute(
"symbolWidth", QString::number(
mSymbolWidth ) );
642 composerLegendElem.setAttribute(
"symbolHeight", QString::number(
mSymbolHeight ) );
643 composerLegendElem.setAttribute(
"wmsLegendWidth", QString::number(
mWmsLegendWidth ) );
644 composerLegendElem.setAttribute(
"wmsLegendHeight", QString::number(
mWmsLegendHeight ) );
645 composerLegendElem.setAttribute(
"wrapChar",
mWrapChar );
646 composerLegendElem.setAttribute(
"fontColor",
mFontColor.name() );
653 QDomElement composerLegendStyles = doc.createElement(
"styles" );
654 composerLegendElem.appendChild( composerLegendStyles );
665 return _writeXML( composerLegendElem, doc );
670 if ( itemElem.isNull() )
676 mTitle = itemElem.attribute(
"title" );
677 if ( !itemElem.attribute(
"titleAlignment" ).isEmpty() )
679 mTitleAlignment = ( Qt::AlignmentFlag )itemElem.attribute(
"titleAlignment" ).toInt();
681 mColumnCount = itemElem.attribute(
"columnCount",
"1" ).toInt();
683 mSplitLayer = itemElem.attribute(
"splitLayer",
"0" ).toInt() == 1;
686 QDomNodeList stylesNodeList = itemElem.elementsByTagName(
"styles" );
687 if ( stylesNodeList.size() > 0 )
689 QDomNode stylesNode = stylesNodeList.at( 0 );
690 for (
int i = 0; i < stylesNode.childNodes().size(); i++ )
692 QDomElement styleElem = stylesNode.childNodes().at( i ).toElement();
694 style.
readXML( styleElem, doc );
695 QString name = styleElem.attribute(
"name" );
708 mFontColor.setNamedColor( itemElem.attribute(
"fontColor",
"#000000" ) );
711 mBoxSpace = itemElem.attribute(
"boxSpace",
"2.0" ).toDouble();
712 mColumnSpace = itemElem.attribute(
"columnSpace",
"2.0" ).toDouble();
714 mSymbolWidth = itemElem.attribute(
"symbolWidth",
"7.0" ).toDouble();
715 mSymbolHeight = itemElem.attribute(
"symbolHeight",
"14.0" ).toDouble();
716 mWmsLegendWidth = itemElem.attribute(
"wmsLegendWidth",
"50" ).toDouble();
717 mWmsLegendHeight = itemElem.attribute(
"wmsLegendHeight",
"25" ).toDouble();
719 mWrapChar = itemElem.attribute(
"wrapChar" );
722 if ( !itemElem.attribute(
"map" ).isEmpty() )
728 QDomNodeList modelNodeList = itemElem.elementsByTagName(
"Model" );
729 if ( modelNodeList.size() > 0 )
731 QDomElement modelElem = modelNodeList.at( 0 ).toElement();
736 QDomNodeList composerItemList = itemElem.elementsByTagName(
"ComposerItem" );
737 if ( composerItemList.size() > 0 )
739 QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
745 QString titleFontString = itemElem.attribute(
"titleFont" );
746 if ( !titleFontString.isEmpty() )
751 QString groupFontString = itemElem.attribute(
"groupFont" );
752 if ( !groupFontString.isEmpty() )
758 QString layerFontString = itemElem.attribute(
"layerFont" );
759 if ( !layerFontString.isEmpty() )
764 QString itemFontString = itemElem.attribute(
"itemFont" );
765 if ( !itemFontString.isEmpty() )
770 if ( !itemElem.attribute(
"groupSpace" ).isEmpty() )
774 if ( !itemElem.attribute(
"layerSpace" ).isEmpty() )
778 if ( !itemElem.attribute(
"symbolSpace" ).isEmpty() )
812 list << stringToSplt;
822 if ( !rootItem )
return atoms;
826 for (
int i = 0; i < rootItem->rowCount(); i++ )
828 QStandardItem* currentLayerItem = rootItem->child( i );
830 if ( !currentLegendItem )
continue;
836 QList<Atom> groupAtoms =
createAtomList( currentLayerItem, splitLayer );
839 nucleon.
item = currentLegendItem;
842 if ( groupAtoms.size() > 0 )
847 groupAtoms[0].nucleons.prepend( nucleon );
848 groupAtoms[0].size.rheight() += nucleon.
size.height();
849 groupAtoms[0].size.rwidth() = qMax( nucleon.
size.width(), groupAtoms[0].size.width() );
856 atom.
size.rwidth() += nucleon.
size.width();
857 atom.
size.rheight() += nucleon.
size.height();
858 atom.
size.rwidth() = qMax( nucleon.
size.width(), atom.
size.width() );
859 groupAtoms.append( atom );
861 atoms.append( groupAtoms );
870 nucleon.
item = currentLegendItem;
873 atom.
size.rwidth() = nucleon.
size.width();
874 atom.
size.rheight() = nucleon.
size.height();
877 QList<Atom> layerAtoms;
879 for (
int j = 0; j < currentLegendItem->rowCount(); j++ )
882 if ( !symbolItem )
continue;
890 atom.
size.rwidth() = qMax( symbolNucleon.
size.width(), atom.
size.width() );
897 atom.
size.rheight() += symbolNucleon.
size.height();
898 atom.
nucleons.append( symbolNucleon );
903 symbolAtom.
nucleons.append( symbolNucleon );
904 symbolAtom.
size.rwidth() = symbolNucleon.
size.width();
905 symbolAtom.
size.rheight() = symbolNucleon.
size.height();
906 layerAtoms.append( symbolAtom );
909 layerAtoms.prepend( atom );
910 atoms.append( layerAtoms );
926 if ( !item )
continue;
931 if ( !groupItem )
continue;
944 if ( !layerItem )
continue;
964 size.rwidth() = qMax( symbolNucleon.
size.width(), size.width() );
966 point.ry() += nucleon.
size.height();
974 if ( atom.
nucleons.size() == 0 )
return 0;
979 if ( !item )
return 0;
1006 double totalHeight = 0;
1008 qreal maxAtomHeight = 0;
1009 foreach (
Atom atom, atomList )
1015 totalHeight += atom.
size.height();
1016 maxAtomHeight = qMax( atom.
size.height(), maxAtomHeight );
1027 int currentColumn = 0;
1028 int currentColumnAtomCount = 0;
1029 double currentColumnHeight = 0;
1030 double maxColumnHeight = 0;
1031 double closedColumnsHeight = 0;
1033 for (
int i = 0; i < atomList.size(); i++ )
1035 Atom atom = atomList[i];
1036 double currentHeight = currentColumnHeight;
1041 currentHeight += atom.
size.height();
1044 avgColumnHeight = ( totalHeight - closedColumnsHeight ) / (
mColumnCount - currentColumn );
1045 if (( currentHeight - avgColumnHeight ) > atom.
size.height() / 2
1046 && currentColumnAtomCount > 0
1047 && currentHeight > maxAtomHeight
1048 && currentHeight > maxColumnHeight
1053 currentColumnAtomCount = 0;
1054 closedColumnsHeight += currentColumnHeight;
1055 currentColumnHeight = atom.
size.height();
1059 currentColumnHeight = currentHeight;
1061 atomList[i].column = currentColumn;
1062 currentColumnAtomCount++;
1063 maxColumnHeight = qMax( currentColumnHeight, maxColumnHeight );
1069 QMap<QString, qreal> maxSymbolWidth;
1070 for (
int i = 0; i < atomList.size(); i++ )
1072 for (
int j = 0; j < atomList[i].nucleons.size(); j++ )
1075 if ( !item )
continue;
1080 QString key = QString(
"%1-%2" ).arg(( qulonglong )item->parent() ).arg( atomList[i].column );
1081 maxSymbolWidth[key] = qMax( atomList[i].nucleons[j].symbolSize.width(), maxSymbolWidth[key] );
1085 for (
int i = 0; i < atomList.size(); i++ )
1087 for (
int j = 0; j < atomList[i].nucleons.size(); j++ )
1090 if ( !item )
continue;
1095 QString key = QString(
"%1-%2" ).arg(( qulonglong )item->parent() ).arg( atomList[i].column );
1098 atomList[i].nucleons[j].labelXOffset = maxSymbolWidth[key] + space;
1099 atomList[i].nucleons[j].size.rwidth() = maxSymbolWidth[key] + space + atomList[i].nucleons[j].labelSize.width();
Base class for all map layer types.
QgsComposerLegendStyle style(QgsComposerLegendStyle::Style s) const
Returns style.
double mWmsLegendWidth
Width of WMS legendGraphic pixmap.
double fontHeightCharacterMM(const QFont &font, const QChar &c) const
Returns the font height of a character in millimeters.
double mColumnSpace
Space between columns.
Qt::AlignmentFlag mTitleAlignment
Title alignment, one of Qt::AlignLeft, Qt::AlignHCenter, Qt::AlignRight)
void readXML(const QDomElement &elem, const QDomDocument &doc)
double mapUnitsToMM() const
Returns the conversion factor map units -> mm.
void setMargin(Side side, double margin)
double mWmsLegendHeight
Height of WMS legendGraphic pixmap.
bool writeXML(QDomElement &elem, QDomDocument &doc) const
stores state in Dom node
void drawPreviewIcon(QPainter *painter, QSize size)
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
Nucleon is either group title, layer title or layer child item.
A item that forms part of a map composition.
QgsLegendModel mLegendModel
virtual void drawFrame(QPainter *p)
Draw black frame around item.
int mColumnCount
Number of legend columns.
void updateLegend()
Updates the model and all legend entries.
double mlineSpacing
Spacing between lines when wrapped.
QStringList splitStringForWrapping(QString stringToSplt)
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
void adjustBoxSize()
Sets item box to the whole content.
QSizeF drawLayerItemTitle(QgsComposerLayerItem *layerItem, QPainter *painter=0, QPointF point=QPointF())
Draws a layer item and all subitems.
void itemChanged()
Used e.g.
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
double fontDescentMillimeters(const QFont &font) const
Returns the font descent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCA...
QSizeF drawGroupItemTitle(QgsComposerGroupItem *groupItem, QPainter *painter=0, QPointF point=QPointF())
Draws a group item and all subitems Returns list of sizes of layers and groups including this group...
QList< Atom > createAtomList(QStandardItem *rootItem, bool splitLayer)
Create list of atoms according to current layer splitting mode.
double mSymbolHeight
Height of symbol icon.
const QgsComposerMap * mComposerMap
Reference to map (because symbols are sometimes in map units)
void setLayerSet(const QStringList &layerIds, double scaleDenominator=-1, QString rule="")
virtual void drawSelectionBoxes(QPainter *p)
Draw selection boxes around item.
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
QStringList layerIdList() const
Helper function that lists ids of layers contained in map canvas.
void drawSymbolV2(QPainter *p, QgsSymbolV2 *s, double currentYCoord, double ¤tXPosition, double &symbolHeight, int opacity=255) const
Draws a symbol at the current y position and returns the new x position.
void setComposerMap(const QgsComposerMap *map)
void synchronizeWithModel()
Data changed.
void setStyleFont(QgsComposerLegendStyle::Style s, const QFont &f)
Set style font.
void setSize(double size)
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
QSizeF drawTitle(QPainter *painter=0, QPointF point=QPointF(), Qt::AlignmentFlag halignment=Qt::AlignLeft)
Draws title in the legend using the title font and the specified alignment If no painter is specified...
bool writeXML(QDomElement &composerLegendElem, QDomDocument &doc) const
QgsComposition * mComposition
void setColumns(QList< Atom > &atomList)
Divide atoms to columns and set columns on atoms.
Graphics scene for map printing.
QFont styleFont(QgsComposerLegendStyle::Style s) const
Abstract base class for the legend item types.
Object representing map window.
QSizeF paintAndDetermineSize(QPainter *painter)
Paints the legend and calculates its size.
void invalidateCurrentMap()
Sets mCompositionMap to 0 if the map is deleted.
bool readXML(const QDomElement &legendModelElem, const QDomDocument &doc)
QgsComposerLegendStyle & rstyle(QgsComposerLegendStyle::Style s)
Returns reference to modifiable style.
void writeXML(QString name, QDomElement &elem, QDomDocument &doc) const
int layerTransparency() const
Read transparency for layer.
bool useAdvancedEffects() const
Returns true if a composition should use advanced effects such as blend modes.
int id() const
Get identification number.
Composer legend components style.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
void setStyleMargin(QgsComposerLegendStyle::Style s, double margin)
Set style margin.
qreal mBoxSpace
Space between item box and contents.
Nucleon drawSymbolItem(QgsComposerLegendItem *symbolItem, QPainter *painter=0, QPointF point=QPointF(), double labelXOffset=0.)
virtual void drawBackground(QPainter *p)
Draw background.
double spaceAboveAtom(Atom atom)
QgsComposerLegendStyle::Style style() const
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
virtual ItemType itemType() const =0
QgsSymbolV2::OutputUnit outputUnit() const
void setStyle(QgsComposerLegendStyle::Style s, const QgsComposerLegendStyle style)
bool mEqualColumnWidth
Use the same width (maximum) for all columns.
QSizeF drawAtom(Atom atom, QPainter *painter=0, QPointF point=QPointF())
Draw atom and return its actual size, the atom is drawn with the space above it so that first atoms i...
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget)
Reimplementation of QCanvasItem::paint.
Atom is indivisible set (indivisible into more columns).
QgsComposerLegendItem * item
Represents a vector layer which manages a vector based data sets.
bool mSplitLayer
Allow splitting layers into multiple columns.
const QgsComposerMap * getComposerMapById(int id) const
Returns the composer map with specified id.
virtual int type() const
return correct graphics item type.
double mSymbolWidth
Width of symbol icon.
QList< Nucleon > nucleons
bool readXML(const QDomElement &itemElem, const QDomDocument &doc)
sets state from Dom document
void setOutputUnit(QgsSymbolV2::OutputUnit u)
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
void setFont(const QFont &font)