Skip to content
Permalink
Browse files

[FEATURE][composer] Vertical alignment control for attribute tables

Sponsored by City of Uster
  • Loading branch information
nyalldawson committed Aug 18, 2015
1 parent 372534e commit 759f842bc3536eccff97d55aa364a5f22c042d10
@@ -65,6 +65,7 @@ class QgsComposerTableColumn: QObject
* @returns horizontal alignment.
* @note added in 2.3
* @see setHAlignment
* @see vAlignment
*/
Qt::AlignmentFlag hAlignment() const;

@@ -73,9 +74,28 @@ class QgsComposerTableColumn: QObject
* @param alignment horizontal alignment for cell.
* @note added in 2.3
* @see hAlignment
* @see setVAlignment
*/
void setHAlignment( Qt::AlignmentFlag alignment );

/** Returns the vertical alignment for a column, which controls the alignment
* used for drawing column values within cells.
* @returns vertical alignment.
* @note added in 2.12
* @see setVAlignment
* @see hAlignment
*/
Qt::AlignmentFlag vAlignment() const;

/** Sets the vertical alignment for a column, which controls the alignment
* used for drawing column values within cells.
* @param alignment vertical alignment for cell.
* @note added in 2.12
* @see vAlignment
* @see setHAlignment
*/
void setVAlignment( Qt::AlignmentFlag alignment );

/** Returns the attribute name or expression used for the column's values. This property
* is only used when the column is part of a QgsComposerAttributeTable.
* @returns attribute name or expression text for column
@@ -48,9 +48,20 @@ QWidget* QgsComposerColumnAlignmentDelegate::createEditor( QWidget* parent, cons

//create a combo box showing alignment options
QComboBox *comboBox = new QComboBox( parent );
QStringList alignments;
alignments << tr( "Left" ) << tr( "Center" ) << tr( "Right" );
comboBox->addItems( alignments );

comboBox->addItem( tr( "Top left" ), int( Qt::AlignTop | Qt::AlignLeft ) );
comboBox->addItem( tr( "Top center" ), int( Qt::AlignTop | Qt::AlignHCenter ) );
comboBox->addItem( tr( "Top right" ), int( Qt::AlignTop | Qt::AlignRight ) );
comboBox->addItem( tr( "Middle left" ), int( Qt::AlignVCenter | Qt::AlignLeft ) );
comboBox->addItem( tr( "Middle center" ), int( Qt::AlignVCenter | Qt::AlignHCenter ) );
comboBox->addItem( tr( "Middle right" ), int( Qt::AlignVCenter | Qt::AlignRight ) );
comboBox->addItem( tr( "Bottom left" ), int( Qt::AlignBottom | Qt::AlignLeft ) );
comboBox->addItem( tr( "Bottom center" ), int( Qt::AlignBottom | Qt::AlignHCenter ) );
comboBox->addItem( tr( "Bottom right" ), int( Qt::AlignBottom | Qt::AlignRight ) );

Qt::AlignmentFlag alignment = ( Qt::AlignmentFlag )index.model()->data( index, Qt::EditRole ).toInt();
comboBox->setCurrentIndex( comboBox->findData( alignment ) );

return comboBox;
}

@@ -60,40 +71,13 @@ void QgsComposerColumnAlignmentDelegate::setEditorData( QWidget* editor, const Q

//set the value for the combobox
QComboBox *comboBox = static_cast<QComboBox*>( editor );
switch ( alignment )
{
case Qt::AlignHCenter:
comboBox->setCurrentIndex( 1 );
break;
case Qt::AlignRight:
comboBox->setCurrentIndex( 2 );
break;
case Qt::AlignLeft:
default:
comboBox->setCurrentIndex( 0 );
break;
}
comboBox->setCurrentIndex( comboBox->findData( alignment ) );
}

void QgsComposerColumnAlignmentDelegate::setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const
{
QComboBox *comboBox = static_cast<QComboBox*>( editor );
int value = comboBox->currentIndex();
Qt::AlignmentFlag alignment;
switch ( value )
{
case 1:
alignment = Qt::AlignHCenter;
break;
case 2:
alignment = Qt::AlignRight;
break;
case 0:
default:
alignment = Qt::AlignLeft;
break;
}

Qt::AlignmentFlag alignment = ( Qt::AlignmentFlag ) comboBox->itemData( comboBox->currentIndex() ).toInt();
model->setData( index, alignment, Qt::EditRole );
}

@@ -105,18 +105,42 @@ QVariant QgsComposerAttributeTableColumnModel::data( const QModelIndex &index, i
switch ( column->hAlignment() )
{
case Qt::AlignHCenter:
return tr( "Center" );
switch ( column->vAlignment() )
{
case Qt::AlignTop:
return tr( "Top center" );
case Qt::AlignBottom:
return tr( "Bottom center" );
default:
return tr( "Middle center" );
}
case Qt::AlignRight:
return tr( "Right" );
switch ( column->vAlignment() )
{
case Qt::AlignTop:
return tr( "Top right" );
case Qt::AlignBottom:
return tr( "Bottom right" );
default:
return tr( "Middle right" );
}
case Qt::AlignLeft:
default:
return tr( "Left" );
switch ( column->vAlignment() )
{
case Qt::AlignTop:
return tr( "Top left" );
case Qt::AlignBottom:
return tr( "Bottom left" );
default:
return tr( "Middle left" );
}
}
}
else
{
//edit role
return column->hAlignment();
return int( column->hAlignment() | column->vAlignment() );
}
}

@@ -198,7 +222,8 @@ bool QgsComposerAttributeTableColumnModel::setData( const QModelIndex& index, co
emit dataChanged( index, index );
return true;
case 2:
column->setHAlignment(( Qt::AlignmentFlag )value.toInt() );
column->setHAlignment( Qt::AlignmentFlag( value.toInt() & Qt::AlignHorizontal_Mask ) );
column->setVAlignment( Qt::AlignmentFlag( value.toInt() & Qt::AlignVertical_Mask ) );
emit dataChanged( index, index );
return true;
default:
@@ -105,18 +105,42 @@ QVariant QgsComposerAttributeTableColumnModelV2::data( const QModelIndex &index,
switch ( column->hAlignment() )
{
case Qt::AlignHCenter:
return tr( "Center" );
switch ( column->vAlignment() )
{
case Qt::AlignTop:
return tr( "Top center" );
case Qt::AlignBottom:
return tr( "Bottom center" );
default:
return tr( "Middle center" );
}
case Qt::AlignRight:
return tr( "Right" );
switch ( column->vAlignment() )
{
case Qt::AlignTop:
return tr( "Top right" );
case Qt::AlignBottom:
return tr( "Bottom right" );
default:
return tr( "Middle right" );
}
case Qt::AlignLeft:
default:
return tr( "Left" );
switch ( column->vAlignment() )
{
case Qt::AlignTop:
return tr( "Top left" );
case Qt::AlignBottom:
return tr( "Bottom left" );
default:
return tr( "Middle left" );
}
}
}
else
{
//edit role
return column->hAlignment();
return int( column->hAlignment() | column->vAlignment() );
}
}
case 3:
@@ -212,7 +236,8 @@ bool QgsComposerAttributeTableColumnModelV2::setData( const QModelIndex& index,
emit dataChanged( index, index );
return true;
case 2:
column->setHAlignment(( Qt::AlignmentFlag )value.toInt() );
column->setHAlignment( Qt::AlignmentFlag( value.toInt() & Qt::AlignHorizontal_Mask ) );
column->setVAlignment( Qt::AlignmentFlag( value.toInt() & Qt::AlignVertical_Mask ) );
emit dataChanged( index, index );
return true;
case 3:
@@ -142,7 +142,7 @@ void QgsComposerTable::paint( QPainter* painter, const QStyleOptionGraphicsItem*

const QgsAttributeMap &currentAttributeMap = *attIt;
QString str = currentAttributeMap[ col ].toString();
QgsComposerUtils::drawText( painter, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, Qt::TextDontClip );
QgsComposerUtils::drawText( painter, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), ( *columnIt )->vAlignment(), Qt::TextDontClip );

currentY += cellBodyHeight;
currentY += mGridStrokeWidth;
@@ -20,6 +20,7 @@
QgsComposerTableColumn::QgsComposerTableColumn( const QString& heading ) :
mBackgroundColor( Qt::transparent ),
mHAlignment( Qt::AlignLeft ),
mVAlignment( Qt::AlignVCenter ),
mHeading( heading ),
mSortByRank( 0 ),
mSortOrder( Qt::AscendingOrder ),
@@ -45,6 +46,7 @@ bool QgsComposerTableColumn::writeXML( QDomElement& columnElem, QDomDocument& do
columnElem.appendChild( bgColorElem );

columnElem.setAttribute( "hAlignment", mHAlignment );
columnElem.setAttribute( "vAlignment", mVAlignment );

columnElem.setAttribute( "heading", mHeading );
columnElem.setAttribute( "attribute", mAttribute );
@@ -60,6 +62,7 @@ bool QgsComposerTableColumn::writeXML( QDomElement& columnElem, QDomDocument& do
bool QgsComposerTableColumn::readXML( const QDomElement& columnElem )
{
mHAlignment = ( Qt::AlignmentFlag )columnElem.attribute( "hAlignment", QString::number( Qt::AlignLeft ) ).toInt();
mVAlignment = ( Qt::AlignmentFlag )columnElem.attribute( "vAlignment", QString::number( Qt::AlignVCenter ) ).toInt();
mHeading = columnElem.attribute( "heading", "" );
mAttribute = columnElem.attribute( "attribute", "" );
mSortByRank = columnElem.attribute( "sortByRank", "0" ).toInt();
@@ -91,6 +94,7 @@ QgsComposerTableColumn* QgsComposerTableColumn::clone()
newColumn->setAttribute( mAttribute );
newColumn->setHeading( mHeading );
newColumn->setHAlignment( mHAlignment );
newColumn->setVAlignment( mVAlignment );
newColumn->setSortByRank( mSortByRank );
newColumn->setSortOrder( mSortOrder );
newColumn->setWidth( mWidth );
@@ -87,6 +87,7 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
* @returns horizontal alignment.
* @note added in 2.3
* @see setHAlignment
* @see vAlignment
*/
Qt::AlignmentFlag hAlignment() const { return mHAlignment; }

@@ -95,9 +96,28 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
* @param alignment horizontal alignment for cell.
* @note added in 2.3
* @see hAlignment
* @see setVAlignment
*/
void setHAlignment( Qt::AlignmentFlag alignment ) { mHAlignment = alignment; }

/** Returns the vertical alignment for a column, which controls the alignment
* used for drawing column values within cells.
* @returns vertical alignment.
* @note added in 2.12
* @see setVAlignment
* @see hAlignment
*/
Qt::AlignmentFlag vAlignment() const { return mVAlignment; }

/** Sets the vertical alignment for a column, which controls the alignment
* used for drawing column values within cells.
* @param alignment vertical alignment for cell.
* @note added in 2.12
* @see vAlignment
* @see setHAlignment
*/
void setVAlignment( Qt::AlignmentFlag alignment ) { mVAlignment = alignment; }

/** Returns the attribute name or expression used for the column's values. This property
* is only used when the column is part of a QgsComposerAttributeTable.
* @returns attribute name or expression text for column
@@ -174,6 +194,7 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject

QColor mBackgroundColor; //curently unused
Qt::AlignmentFlag mHAlignment;
Qt::AlignmentFlag mVAlignment;
QString mHeading;
QString mAttribute;
int mSortByRank;
@@ -473,7 +473,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameInd
QVariant cellContents = mTableContents.at( row ).at( col );
QString str = cellContents.toString();

QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, textFlag );
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), ( *columnIt )->vAlignment(), textFlag );

currentX += mMaxColumnWidthMap[ col ];
currentX += mCellMargin;
@@ -69,8 +69,8 @@ class TestQgsComposerTableV2 : public QObject
void attributeTableRelationSource(); //test attribute table in relation mode
void contentsContainsRow(); //test the contentsContainsRow function
void removeDuplicates(); //test removing duplicate rows

void multiLineText(); //test rendering a table with multiline text
void align(); //test alignment of table cells

private:
QgsComposition* mComposition;
@@ -663,5 +663,45 @@ void TestQgsComposerTableV2::multiLineText()
delete multiLineLayer;
}

void TestQgsComposerTableV2::align()
{
QgsVectorLayer* multiLineLayer = new QgsVectorLayer( "Point?field=col1:string&field=col2:string&field=col3:string", "multiline", "memory" );
QVERIFY( multiLineLayer->isValid() );
QgsFeature f1( multiLineLayer->dataProvider()->fields(), 1 );
f1.setAttribute( "col1", "multiline\nstring" );
f1.setAttribute( "col2", "singleline string" );
f1.setAttribute( "col3", "singleline" );
QgsFeature f2( multiLineLayer->dataProvider()->fields(), 2 );
f2.setAttribute( "col1", "singleline string" );
f2.setAttribute( "col2", "multiline\nstring" );
f2.setAttribute( "col3", "singleline" );
QgsFeature f3( multiLineLayer->dataProvider()->fields(), 3 );
f3.setAttribute( "col1", "singleline" );
f3.setAttribute( "col2", "singleline" );
f3.setAttribute( "col3", "multiline\nstring" );
QgsFeature f4( multiLineLayer->dataProvider()->fields(), 4 );
f4.setAttribute( "col1", "long triple\nline\nstring" );
f4.setAttribute( "col2", "double\nlinestring" );
f4.setAttribute( "col3", "singleline" );
multiLineLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 << f3 << f4 );

mFrame2->setSceneRect( QRectF( 5, 40, 100, 90 ) );

mComposerAttributeTable->setMaximumNumberOfFeatures( 20 );
mComposerAttributeTable->setVectorLayer( multiLineLayer );

mComposerAttributeTable->columns()->at( 0 )->setHAlignment( Qt::AlignLeft );
mComposerAttributeTable->columns()->at( 0 )->setVAlignment( Qt::AlignTop );
mComposerAttributeTable->columns()->at( 1 )->setHAlignment( Qt::AlignHCenter );
mComposerAttributeTable->columns()->at( 1 )->setVAlignment( Qt::AlignVCenter );
mComposerAttributeTable->columns()->at( 2 )->setHAlignment( Qt::AlignRight );
mComposerAttributeTable->columns()->at( 2 )->setVAlignment( Qt::AlignBottom );
QgsCompositionChecker checker( "composerattributetable_align", mComposition );
bool result = checker.testComposition( mReport );
QVERIFY( result );

delete multiLineLayer;
}

QTEST_MAIN( TestQgsComposerTableV2 )
#include "testqgscomposertablev2.moc"
Binary file not shown.
Binary file not shown.

0 comments on commit 759f842

Please sign in to comment.
You can’t perform that action at this time.