Skip to content

Commit b893cb2

Browse files
committedSep 22, 2014
[FEATURE][composer] Allow manual control of column widths for attribute table items.
1 parent 97805b6 commit b893cb2

File tree

9 files changed

+161
-10
lines changed

9 files changed

+161
-10
lines changed
 

‎python/core/composer/qgscomposertablecolumn.sip

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@ class QgsComposerTableColumn: QObject
2525
* @see writeXML
2626
*/
2727
virtual bool readXML( const QDomElement& columnElem );
28+
29+
/**Returns the width for a column.
30+
* @returns column width in mm, or 0 if column width is automatically calculated.
31+
* @note added in 2.5
32+
* @see setWidth
33+
*/
34+
double width() const;
35+
36+
/**Sets the width for a column.
37+
* @param width column width in mm, or 0 if column width is to be automatically calculated.
38+
* @note added in 2.5
39+
* @see width
40+
*/
41+
void setWidth( const double width );
2842

2943
/**Returns the heading for a column, which is the value displayed in the columns
3044
* header cell.

‎src/app/composer/qgsattributeselectiondialog.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,52 @@ void QgsComposerColumnSortOrderDelegate::updateEditorGeometry( QWidget* editor,
217217
}
218218

219219

220+
//
221+
// QgsComposerColumnWidthDelegate
222+
//
223+
224+
QgsComposerColumnWidthDelegate::QgsComposerColumnWidthDelegate( QObject *parent )
225+
: QItemDelegate( parent )
226+
{
227+
228+
}
229+
230+
QWidget *QgsComposerColumnWidthDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
231+
{
232+
Q_UNUSED( index );
233+
Q_UNUSED( option );
234+
QDoubleSpinBox *editor = new QDoubleSpinBox( parent );
235+
editor->setMinimum( 0 );
236+
editor->setMaximum( 1000 );
237+
editor->setDecimals( 2 );
238+
editor->setSuffix( tr( " mm" ) );
239+
editor->setSpecialValueText( tr( "Automatic" ) );
240+
return editor;
241+
}
242+
243+
void QgsComposerColumnWidthDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
244+
{
245+
int value = index.model()->data( index, Qt::EditRole ).toInt();
246+
247+
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>( editor );
248+
spinBox->setValue( value );
249+
}
250+
251+
void QgsComposerColumnWidthDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
252+
{
253+
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>( editor );
254+
spinBox->interpretText();
255+
int value = spinBox->value();
256+
257+
model->setData( index, value, Qt::EditRole );
258+
}
259+
260+
void QgsComposerColumnWidthDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
261+
{
262+
Q_UNUSED( index );
263+
editor->setGeometry( option.rect );
264+
}
265+
220266

221267
// QgsAttributeSelectionDialog
222268

@@ -232,7 +278,8 @@ QgsAttributeSelectionDialog::QgsAttributeSelectionDialog( QgsComposerAttributeTa
232278
mAvailableSortProxyModel( 0 ),
233279
mAvailableSortProxyModelV1( 0 ),
234280
mColumnAlignmentDelegate( 0 ),
235-
mColumnSortOrderDelegate( 0 )
281+
mColumnSortOrderDelegate( 0 ),
282+
mColumnWidthDelegate( 0 )
236283
{
237284
setupUi( this );
238285

@@ -250,6 +297,8 @@ QgsAttributeSelectionDialog::QgsAttributeSelectionDialog( QgsComposerAttributeTa
250297
mColumnsTableView->setItemDelegateForColumn( 0, mColumnSourceDelegate );
251298
mColumnAlignmentDelegate = new QgsComposerColumnAlignmentDelegate( mColumnsTableView );
252299
mColumnsTableView->setItemDelegateForColumn( 2, mColumnAlignmentDelegate );
300+
mColumnWidthDelegate = new QgsComposerColumnWidthDelegate( mColumnsTableView );
301+
mColumnsTableView->setItemDelegateForColumn( 3, mColumnWidthDelegate );
253302

254303
mAvailableSortProxyModel = new QgsComposerTableSortColumnsProxyModelV2( mComposerTable, QgsComposerTableSortColumnsProxyModelV2::ShowUnsortedColumns, mSortColumnComboBox );
255304
mAvailableSortProxyModel->setSourceModel( mColumnModel );
@@ -540,3 +589,4 @@ void QgsAttributeSelectionDialog::on_mSortColumnDownPushButton_clicked()
540589
mColumnModelV1->moveColumnInSortRank( column, QgsComposerAttributeTableColumnModel::ShiftDown );
541590
}
542591
}
592+

‎src/app/composer/qgsattributeselectiondialog.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ class QgsComposerColumnSourceDelegate : public QItemDelegate
7171
QgsVectorLayer* mVectorLayer;
7272
};
7373

74+
// QgsComposerColumnWidthDelegate
75+
76+
/**A delegate for showing column width as a spin box*/
77+
class QgsComposerColumnWidthDelegate : public QItemDelegate
78+
{
79+
Q_OBJECT
80+
81+
public:
82+
QgsComposerColumnWidthDelegate( QObject *parent = 0 );
83+
QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
84+
void setEditorData( QWidget *editor, const QModelIndex &index ) const;
85+
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const;
86+
void updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
87+
88+
};
89+
7490

7591
// QgsComposerColumnSortOrderDelegate
7692

@@ -133,6 +149,7 @@ class QgsAttributeSelectionDialog: public QDialog, private Ui::QgsAttributeSelec
133149
QgsComposerColumnAlignmentDelegate *mColumnAlignmentDelegate;
134150
QgsComposerColumnSourceDelegate *mColumnSourceDelegate;
135151
QgsComposerColumnSortOrderDelegate *mColumnSortOrderDelegate;
152+
QgsComposerColumnWidthDelegate *mColumnWidthDelegate;
136153

137154
};
138155

‎src/core/composer/qgscomposerattributetablemodelv2.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int QgsComposerAttributeTableColumnModelV2::rowCount( const QModelIndex &parent
6363
int QgsComposerAttributeTableColumnModelV2::columnCount( const QModelIndex &parent ) const
6464
{
6565
Q_UNUSED( parent );
66-
return 3;
66+
return 4;
6767
}
6868

6969
QVariant QgsComposerAttributeTableColumnModelV2::data( const QModelIndex &index, int role ) const
@@ -119,7 +119,18 @@ QVariant QgsComposerAttributeTableColumnModelV2::data( const QModelIndex &index,
119119
return column->hAlignment();
120120
}
121121
}
122-
122+
case 3:
123+
{
124+
if ( role == Qt::DisplayRole )
125+
{
126+
return column->width() <= 0 ? tr( "Automatic" ) : QString( tr( "%1 mm" ) ).arg( column->width(), 0, 'f', 2 );
127+
}
128+
else
129+
{
130+
//edit role
131+
return column->width();
132+
}
133+
}
123134
default:
124135
return QVariant();
125136
}
@@ -152,6 +163,9 @@ QVariant QgsComposerAttributeTableColumnModelV2::headerData( int section, Qt::Or
152163
case 2:
153164
return QVariant( tr( "Alignment" ) );
154165

166+
case 3:
167+
return QVariant( tr( "Width" ) );
168+
155169
default:
156170
return QVariant();
157171
}
@@ -201,6 +215,10 @@ bool QgsComposerAttributeTableColumnModelV2::setData( const QModelIndex& index,
201215
column->setHAlignment(( Qt::AlignmentFlag )value.toInt() );
202216
emit dataChanged( index, index );
203217
return true;
218+
case 3:
219+
column->setWidth( value.toDouble( ) );
220+
emit dataChanged( index, index );
221+
return true;
204222
default:
205223
break;
206224
}

‎src/core/composer/qgscomposertablecolumn.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ QgsComposerTableColumn::QgsComposerTableColumn() :
2121
mBackgroundColor( Qt::transparent ),
2222
mHAlignment( Qt::AlignLeft ),
2323
mSortByRank( 0 ),
24-
mSortOrder( Qt::AscendingOrder )
24+
mSortOrder( Qt::AscendingOrder ),
25+
mWidth( 0.0 )
2526
{
2627

2728
}
@@ -49,6 +50,8 @@ bool QgsComposerTableColumn::writeXML( QDomElement& columnElem, QDomDocument& do
4950
columnElem.setAttribute( "sortByRank", QString::number( mSortByRank ) );
5051
columnElem.setAttribute( "sortOrder", QString::number( mSortOrder ) );
5152

53+
columnElem.setAttribute( "width", QString::number( mWidth ) );
54+
5255
return true;
5356
}
5457

@@ -59,6 +62,7 @@ bool QgsComposerTableColumn::readXML( const QDomElement& columnElem )
5962
mAttribute = columnElem.attribute( "attribute", "" );
6063
mSortByRank = columnElem.attribute( "sortByRank", "0" ).toInt();
6164
mSortOrder = ( Qt::SortOrder )columnElem.attribute( "sortOrder", QString::number( Qt::AscendingOrder ) ).toInt();
65+
mWidth = columnElem.attribute( "width", "0.0" ).toDouble();
6266

6367
QDomNodeList bgColorList = columnElem.elementsByTagName( "backgroundColor" );
6468
if ( bgColorList.size() > 0 )
@@ -87,5 +91,6 @@ QgsComposerTableColumn* QgsComposerTableColumn::clone()
8791
newColumn->setHAlignment( mHAlignment );
8892
newColumn->setSortByRank( mSortByRank );
8993
newColumn->setSortOrder( mSortOrder );
94+
newColumn->setWidth( mWidth );
9095
return newColumn;
9196
}

‎src/core/composer/qgscomposertablecolumn.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
4848
*/
4949
virtual bool readXML( const QDomElement& columnElem );
5050

51+
/**Returns the width for a column.
52+
* @returns column width in mm, or 0 if column width is automatically calculated.
53+
* @note added in 2.5
54+
* @see setWidth
55+
*/
56+
double width() const { return mWidth; }
57+
58+
/**Sets the width for a column.
59+
* @param width column width in mm, or 0 if column width is to be automatically calculated.
60+
* @note added in 2.5
61+
* @see width
62+
*/
63+
void setWidth( const double width ) { mWidth = width; }
64+
5165
/**Returns the heading for a column, which is the value displayed in the columns
5266
* header cell.
5367
* @returns Heading for column.
@@ -160,6 +174,7 @@ class CORE_EXPORT QgsComposerTableColumn: public QObject
160174
QString mAttribute;
161175
int mSortByRank;
162176
Qt::SortOrder mSortOrder;
177+
double mWidth;
163178

164179
};
165180

‎src/core/composer/qgscomposertablev2.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
266266
currentY = ( mShowGrid ? mGridStrokeWidth : 0 );
267267
currentX += mCellMargin;
268268

269+
Qt::TextFlag textFlag = ( Qt::TextFlag )0;
270+
if (( *columnIt )->width() <= 0 )
271+
{
272+
//automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text
273+
//which may slightly exceed the calculated width
274+
//if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width
275+
textFlag = Qt::TextDontClip;
276+
}
277+
269278
if ( drawHeader )
270279
{
271280
//draw the header
@@ -289,8 +298,7 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
289298
break;
290299
}
291300

292-
293-
QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, Qt::TextDontClip );
301+
QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag );
294302

295303
currentY += cellHeaderHeight;
296304
currentY += ( mShowGrid ? mGridStrokeWidth : 0 );
@@ -303,7 +311,8 @@ void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const
303311

304312
QVariant cellContents = mTableContents.at( row ).at( col );
305313
QString str = cellContents.toString();
306-
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, Qt::TextDontClip );
314+
315+
QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, textFlag );
307316

308317
currentY += cellBodyHeight;
309318
currentY += ( mShowGrid ? mGridStrokeWidth : 0 );
@@ -537,10 +546,16 @@ bool QgsComposerTableV2::calculateMaxColumnWidths()
537546
for ( ; columnIt != mColumns.constEnd(); ++columnIt )
538547
{
539548
double width = 0;
540-
if ( mHeaderMode != QgsComposerTableV2::NoHeaders )
549+
if (( *columnIt )->width() > 0 )
550+
{
551+
//column has manually specified width
552+
width = ( *columnIt )->width();
553+
}
554+
else if ( mHeaderMode != QgsComposerTableV2::NoHeaders )
541555
{
542556
width = QgsComposerUtils::textWidthMM( mHeaderFont, ( *columnIt )->heading() );
543557
}
558+
544559
mMaxColumnWidthMap.insert( col, width );
545560
col++;
546561
}
@@ -554,8 +569,12 @@ bool QgsComposerTableV2::calculateMaxColumnWidths()
554569
int columnNumber = 0;
555570
for ( ; colIt != rowIt->constEnd(); ++colIt )
556571
{
557-
currentCellTextWidth = QgsComposerUtils::textWidthMM( mContentFont, ( *colIt ).toString() );
558-
mMaxColumnWidthMap[ columnNumber ] = qMax( currentCellTextWidth, mMaxColumnWidthMap[ columnNumber ] );
572+
if ( mColumns.at( columnNumber )->width() <= 0 )
573+
{
574+
//column width set to automatic, so check content size
575+
currentCellTextWidth = QgsComposerUtils::textWidthMM( mContentFont, ( *colIt ).toString() );
576+
mMaxColumnWidthMap[ columnNumber ] = qMax( currentCellTextWidth, mMaxColumnWidthMap[ columnNumber ] );
577+
}
559578
columnNumber++;
560579
}
561580
}

‎tests/src/core/testqgscomposertablev2.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "qgscomposition.h"
2020
#include "qgscomposermap.h"
2121
#include "qgscomposerattributetablev2.h"
22+
#include "qgscomposertablecolumn.h"
2223
#include "qgscomposerframe.h"
2324
#include "qgsmapsettings.h"
2425
#include "qgsvectorlayer.h"
@@ -46,6 +47,8 @@ class TestQgsComposerTableV2: public QObject
4647
void attributeTableVisibleOnly(); //test displaying only visible attributes
4748
void attributeTableRender(); //test rendering attribute table
4849

50+
void manualColumnWidth(); //test setting manual column widths
51+
4952
void attributeTableExtend();
5053
void attributeTableRepeat();
5154

@@ -301,6 +304,16 @@ void TestQgsComposerTableV2::attributeTableRender()
301304
QVERIFY( result );
302305
}
303306

307+
void TestQgsComposerTableV2::manualColumnWidth()
308+
{
309+
mComposerAttributeTable->setMaximumNumberOfFeatures( 20 );
310+
mComposerAttributeTable->columns()->at( 0 )->setWidth( 5 );
311+
QgsCompositionChecker checker( "composerattributetable_columnwidth", mComposition );
312+
bool result = checker.testComposition( mReport, 0 );
313+
mComposerAttributeTable->columns()->at( 0 )->setWidth( 0 );
314+
QVERIFY( result );
315+
}
316+
304317
void TestQgsComposerTableV2::attributeTableExtend()
305318
{
306319
//test that adding and removing frames automatically does not result in a crash

0 commit comments

Comments
 (0)
Please sign in to comment.