Skip to content

Commit b266f6a

Browse files
author
mhugent
committedJan 6, 2010
[FEATURE]: A table widget to display feature attributes in the composer (but it still needs a bit more settings...)
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@12682 c8812cc2-4d05-0410-92ff-de0c093fc19c

14 files changed

+863
-3
lines changed
 

‎src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ SET(QGIS_APP_SRCS
8383
composer/qgscomposermapwidget.cpp
8484
composer/qgscomposerscalebarwidget.cpp
8585
composer/qgscomposershapewidget.cpp
86+
composer/qgscomposertablewidget.cpp
8687
composer/qgscomposerlegenditemdialog.cpp
8788
composer/qgscomposerlegendwidget.cpp
8889
composer/qgscompositionwidget.cpp
@@ -184,6 +185,7 @@ SET (QGIS_APP_MOC_HDRS
184185
composer/qgscomposermapwidget.h
185186
composer/qgscomposerpicturewidget.h
186187
composer/qgscomposerscalebarwidget.h
188+
composer/qgscomposertablewidget.h
187189
composer/qgscomposershapewidget.h
188190
composer/qgscompositionwidget.h
189191
composer/qgsitempositiondialog.h

‎src/app/composer/qgscomposer.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include "qgscomposerscalebarwidget.h"
3636
#include "qgscomposershape.h"
3737
#include "qgscomposershapewidget.h"
38+
#include "qgscomposertable.h"
39+
#include "qgscomposertablewidget.h"
3840
#include "qgsexception.h"
3941
#include "qgsproject.h"
4042
#include "qgsmapcanvas.h"
@@ -112,6 +114,7 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title ): QMainWindow(),
112114
toggleActionGroup->addAction( mActionSelectMoveItem );
113115
toggleActionGroup->addAction( mActionAddBasicShape );
114116
toggleActionGroup->addAction( mActionAddArrow );
117+
toggleActionGroup->addAction( mActionAddTable );
115118
toggleActionGroup->setExclusive( true );
116119

117120
mActionAddNewMap->setCheckable( true );
@@ -160,6 +163,7 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title ): QMainWindow(),
160163
layoutMenu->addAction( mActionMoveItemContent );
161164
layoutMenu->addAction( mActionAddBasicShape );
162165
layoutMenu->addAction( mActionAddArrow );
166+
layoutMenu->addAction( mActionAddTable );
163167
layoutMenu->addSeparator();
164168
layoutMenu->addAction( mActionGroupItems );
165169
layoutMenu->addAction( mActionUngroupItems );
@@ -255,6 +259,7 @@ void QgsComposer::setupTheme()
255259
mActionAddNewScalebar->setIcon( QgisApp::getThemeIcon( "/mActionScaleBar.png" ) );
256260
mActionAddBasicShape->setIcon( QgisApp::getThemeIcon( "/mActionAddBasicShape.png" ) );
257261
mActionAddArrow->setIcon( QgisApp::getThemeIcon( "/mActionAddArrow.png" ) );
262+
mActionAddTable->setIcon( QgisApp::getThemeIcon( "/mActionOpenTable.png" ) );
258263
mActionSelectMoveItem->setIcon( QgisApp::getThemeIcon( "/mActionSelectPan.png" ) );
259264
mActionMoveItemContent->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemContent.png" ) );
260265
mActionGroupItems->setIcon( QgisApp::getThemeIcon( "/mActionGroupItems.png" ) );
@@ -282,6 +287,7 @@ void QgsComposer::connectSlots()
282287
connect( mView, SIGNAL( composerPictureAdded( QgsComposerPicture* ) ), this, SLOT( addComposerPicture( QgsComposerPicture* ) ) );
283288
connect( mView, SIGNAL( composerShapeAdded( QgsComposerShape* ) ), this, SLOT( addComposerShape( QgsComposerShape* ) ) );
284289
connect( mView, SIGNAL( composerArrowAdded( QgsComposerArrow* ) ), this, SLOT( addComposerArrow( QgsComposerArrow* ) ) );
290+
connect( mView, SIGNAL( composerTableAdded( QgsComposerTable* ) ), this, SLOT( addComposerTable( QgsComposerTable* ) ) );
285291
connect( mView, SIGNAL( actionFinished() ), this, SLOT( setSelectionTool() ) );
286292
}
287293

@@ -826,6 +832,14 @@ void QgsComposer::on_mActionAddBasicShape_triggered()
826832
}
827833
}
828834

835+
void QgsComposer::on_mActionAddTable_triggered()
836+
{
837+
if ( mView )
838+
{
839+
mView->setCurrentTool( QgsComposerView::AddTable );
840+
}
841+
}
842+
829843
void QgsComposer::on_mActionAddArrow_triggered()
830844
{
831845
if ( mView )
@@ -1260,6 +1274,21 @@ void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument&
12601274
showItemOptions( newArrow );
12611275
}
12621276

1277+
//composer tables
1278+
QDomNodeList composerTableList = composerElem.elementsByTagName( "ComposerTable" );
1279+
for ( int i = 0; i < composerTableList.size(); ++i )
1280+
{
1281+
QDomElement currentTableElem = composerTableList.at( i ).toElement();
1282+
QgsComposerTable* newTable = new QgsComposerTable( mComposition );
1283+
newTable->readXML( currentTableElem, doc );
1284+
addComposerTable( newTable );
1285+
mComposition->addItem( newTable );
1286+
mComposition->update();
1287+
mComposition->clearSelection();
1288+
newTable->setSelected( true );
1289+
showItemOptions( newTable );
1290+
}
1291+
12631292
mComposition->sortZList();
12641293
mView->setComposition( mComposition );
12651294

@@ -1355,6 +1384,16 @@ void QgsComposer::addComposerShape( QgsComposerShape* shape )
13551384
mItemWidgetMap.insert( shape, sWidget );
13561385
}
13571386

1387+
void QgsComposer::addComposerTable( QgsComposerTable* table )
1388+
{
1389+
if ( !table )
1390+
{
1391+
return;
1392+
}
1393+
QgsComposerTableWidget* tWidget = new QgsComposerTableWidget( table );
1394+
mItemWidgetMap.insert( table, tWidget );
1395+
}
1396+
13581397
void QgsComposer::deleteItem( QgsComposerItem* item )
13591398
{
13601399
QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( item );

‎src/app/composer/qgscomposer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class QgsComposerMap;
2929
class QgsComposerPicture;
3030
class QgsComposerScaleBar;
3131
class QgsComposerShape;
32+
class QgsComposerTable;
3233
class QgsComposerView;
3334
class QgsComposition;
3435
class QgsMapCanvas;
@@ -150,6 +151,9 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
150151
//! Add ellipse shape item
151152
void on_mActionAddBasicShape_triggered();
152153

154+
//! Add attribute table
155+
void on_mActionAddTable_triggered();
156+
153157
//! Save composer as template
154158
void on_mActionSaveAsTemplate_triggered();
155159

@@ -218,6 +222,9 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
218222
/**Adds a composer shape to the item/widget map and creates a configuration widget*/
219223
void addComposerShape( QgsComposerShape* shape );
220224

225+
/**Adds a composer table to the item/widget map and creates a configuration widget*/
226+
void addComposerTable( QgsComposerTable* table );
227+
221228
/**Removes item from the item/widget map and deletes the configuration widget*/
222229
void deleteItem( QgsComposerItem* item );
223230

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/***************************************************************************
2+
qgscomposertablewidget.cpp
3+
--------------------------
4+
begin : January 2010
5+
copyright : (C) 2010 by Marco Hugentobler
6+
email : marco at hugis dot net
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgscomposertablewidget.h"
19+
#include "qgscomposeritemwidget.h"
20+
#include "qgscomposertable.h"
21+
#include "qgscomposermap.h"
22+
#include "qgsmaplayerregistry.h"
23+
#include "qgsvectorlayer.h"
24+
#include <QFontDialog>
25+
26+
QgsComposerTableWidget::QgsComposerTableWidget( QgsComposerTable* table ): QWidget( 0 ), mComposerTable( table )
27+
{
28+
setupUi( this );
29+
//add widget for general composer item properties
30+
QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, mComposerTable );
31+
mToolBox->addItem( itemPropertiesWidget, tr( "General options" ) );
32+
33+
//insert vector layers into combo
34+
QMap<QString, QgsMapLayer*> layerMap = QgsMapLayerRegistry::instance()->mapLayers();
35+
QMap<QString, QgsMapLayer*>::const_iterator mapIt = layerMap.constBegin();
36+
37+
for ( ; mapIt != layerMap.constEnd(); ++mapIt )
38+
{
39+
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( mapIt.value() );
40+
if ( vl )
41+
{
42+
mLayerComboBox->addItem( vl->name(), mapIt.key() );
43+
}
44+
}
45+
46+
//insert composer maps into combo
47+
if ( mComposerTable )
48+
{
49+
const QgsComposition* tableComposition = mComposerTable->composition();
50+
if ( tableComposition )
51+
{
52+
QList<const QgsComposerMap*> mapList = tableComposition->composerMapItems();
53+
QList<const QgsComposerMap*>::const_iterator mapIt = mapList.constBegin();
54+
for ( ; mapIt != mapList.constEnd(); ++mapIt )
55+
{
56+
int mapId = ( *mapIt )->id();
57+
mComposerMapComboBox->addItem( tr( "Map %1" ).arg( mapId ), mapId );
58+
}
59+
}
60+
}
61+
62+
updateGuiElements();
63+
}
64+
65+
QgsComposerTableWidget::~QgsComposerTableWidget()
66+
{
67+
68+
}
69+
70+
void QgsComposerTableWidget::on_mLayerComboBox_currentIndexChanged( int index )
71+
{
72+
if ( !mComposerTable )
73+
{
74+
return;
75+
}
76+
77+
//set new layer to table item
78+
QVariant itemData = mLayerComboBox->itemData( index );
79+
if ( itemData.type() == QVariant::Invalid )
80+
{
81+
return;
82+
}
83+
84+
QString layerId = itemData.toString();
85+
QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId );
86+
if ( ml )
87+
{
88+
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( ml );
89+
if ( vl )
90+
{
91+
mComposerTable->setVectorLayer( vl );
92+
mComposerTable->update();
93+
}
94+
}
95+
}
96+
97+
void QgsComposerTableWidget::on_mComposerMapComboBox_currentIndexChanged( int index )
98+
{
99+
if ( !mComposerTable )
100+
{
101+
return;
102+
}
103+
104+
QVariant itemData = mComposerMapComboBox->itemData( index );
105+
if ( itemData.type() == QVariant::Invalid )
106+
{
107+
return;
108+
}
109+
110+
int mapId = itemData.toInt();
111+
const QgsComposition* tableComposition = mComposerTable->composition();
112+
if ( tableComposition )
113+
{
114+
mComposerTable->setComposerMap( tableComposition->getComposerMapById( mapId ) );
115+
mComposerTable->update();
116+
}
117+
}
118+
119+
void QgsComposerTableWidget::on_mMaximumColumnsSpinBox_valueChanged( int i )
120+
{
121+
if ( !mComposerTable )
122+
{
123+
return;
124+
}
125+
126+
mComposerTable->setMaximumNumberOfFeatures( i );
127+
mComposerTable->update();
128+
}
129+
130+
void QgsComposerTableWidget::on_mMarginSpinBox_valueChanged( double d )
131+
{
132+
if ( !mComposerTable )
133+
{
134+
return;
135+
}
136+
mComposerTable->setLineTextDistance( d );
137+
mComposerTable->update();
138+
}
139+
140+
void QgsComposerTableWidget::on_mHeaderFontPushButton_clicked()
141+
{
142+
if ( !mComposerTable )
143+
{
144+
return;
145+
}
146+
147+
bool ok;
148+
QFont newFont = QFontDialog::getFont( &ok, mComposerTable->headerFont(), 0, tr( "Select Font" ) );
149+
if ( ok )
150+
{
151+
mComposerTable->setHeaderFont( newFont );
152+
}
153+
}
154+
155+
void QgsComposerTableWidget::on_mContentFontPushButton_clicked()
156+
{
157+
if ( !mComposerTable )
158+
{
159+
return;
160+
}
161+
162+
bool ok;
163+
QFont newFont = QFontDialog::getFont( &ok, mComposerTable->contentFont(), 0, tr( "Select Font" ) );
164+
if ( ok )
165+
{
166+
mComposerTable->setContentFont( newFont );
167+
}
168+
}
169+
170+
void QgsComposerTableWidget::updateGuiElements()
171+
{
172+
if ( !mComposerTable )
173+
{
174+
return;
175+
}
176+
177+
blockAllSignals( true );
178+
179+
//layer combo box
180+
const QgsVectorLayer* vl = mComposerTable->vectorLayer();
181+
if ( vl )
182+
{
183+
int layerIndex = mLayerComboBox->findText( vl->name() );
184+
if ( layerIndex != -1 )
185+
{
186+
mLayerComboBox->setCurrentIndex( layerIndex );
187+
}
188+
}
189+
190+
//map combo box
191+
const QgsComposerMap* cm = mComposerTable->composerMap();
192+
if ( cm )
193+
{
194+
int mapIndex = mComposerMapComboBox->findText( tr( "Map %1" ).arg( cm->id() ) );
195+
if ( mapIndex != -1 )
196+
{
197+
mComposerMapComboBox->setCurrentIndex( mapIndex );
198+
}
199+
}
200+
mMaximumColumnsSpinBox->setValue( mComposerTable->maximumNumberOfFeatures() );
201+
mMarginSpinBox->setValue( mComposerTable->lineTextDistance() );
202+
blockAllSignals( false );
203+
}
204+
205+
void QgsComposerTableWidget::blockAllSignals( bool b )
206+
{
207+
mLayerComboBox->blockSignals( b );
208+
mComposerMapComboBox->blockSignals( b );
209+
mMaximumColumnsSpinBox->blockSignals( b );
210+
mMarginSpinBox->blockSignals( b );
211+
}
212+
213+
214+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/***************************************************************************
2+
qgscomposertablewidget.h
3+
------------------------
4+
begin : January 2010
5+
copyright : (C) 2010 by Marco Hugentobler
6+
email : marco at hugis dot net
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSCOMPOSERTABLEWIDGET_H
19+
#define QGSCOMPOSERTABLEWIDGET_H
20+
21+
#include "ui_qgscomposertablewidgetbase.h"
22+
23+
class QgsComposerTable;
24+
25+
class QgsComposerTableWidget: public QWidget, private Ui::QgsComposerTableWidgetBase
26+
{
27+
Q_OBJECT
28+
public:
29+
QgsComposerTableWidget( QgsComposerTable* table );
30+
~QgsComposerTableWidget();
31+
32+
private:
33+
QgsComposerTable* mComposerTable;
34+
35+
/**Sets the GUI elements to the values of mComposerTable*/
36+
void updateGuiElements();
37+
/**Blocks / unblocks the signals of all GUI elements*/
38+
void blockAllSignals( bool b );
39+
40+
private slots:
41+
void on_mLayerComboBox_currentIndexChanged( int index );
42+
void on_mComposerMapComboBox_currentIndexChanged( int index );
43+
void on_mMaximumColumnsSpinBox_valueChanged( int i );
44+
void on_mMarginSpinBox_valueChanged( double d );
45+
void on_mHeaderFontPushButton_clicked();
46+
void on_mContentFontPushButton_clicked();
47+
};
48+
49+
#endif // QGSCOMPOSERTABLEWIDGET_H

‎src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ SET(QGIS_CORE_SRCS
7676
composer/qgscomposerlabel.cpp
7777
composer/qgscomposerpicture.cpp
7878
composer/qgscomposermap.cpp
79+
composer/qgscomposertable.cpp
7980
composer/qgscomposerscalebar.cpp
8081
composer/qgscomposershape.cpp
8182
composer/qgslegendmodel.cpp

‎src/core/composer/qgscomposeritem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,3 +995,8 @@ void QgsComposerItem::rotate( double angle, double& x, double& y ) const
995995
x = xRot;
996996
y = yRot;
997997
}
998+
999+
void QgsComposerItem::repaint()
1000+
{
1001+
update();
1002+
}

‎src/core/composer/qgscomposeritem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
173173

174174
public slots:
175175
virtual void setRotation( double r );
176+
void repaint();
176177

177178
protected:
178179

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
/***************************************************************************
2+
qgscomposertable.cpp
3+
--------------------
4+
begin : January 2010
5+
copyright : (C) 2010 by Marco Hugentobler
6+
email : marco at hugis dot net
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgscomposertable.h"
19+
#include "qgscomposermap.h"
20+
#include "qgslogger.h"
21+
#include "qgsmaplayerregistry.h"
22+
#include "qgsvectorlayer.h"
23+
#include <QPainter>
24+
25+
QgsComposerTable::QgsComposerTable( QgsComposition* composition ): QgsComposerItem( composition ), mVectorLayer( 0 ), mComposerMap( 0 ), mMaximumNumberOfFeatures( 5 )
26+
{
27+
mLineTextDistance = 1;
28+
}
29+
30+
QgsComposerTable::~QgsComposerTable()
31+
{
32+
33+
}
34+
35+
void QgsComposerTable::setComposerMap( const QgsComposerMap* map )
36+
{
37+
if ( mComposerMap )
38+
{
39+
QObject::disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( repaint() ) );
40+
}
41+
mComposerMap = map;
42+
if ( mComposerMap )
43+
{
44+
QObject::connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( repaint() ) );
45+
}
46+
}
47+
48+
void QgsComposerTable::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
49+
{
50+
if ( !painter )
51+
{
52+
return;
53+
}
54+
55+
if ( mComposerMap && mComposerMap->isDrawing() )
56+
{
57+
return;
58+
}
59+
60+
//getFeatureAttributes
61+
QList<QgsAttributeMap> attributeList;
62+
if ( !getFeatureAttributes( attributeList ) )
63+
{
64+
return;
65+
}
66+
67+
QMap<int, double> maxColumnWidthMap;
68+
//check how much space each column needs
69+
calculateMaxColumnWidths( maxColumnWidthMap, attributeList );
70+
//adapt item fram to max width / height
71+
adaptItemFrame( maxColumnWidthMap, attributeList );
72+
73+
//now draw the text
74+
double currentX = 0;
75+
double currentY;
76+
77+
QgsFieldMap vectorFields = mVectorLayer->pendingFields();
78+
QgsFieldMap::const_iterator fieldIt = vectorFields.constBegin();
79+
for ( ; fieldIt != vectorFields.constEnd(); ++fieldIt )
80+
{
81+
currentY = 0;
82+
currentY += mLineTextDistance;
83+
currentY += fontAscentMillimeters( mHeaderFont );
84+
currentX += mLineTextDistance;
85+
drawText( painter, currentX, currentY, fieldIt.value().name(), mHeaderFont );
86+
87+
currentY += mLineTextDistance;
88+
89+
//draw the attribute values
90+
QList<QgsAttributeMap>::const_iterator attIt = attributeList.begin();
91+
for ( ; attIt != attributeList.end(); ++attIt )
92+
{
93+
currentY += fontAscentMillimeters( mContentFont );
94+
currentY += mLineTextDistance;
95+
96+
QgsAttributeMap currentAttributeMap = *attIt;
97+
QgsAttributeMap::const_iterator attMapIt = currentAttributeMap.find( fieldIt.key() );
98+
if ( attMapIt != currentAttributeMap.constEnd() )
99+
{
100+
drawText( painter, currentX, currentY, attMapIt.value().toString(), mContentFont );
101+
}
102+
103+
currentY += mLineTextDistance;
104+
}
105+
106+
currentX += mLineTextDistance;
107+
currentX += maxColumnWidthMap[fieldIt.key()];
108+
}
109+
110+
//and the borders
111+
painter->setPen( mGridPen );
112+
drawHorizontalGridLines( painter, attributeList.size() );
113+
drawVerticalGridLines( painter, maxColumnWidthMap );
114+
115+
//draw frame and selection boxes if necessary
116+
drawFrame( painter );
117+
if ( isSelected() )
118+
{
119+
drawSelectionBoxes( painter );
120+
}
121+
}
122+
123+
bool QgsComposerTable::writeXML( QDomElement& elem, QDomDocument & doc ) const
124+
{
125+
QDomElement composerTableElem = doc.createElement( "ComposerTable" );
126+
composerTableElem.setAttribute( "maxFeatures", mMaximumNumberOfFeatures );
127+
composerTableElem.setAttribute( "lineTextDist", mLineTextDistance );
128+
composerTableElem.setAttribute( "headerFont", mHeaderFont.toString() );
129+
composerTableElem.setAttribute( "contentFont", mContentFont.toString() );
130+
if ( mComposerMap )
131+
{
132+
composerTableElem.setAttribute( "composerMap", mComposerMap->id() );
133+
}
134+
else
135+
{
136+
composerTableElem.setAttribute( "composerMap", -1 );
137+
}
138+
if ( mVectorLayer )
139+
{
140+
composerTableElem.setAttribute( "vectorLayer", mVectorLayer->getLayerID() );
141+
}
142+
elem.appendChild( composerTableElem );
143+
return _writeXML( composerTableElem, doc );;
144+
}
145+
146+
bool QgsComposerTable::readXML( const QDomElement& itemElem, const QDomDocument& doc )
147+
{
148+
if ( itemElem.isNull() )
149+
{
150+
return false;
151+
}
152+
153+
mMaximumNumberOfFeatures = itemElem.attribute( "maxFeatures", "5" ).toInt();
154+
mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
155+
mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
156+
mLineTextDistance = itemElem.attribute( "lineTextDist", "1.0" ).toDouble();
157+
158+
//composer map
159+
int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt();
160+
if ( composerMapId == -1 )
161+
{
162+
mComposerMap = 0;
163+
}
164+
165+
if ( composition() )
166+
{
167+
mComposerMap = composition()->getComposerMapById( composerMapId );
168+
}
169+
else
170+
{
171+
mComposerMap = 0;
172+
}
173+
174+
//vector layer
175+
QString layerId = itemElem.attribute( "vectorLayer", "not_existing" );
176+
if ( layerId == "not_existing" )
177+
{
178+
mVectorLayer = 0;
179+
}
180+
else
181+
{
182+
QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId );
183+
if ( ml )
184+
{
185+
mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml );
186+
}
187+
}
188+
189+
//restore general composer item properties
190+
QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
191+
if ( composerItemList.size() > 0 )
192+
{
193+
QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
194+
_readXML( composerItemElem, doc );
195+
}
196+
return true;
197+
}
198+
199+
bool QgsComposerTable::getFeatureAttributes( QList<QgsAttributeMap>& attributes )
200+
{
201+
if ( !mVectorLayer )
202+
{
203+
return false;
204+
}
205+
attributes.clear();
206+
207+
QgsRectangle selectionRect;
208+
if ( mComposerMap )
209+
{
210+
selectionRect = mComposerMap->extent();
211+
}
212+
213+
mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), selectionRect, false, true );
214+
QgsFeature f;
215+
int counter = 0;
216+
while ( mVectorLayer->nextFeature( f ) && counter < mMaximumNumberOfFeatures )
217+
{
218+
attributes.push_back( f.attributeMap() );
219+
++counter;
220+
}
221+
return true;
222+
}
223+
224+
bool QgsComposerTable::calculateMaxColumnWidths( QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeList ) const
225+
{
226+
maxWidthMap.clear();
227+
if ( !mVectorLayer )
228+
{
229+
return false;
230+
}
231+
232+
QgsFieldMap vectorFields = mVectorLayer->pendingFields();
233+
234+
//initialize max width map with attribute names
235+
QgsFieldMap::const_iterator fieldIt = vectorFields.constBegin();
236+
for ( ; fieldIt != vectorFields.constEnd(); ++fieldIt )
237+
{
238+
maxWidthMap.insert( fieldIt.key(), textWidthMillimeters( mHeaderFont, fieldIt.value().name() ) );
239+
}
240+
241+
//go through all the attributes and adapt the max width values
242+
QList<QgsAttributeMap>::const_iterator attIt = attributeList.constBegin();
243+
244+
QgsAttributeMap currentAttributeMap;
245+
double currentAttributeTextWidth;
246+
247+
for ( ; attIt != attributeList.constEnd(); ++attIt )
248+
{
249+
currentAttributeMap = *attIt;
250+
QgsAttributeMap::const_iterator attMapIt = currentAttributeMap.constBegin();
251+
for ( ; attMapIt != currentAttributeMap.constEnd(); ++attMapIt )
252+
{
253+
currentAttributeTextWidth = textWidthMillimeters( mContentFont, attMapIt.value().toString() );
254+
if ( currentAttributeTextWidth > maxWidthMap[attMapIt.key()] )
255+
{
256+
maxWidthMap[attMapIt.key()] = currentAttributeTextWidth;
257+
}
258+
}
259+
}
260+
return true;
261+
}
262+
263+
void QgsComposerTable::adaptItemFrame( const QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeList )
264+
{
265+
//calculate height
266+
double totalHeight = fontAscentMillimeters( mHeaderFont ) + attributeList.size() * fontAscentMillimeters( mContentFont ) + ( attributeList.size() + 1 ) * mLineTextDistance * 2;
267+
268+
//adapt frame to total width
269+
double totalWidth = 0;
270+
QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
271+
for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
272+
{
273+
totalWidth += maxColWidthIt.value();
274+
}
275+
totalWidth += ( 2 * maxWidthMap.size() * mLineTextDistance );
276+
QTransform t = transform();
277+
setSceneRect( QRectF( t.dx(), t.dy(), totalWidth, totalHeight ) );
278+
}
279+
280+
void QgsComposerTable::drawHorizontalGridLines( QPainter* p, int nAttributes )
281+
{
282+
//horizontal lines
283+
double currentY = 0;
284+
p->drawLine( QPointF( 0, currentY ), QPointF( rect().width(), currentY ) );
285+
currentY += ( fontAscentMillimeters( mHeaderFont ) + 2 * mLineTextDistance );
286+
for ( int i = 0; i < nAttributes; ++i )
287+
{
288+
p->drawLine( QPointF( 0, currentY ), QPointF( rect().width(), currentY ) );
289+
currentY += ( fontAscentMillimeters( mContentFont ) + 2 * mLineTextDistance );
290+
}
291+
p->drawLine( QPointF( 0, currentY ), QPointF( rect().width(), currentY ) );
292+
}
293+
294+
void QgsComposerTable::drawVerticalGridLines( QPainter* p, const QMap<int, double>& maxWidthMap )
295+
{
296+
//vertical lines
297+
double currentX = 0;
298+
p->drawLine( QPointF( currentX, 0 ), QPointF( currentX, rect().height() ) );
299+
QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
300+
for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
301+
{
302+
currentX += ( maxColWidthIt.value() + 2 * mLineTextDistance );
303+
p->drawLine( QPointF( currentX, 0 ), QPointF( currentX, rect().height() ) );
304+
}
305+
}
306+

‎src/core/composer/qgscomposertable.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/***************************************************************************
2+
qgscomposertable.h
3+
------------------
4+
begin : January 2010
5+
copyright : (C) 2010 by Marco Hugentobler
6+
email : marco at hugis dot net
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSCOMPOSERTABLE_H
19+
#define QGSCOMPOSERTABLE_H
20+
21+
#include "qgscomposeritem.h"
22+
#include "qgsfeature.h"
23+
24+
class QgsComposerMap;
25+
class QgsVectorLayer;
26+
27+
/**A class to display feature attributes in the print composer*/
28+
class QgsComposerTable: public QgsComposerItem
29+
{
30+
public:
31+
QgsComposerTable( QgsComposition* composition );
32+
~QgsComposerTable();
33+
34+
/** \brief Reimplementation of QCanvasItem::paint*/
35+
void paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget );
36+
37+
bool writeXML( QDomElement& elem, QDomDocument & doc ) const;
38+
bool readXML( const QDomElement& itemElem, const QDomDocument& doc );
39+
40+
void setVectorLayer( QgsVectorLayer* vl ) { mVectorLayer = vl; }
41+
const QgsVectorLayer* vectorLayer() const { return mVectorLayer; }
42+
43+
void setComposerMap( const QgsComposerMap* map );
44+
const QgsComposerMap* composerMap() const { return mComposerMap; }
45+
46+
void setMaximumNumberOfFeatures( int nr ) { mMaximumNumberOfFeatures = nr; }
47+
int maximumNumberOfFeatures() const { return mMaximumNumberOfFeatures; }
48+
49+
void setLineTextDistance( double d ) { mLineTextDistance = d; }
50+
double lineTextDistance() const { return mLineTextDistance; }
51+
52+
void setHeaderFont( const QFont& f ) { mHeaderFont = f;}
53+
QFont headerFont() const { return mHeaderFont; }
54+
55+
void setContentFont( const QFont& f ) { mContentFont = f; }
56+
QFont contentFont() const { return mContentFont; }
57+
58+
private:
59+
/**Associated vector layer*/
60+
QgsVectorLayer* mVectorLayer;
61+
/**Associated composer map (used to display the visible features)*/
62+
const QgsComposerMap* mComposerMap;
63+
/**Maximum number of features that is displayed*/
64+
int mMaximumNumberOfFeatures;
65+
/**Distance between table lines and text*/
66+
double mLineTextDistance;
67+
QPen mGridPen;
68+
QFont mHeaderFont;
69+
QFont mContentFont;
70+
71+
/**Retrieves feature attributes*/
72+
bool getFeatureAttributes( QList<QgsAttributeMap>& attributes );
73+
/**Calculate the maximum width values of the vector attributes*/
74+
bool calculateMaxColumnWidths( QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeList ) const;
75+
/**Adapts the size of the item frame to match the content*/
76+
void adaptItemFrame( const QMap<int, double>& maxWidthMap, const QList<QgsAttributeMap>& attributeList );
77+
void drawHorizontalGridLines( QPainter* p, int nAttributes );
78+
void drawVerticalGridLines( QPainter* p, const QMap<int, double>& maxWidthMap );
79+
};
80+
81+
#endif // QGSCOMPOSERTABLE_H

‎src/gui/qgscomposerview.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "qgscomposerpicture.h"
2929
#include "qgscomposerscalebar.h"
3030
#include "qgscomposershape.h"
31+
#include "qgscomposertable.h"
3132

3233
QgsComposerView::QgsComposerView( QWidget* parent, const char* name, Qt::WFlags f ) :
3334
QGraphicsView( parent ), mShiftKeyPressed( false ), mRubberBandItem( 0 ), mRubberBandLineItem( 0 ), mMoveContentItem( 0 )
@@ -147,6 +148,7 @@ void QgsComposerView::mousePressEvent( QMouseEvent* e )
147148
QgsComposerLegend* newLegend = new QgsComposerLegend( composition() );
148149
addComposerLegend( newLegend );
149150
newLegend->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLegend->rect().width(), newLegend->rect().height() ) );
151+
emit actionFinished();
150152
break;
151153
}
152154
case AddPicture:
@@ -156,6 +158,13 @@ void QgsComposerView::mousePressEvent( QMouseEvent* e )
156158
newPicture->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 30, 30 ) );
157159
emit actionFinished();
158160
}
161+
case AddTable:
162+
{
163+
QgsComposerTable* newTable = new QgsComposerTable( composition() );
164+
addComposerTable( newTable );
165+
newTable->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 50, 50 ) );
166+
emit actionFinished();
167+
}
159168

160169
default:
161170
break;
@@ -499,7 +508,6 @@ void QgsComposerView::addComposerLegend( QgsComposerLegend* legend )
499508
scene()->clearSelection();
500509
legend->setSelected( true );
501510
emit selectedItemChanged( legend );
502-
emit actionFinished();
503511
}
504512

505513
void QgsComposerView::addComposerPicture( QgsComposerPicture* picture )
@@ -520,6 +528,15 @@ void QgsComposerView::addComposerShape( QgsComposerShape* shape )
520528
emit selectedItemChanged( shape );
521529
}
522530

531+
void QgsComposerView::addComposerTable( QgsComposerTable* table )
532+
{
533+
scene()->addItem( table );
534+
emit composerTableAdded( table );
535+
scene()->clearSelection();
536+
table->setSelected( true );
537+
emit selectedItemChanged( table );
538+
}
539+
523540
void QgsComposerView::groupItems()
524541
{
525542
if ( !composition() )

‎src/gui/qgscomposerview.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class QgsComposerMap;
3232
class QgsComposerPicture;
3333
class QgsComposerScaleBar;
3434
class QgsComposerShape;
35+
class QgsComposerTable;
3536

3637
/** \ingroup MapComposer
3738
* \ingroup gui
@@ -57,6 +58,7 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
5758
AddScalebar, // add scalebar
5859
AddPicture, // add raster/vector picture
5960
AddShape, //add shape item (ellipse, rectangle, triangle)
61+
AddTable, //add attribute table
6062
MoveItemContent //move content of item (e.g. content of map)
6163
};
6264

@@ -88,8 +90,10 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
8890
void addComposerLegend( QgsComposerLegend* legend );
8991
/**Adds picture to the graphics scene and advices composer to create a widget for it (through signal)*/
9092
void addComposerPicture( QgsComposerPicture* picture );
91-
/**Adds a composer shape to the graphics scene and acvices composer to create a widget for it (through signal)*/
93+
/**Adds a composer shape to the graphics scene and advices composer to create a widget for it (through signal)*/
9294
void addComposerShape( QgsComposerShape* shape );
95+
/**Adds a composer table to the graphics scene and advices composer to create a widget for it (through signal)*/
96+
void addComposerTable( QgsComposerTable* table );
9397

9498
/**Returns the composer main window*/
9599
QMainWindow* composerWindow();
@@ -141,6 +145,8 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
141145
void composerPictureAdded( QgsComposerPicture* picture );
142146
/**Is emitted when a new composer shape has been added*/
143147
void composerShapeAdded( QgsComposerShape* shape );
148+
/**Is emitted when a new composer table has been added*/
149+
void composerTableAdded( QgsComposerTable* table );
144150
/**Is emitted when a composer item has been removed from the scene*/
145151
void itemRemoved( QgsComposerItem* );
146152
/**Current action (e.g. adding composer map) has been finished. The purpose of this signal is that

‎src/ui/qgscomposerbase.ui

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>737</width>
9+
<width>799</width>
1010
<height>609</height>
1111
</rect>
1212
</property>
@@ -171,6 +171,7 @@
171171
<addaction name="mActionAddNewScalebar"/>
172172
<addaction name="mActionAddBasicShape"/>
173173
<addaction name="mActionAddArrow"/>
174+
<addaction name="mActionAddTable"/>
174175
<addaction name="mActionSelectMoveItem"/>
175176
<addaction name="mActionMoveItemContent"/>
176177
<addaction name="mActionGroupItems"/>
@@ -461,6 +462,17 @@
461462
<string>Add arrow</string>
462463
</property>
463464
</action>
465+
<action name="mActionAddTable">
466+
<property name="checkable">
467+
<bool>true</bool>
468+
</property>
469+
<property name="text">
470+
<string>Add table</string>
471+
</property>
472+
<property name="toolTip">
473+
<string>Adds attribute table</string>
474+
</property>
475+
</action>
464476
</widget>
465477
<tabstops>
466478
<tabstop>mCompositionNameComboBox</tabstop>

‎src/ui/qgscomposertablewidgetbase.ui

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsComposerTableWidgetBase</class>
4+
<widget class="QWidget" name="QgsComposerTableWidgetBase">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>287</width>
10+
<height>238</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Form</string>
15+
</property>
16+
<layout class="QGridLayout" name="gridLayout_2">
17+
<item row="0" column="0">
18+
<widget class="QToolBox" name="mToolBox">
19+
<property name="currentIndex">
20+
<number>0</number>
21+
</property>
22+
<widget class="QWidget" name="page">
23+
<property name="geometry">
24+
<rect>
25+
<x>0</x>
26+
<y>0</y>
27+
<width>269</width>
28+
<height>194</height>
29+
</rect>
30+
</property>
31+
<attribute name="label">
32+
<string>Table</string>
33+
</attribute>
34+
<layout class="QGridLayout" name="gridLayout">
35+
<item row="0" column="0" colspan="2">
36+
<layout class="QHBoxLayout" name="horizontalLayout_4">
37+
<item>
38+
<widget class="QLabel" name="mLayerLabel">
39+
<property name="text">
40+
<string>Layer</string>
41+
</property>
42+
</widget>
43+
</item>
44+
<item>
45+
<widget class="QComboBox" name="mLayerComboBox"/>
46+
</item>
47+
</layout>
48+
</item>
49+
<item row="1" column="0" colspan="2">
50+
<layout class="QHBoxLayout" name="horizontalLayout_3">
51+
<item>
52+
<widget class="QLabel" name="mComposerMapLabel">
53+
<property name="text">
54+
<string>Composer map</string>
55+
</property>
56+
</widget>
57+
</item>
58+
<item>
59+
<widget class="QComboBox" name="mComposerMapComboBox"/>
60+
</item>
61+
</layout>
62+
</item>
63+
<item row="2" column="0" colspan="2">
64+
<layout class="QHBoxLayout" name="horizontalLayout_2">
65+
<item>
66+
<widget class="QLabel" name="mMaxNumFeaturesLabel">
67+
<property name="text">
68+
<string>Maximum columns</string>
69+
</property>
70+
</widget>
71+
</item>
72+
<item>
73+
<widget class="QSpinBox" name="mMaximumColumnsSpinBox"/>
74+
</item>
75+
</layout>
76+
</item>
77+
<item row="3" column="0">
78+
<layout class="QHBoxLayout" name="horizontalLayout">
79+
<item>
80+
<widget class="QLabel" name="mMarginLabel">
81+
<property name="text">
82+
<string>Margin</string>
83+
</property>
84+
</widget>
85+
</item>
86+
<item>
87+
<widget class="QDoubleSpinBox" name="mMarginSpinBox"/>
88+
</item>
89+
</layout>
90+
</item>
91+
<item row="4" column="0">
92+
<widget class="QPushButton" name="mHeaderFontPushButton">
93+
<property name="text">
94+
<string>Header Font...</string>
95+
</property>
96+
</widget>
97+
</item>
98+
<item row="4" column="1">
99+
<widget class="QPushButton" name="mContentFontPushButton">
100+
<property name="text">
101+
<string>Content Font...</string>
102+
</property>
103+
</widget>
104+
</item>
105+
</layout>
106+
<zorder>mHeaderFontPushButton</zorder>
107+
<zorder>mContentFontPushButton</zorder>
108+
<zorder></zorder>
109+
<zorder></zorder>
110+
<zorder></zorder>
111+
<zorder></zorder>
112+
<zorder></zorder>
113+
</widget>
114+
</widget>
115+
</item>
116+
</layout>
117+
</widget>
118+
<resources/>
119+
<connections/>
120+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.