895 changes: 501 additions & 394 deletions src/core/composer/qgscomposerlegend.cpp

Large diffs are not rendered by default.

91 changes: 57 additions & 34 deletions src/core/composer/qgscomposerlegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
int columnCount() const { return mColumnCount; }
void setColumnCount( int c ) { mColumnCount = c;mColumns.clear();}

int splitLayer() const { return mSplitLayer; }
void setSplitLayer( bool s ) { mSplitLayer = s;}

int equalColumnWidth() const { return mEqualColumnWidth; }
void setEqualColumnWidth( bool s ) { mEqualColumnWidth = s;}

void setComposerMap( const QgsComposerMap* map );
const QgsComposerMap* composerMap() const { return mComposerMap;}

Expand Down Expand Up @@ -161,60 +167,76 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
/**Reference to map (because symbols are sometimes in map units)*/
const QgsComposerMap* mComposerMap;

/** Allow splitting layers into multiple columns */
bool mSplitLayer;

/** Use the same width (maximum) for all columns */
bool mEqualColumnWidth;

private:
// Group or layer size
struct Size
{
QSizeF size;
//bool isLayer; // layer or group
QgsComposerLegendItem::ItemType type;
QStandardItem * item;
Size() {}
Size( QSizeF s, QgsComposerLegendItem::ItemType t, QStandardItem * i ): size( s ), type( t ), item( i ) {}
} ;
struct LegendSize
/** Nucleon is either group title, layer title or layer child item.
* Nucleon is similar to QgsComposerLegendItem but it does not have
* the same hierarchy. E.g. layer title nucleon is just title, it does not
* include all layer subitems, the same with groups.
*/
class Nucleon
{
QSizeF size; // legend size
QList<Size> sizes; // layer / group sizes
LegendSize() {}
LegendSize( QSizeF s, QList<Size>ls ): size( s ), sizes( ls ) {}
public:
QgsComposerLegendItem* item;
// Symbol size size without any space around for symbol item
QSizeF symbolSize;
// Label size without any space around for symbol item
QSizeF labelSize;
QSizeF size;
// Offset of symbol label, this offset is the same for all symbol labels
// of the same layer in the same column
double labelXOffset;
};
class Position

/** Atom is indivisible set (indivisible into more columns). It may consists
* of one or more Nucleon, depending on layer splitting mode:
* 1) no layer split: [group_title ...] layer_title layer_item [layer_item ...]
* 2) layer split: [group_title ...] layer_title layer_item
* or: layer_item
* It means that group titles must not be split from layer title and layer title
* must not be split from first item, because it would look bad and it would not
* be readable to leave group or layer title at the bottom of column.
*/
class Atom
{
public:
QSizeF titleSize; // without spaces around
QPointF point; // current position
double columnTop; // y coord where columns start (mBoxSpace + title height)
Atom(): size( QSizeF( 0, 0 ) ), column( 0 ) {}
QList<Nucleon> nucleons;
// Atom size including nucleons interspaces but without any space around atom.
QSizeF size;
int column;
QMap<QStandardItem *, int> columns;
// widths of columns, does not include spaces before/between/after columns
QVector<double> widths;
double maxColumnHeight;
// set max width for current column
void expandWidth( double w );
// set column and x position
void setColumn( QStandardItem *item );
double boxSpace;
double columnSpace; // space between columns
};

/** Create list of atoms according to current layer splitting mode */
QList<Atom> createAtomList( QStandardItem* rootItem, bool splitLayer );

/** Divide atoms to columns and set columns on atoms */
void setColumns( QList<Atom>& atomList );

QgsComposerLegend(); //forbidden

QSizeF drawTitle( QPainter* painter = 0, QPointF point = QPointF(), Qt::AlignmentFlag halignement = Qt::AlignLeft );

/**Draws a group item and all subitems
* Returns list of sizes of layers and groups including this group.
*/
QList<Size> drawGroupItem( QPainter* p, QgsComposerGroupItem* groupItem, Position& currentPosition );
QSizeF drawGroupItemTitle( QgsComposerGroupItem* groupItem, QPainter* painter = 0, QPointF point = QPointF() );
/**Draws a layer item and all subitems*/
Size drawLayerItem( QPainter* p, QgsComposerLayerItem* layerItem, Position& currentPosition );
QSizeF drawLayerItemTitle( QgsComposerLayerItem* layerItem, QPainter* painter = 0, QPointF point = QPointF() );

/**Draws child items of a layer item
@param p painter
@param layerItem parent model item (layer)
@param currentPosition in/out: current y position of legend item
@param layerOpacity opacity of the corresponding map layer
*/
QSizeF drawLayerChildItems( QPainter* p, QStandardItem* layerItem, Position& currentPosition, int layerOpacity = 255 );

Nucleon drawSymbolItem( QgsComposerLegendItem* symbolItem, QPainter* painter = 0, QPointF point = QPointF(), double labelXOffset = 0. );

/**Draws a symbol at the current y position and returns the new x position. Returns real symbol height, because for points,
it is possible that it differs from mSymbolHeight*/
Expand All @@ -224,12 +246,13 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
void drawLineSymbol( QPainter*, QgsSymbol* s, double currentYCoord, double& currentXPosition, int opacity = 255 ) const;
void drawPolygonSymbol( QPainter* p, QgsSymbol* s, double currentYCoord, double& currentXPosition, int opacity = 255 ) const;

LegendSize paintAndDetermineSize( QPainter* painter, QMap<QStandardItem *, int> columns );
void drawAtom( Atom atom, QPainter* painter = 0, QPointF point = QPointF() );

double spaceAboveAtom( Atom atom );

/**Helper function that lists ids of layers contained in map canvas*/
QStringList layerIdList() const;

private:
/** Splits a string using the wrap char taking into account handling empty
wrap char which means no wrapping */
QStringList splitStringForWrapping( QString stringToSplt );
Expand Down
51 changes: 34 additions & 17 deletions src/ui/qgscomposerlegendwidgetbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
<x>0</x>
<y>0</y>
<width>370</width>
<height>479</height>
<height>533</height>
</rect>
</property>
<attribute name="label">
<string>General</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="1">
<item row="7" column="1">
<widget class="QPushButton" name="mTitleFontButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
Expand All @@ -72,28 +72,28 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="8" column="1">
<widget class="QPushButton" name="mGroupFontButton">
<property name="text">
<string>Group Font...</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="9" column="1">
<widget class="QPushButton" name="mLayerFontButton">
<property name="text">
<string>Layer Font...</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="10" column="1">
<widget class="QPushButton" name="mItemFontButton">
<property name="text">
<string>Item Font...</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="11" column="1">
<widget class="QDoubleSpinBox" name="mSymbolWidthSpinBox">
<property name="prefix">
<string>Symbol width </string>
Expand All @@ -103,7 +103,7 @@
</property>
</widget>
</item>
<item row="10" column="1">
<item row="12" column="1">
<widget class="QDoubleSpinBox" name="mSymbolHeightSpinBox">
<property name="prefix">
<string>Symbol height </string>
Expand All @@ -113,7 +113,7 @@
</property>
</widget>
</item>
<item row="12" column="1">
<item row="14" column="1">
<widget class="QDoubleSpinBox" name="mLayerSpaceSpinBox">
<property name="prefix">
<string>Layer space </string>
Expand All @@ -123,7 +123,7 @@
</property>
</widget>
</item>
<item row="14" column="1">
<item row="16" column="1">
<widget class="QDoubleSpinBox" name="mSymbolSpaceSpinBox">
<property name="prefix">
<string>Symbol space </string>
Expand All @@ -133,7 +133,7 @@
</property>
</widget>
</item>
<item row="15" column="1">
<item row="17" column="1">
<widget class="QDoubleSpinBox" name="mIconLabelSpaceSpinBox">
<property name="prefix">
<string>Icon label space </string>
Expand All @@ -143,7 +143,7 @@
</property>
</widget>
</item>
<item row="16" column="1">
<item row="18" column="1">
<widget class="QDoubleSpinBox" name="mBoxSpaceSpinBox">
<property name="prefix">
<string>Box space </string>
Expand All @@ -153,7 +153,7 @@
</property>
</widget>
</item>
<item row="22" column="1">
<item row="24" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
Expand All @@ -166,17 +166,17 @@
</property>
</spacer>
</item>
<item row="18" column="1">
<item row="20" column="1">
<widget class="QComboBox" name="mMapComboBox"/>
</item>
<item row="17" column="1">
<item row="19" column="1">
<widget class="QLabel" name="mMapLabel">
<property name="text">
<string>Map</string>
</property>
</widget>
</item>
<item row="11" column="1">
<item row="13" column="1">
<widget class="QDoubleSpinBox" name="mGroupSpaceSpinBox">
<property name="prefix">
<string>Group Space </string>
Expand All @@ -186,14 +186,14 @@
</property>
</widget>
</item>
<item row="20" column="1">
<item row="22" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Wrap text on</string>
</property>
</widget>
</item>
<item row="21" column="1">
<item row="23" column="1">
<widget class="QLineEdit" name="mWrapCharLineEdit">
<property name="frame">
<bool>true</bool>
Expand Down Expand Up @@ -230,6 +230,23 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="mSplitLayerCheckBox">
<property name="toolTip">
<string>Allow to split layer items into multiple columns.</string>
</property>
<property name="text">
<string>Split layers</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="mEqualColumnWidthCheckBox">
<property name="text">
<string>Equal column widths</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
Expand Down