[FEATURE][composer] Allow manual control of column widths for attribute table items.

This commit is contained in:
Nyall Dawson 2014-09-22 19:13:47 +10:00
parent 97805b64d0
commit b893cb241c
9 changed files with 161 additions and 10 deletions

View File

@ -25,6 +25,20 @@ class QgsComposerTableColumn: QObject
* @see writeXML * @see writeXML
*/ */
virtual bool readXML( const QDomElement& columnElem ); virtual bool readXML( const QDomElement& columnElem );
/**Returns the width for a column.
* @returns column width in mm, or 0 if column width is automatically calculated.
* @note added in 2.5
* @see setWidth
*/
double width() const;
/**Sets the width for a column.
* @param width column width in mm, or 0 if column width is to be automatically calculated.
* @note added in 2.5
* @see width
*/
void setWidth( const double width );
/**Returns the heading for a column, which is the value displayed in the columns /**Returns the heading for a column, which is the value displayed in the columns
* header cell. * header cell.

View File

@ -217,6 +217,52 @@ void QgsComposerColumnSortOrderDelegate::updateEditorGeometry( QWidget* editor,
} }
//
// QgsComposerColumnWidthDelegate
//
QgsComposerColumnWidthDelegate::QgsComposerColumnWidthDelegate( QObject *parent )
: QItemDelegate( parent )
{
}
QWidget *QgsComposerColumnWidthDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
Q_UNUSED( index );
Q_UNUSED( option );
QDoubleSpinBox *editor = new QDoubleSpinBox( parent );
editor->setMinimum( 0 );
editor->setMaximum( 1000 );
editor->setDecimals( 2 );
editor->setSuffix( tr( " mm" ) );
editor->setSpecialValueText( tr( "Automatic" ) );
return editor;
}
void QgsComposerColumnWidthDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
{
int value = index.model()->data( index, Qt::EditRole ).toInt();
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>( editor );
spinBox->setValue( value );
}
void QgsComposerColumnWidthDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>( editor );
spinBox->interpretText();
int value = spinBox->value();
model->setData( index, value, Qt::EditRole );
}
void QgsComposerColumnWidthDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
Q_UNUSED( index );
editor->setGeometry( option.rect );
}
// QgsAttributeSelectionDialog // QgsAttributeSelectionDialog
@ -232,7 +278,8 @@ QgsAttributeSelectionDialog::QgsAttributeSelectionDialog( QgsComposerAttributeTa
mAvailableSortProxyModel( 0 ), mAvailableSortProxyModel( 0 ),
mAvailableSortProxyModelV1( 0 ), mAvailableSortProxyModelV1( 0 ),
mColumnAlignmentDelegate( 0 ), mColumnAlignmentDelegate( 0 ),
mColumnSortOrderDelegate( 0 ) mColumnSortOrderDelegate( 0 ),
mColumnWidthDelegate( 0 )
{ {
setupUi( this ); setupUi( this );
@ -250,6 +297,8 @@ QgsAttributeSelectionDialog::QgsAttributeSelectionDialog( QgsComposerAttributeTa
mColumnsTableView->setItemDelegateForColumn( 0, mColumnSourceDelegate ); mColumnsTableView->setItemDelegateForColumn( 0, mColumnSourceDelegate );
mColumnAlignmentDelegate = new QgsComposerColumnAlignmentDelegate( mColumnsTableView ); mColumnAlignmentDelegate = new QgsComposerColumnAlignmentDelegate( mColumnsTableView );
mColumnsTableView->setItemDelegateForColumn( 2, mColumnAlignmentDelegate ); mColumnsTableView->setItemDelegateForColumn( 2, mColumnAlignmentDelegate );
mColumnWidthDelegate = new QgsComposerColumnWidthDelegate( mColumnsTableView );
mColumnsTableView->setItemDelegateForColumn( 3, mColumnWidthDelegate );
mAvailableSortProxyModel = new QgsComposerTableSortColumnsProxyModelV2( mComposerTable, QgsComposerTableSortColumnsProxyModelV2::ShowUnsortedColumns, mSortColumnComboBox ); mAvailableSortProxyModel = new QgsComposerTableSortColumnsProxyModelV2( mComposerTable, QgsComposerTableSortColumnsProxyModelV2::ShowUnsortedColumns, mSortColumnComboBox );
mAvailableSortProxyModel->setSourceModel( mColumnModel ); mAvailableSortProxyModel->setSourceModel( mColumnModel );
@ -540,3 +589,4 @@ void QgsAttributeSelectionDialog::on_mSortColumnDownPushButton_clicked()
mColumnModelV1->moveColumnInSortRank( column, QgsComposerAttributeTableColumnModel::ShiftDown ); mColumnModelV1->moveColumnInSortRank( column, QgsComposerAttributeTableColumnModel::ShiftDown );
} }
} }

View File

@ -71,6 +71,22 @@ class QgsComposerColumnSourceDelegate : public QItemDelegate
QgsVectorLayer* mVectorLayer; QgsVectorLayer* mVectorLayer;
}; };
// QgsComposerColumnWidthDelegate
/**A delegate for showing column width as a spin box*/
class QgsComposerColumnWidthDelegate : public QItemDelegate
{
Q_OBJECT
public:
QgsComposerColumnWidthDelegate( QObject *parent = 0 );
QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
void setEditorData( QWidget *editor, const QModelIndex &index ) const;
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const;
void updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
};
// QgsComposerColumnSortOrderDelegate // QgsComposerColumnSortOrderDelegate
@ -133,6 +149,7 @@ class QgsAttributeSelectionDialog: public QDialog, private Ui::QgsAttributeSelec
QgsComposerColumnAlignmentDelegate *mColumnAlignmentDelegate; QgsComposerColumnAlignmentDelegate *mColumnAlignmentDelegate;
QgsComposerColumnSourceDelegate *mColumnSourceDelegate; QgsComposerColumnSourceDelegate *mColumnSourceDelegate;
QgsComposerColumnSortOrderDelegate *mColumnSortOrderDelegate; QgsComposerColumnSortOrderDelegate *mColumnSortOrderDelegate;
QgsComposerColumnWidthDelegate *mColumnWidthDelegate;
}; };

View File

@ -63,7 +63,7 @@ int QgsComposerAttributeTableColumnModelV2::rowCount( const QModelIndex &parent
int QgsComposerAttributeTableColumnModelV2::columnCount( const QModelIndex &parent ) const int QgsComposerAttributeTableColumnModelV2::columnCount( const QModelIndex &parent ) const
{ {
Q_UNUSED( parent ); Q_UNUSED( parent );
return 3; return 4;
} }
QVariant QgsComposerAttributeTableColumnModelV2::data( const QModelIndex &index, int role ) const QVariant QgsComposerAttributeTableColumnModelV2::data( const QModelIndex &index, int role ) const
@ -119,7 +119,18 @@ QVariant QgsComposerAttributeTableColumnModelV2::data( const QModelIndex &index,
return column->hAlignment(); return column->hAlignment();
} }
} }
case 3:
{
if ( role == Qt::DisplayRole )
{
return column->width() <= 0 ? tr( "Automatic" ) : QString( tr( "%1 mm" ) ).arg( column->width(), 0, 'f', 2 );
}
else
{
//edit role
return column->width();
}
}
default: default:
return QVariant(); return QVariant();
} }
@ -152,6 +163,9 @@ QVariant QgsComposerAttributeTableColumnModelV2::headerData( int section, Qt::Or
case 2: case 2:
return QVariant( tr( "Alignment" ) ); return QVariant( tr( "Alignment" ) );
case 3:
return QVariant( tr( "Width" ) );
default: default:
return QVariant(); return QVariant();
} }
@ -201,6 +215,10 @@ bool QgsComposerAttributeTableColumnModelV2::setData( const QModelIndex& index,
column->setHAlignment(( Qt::AlignmentFlag )value.toInt() ); column->setHAlignment(( Qt::AlignmentFlag )value.toInt() );
emit dataChanged( index, index ); emit dataChanged( index, index );
return true; return true;
case 3:
column->setWidth( value.toDouble( ) );
emit dataChanged( index, index );
return true;
default: default:
break; break;
} }

View File

@ -21,7 +21,8 @@ QgsComposerTableColumn::QgsComposerTableColumn() :
mBackgroundColor( Qt::transparent ), mBackgroundColor( Qt::transparent ),
mHAlignment( Qt::AlignLeft ), mHAlignment( Qt::AlignLeft ),
mSortByRank( 0 ), mSortByRank( 0 ),
mSortOrder( Qt::AscendingOrder ) mSortOrder( Qt::AscendingOrder ),
mWidth( 0.0 )
{ {
} }
@ -49,6 +50,8 @@ bool QgsComposerTableColumn::writeXML( QDomElement& columnElem, QDomDocument& do
columnElem.setAttribute( "sortByRank", QString::number( mSortByRank ) ); columnElem.setAttribute( "sortByRank", QString::number( mSortByRank ) );
columnElem.setAttribute( "sortOrder", QString::number( mSortOrder ) ); columnElem.setAttribute( "sortOrder", QString::number( mSortOrder ) );
columnElem.setAttribute( "width", QString::number( mWidth ) );
return true; return true;
} }
@ -59,6 +62,7 @@ bool QgsComposerTableColumn::readXML( const QDomElement& columnElem )
mAttribute = columnElem.attribute( "attribute", "" ); mAttribute = columnElem.attribute( "attribute", "" );
mSortByRank = columnElem.attribute( "sortByRank", "0" ).toInt(); mSortByRank = columnElem.attribute( "sortByRank", "0" ).toInt();
mSortOrder = ( Qt::SortOrder )columnElem.attribute( "sortOrder", QString::number( Qt::AscendingOrder ) ).toInt(); mSortOrder = ( Qt::SortOrder )columnElem.attribute( "sortOrder", QString::number( Qt::AscendingOrder ) ).toInt();
mWidth = columnElem.attribute( "width", "0.0" ).toDouble();
QDomNodeList bgColorList = columnElem.elementsByTagName( "backgroundColor" ); QDomNodeList bgColorList = columnElem.elementsByTagName( "backgroundColor" );
if ( bgColorList.size() > 0 ) if ( bgColorList.size() > 0 )
@ -87,5 +91,6 @@ QgsComposerTableColumn* QgsComposerTableColumn::clone()
newColumn->setHAlignment( mHAlignment ); newColumn->setHAlignment( mHAlignment );
newColumn->setSortByRank( mSortByRank ); newColumn->setSortByRank( mSortByRank );
newColumn->setSortOrder( mSortOrder ); newColumn->setSortOrder( mSortOrder );
newColumn->setWidth( mWidth );
return newColumn; return newColumn;
} }

View File

@ -48,6 +48,20 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
*/ */
virtual bool readXML( const QDomElement& columnElem ); virtual bool readXML( const QDomElement& columnElem );
/**Returns the width for a column.
* @returns column width in mm, or 0 if column width is automatically calculated.
* @note added in 2.5
* @see setWidth
*/
double width() const { return mWidth; }
/**Sets the width for a column.
* @param width column width in mm, or 0 if column width is to be automatically calculated.
* @note added in 2.5
* @see width
*/
void setWidth( const double width ) { mWidth = width; }
/**Returns the heading for a column, which is the value displayed in the columns /**Returns the heading for a column, which is the value displayed in the columns
* header cell. * header cell.
* @returns Heading for column. * @returns Heading for column.
@ -160,6 +174,7 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
QString mAttribute; QString mAttribute;
int mSortByRank; int mSortByRank;
Qt::SortOrder mSortOrder; Qt::SortOrder mSortOrder;
double mWidth;
}; };

View File

@ -266,6 +266,15 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
currentY = ( mShowGrid ? mGridStrokeWidth : 0 ); currentY = ( mShowGrid ? mGridStrokeWidth : 0 );
currentX += mCellMargin; currentX += mCellMargin;
Qt::TextFlag textFlag = ( Qt::TextFlag )0;
if (( *columnIt )->width() <= 0 )
{
//automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text
//which may slightly exceed the calculated width
//if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width
textFlag = Qt::TextDontClip;
}
if ( drawHeader ) if ( drawHeader )
{ {
//draw the header //draw the header
@ -289,8 +298,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
break; break;
} }
QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag );
QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, Qt::TextDontClip );
currentY += cellHeaderHeight; currentY += cellHeaderHeight;
currentY += ( mShowGrid ? mGridStrokeWidth : 0 ); currentY += ( mShowGrid ? mGridStrokeWidth : 0 );
@ -303,7 +311,8 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
QVariant cellContents = mTableContents.at( row ).at( col ); QVariant cellContents = mTableContents.at( row ).at( col );
QString str = cellContents.toString(); QString str = cellContents.toString();
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, Qt::TextDontClip );
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, textFlag );
currentY += cellBodyHeight; currentY += cellBodyHeight;
currentY += ( mShowGrid ? mGridStrokeWidth : 0 ); currentY += ( mShowGrid ? mGridStrokeWidth : 0 );
@ -537,10 +546,16 @@ bool QgsComposerTableV2::calculateMaxColumnWidths()
for ( ; columnIt != mColumns.constEnd(); ++columnIt ) for ( ; columnIt != mColumns.constEnd(); ++columnIt )
{ {
double width = 0; double width = 0;
if ( mHeaderMode != QgsComposerTableV2::NoHeaders ) if (( *columnIt )->width() > 0 )
{
//column has manually specified width
width = ( *columnIt )->width();
}
else if ( mHeaderMode != QgsComposerTableV2::NoHeaders )
{ {
width = QgsComposerUtils::textWidthMM( mHeaderFont, ( *columnIt )->heading() ); width = QgsComposerUtils::textWidthMM( mHeaderFont, ( *columnIt )->heading() );
} }
mMaxColumnWidthMap.insert( col, width ); mMaxColumnWidthMap.insert( col, width );
col++; col++;
} }
@ -554,8 +569,12 @@ bool QgsComposerTableV2::calculateMaxColumnWidths()
int columnNumber = 0; int columnNumber = 0;
for ( ; colIt != rowIt->constEnd(); ++colIt ) for ( ; colIt != rowIt->constEnd(); ++colIt )
{ {
currentCellTextWidth = QgsComposerUtils::textWidthMM( mContentFont, ( *colIt ).toString() ); if ( mColumns.at( columnNumber )->width() <= 0 )
mMaxColumnWidthMap[ columnNumber ] = qMax( currentCellTextWidth, mMaxColumnWidthMap[ columnNumber ] ); {
//column width set to automatic, so check content size
currentCellTextWidth = QgsComposerUtils::textWidthMM( mContentFont, ( *colIt ).toString() );
mMaxColumnWidthMap[ columnNumber ] = qMax( currentCellTextWidth, mMaxColumnWidthMap[ columnNumber ] );
}
columnNumber++; columnNumber++;
} }
} }

View File

@ -19,6 +19,7 @@
#include "qgscomposition.h" #include "qgscomposition.h"
#include "qgscomposermap.h" #include "qgscomposermap.h"
#include "qgscomposerattributetablev2.h" #include "qgscomposerattributetablev2.h"
#include "qgscomposertablecolumn.h"
#include "qgscomposerframe.h" #include "qgscomposerframe.h"
#include "qgsmapsettings.h" #include "qgsmapsettings.h"
#include "qgsvectorlayer.h" #include "qgsvectorlayer.h"
@ -46,6 +47,8 @@ class TestQgsComposerTableV2: public QObject
void attributeTableVisibleOnly(); //test displaying only visible attributes void attributeTableVisibleOnly(); //test displaying only visible attributes
void attributeTableRender(); //test rendering attribute table void attributeTableRender(); //test rendering attribute table
void manualColumnWidth(); //test setting manual column widths
void attributeTableExtend(); void attributeTableExtend();
void attributeTableRepeat(); void attributeTableRepeat();
@ -301,6 +304,16 @@ void TestQgsComposerTableV2::attributeTableRender()
QVERIFY( result ); QVERIFY( result );
} }
void TestQgsComposerTableV2::manualColumnWidth()
{
mComposerAttributeTable->setMaximumNumberOfFeatures( 20 );
mComposerAttributeTable->columns()->at( 0 )->setWidth( 5 );
QgsCompositionChecker checker( "composerattributetable_columnwidth", mComposition );
bool result = checker.testComposition( mReport, 0 );
mComposerAttributeTable->columns()->at( 0 )->setWidth( 0 );
QVERIFY( result );
}
void TestQgsComposerTableV2::attributeTableExtend() void TestQgsComposerTableV2::attributeTableExtend()
{ {
//test that adding and removing frames automatically does not result in a crash //test that adding and removing frames automatically does not result in a crash

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB