Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE][composer] Add support for specifying legend title horizonta…
…l alignment in composer
  • Loading branch information
manisandro authored and nyalldawson committed Apr 13, 2014
1 parent ca2e68c commit a714a18
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 36 deletions.
13 changes: 13 additions & 0 deletions python/core/composer/qgscomposerlegend.sip
Expand Up @@ -31,6 +31,19 @@ class QgsComposerLegend : QgsComposerItem
void setTitle( const QString& t );
QString title() const;

/*Returns the alignment of the legend title
* @returns Qt::AlignmentFlag for the legend title
* @note added in 2.3
* @see setTitleAlignment
*/
Qt::AlignmentFlag titleAlignment() const;
/**Sets the alignment of the legend title
* @param alignment Text alignment for drawing the legend title
* @note added in 2.3
* @see titleAlignment
*/
void setTitleAlignment( Qt::AlignmentFlag alignment );

/** Returns reference to modifiable style */
QgsComposerLegendStyle & rstyle( QgsComposerLegendStyle::Style s );
/** Returns style */
Expand Down
17 changes: 17 additions & 0 deletions src/app/composer/qgscomposerlegendwidget.cpp
Expand Up @@ -161,8 +161,11 @@ void QgsComposerLegendWidget::setGuiElements()
return;
}

int alignment = mLegend->titleAlignment() == Qt::AlignLeft ? 0 : mLegend->titleAlignment() == Qt::AlignHCenter ? 1 : 2;

blockAllSignals( true );
mTitleLineEdit->setText( mLegend->title() );
mTitleAlignCombo->setCurrentIndex( alignment );
mColumnCountSpinBox->setValue( mLegend->columnCount() );
mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
Expand Down Expand Up @@ -220,6 +223,18 @@ void QgsComposerLegendWidget::on_mTitleLineEdit_textChanged( const QString& text
}
}

void QgsComposerLegendWidget::on_mTitleAlignCombo_currentIndexChanged( int index )
{
if ( mLegend )
{
Qt::AlignmentFlag alignment = index == 0 ? Qt::AlignLeft : index == 1 ? Qt::AlignHCenter : Qt::AlignRight;
mLegend->beginCommand( tr( "Legend title alignment changed" ) );
mLegend->setTitleAlignment( alignment );
mLegend->update();
mLegend->endCommand();
}
}

void QgsComposerLegendWidget::on_mColumnCountSpinBox_valueChanged( int c )
{
if ( mLegend )
Expand Down Expand Up @@ -916,6 +931,7 @@ void QgsComposerLegendWidget::updateLegend()
void QgsComposerLegendWidget::blockAllSignals( bool b )
{
mTitleLineEdit->blockSignals( b );
mTitleAlignCombo->blockSignals( b );
mItemTreeView->blockSignals( b );
mCheckBoxAutoUpdate->blockSignals( b );
mMapComboBox->blockSignals( b );
Expand Down Expand Up @@ -997,3 +1013,4 @@ void QgsComposerLegendWidget::selectedChanged( const QModelIndex & current, cons
mCountToolButton->setChecked( layerItem->showFeatureCount() );
mCountToolButton->setEnabled( true );
}

2 changes: 2 additions & 0 deletions src/app/composer/qgscomposerlegendwidget.h
Expand Up @@ -54,6 +54,7 @@ class QgsComposerLegendWidget: public QWidget, private Ui::QgsComposerLegendWidg

void on_mWrapCharLineEdit_textChanged( const QString& text );
void on_mTitleLineEdit_textChanged( const QString& text );
void on_mTitleAlignCombo_currentIndexChanged( int index );
void on_mColumnCountSpinBox_valueChanged( int c );
void on_mSplitLayerCheckBox_toggled( bool checked );
void on_mEqualColumnWidthCheckBox_toggled( bool checked );
Expand Down Expand Up @@ -106,3 +107,4 @@ class QgsComposerLegendWidget: public QWidget, private Ui::QgsComposerLegendWidg
};

#endif

92 changes: 63 additions & 29 deletions src/core/composer/qgscomposerlegend.cpp
Expand Up @@ -36,6 +36,7 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition* composition )
, mFontColor( QColor( 0, 0, 0 ) )
, mBoxSpace( 2 )
, mColumnSpace( 2 )
, mTitleAlignment( Qt::AlignLeft )
, mColumnCount( 1 )
, mComposerMap( 0 )
, mSplitLayer( false )
Expand Down Expand Up @@ -106,7 +107,10 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
}
}

//calculate size of title
QSizeF titleSize = drawTitle();
//add title margin to size of title text
titleSize.rwidth() += mBoxSpace * 2.0;
double columnTop = mBoxSpace + titleSize.height() + style( QgsComposerLegendStyle::Title ).margin( QgsComposerLegendStyle::Bottom );

QPointF point( mBoxSpace, columnTop );
Expand Down Expand Up @@ -149,30 +153,12 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )

size.rheight() = columnTop + columnMaxHeight + mBoxSpace;
size.rwidth() = point.x();

// Now we know total width and can draw the title centered
if ( !mTitle.isEmpty() )
{
// For multicolumn center if we stay in totalWidth, otherwise allign to left
// and expand total width. With single column keep alligned to left be cause
// it looks better alligned with items bellow instead of centered
Qt::AlignmentFlag halignment;
if ( mColumnCount > 1 && titleSize.width() + 2 * mBoxSpace < size.width() )
{
halignment = Qt::AlignHCenter;
point.rx() = mBoxSpace + size.rwidth() / 2;
}
else
{
halignment = Qt::AlignLeft;
point.rx() = mBoxSpace;
size.rwidth() = qMax( titleSize.width() + 2 * mBoxSpace, size.width() );
}
point.ry() = mBoxSpace;
drawTitle( painter, point, halignment );
size.rwidth() = qMax( titleSize.width(), size.width() );
}

//adjust box if width or height is to small
//adjust box if width or height is too small
if ( painter && size.height() > rect().height() )
{
setSceneRect( QRectF( pos().x(), pos().y(), rect().width(), size.height() ) );
Expand All @@ -182,6 +168,25 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
setSceneRect( QRectF( pos().x(), pos().y(), size.width(), rect().height() ) );
}

// Now we have set the correct total item width and can draw the title centered
if ( !mTitle.isEmpty() )
{
if ( mTitleAlignment == Qt::AlignLeft )
{
point.rx() = mBoxSpace;
}
else if ( mTitleAlignment == Qt::AlignHCenter )
{
point.rx() = rect().width() / 2;
}
else
{
point.rx() = rect().width() - mBoxSpace;
}
point.ry() = mBoxSpace;
drawTitle( painter, point, mTitleAlignment );
}

if ( painter )
{
painter->restore();
Expand All @@ -200,27 +205,55 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
QSizeF QgsComposerLegend::drawTitle( QPainter* painter, QPointF point, Qt::AlignmentFlag halignment )
{
QSizeF size( 0, 0 );
if ( mTitle.isEmpty() ) return size;
if ( mTitle.isEmpty() )
{
return size;
}

QStringList lines = splitStringForWrapping( mTitle );

double y = point.y();

if ( painter ) painter->setPen( mFontColor );
if ( painter )
{
painter->setPen( mFontColor );
}

//calculate width and left pos of rectangle to draw text into
double textBoxWidth;
double textBoxLeft;
switch ( halignment )
{
case Qt::AlignHCenter:
textBoxWidth = ( qMin( point.x(), rect().width() - point.x() ) - mBoxSpace ) * 2.0;
textBoxLeft = point.x() - textBoxWidth / 2.;
break;
case Qt::AlignRight:
textBoxLeft = mBoxSpace;
textBoxWidth = point.x() - mBoxSpace;
break;
case Qt::AlignLeft:
default:
textBoxLeft = point.x();
textBoxWidth = rect().width() - point.x() - mBoxSpace;
break;
}

for ( QStringList::Iterator titlePart = lines.begin(); titlePart != lines.end(); ++titlePart )
{
// it does not draw the last world if rectangle width is exactly text width
//last word is not drawn if rectangle width is exactly text width, so add 1
//TODO - correctly calculate size of italicized text, since QFontMetrics does not
qreal width = textWidthMillimeters( styleFont( QgsComposerLegendStyle::Title ), *titlePart ) + 1;
qreal height = fontAscentMillimeters( styleFont( QgsComposerLegendStyle::Title ) ) + fontDescentMillimeters( styleFont( QgsComposerLegendStyle::Title ) );

double left = halignment == Qt::AlignLeft ? point.x() : point.x() - width / 2;
QRectF r( textBoxLeft, y, textBoxWidth, height );

QRectF rect( left, y, width, height );
if ( painter )
{
drawText( painter, r, *titlePart, styleFont( QgsComposerLegendStyle::Title ), halignment, Qt::AlignVCenter );
}

if ( painter ) drawText( painter, rect, *titlePart, styleFont( QgsComposerLegendStyle::Title ), halignment, Qt::AlignVCenter );

size.rwidth() = qMax( width, size.width() );
//update max width of title
size.rwidth() = qMax( width, size.rwidth() );

y += height;
if ( titlePart != lines.end() )
Expand Down Expand Up @@ -1039,3 +1072,4 @@ void QgsComposerLegend::setColumns( QList<Atom>& atomList )
}
}


20 changes: 20 additions & 0 deletions src/core/composer/qgscomposerlegend.h
Expand Up @@ -58,6 +58,19 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
void setTitle( const QString& t ) {mTitle = t;}
QString title() const {return mTitle;}

/*Returns the alignment of the legend title
* @returns Qt::AlignmentFlag for the legend title
* @note added in 2.3
* @see setTitleAlignment
*/
Qt::AlignmentFlag titleAlignment() const { return mTitleAlignment; }
/**Sets the alignment of the legend title
* @param alignment Text alignment for drawing the legend title
* @note added in 2.3
* @see titleAlignment
*/
void setTitleAlignment( Qt::AlignmentFlag alignment ) { mTitleAlignment = alignment; }

/** Returns reference to modifiable style */
QgsComposerLegendStyle & rstyle( QgsComposerLegendStyle::Style s ) { return mStyleMap[s]; }
/** Returns style */
Expand Down Expand Up @@ -153,6 +166,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
/** Spacing between lines when wrapped */
double mlineSpacing;

/** Title alignment, one of Qt::AlignLeft, Qt::AlignHCenter, Qt::AlignRight) */
Qt::AlignmentFlag mTitleAlignment;

/** Number of legend columns */
int mColumnCount;

Expand Down Expand Up @@ -214,6 +230,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem

QgsComposerLegend(); //forbidden

/**Draws title in the legend using the title font and the specified alignment
* If no painter is specified, function returns the required width/height to draw the title.
*/
QSizeF drawTitle( QPainter* painter = 0, QPointF point = QPointF(), Qt::AlignmentFlag halignment = Qt::AlignLeft );

/**Draws a group item and all subitems
Expand Down Expand Up @@ -247,3 +266,4 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
};

#endif

49 changes: 42 additions & 7 deletions src/ui/qgscomposerlegendwidgetbase.ui
Expand Up @@ -23,7 +23,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
Expand Down Expand Up @@ -55,8 +64,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>375</width>
<height>1287</height>
<width>377</width>
<height>1251</height>
</rect>
</property>
<layout class="QVBoxLayout" name="mainLayout">
Expand Down Expand Up @@ -94,7 +103,7 @@
<item row="0" column="1">
<widget class="QLineEdit" name="mTitleLineEdit"/>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="mMapLabel">
<property name="text">
<string>Map</string>
Expand All @@ -104,10 +113,10 @@
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QComboBox" name="mMapComboBox"/>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Wrap text on</string>
Expand All @@ -117,13 +126,39 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QLineEdit" name="mWrapCharLineEdit">
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Title alignment:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="mTitleAlignCombo">
<item>
<property name="text">
<string>Left</string>
</property>
</item>
<item>
<property name="text">
<string>Center</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down

0 comments on commit a714a18

Please sign in to comment.