Skip to content

Commit 83f177c

Browse files
committedNov 7, 2017
Start porting label item
1 parent 87d497e commit 83f177c

File tree

16 files changed

+1495
-1
lines changed

16 files changed

+1495
-1
lines changed
 

‎python/core/composer/qgscomposerlabel.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ Get font color
189189
%End
190190

191191
public slots:
192+
192193
void refreshExpressionContext();
193194

194195

‎python/core/core_auto.sip

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@
168168
%Include layout/qgslayoutsize.sip
169169
%Include layout/qgslayoutsnapper.sip
170170
%Include layout/qgslayoutundocommand.sip
171-
%Include layout/qgslayoutundostack.sip
172171
%Include layout/qgslayoututils.sip
173172
%Include metadata/qgslayermetadata.sip
174173
%Include metadata/qgslayermetadatavalidator.sip
@@ -408,6 +407,7 @@
408407
%Include layout/qgslayoutguidecollection.sip
409408
%Include layout/qgslayoutitem.sip
410409
%Include layout/qgslayoutitemgroup.sip
410+
%Include layout/qgslayoutitemlabel.sip
411411
%Include layout/qgslayoutitemmap.sip
412412
%Include layout/qgslayoutitemmapgrid.sip
413413
%Include layout/qgslayoutitemmapitem.sip
@@ -422,6 +422,7 @@
422422
%Include layout/qgslayoutmodel.sip
423423
%Include layout/qgslayoutpagecollection.sip
424424
%Include layout/qgslayoutobject.sip
425+
%Include layout/qgslayoutundostack.sip
425426
%Include symbology/qgscptcityarchive.sip
426427
%Include symbology/qgssvgcache.sip
427428
%Include symbology/qgsstyle.sip
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/layout/qgslayoutitemlabel.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsLayoutItemLabel: QgsLayoutItem
13+
{
14+
%Docstring
15+
A layout item subclass for text labels.
16+
.. versionadded:: 3.0
17+
%End
18+
19+
%TypeHeaderCode
20+
#include "qgslayoutitemlabel.h"
21+
%End
22+
public:
23+
24+
enum Mode
25+
{
26+
ModeFont,
27+
ModeHtml,
28+
};
29+
30+
QgsLayoutItemLabel( QgsLayout *layout );
31+
%Docstring
32+
Constructor for QgsLayoutItemLabel, with the specified parent ``layout``.
33+
%End
34+
35+
static QgsLayoutItemLabel *create( QgsLayout *layout ) /Factory/;
36+
%Docstring
37+
Returns a new label item for the specified ``layout``.
38+
39+
The caller takes responsibility for deleting the returned object.
40+
:rtype: QgsLayoutItemLabel
41+
%End
42+
43+
44+
virtual int type() const;
45+
46+
virtual QString stringType() const;
47+
48+
virtual QString displayName() const;
49+
50+
void adjustSizeToText();
51+
%Docstring
52+
Resizes the item so that the label's text fits to the item. Keeps the top left point stationary.
53+
%End
54+
55+
QString text();
56+
%Docstring
57+
Returns the label's preset text.
58+
.. seealso:: currentText()
59+
.. seealso:: setText()
60+
:rtype: str
61+
%End
62+
63+
void setText( const QString &text );
64+
%Docstring
65+
Sets the label's preset ``text``.
66+
.. seealso:: text()
67+
%End
68+
69+
QString currentText() const;
70+
%Docstring
71+
Returns the text as it appears on the label (with evaluated expressions
72+
and other dynamic content).
73+
.. seealso:: text()
74+
:rtype: str
75+
%End
76+
77+
Mode mode() const;
78+
%Docstring
79+
Returns the label's current mode.
80+
.. seealso:: setMode()
81+
:rtype: Mode
82+
%End
83+
84+
void setMode( Mode mode );
85+
%Docstring
86+
Sets the label's current ``mode``, allowing the label
87+
to switch between font based and HTML based rendering.
88+
.. seealso:: mode()
89+
%End
90+
91+
QFont font() const;
92+
%Docstring
93+
Returns the label's current font.
94+
.. seealso:: setFont()
95+
:rtype: QFont
96+
%End
97+
98+
void setFont( const QFont &font );
99+
%Docstring
100+
Sets the label's current ``font``.
101+
.. seealso:: font()
102+
%End
103+
104+
Qt::AlignmentFlag vAlign() const;
105+
%Docstring
106+
Returns for the vertical alignment of the label.
107+
.. seealso:: setVAlign()
108+
.. seealso:: hAlign()
109+
:rtype: Qt.AlignmentFlag
110+
%End
111+
112+
Qt::AlignmentFlag hAlign() const;
113+
%Docstring
114+
Returns the horizontal alignment of the label.
115+
.. seealso:: vAlign()
116+
.. seealso:: setHAlign()
117+
:rtype: Qt.AlignmentFlag
118+
%End
119+
120+
void setHAlign( Qt::AlignmentFlag alignment );
121+
%Docstring
122+
Sets the horizontal ``alignment`` of the label.
123+
.. seealso:: hAlign()
124+
.. seealso:: setVAlign()
125+
%End
126+
127+
void setVAlign( Qt::AlignmentFlag alignment );
128+
%Docstring
129+
Sets for the vertical ``alignment`` of the label.
130+
.. seealso:: vAlign()
131+
.. seealso:: setHAlign()
132+
%End
133+
134+
double marginX() const;
135+
%Docstring
136+
Returns the horizontal margin between the edge of the frame and the label
137+
contents, in layout units.
138+
.. seealso:: setMargin()
139+
.. seealso:: marginY()
140+
:rtype: float
141+
%End
142+
143+
double marginY() const;
144+
%Docstring
145+
Returns the vertical margin between the edge of the frame and the label
146+
contents, in layout units.
147+
.. seealso:: setMargin()
148+
.. seealso:: marginX()
149+
:rtype: float
150+
%End
151+
152+
void setMargin( double margin );
153+
%Docstring
154+
Sets the ``margin`` between the edge of the frame and the label contents.
155+
This method sets both the horizontal and vertical margins to the same
156+
value. The margins can be individually controlled using the setMarginX()
157+
and setMarginY() methods.
158+
159+
Margins are set using the current layout units.
160+
161+
.. seealso:: setMarginX()
162+
.. seealso:: setMarginY()
163+
%End
164+
165+
void setMarginX( double margin );
166+
%Docstring
167+
Sets the horizontal ``margin`` between the edge of the frame and the label
168+
contents, in layout units.
169+
.. seealso:: setMargin()
170+
.. seealso:: setMarginY()
171+
%End
172+
173+
void setMarginY( double margin );
174+
%Docstring
175+
Sets the vertical ``margin`` between the edge of the frame and the label
176+
contents, in layout units.
177+
.. seealso:: setMargin()
178+
.. seealso:: setMarginX()
179+
%End
180+
181+
void setFontColor( const QColor &color );
182+
%Docstring
183+
Sets the label font ``color``.
184+
.. seealso:: fontColor()
185+
%End
186+
187+
QColor fontColor() const;
188+
%Docstring
189+
Returns the label font color.
190+
.. seealso:: setFontColor()
191+
:rtype: QColor
192+
%End
193+
194+
virtual QRectF boundingRect() const;
195+
196+
197+
virtual void setFrameEnabled( const bool drawFrame );
198+
199+
200+
virtual void setFrameStrokeWidth( const QgsLayoutMeasurement &strokeWidth );
201+
202+
203+
public slots:
204+
205+
virtual void refresh();
206+
207+
208+
protected:
209+
virtual void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = 0 );
210+
211+
virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
212+
213+
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );
214+
215+
216+
};
217+
218+
/************************************************************************
219+
* This file has been generated automatically from *
220+
* *
221+
* src/core/layout/qgslayoutitemlabel.h *
222+
* *
223+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
224+
************************************************************************/

‎python/core/layout/qgslayoutitemregistry.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class QgsLayoutItemRegistry : QObject
104104
LayoutPage,
105105
LayoutMap,
106106
LayoutPicture,
107+
LayoutLabel,
107108
LayoutShape,
108109
LayoutPolygon,
109110
LayoutPolyline,

‎src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ SET(QGIS_CORE_SRCS
369369
layout/qgslayoutitem.cpp
370370
layout/qgslayoutitemgroup.cpp
371371
layout/qgslayoutitemgroupundocommand.cpp
372+
layout/qgslayoutitemlabel.cpp
372373
layout/qgslayoutitemmap.cpp
373374
layout/qgslayoutitemmapgrid.cpp
374375
layout/qgslayoutitemmapitem.cpp
@@ -728,6 +729,7 @@ SET(QGIS_CORE_MOC_HDRS
728729
layout/qgslayoutitem.h
729730
layout/qgslayoutitemgroup.h
730731
layout/qgslayoutitemgroupundocommand.h
732+
layout/qgslayoutitemlabel.h
731733
layout/qgslayoutitemmap.h
732734
layout/qgslayoutitemmapgrid.h
733735
layout/qgslayoutitemmapitem.h

‎src/core/composer/qgscomposerlabel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class CORE_EXPORT QgsComposerLabel: public QgsComposerItem
170170
virtual void setFrameStrokeWidth( const double strokeWidth ) override;
171171

172172
public slots:
173+
173174
void refreshExpressionContext();
174175

175176

‎src/core/layout/qgslayoutitemlabel.cpp

Lines changed: 603 additions & 0 deletions
Large diffs are not rendered by default.

‎src/core/layout/qgslayoutitemlabel.h

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
/***************************************************************************
2+
qgslayoutitemlabel.h
3+
-------------------
4+
begin : October 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
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+
#ifndef QGSLAYOUTITEMLABEL_H
18+
#define QGSLAYOUTITEMLABEL_H
19+
20+
#include "qgis_core.h"
21+
#include "qgslayoutitem.h"
22+
#include "qgswebpage.h"
23+
#include <QFont>
24+
25+
class QgsVectorLayer;
26+
class QgsFeature;
27+
class QgsDistanceArea;
28+
29+
/**
30+
* \ingroup core
31+
* A layout item subclass for text labels.
32+
* \since QGIS 3.0
33+
*/
34+
class CORE_EXPORT QgsLayoutItemLabel: public QgsLayoutItem
35+
{
36+
Q_OBJECT
37+
38+
public:
39+
40+
//! Label modes
41+
enum Mode
42+
{
43+
ModeFont, //!< Label displays text rendered using a single font
44+
ModeHtml, //!< Label displays rendered HTML content
45+
};
46+
47+
/**
48+
* Constructor for QgsLayoutItemLabel, with the specified parent \a layout.
49+
*/
50+
QgsLayoutItemLabel( QgsLayout *layout );
51+
52+
/**
53+
* Returns a new label item for the specified \a layout.
54+
*
55+
* The caller takes responsibility for deleting the returned object.
56+
*/
57+
static QgsLayoutItemLabel *create( QgsLayout *layout ) SIP_FACTORY;
58+
59+
60+
int type() const override;
61+
QString stringType() const override;
62+
//Overridden to contain part of label's text
63+
virtual QString displayName() const override;
64+
65+
/**
66+
* Resizes the item so that the label's text fits to the item. Keeps the top left point stationary.
67+
*/
68+
void adjustSizeToText();
69+
70+
/**
71+
* Returns the label's preset text.
72+
* \see currentText()
73+
* \see setText()
74+
*/
75+
QString text() { return mText; }
76+
77+
/**
78+
* Sets the label's preset \a text.
79+
* \see text()
80+
*/
81+
void setText( const QString &text );
82+
83+
/**
84+
* Returns the text as it appears on the label (with evaluated expressions
85+
* and other dynamic content).
86+
* \see text()
87+
*/
88+
QString currentText() const;
89+
90+
/**
91+
* Returns the label's current mode.
92+
* \see setMode()
93+
*/
94+
Mode mode() const { return mMode; }
95+
96+
/**
97+
* Sets the label's current \a mode, allowing the label
98+
* to switch between font based and HTML based rendering.
99+
* \see mode()
100+
*/
101+
void setMode( Mode mode );
102+
103+
/**
104+
* Returns the label's current font.
105+
* \see setFont()
106+
*/
107+
QFont font() const;
108+
109+
/**
110+
* Sets the label's current \a font.
111+
* \see font()
112+
*/
113+
void setFont( const QFont &font );
114+
115+
/**
116+
* Returns for the vertical alignment of the label.
117+
* \see setVAlign()
118+
* \see hAlign()
119+
*/
120+
Qt::AlignmentFlag vAlign() const { return mVAlignment; }
121+
122+
/**
123+
* Returns the horizontal alignment of the label.
124+
* \see vAlign()
125+
* \see setHAlign()
126+
*/
127+
Qt::AlignmentFlag hAlign() const { return mHAlignment; }
128+
129+
/**
130+
* Sets the horizontal \a alignment of the label.
131+
* \see hAlign()
132+
* \see setVAlign()
133+
*/
134+
void setHAlign( Qt::AlignmentFlag alignment ) { mHAlignment = alignment; }
135+
136+
/**
137+
* Sets for the vertical \a alignment of the label.
138+
* \see vAlign()
139+
* \see setHAlign()
140+
*/
141+
void setVAlign( Qt::AlignmentFlag alignment ) { mVAlignment = alignment; }
142+
143+
/**
144+
* Returns the horizontal margin between the edge of the frame and the label
145+
* contents, in layout units.
146+
* \see setMargin()
147+
* \see marginY()
148+
*/
149+
double marginX() const { return mMarginX; }
150+
151+
/**
152+
* Returns the vertical margin between the edge of the frame and the label
153+
* contents, in layout units.
154+
* \see setMargin()
155+
* \see marginX()
156+
*/
157+
double marginY() const { return mMarginY; }
158+
159+
/**
160+
* Sets the \a margin between the edge of the frame and the label contents.
161+
* This method sets both the horizontal and vertical margins to the same
162+
* value. The margins can be individually controlled using the setMarginX()
163+
* and setMarginY() methods.
164+
*
165+
* Margins are set using the current layout units.
166+
167+
* \see setMarginX()
168+
* \see setMarginY()
169+
*/
170+
void setMargin( double margin );
171+
172+
/**
173+
* Sets the horizontal \a margin between the edge of the frame and the label
174+
* contents, in layout units.
175+
* \see setMargin()
176+
* \see setMarginY()
177+
*/
178+
void setMarginX( double margin );
179+
180+
/**
181+
* Sets the vertical \a margin between the edge of the frame and the label
182+
* contents, in layout units.
183+
* \see setMargin()
184+
* \see setMarginX()
185+
*/
186+
void setMarginY( double margin );
187+
188+
/**
189+
* Sets the label font \a color.
190+
* \see fontColor()
191+
*/
192+
void setFontColor( const QColor &color ) { mFontColor = color; }
193+
194+
/**
195+
* Returns the label font color.
196+
* \see setFontColor()
197+
*/
198+
QColor fontColor() const { return mFontColor; }
199+
200+
// In case of negative margins, the bounding rect may be larger than the
201+
// label's frame
202+
QRectF boundingRect() const override;
203+
204+
// Reimplemented to call prepareGeometryChange after toggling frame
205+
void setFrameEnabled( const bool drawFrame ) override;
206+
207+
// Reimplemented to call prepareGeometryChange after changing stroke width
208+
void setFrameStrokeWidth( const QgsLayoutMeasurement &strokeWidth ) override;
209+
210+
public slots:
211+
212+
void refresh() override;
213+
214+
protected:
215+
void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = nullptr ) override;
216+
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
217+
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;
218+
219+
private slots:
220+
221+
//! Track when QWebPage has finished loading its html contents
222+
void loadingHtmlFinished( bool );
223+
224+
void refreshExpressionContext();
225+
226+
private:
227+
bool mFirstRender = true;
228+
229+
// Text
230+
QString mText;
231+
232+
Mode mMode = ModeFont;
233+
double mHtmlUnitsToLayoutUnits = 1.0;
234+
double htmlUnitsToLayoutUnits(); //calculate scale factor
235+
bool mHtmlLoaded = false;
236+
237+
//! Helper function to calculate x/y shift for adjustSizeToText() depending on rotation, current size and alignment
238+
void itemShiftAdjustSize( double newWidth, double newHeight, double &xShift, double &yShift ) const;
239+
240+
//! Called when the content is changed to handle HTML loading
241+
void contentChanged();
242+
243+
//! Font
244+
QFont mFont;
245+
246+
//! Horizontal margin between contents and frame (in mm)
247+
double mMarginX = 0.0;
248+
//! Vertical margin between contents and frame (in mm)
249+
double mMarginY = 0.0;
250+
251+
//! Font color
252+
QColor mFontColor = QColor( 0, 0, 0 );
253+
254+
//! Horizontal Alignment
255+
Qt::AlignmentFlag mHAlignment = Qt::AlignJustify;
256+
257+
//! Vertical Alignment
258+
Qt::AlignmentFlag mVAlignment = Qt::AlignTop;
259+
260+
//! Replaces replace '$CURRENT_DATE<(FORMAT)>' with the current date (e.g. $CURRENT_DATE(d 'June' yyyy)
261+
void replaceDateText( QString &text ) const;
262+
263+
//! Creates an encoded stylesheet url using the current font and label appearance settings
264+
QUrl createStylesheetUrl() const;
265+
266+
std::unique_ptr< QgsDistanceArea > mDistanceArea;
267+
268+
std::unique_ptr< QgsWebPage > mWebPage;
269+
};
270+
271+
#endif //QGSLAYOUTITEMLABEL_H

‎src/core/layout/qgslayoutitemregistry.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "qgslayoutitemregistry.h"
1818
#include "qgslayoutitemshape.h"
1919
#include "qgslayoutitemmap.h"
20+
#include "qgslayoutitemlabel.h"
2021
#include "qgslayoutitempolygon.h"
2122
#include "qgslayoutitempolyline.h"
2223
#include "qgslayoutitempage.h"
@@ -52,6 +53,7 @@ bool QgsLayoutItemRegistry::populate()
5253
addLayoutItemType( new QgsLayoutItemMetadata( LayoutPage, QStringLiteral( "Page" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileNew.svg" ) ), QgsLayoutItemPage::create ) );
5354
addLayoutItemType( new QgsLayoutItemMetadata( LayoutMap, QStringLiteral( "Map" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddMap.svg" ) ), QgsLayoutItemMap::create ) );
5455
addLayoutItemType( new QgsLayoutItemMetadata( LayoutPicture, QStringLiteral( "Picture" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddImage.svg" ) ), QgsLayoutItemPicture::create ) );
56+
addLayoutItemType( new QgsLayoutItemMetadata( LayoutLabel, QStringLiteral( "Label" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLabel.svg" ) ), QgsLayoutItemLabel::create ) );
5557
addLayoutItemType( new QgsLayoutItemMetadata( LayoutShape, QStringLiteral( "Shape" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicRectangle.svg" ) ), []( QgsLayout * layout )
5658
{
5759
QgsLayoutItemShape *shape = new QgsLayoutItemShape( layout );

‎src/core/layout/qgslayoutitemregistry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class CORE_EXPORT QgsLayoutItemRegistry : public QObject
186186
LayoutPage, //!< Page items
187187
LayoutMap, //!< Map item
188188
LayoutPicture, //!< Picture item
189+
LayoutLabel, //!< Label item
189190
LayoutShape, //!< Shape item
190191
LayoutPolygon, //!< Polygon shape item
191192
LayoutPolyline, //!< Polyline shape item

‎tests/src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ SET(TESTS
135135
testqgslayoutcontext.cpp
136136
testqgslayoutitem.cpp
137137
testqgslayoutitemgroup.cpp
138+
testqgslayoutlabel.cpp
138139
testqgslayoutmap.cpp
139140
testqgslayoutmapgrid.cpp
140141
testqgslayoutmapoverview.cpp

‎tests/src/core/testqgslayoutlabel.cpp

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/***************************************************************************
2+
testqgslayoutlabel.cpp
3+
----------------------
4+
begin : October 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
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 "qgsapplication.h"
19+
#include "qgslayout.h"
20+
#include "qgslayoutitemlabel.h"
21+
#include "qgsvectorlayer.h"
22+
#include "qgsvectordataprovider.h"
23+
#include "qgsmultirenderchecker.h"
24+
#include "qgsfontutils.h"
25+
#include "qgsproject.h"
26+
27+
#include <QObject>
28+
#include "qgstest.h"
29+
30+
class TestQgsLayoutLabel : public QObject
31+
{
32+
Q_OBJECT
33+
34+
public:
35+
TestQgsLayoutLabel() = default;
36+
37+
private slots:
38+
void initTestCase();// will be called before the first testfunction is executed.
39+
void cleanupTestCase();// will be called after the last testfunction was executed.
40+
void init();// will be called before each testfunction is executed.
41+
void cleanup();// will be called after every testfunction.
42+
43+
// test simple expression evaluation
44+
void evaluation();
45+
// test expression evaluation when a feature is set
46+
void feature_evaluation();
47+
// test page expressions
48+
void page_evaluation();
49+
void marginMethods(); //tests getting/setting margins
50+
void render();
51+
void renderAsHtml();
52+
void renderAsHtmlRelative();
53+
54+
private:
55+
QgsVectorLayer *mVectorLayer = nullptr;
56+
QString mReport;
57+
};
58+
59+
void TestQgsLayoutLabel::initTestCase()
60+
{
61+
QgsApplication::init();
62+
QgsApplication::initQgis();
63+
64+
//create maplayers from testdata and add to layer registry
65+
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + '/' + "france_parts.shp" );
66+
mVectorLayer = new QgsVectorLayer( vectorFileInfo.filePath(),
67+
vectorFileInfo.completeBaseName(),
68+
QStringLiteral( "ogr" ) );
69+
70+
}
71+
72+
void TestQgsLayoutLabel::cleanupTestCase()
73+
{
74+
QString myReportFile = QDir::tempPath() + "/qgistest.html";
75+
QFile myFile( myReportFile );
76+
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
77+
{
78+
QTextStream myQTextStream( &myFile );
79+
myQTextStream << mReport;
80+
myFile.close();
81+
}
82+
83+
delete mVectorLayer;
84+
85+
QgsApplication::exitQgis();
86+
}
87+
88+
void TestQgsLayoutLabel::init()
89+
{
90+
}
91+
92+
void TestQgsLayoutLabel::cleanup()
93+
{
94+
}
95+
96+
void TestQgsLayoutLabel::evaluation()
97+
{
98+
QgsLayout l( QgsProject::instance() );
99+
l.initializeDefaults();
100+
101+
#if 0 //TODO
102+
l.atlasComposition().setCoverageLayer( mVectorLayer );
103+
#endif
104+
105+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
106+
label->setMargin( 1 );
107+
l.addLayoutItem( label );
108+
109+
qWarning() << "composer label font: " << label->font().toString() << " exactMatch:" << label->font().exactMatch();
110+
111+
112+
{
113+
// $CURRENT_DATE evaluation
114+
QString expected = "__" + QDate::currentDate().toString() + "__";
115+
label->setText( QStringLiteral( "__$CURRENT_DATE__" ) );
116+
QString evaluated = label->currentText();
117+
QCOMPARE( evaluated, expected );
118+
}
119+
{
120+
// $CURRENT_DATE() evaluation
121+
QDateTime now = QDateTime::currentDateTime();
122+
QString expected = "__" + now.toString( QStringLiteral( "dd" ) ) + "(ok)__";
123+
label->setText( QStringLiteral( "__$CURRENT_DATE(dd)(ok)__" ) );
124+
QString evaluated = label->currentText();
125+
QCOMPARE( evaluated, expected );
126+
}
127+
{
128+
// $CURRENT_DATE() evaluation (inside an expression)
129+
QDate now = QDate::currentDate();
130+
int dd = now.day();
131+
132+
QString expected = "__" + QStringLiteral( "%1" ).arg( dd + 1 ) + "(ok)__";
133+
label->setText( QStringLiteral( "__[%$CURRENT_DATE(dd) + 1%](ok)__" ) );
134+
QString evaluated = label->currentText();
135+
QCOMPARE( evaluated, expected );
136+
}
137+
{
138+
// expression evaluation (without feature)
139+
QString expected = QStringLiteral( "__[NAME_1]42__" );
140+
label->setText( QStringLiteral( "__[%\"NAME_1\"%][%21*2%]__" ) );
141+
QString evaluated = label->currentText();
142+
QCOMPARE( evaluated, expected );
143+
}
144+
}
145+
146+
void TestQgsLayoutLabel::feature_evaluation()
147+
{
148+
QgsLayout l( QgsProject::instance() );
149+
l.initializeDefaults();
150+
#if 0 //TODO
151+
l.atlasComposition().setCoverageLayer( mVectorLayer );
152+
#endif
153+
154+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
155+
label->setMargin( 1 );
156+
l.addLayoutItem( label );
157+
158+
#if 0 //TODO
159+
l.atlasComposition().setEnabled( true );
160+
l.setAtlasMode( QgsComposition::ExportAtlas );
161+
l.atlasComposition().updateFeatures();
162+
l.atlasComposition().prepareForFeature( 0 );
163+
164+
{
165+
// evaluation with a feature
166+
label->setText( QStringLiteral( "[%\"NAME_1\"||'_ok'%]" ) );
167+
QString evaluated = label->displayText();
168+
QString expected = QStringLiteral( "Basse-Normandie_ok" );
169+
QCOMPARE( evaluated, expected );
170+
}
171+
mComposition->atlasComposition().prepareForFeature( 1 );
172+
{
173+
// evaluation with a feature
174+
label->setText( QStringLiteral( "[%\"NAME_1\"||'_ok'%]" ) );
175+
QString evaluated = label->displayText();
176+
QString expected = QStringLiteral( "Bretagne_ok" );
177+
QCOMPARE( evaluated, expected );
178+
}
179+
mComposition->atlasComposition().setEnabled( false );
180+
#endif
181+
}
182+
183+
void TestQgsLayoutLabel::page_evaluation()
184+
{
185+
#if 0 //TODO
186+
QgsLayout l( QgsProject::instance() );
187+
l.initializeDefaults();
188+
mComposition->atlasComposition().setCoverageLayer( mVectorLayer );
189+
190+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
191+
label->setMargin( 1 );
192+
l.addLayoutItem( label );
193+
194+
mComposition->setNumPages( 2 );
195+
{
196+
label->setText( QStringLiteral( "[%@layout_page||'/'||@layout_numpages%]" ) );
197+
QString evaluated = label->displayText();
198+
QString expected = QStringLiteral( "1/2" );
199+
QCOMPARE( evaluated, expected );
200+
201+
// move to the second page and re-evaluate
202+
label->setItemPosition( 0, 320 );
203+
QCOMPARE( label->displayText(), QString( "2/2" ) );
204+
}
205+
#endif
206+
}
207+
208+
void TestQgsLayoutLabel::marginMethods()
209+
{
210+
QgsLayout l( QgsProject::instance() );
211+
l.initializeDefaults();
212+
213+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
214+
label->setMargin( 1 );
215+
l.addLayoutItem( label );
216+
217+
//test setting margins separately
218+
label->setMarginX( 3.0 );
219+
label->setMarginY( 4.0 );
220+
QCOMPARE( label->marginX(), 3.0 );
221+
QCOMPARE( label->marginY(), 4.0 );
222+
//test setting margins together
223+
label->setMargin( 5.0 );
224+
QCOMPARE( label->marginX(), 5.0 );
225+
QCOMPARE( label->marginY(), 5.0 );
226+
}
227+
228+
void TestQgsLayoutLabel::render()
229+
{
230+
QgsLayout l( QgsProject::instance() );
231+
l.initializeDefaults();
232+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
233+
label->setMargin( 1 );
234+
l.addLayoutItem( label );
235+
236+
label->setText( QStringLiteral( "test label" ) );
237+
label->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 48 ) );
238+
label->attemptMove( QgsLayoutPoint( 70, 70 ) );
239+
label->adjustSizeToText();
240+
241+
QgsLayoutChecker checker( QStringLiteral( "composerlabel_render" ), &l );
242+
checker.setControlPathPrefix( QStringLiteral( "composer_label" ) );
243+
QVERIFY( checker.testLayout( mReport, 0, 0 ) );
244+
}
245+
246+
void TestQgsLayoutLabel::renderAsHtml()
247+
{
248+
QgsLayout l( QgsProject::instance() );
249+
l.initializeDefaults();
250+
251+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
252+
label->setMargin( 1 );
253+
l.addLayoutItem( label );
254+
255+
label->setFontColor( QColor( 200, 40, 60 ) );
256+
label->setText( QStringLiteral( "test <i>html</i>" ) );
257+
label->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 48 ) );
258+
label->setPos( 70, 70 );
259+
label->adjustSizeToText();
260+
label->setMode( QgsLayoutItemLabel::ModeHtml );
261+
label->update();
262+
263+
QgsLayoutChecker checker( QStringLiteral( "composerlabel_renderhtml" ), &l );
264+
checker.setControlPathPrefix( QStringLiteral( "composer_label" ) );
265+
QVERIFY( checker.testLayout( mReport, 0, 10 ) );
266+
}
267+
268+
void TestQgsLayoutLabel::renderAsHtmlRelative()
269+
{
270+
QgsLayout l( QgsProject::instance() );
271+
l.initializeDefaults();
272+
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
273+
label->setMargin( 1 );
274+
l.addLayoutItem( label );
275+
276+
QgsProject::instance()->setFileName( QStringLiteral( TEST_DATA_DIR ) + QDir::separator() + "test.qgs" );
277+
label->setFontColor( QColor( 200, 40, 60 ) );
278+
label->setText( QStringLiteral( "test <img src=\"small_sample_image.png\" />" ) );
279+
label->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 48 ) );
280+
label->setPos( 70, 70 );
281+
label->adjustSizeToText();
282+
label->setMode( QgsLayoutItemLabel::ModeHtml );
283+
label->update();
284+
285+
QgsLayoutChecker checker( QStringLiteral( "composerlabel_renderhtmlrelative" ), &l );
286+
checker.setControlPathPrefix( QStringLiteral( "composer_label" ) );
287+
QVERIFY( checker.testLayout( mReport, 0, 0 ) );
288+
}
289+
290+
QGSTEST_MAIN( TestQgsLayoutLabel )
291+
#include "testqgslayoutlabel.moc"

‎tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ ADD_PYTHON_TEST(PyQgsLayoutGridSettings test_qgslayoutgridsettings.py)
8686
ADD_PYTHON_TEST(PyQgsLayoutGuide test_qgslayoutguides.py)
8787
ADD_PYTHON_TEST(PyQgsLayoutItem test_qgslayoutitem.py)
8888
ADD_PYTHON_TEST(PyQgsLayoutItemPropertiesDialog test_qgslayoutitempropertiesdialog.py)
89+
ADD_PYTHON_TEST(PyQgsLayoutLabel test_qgslayoutlabel.py)
8990
ADD_PYTHON_TEST(PyQgsLayoutMap test_qgslayoutmap.py)
9091
ADD_PYTHON_TEST(PyQgsLayoutMapGrid test_qgslayoutmapgrid.py)
9192
ADD_PYTHON_TEST(PyQgsLayoutPicture test_qgslayoutpicture.py)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for QgsLayoutItemLabel.
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = '(C) 2017 by Nyall Dawson'
10+
__date__ = '23/10/2017'
11+
__copyright__ = 'Copyright 2017, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import qgis # NOQA
16+
17+
from qgis.testing import start_app, unittest
18+
from qgis.PyQt.QtCore import QFileInfo, QDate, QDateTime
19+
from qgis.core import QgsVectorLayer, QgsLayout, QgsLayoutItemLabel, QgsProject
20+
from utilities import unitTestDataPath
21+
22+
23+
start_app()
24+
25+
26+
class TestQgsLayoutItemLabel(unittest.TestCase):
27+
28+
def testCase(self):
29+
TEST_DATA_DIR = unitTestDataPath()
30+
vectorFileInfo = QFileInfo(TEST_DATA_DIR + "/france_parts.shp")
31+
mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr")
32+
33+
QgsProject.instance().addMapLayers([mVectorLayer])
34+
35+
layout = QgsLayout(QgsProject.instance())
36+
layout.initializeDefaults()
37+
38+
label = QgsLayoutItemLabel(layout)
39+
layout.addLayoutItem(label)
40+
41+
self.evaluation_test(layout, label)
42+
self.feature_evaluation_test(layout, label, mVectorLayer)
43+
self.page_evaluation_test(layout, label, mVectorLayer)
44+
45+
def evaluation_test(self, layout, label):
46+
# $CURRENT_DATE evaluation
47+
label.setText("__$CURRENT_DATE__")
48+
assert label.currentText() == ("__" + QDate.currentDate().toString() + "__")
49+
50+
# $CURRENT_DATE() evaluation
51+
label.setText("__$CURRENT_DATE(dd)(ok)__")
52+
expected = "__" + QDateTime.currentDateTime().toString("dd") + "(ok)__"
53+
assert label.currentText() == expected
54+
55+
# $CURRENT_DATE() evaluation (inside an expression)
56+
label.setText("__[%$CURRENT_DATE(dd) + 1%](ok)__")
57+
dd = QDate.currentDate().day()
58+
expected = "__%d(ok)__" % (dd + 1)
59+
assert label.currentText() == expected
60+
61+
# expression evaluation (without associated feature)
62+
label.setText("__[%\"NAME_1\"%][%21*2%]__")
63+
assert label.currentText() == "__[NAME_1]42__"
64+
65+
def feature_evaluation_test(self, layout, label, mVectorLayer):
66+
pass
67+
# TODO
68+
#atlas = layout.atlasComposition()
69+
#atlas.setCoverageLayer(mVectorLayer)
70+
#atlas.setEnabled(True)
71+
#layout.setAtlasMode(QgsComposition.ExportAtlas)
72+
73+
#label.setText("[%\"NAME_1\"||'_ok'%]")
74+
#atlas.beginRender()
75+
#atlas.prepareForFeature(0)
76+
#assert label.currentText() == "Basse-Normandie_ok"
77+
78+
#atlas.prepareForFeature(1)
79+
#assert label.currentText() == "Bretagne_ok"
80+
81+
def page_evaluation_test(self, layout, label, mVectorLayer):
82+
pass
83+
# TODO
84+
#layout.setNumPages(2)
85+
#label.setText("[%@layout_page||'/'||@layout_numpages%]")
86+
#assert label.currentText() == "1/2"
87+
88+
# move the the second page and re-evaluate
89+
#label.setItemPosition(0, 320)
90+
#assert label.currentText() == "2/2"
91+
92+
93+
if __name__ == '__main__':
94+
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.