Skip to content

Commit 6a54130

Browse files
committedJun 23, 2017
[layout] Add layout measurement and size classes
These classes are used for storing measurements for a layout (QgsLayoutMeasurement), sizes for a layout (QgsLayoutSize) and points in a layout (QgsLayoutPoint) They support storing a measurement unit alongside a measurement length/size. A new class QgsLayoutMeasurementConverter handles conversion between different units, including converting to and from pixels via a specified DPI property.
1 parent 81855a7 commit 6a54130

22 files changed

+2621
-0
lines changed
 

‎doc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ IF(WITH_APIDOC)
6363
${CMAKE_SOURCE_DIR}/src/core/geometry
6464
${CMAKE_SOURCE_DIR}/src/core/gps
6565
${CMAKE_SOURCE_DIR}/src/core/layertree
66+
${CMAKE_SOURCE_DIR}/src/core/layout
6667
${CMAKE_SOURCE_DIR}/src/core/metadata
6768
${CMAKE_SOURCE_DIR}/src/core/pal
6869
${CMAKE_SOURCE_DIR}/src/core/processing

‎python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ INCLUDE_DIRECTORIES(
106106
${CMAKE_SOURCE_DIR}/src/core/geometry
107107
${CMAKE_SOURCE_DIR}/src/core/gps
108108
${CMAKE_SOURCE_DIR}/src/core/layertree
109+
${CMAKE_SOURCE_DIR}/src/core/layout
109110
${CMAKE_SOURCE_DIR}/src/core/metadata
110111
${CMAKE_SOURCE_DIR}/src/core/processing
111112
${CMAKE_SOURCE_DIR}/src/core/providers

‎python/core/core.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@ done:
369369
%Include layertree/qgslayertreeregistrybridge.sip
370370
%Include layertree/qgslayertreeutils.sip
371371

372+
%Include layout/qgslayoutmeasurement.sip
373+
%Include layout/qgslayoutmeasurementconverter.sip
374+
%Include layout/qgslayoutpoint.sip
375+
%Include layout/qgslayoutsize.sip
376+
372377
%Include metadata/qgslayermetadata.sip
373378
%Include metadata/qgslayermetadatavalidator.sip
374379

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/layout/qgslayoutmeasurement.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsLayoutMeasurement
14+
{
15+
%Docstring
16+
This class provides a method of storing measurements for use in QGIS layouts
17+
using a variety of different measurement units.
18+
.. seealso:: QgsLayoutMeasurementConverter
19+
.. versionadded:: 3.0
20+
%End
21+
22+
%TypeHeaderCode
23+
#include "qgslayoutmeasurement.h"
24+
%End
25+
public:
26+
27+
explicit QgsLayoutMeasurement( const double length, const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
28+
%Docstring
29+
Constructor for QgsLayoutMeasurement.
30+
\param length measurement length
31+
\param units measurement units
32+
%End
33+
34+
~QgsLayoutMeasurement();
35+
36+
double length() const;
37+
%Docstring
38+
Returns the length of the measurement.
39+
.. seealso:: setLength()
40+
:rtype: float
41+
%End
42+
43+
void setLength( const double length );
44+
%Docstring
45+
Sets the ``length`` of the measurement.
46+
.. seealso:: length()
47+
%End
48+
49+
QgsUnitTypes::LayoutUnit units() const;
50+
%Docstring
51+
Returns the units for the measurement.
52+
.. seealso:: setUnits()
53+
:rtype: QgsUnitTypes.LayoutUnit
54+
%End
55+
56+
void setUnits( const QgsUnitTypes::LayoutUnit units );
57+
%Docstring
58+
Sets the ``units`` for the measurement. Does not alter the stored length,
59+
ie. no length conversion is done.
60+
.. seealso:: units()
61+
%End
62+
63+
QString encodeMeasurement() const;
64+
%Docstring
65+
Encodes the layout measurement to a string
66+
.. seealso:: decodeMeasurement()
67+
:rtype: str
68+
%End
69+
70+
static QgsLayoutMeasurement decodeMeasurement( const QString &string );
71+
%Docstring
72+
Decodes a measurement from a ``string``.
73+
.. seealso:: encodeMeasurement()
74+
:rtype: QgsLayoutMeasurement
75+
%End
76+
77+
bool operator==( const QgsLayoutMeasurement &other ) const;
78+
bool operator!=( const QgsLayoutMeasurement &other ) const;
79+
%Docstring
80+
:rtype: bool
81+
%End
82+
QgsLayoutMeasurement operator+( const double v ) const;
83+
%Docstring
84+
:rtype: QgsLayoutMeasurement
85+
%End
86+
QgsLayoutMeasurement operator+=( const double v );
87+
%Docstring
88+
:rtype: QgsLayoutMeasurement
89+
%End
90+
QgsLayoutMeasurement operator-( const double v ) const;
91+
%Docstring
92+
:rtype: QgsLayoutMeasurement
93+
%End
94+
QgsLayoutMeasurement operator-=( const double v );
95+
%Docstring
96+
:rtype: QgsLayoutMeasurement
97+
%End
98+
QgsLayoutMeasurement operator*( const double v ) const;
99+
%Docstring
100+
:rtype: QgsLayoutMeasurement
101+
%End
102+
QgsLayoutMeasurement operator*=( const double v );
103+
%Docstring
104+
:rtype: QgsLayoutMeasurement
105+
%End
106+
QgsLayoutMeasurement operator/( const double v ) const;
107+
%Docstring
108+
:rtype: QgsLayoutMeasurement
109+
%End
110+
QgsLayoutMeasurement operator/=( const double v );
111+
%Docstring
112+
:rtype: QgsLayoutMeasurement
113+
%End
114+
115+
};
116+
117+
/************************************************************************
118+
* This file has been generated automatically from *
119+
* *
120+
* src/core/layout/qgslayoutmeasurement.h *
121+
* *
122+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
123+
************************************************************************/
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/layout/qgslayoutmeasurementconverter.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsLayoutMeasurementConverter
14+
{
15+
%Docstring
16+
This class provides a method of converting QgsLayoutMeasurements from
17+
one unit to another. Conversion to or from pixel units utilizes a specified
18+
dots per inch (DPI) property for the converter. Converters default to using
19+
300 DPI.
20+
.. seealso:: QgsLayoutMeasurement
21+
.. versionadded:: 3.0
22+
%End
23+
24+
%TypeHeaderCode
25+
#include "qgslayoutmeasurementconverter.h"
26+
%End
27+
public:
28+
29+
QgsLayoutMeasurementConverter();
30+
31+
~QgsLayoutMeasurementConverter();
32+
33+
void setDpi( const double dpi );
34+
%Docstring
35+
Sets the dots per inch (``dpi``) for the measurement converter. This is used
36+
when converting measurements to and from pixels.
37+
.. seealso:: dpi()
38+
%End
39+
40+
double dpi() const;
41+
%Docstring
42+
Returns the Dots per inch (DPI) of the measurement converter. This is used
43+
when converting measurements to and from pixels.
44+
.. seealso:: setDpi()
45+
:rtype: float
46+
%End
47+
48+
QgsLayoutMeasurement convert( const QgsLayoutMeasurement &measurement, const QgsUnitTypes::LayoutUnit targetUnits ) const;
49+
%Docstring
50+
Converts a measurement from one unit to another.
51+
\param measurement measurement to convert
52+
\param targetUnits units to convert measurement into
53+
:return: measurement converted to target units
54+
:rtype: QgsLayoutMeasurement
55+
%End
56+
57+
QgsLayoutSize convert( const QgsLayoutSize &size, const QgsUnitTypes::LayoutUnit targetUnits ) const;
58+
%Docstring
59+
Converts a layout size from one unit to another.
60+
\param size layout size to convert
61+
\param targetUnits units to convert size into
62+
:return: size converted to target units
63+
:rtype: QgsLayoutSize
64+
%End
65+
66+
QgsLayoutPoint convert( const QgsLayoutPoint &point, const QgsUnitTypes::LayoutUnit targetUnits ) const;
67+
%Docstring
68+
Converts a layout point from one unit to another.
69+
\param point layout point to convert
70+
\param targetUnits units to convert point into
71+
:return: point converted to target units
72+
:rtype: QgsLayoutPoint
73+
%End
74+
75+
};
76+
77+
/************************************************************************
78+
* This file has been generated automatically from *
79+
* *
80+
* src/core/layout/qgslayoutmeasurementconverter.h *
81+
* *
82+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
83+
************************************************************************/

‎python/core/layout/qgslayoutpoint.sip

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/layout/qgslayoutpoint.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsLayoutPoint
13+
{
14+
%Docstring
15+
This class provides a method of storing points, consisting of an x and y coordinate,
16+
for use in QGIS layouts. Measurement units are stored alongside the position.
17+
18+
.. seealso:: QgsLayoutMeasurementConverter
19+
.. versionadded:: 3.0
20+
.. note::
21+
22+
This class does not inherit from QPointF since QPointF includes methods which should not apply
23+
to positions with with units. For instance, the + and - operators would mislead users of this class
24+
to believe that addition of two QgsLayoutPoints with different unit types would automatically convert
25+
units. Instead, all unit conversion must be handled by a QgsLayoutMeasurementConverter so that
26+
conversion between paper and screen units can be correctly performed.
27+
%End
28+
29+
%TypeHeaderCode
30+
#include "qgslayoutpoint.h"
31+
%End
32+
public:
33+
34+
QgsLayoutPoint( const double x, const double y, const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
35+
%Docstring
36+
Constructor for QgsLayoutPoint.
37+
\param x x coordinate
38+
\param x y coordinate
39+
\param units units for x and y
40+
%End
41+
42+
explicit QgsLayoutPoint( const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
43+
%Docstring
44+
Constructor for an empty point, where both x and y are set to 0.
45+
\param units units for measurement
46+
%End
47+
48+
~QgsLayoutPoint();
49+
50+
void setPoint( const double x, const double y );
51+
%Docstring
52+
Sets new x and y coordinates for the point.
53+
.. seealso:: setX()
54+
.. seealso:: setY()
55+
.. seealso:: setUnits()
56+
%End
57+
58+
double x() const;
59+
%Docstring
60+
Returns x coordinate of point.
61+
.. seealso:: setX()
62+
.. seealso:: y()
63+
:rtype: float
64+
%End
65+
66+
void setX( const double x );
67+
%Docstring
68+
Sets the x coordinate of point.
69+
.. seealso:: x()
70+
.. seealso:: setY()
71+
%End
72+
73+
double y() const;
74+
%Docstring
75+
Returns y coordinate of point.
76+
.. seealso:: setY()
77+
.. seealso:: x()
78+
:rtype: float
79+
%End
80+
81+
void setY( const double y );
82+
%Docstring
83+
Sets y coordinate of point.
84+
.. seealso:: y()
85+
.. seealso:: setX()
86+
%End
87+
88+
QgsUnitTypes::LayoutUnit units() const;
89+
%Docstring
90+
Returns the units for the point.
91+
.. seealso:: setUnits()
92+
:rtype: QgsUnitTypes.LayoutUnit
93+
%End
94+
95+
void setUnits( const QgsUnitTypes::LayoutUnit units );
96+
%Docstring
97+
Sets the ``units`` for the point. Does not alter the stored coordinates,
98+
ie. no conversion is done.
99+
.. seealso:: units()
100+
%End
101+
102+
bool isNull() const;
103+
%Docstring
104+
Tests whether the position is null, ie both its x and y coordinates
105+
are zero.
106+
:return: true if point is null
107+
:rtype: bool
108+
%End
109+
110+
QPointF toQPointF() const;
111+
%Docstring
112+
Converts the layout point to a QPointF. The unit information is discarded
113+
during this operation.
114+
:return: QPointF with same x and y coordinates as layout point
115+
:rtype: QPointF
116+
%End
117+
118+
QString encodePoint() const;
119+
%Docstring
120+
Encodes the layout point to a string
121+
.. seealso:: decodePoint()
122+
:rtype: str
123+
%End
124+
125+
static QgsLayoutPoint decodePoint( const QString &string );
126+
%Docstring
127+
Decodes a point from a ``string``.
128+
.. seealso:: encodePoint()
129+
:rtype: QgsLayoutPoint
130+
%End
131+
132+
bool operator==( const QgsLayoutPoint &other ) const;
133+
bool operator!=( const QgsLayoutPoint &other ) const;
134+
%Docstring
135+
:rtype: bool
136+
%End
137+
QgsLayoutPoint operator*( const double v ) const;
138+
%Docstring
139+
:rtype: QgsLayoutPoint
140+
%End
141+
QgsLayoutPoint operator*=( const double v );
142+
%Docstring
143+
:rtype: QgsLayoutPoint
144+
%End
145+
QgsLayoutPoint operator/( const double v ) const;
146+
%Docstring
147+
:rtype: QgsLayoutPoint
148+
%End
149+
QgsLayoutPoint operator/=( const double v );
150+
%Docstring
151+
:rtype: QgsLayoutPoint
152+
%End
153+
154+
};
155+
156+
/************************************************************************
157+
* This file has been generated automatically from *
158+
* *
159+
* src/core/layout/qgslayoutpoint.h *
160+
* *
161+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
162+
************************************************************************/

‎python/core/layout/qgslayoutsize.sip

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/layout/qgslayoutsize.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsLayoutSize
14+
{
15+
%Docstring
16+
This class provides a method of storing sizes, consisting of a width and height,
17+
for use in QGIS layouts. Measurement units are stored alongside the size.
18+
19+
.. seealso:: QgsLayoutMeasurementConverter
20+
.. versionadded:: 3.0
21+
.. note::
22+
23+
This class does not inherit from QSizeF since QSizeF includes methods which should not apply to sizes
24+
with units. For instance, the + and - operators would mislead users of this class to believe that
25+
addition of two QgsLayoutSize with different unit types would automatically convert units. Instead,
26+
all unit conversion must be handled by a QgsLayoutMeasurementConverter so that conversion between
27+
paper and screen units can be correctly performed.
28+
%End
29+
30+
%TypeHeaderCode
31+
#include "qgslayoutsize.h"
32+
%End
33+
public:
34+
35+
QgsLayoutSize( const double width, const double height, const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
36+
%Docstring
37+
Constructor for QgsLayoutSize.
38+
\param width width
39+
\param height height
40+
\param units units for width and height
41+
%End
42+
43+
explicit QgsLayoutSize( const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
44+
%Docstring
45+
Constructor for an empty layout size
46+
\param units units for measurement
47+
%End
48+
49+
~QgsLayoutSize();
50+
51+
void setSize( const double width, const double height );
52+
%Docstring
53+
Sets new ``width`` and ``height`` for the size.
54+
.. seealso:: setWidth()
55+
.. seealso:: setHeight()
56+
.. seealso:: setUnits()
57+
%End
58+
59+
double width() const;
60+
%Docstring
61+
Returns the width of the size.
62+
.. seealso:: setWidth()
63+
.. seealso:: height()
64+
:rtype: float
65+
%End
66+
67+
void setWidth( const double width );
68+
%Docstring
69+
Sets the ``width`` for the size.
70+
.. seealso:: width()
71+
.. seealso:: setHeight()
72+
%End
73+
74+
double height() const;
75+
%Docstring
76+
Returns the height of the size.
77+
.. seealso:: setHeight()
78+
.. seealso:: width()
79+
:rtype: float
80+
%End
81+
82+
void setHeight( const double height );
83+
%Docstring
84+
Sets the ``height`` for the size.
85+
.. seealso:: height()
86+
.. seealso:: setWidth()
87+
%End
88+
89+
QgsUnitTypes::LayoutUnit units() const;
90+
%Docstring
91+
Returns the units for the size.
92+
.. seealso:: setUnits()
93+
:rtype: QgsUnitTypes.LayoutUnit
94+
%End
95+
96+
void setUnits( const QgsUnitTypes::LayoutUnit units );
97+
%Docstring
98+
Sets the ``units`` for the size. Does not alter the stored width or height,
99+
ie. no conversion is done.
100+
.. seealso:: units()
101+
%End
102+
103+
bool isEmpty() const;
104+
%Docstring
105+
Tests whether the size is empty, ie both its width and height
106+
are zero.
107+
:return: true if size is empty
108+
:rtype: bool
109+
%End
110+
111+
QSizeF toQSizeF() const;
112+
%Docstring
113+
Converts the layout size to a QSizeF. The unit information is discarded
114+
during this operation.
115+
:return: QSizeF with same dimensions as layout size
116+
:rtype: QSizeF
117+
%End
118+
119+
QString encodeSize() const;
120+
%Docstring
121+
Encodes the layout size to a string
122+
.. seealso:: decodeSize()
123+
:rtype: str
124+
%End
125+
126+
static QgsLayoutSize decodeSize( const QString &string );
127+
%Docstring
128+
Decodes a size from a ``string``.
129+
.. seealso:: encodeSize()
130+
:rtype: QgsLayoutSize
131+
%End
132+
133+
bool operator==( const QgsLayoutSize &other ) const;
134+
bool operator!=( const QgsLayoutSize &other ) const;
135+
%Docstring
136+
:rtype: bool
137+
%End
138+
QgsLayoutSize operator*( const double v ) const;
139+
%Docstring
140+
:rtype: QgsLayoutSize
141+
%End
142+
QgsLayoutSize operator*=( const double v );
143+
%Docstring
144+
:rtype: QgsLayoutSize
145+
%End
146+
QgsLayoutSize operator/( const double v ) const;
147+
%Docstring
148+
:rtype: QgsLayoutSize
149+
%End
150+
QgsLayoutSize operator/=( const double v );
151+
%Docstring
152+
:rtype: QgsLayoutSize
153+
%End
154+
155+
};
156+
157+
/************************************************************************
158+
* This file has been generated automatically from *
159+
* *
160+
* src/core/layout/qgslayoutsize.h *
161+
* *
162+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
163+
************************************************************************/

‎python/core/qgsunittypes.sip

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@ class QgsUnitTypes
8181
RenderUnknownUnit,
8282
};
8383

84+
enum LayoutUnit
85+
{
86+
LayoutMillimeters,
87+
LayoutCentimeters,
88+
LayoutMeters,
89+
LayoutInches,
90+
LayoutFeet,
91+
LayoutPoints,
92+
LayoutPicas,
93+
LayoutPixels
94+
};
95+
96+
enum LayoutUnitType
97+
{
98+
LayoutPaperUnits,
99+
LayoutScreenUnits
100+
};
101+
84102
struct DistanceValue
85103
{
86104

@@ -368,6 +386,34 @@ class QgsUnitTypes
368386
.. versionadded:: 3.0
369387
:rtype: str
370388
%End
389+
390+
391+
392+
static QString encodeUnit( LayoutUnit unit );
393+
%Docstring
394+
Encodes a layout unit to a string.
395+
\param unit unit to encode
396+
:return: encoded string
397+
.. seealso:: decodeLayoutUnit()
398+
:rtype: str
399+
%End
400+
401+
static LayoutUnit decodeLayoutUnit( const QString &string, bool *ok /Out/ = 0 );
402+
%Docstring
403+
Decodes a layout unit from a string.
404+
\param string string to decode
405+
\param ok optional boolean, will be set to true if string was converted successfully
406+
:return: decoded units
407+
.. seealso:: encodeUnit()
408+
:rtype: LayoutUnit
409+
%End
410+
411+
static LayoutUnitType unitType( const LayoutUnit units );
412+
%Docstring
413+
Returns the type for a unit of measurement.
414+
:rtype: LayoutUnitType
415+
%End
416+
371417
};
372418

373419
/************************************************************************

‎src/core/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ SET(QGIS_CORE_SRCS
343343
dxf/qgsdxfpaintengine.cpp
344344
dxf/qgsdxfpallabeling.cpp
345345

346+
layout/qgslayoutmeasurement.cpp
347+
layout/qgslayoutmeasurementconverter.cpp
348+
layout/qgslayoutpoint.cpp
349+
layout/qgslayoutsize.cpp
350+
346351
pal/costcalculator.cpp
347352
pal/feature.cpp
348353
pal/geomfunction.cpp
@@ -892,6 +897,11 @@ SET(QGIS_CORE_HDRS
892897
composer/qgscomposertexttable.h
893898
composer/qgspaperitem.h
894899

900+
layout/qgslayoutmeasurement.h
901+
layout/qgslayoutmeasurementconverter.h
902+
layout/qgslayoutpoint.h
903+
layout/qgslayoutsize.h
904+
895905
metadata/qgslayermetadata.h
896906
metadata/qgslayermetadatavalidator.h
897907

@@ -1042,6 +1052,7 @@ INCLUDE_DIRECTORIES(
10421052
fieldformatter
10431053
geometry
10441054
layertree
1055+
layout
10451056
metadata
10461057
pal
10471058
processing
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/***************************************************************************
2+
qgslayoutmeasurement.cpp
3+
--------------------
4+
begin : June 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 "qgslayoutmeasurement.h"
19+
20+
#include <QStringList>
21+
22+
QgsLayoutMeasurement::QgsLayoutMeasurement( const double length, const QgsUnitTypes::LayoutUnit units )
23+
: mLength( length )
24+
, mUnits( units )
25+
{
26+
}
27+
28+
QgsLayoutMeasurement::~QgsLayoutMeasurement()
29+
{
30+
}
31+
32+
QString QgsLayoutMeasurement::encodeMeasurement() const
33+
{
34+
return QStringLiteral( "%1,%2" ).arg( mLength ).arg( QgsUnitTypes::encodeUnit( mUnits ) );
35+
}
36+
37+
QgsLayoutMeasurement QgsLayoutMeasurement::decodeMeasurement( const QString &string )
38+
{
39+
QStringList parts = string.split( ',' );
40+
if ( parts.count() != 2 )
41+
{
42+
return QgsLayoutMeasurement( 0 );
43+
}
44+
return QgsLayoutMeasurement( parts[0].toDouble(), QgsUnitTypes::decodeLayoutUnit( parts[1] ) );
45+
}
46+
47+
bool QgsLayoutMeasurement::operator==( const QgsLayoutMeasurement &other ) const
48+
{
49+
return other.units() == mUnits && other.length() == mLength;
50+
}
51+
52+
bool QgsLayoutMeasurement::operator!=( const QgsLayoutMeasurement &other ) const
53+
{
54+
return ( ! operator==( other ) );
55+
}
56+
57+
QgsLayoutMeasurement QgsLayoutMeasurement::operator+( const double v ) const
58+
{
59+
return QgsLayoutMeasurement( mLength + v, mUnits );
60+
}
61+
62+
QgsLayoutMeasurement QgsLayoutMeasurement::operator+=( const double v )
63+
{
64+
*this = *this + v;
65+
return *this;
66+
}
67+
68+
QgsLayoutMeasurement QgsLayoutMeasurement::operator-( const double v ) const
69+
{
70+
return QgsLayoutMeasurement( mLength - v, mUnits );
71+
}
72+
73+
QgsLayoutMeasurement QgsLayoutMeasurement::operator-=( const double v )
74+
{
75+
*this = *this - v;
76+
return *this;
77+
}
78+
79+
QgsLayoutMeasurement QgsLayoutMeasurement::operator*( const double v ) const
80+
{
81+
return QgsLayoutMeasurement( mLength * v, mUnits );
82+
}
83+
84+
QgsLayoutMeasurement QgsLayoutMeasurement::operator*=( const double v )
85+
{
86+
*this = *this * v;
87+
return *this;
88+
}
89+
90+
QgsLayoutMeasurement QgsLayoutMeasurement::operator/( const double v ) const
91+
{
92+
return QgsLayoutMeasurement( mLength / v, mUnits );
93+
}
94+
95+
QgsLayoutMeasurement QgsLayoutMeasurement::operator/=( const double v )
96+
{
97+
*this = *this / v;
98+
return *this;
99+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/***************************************************************************
2+
qgslayoutmeasurement.h
3+
--------------------
4+
begin : June 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+
#ifndef QGSLAYOUTMEASUREMENT_H
19+
#define QGSLAYOUTMEASUREMENT_H
20+
21+
#include "qgis_core.h"
22+
23+
#include "qgsunittypes.h"
24+
25+
/** \ingroup Layout
26+
* \class QgsLayoutMeasurement
27+
* \brief This class provides a method of storing measurements for use in QGIS layouts
28+
* using a variety of different measurement units.
29+
* \see QgsLayoutMeasurementConverter
30+
* \since QGIS 3.0
31+
*/
32+
class CORE_EXPORT QgsLayoutMeasurement
33+
{
34+
public:
35+
36+
/**
37+
* Constructor for QgsLayoutMeasurement.
38+
* \param length measurement length
39+
* \param units measurement units
40+
*/
41+
explicit QgsLayoutMeasurement( const double length, const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
42+
43+
~QgsLayoutMeasurement();
44+
45+
/**
46+
* Returns the length of the measurement.
47+
* \see setLength()
48+
*/
49+
double length() const { return mLength; }
50+
51+
/**
52+
* Sets the \a length of the measurement.
53+
* \see length()
54+
*/
55+
void setLength( const double length ) { mLength = length; }
56+
57+
/**
58+
* Returns the units for the measurement.
59+
* \see setUnits()
60+
*/
61+
QgsUnitTypes::LayoutUnit units() const { return mUnits; }
62+
63+
/**
64+
* Sets the \a units for the measurement. Does not alter the stored length,
65+
* ie. no length conversion is done.
66+
* \see units()
67+
*/
68+
void setUnits( const QgsUnitTypes::LayoutUnit units ) { mUnits = units; }
69+
70+
/**
71+
* Encodes the layout measurement to a string
72+
* \see decodeMeasurement()
73+
*/
74+
QString encodeMeasurement() const;
75+
76+
/**
77+
* Decodes a measurement from a \a string.
78+
* \see encodeMeasurement()
79+
*/
80+
static QgsLayoutMeasurement decodeMeasurement( const QString &string );
81+
82+
bool operator==( const QgsLayoutMeasurement &other ) const;
83+
bool operator!=( const QgsLayoutMeasurement &other ) const;
84+
QgsLayoutMeasurement operator+( const double v ) const;
85+
QgsLayoutMeasurement operator+=( const double v );
86+
QgsLayoutMeasurement operator-( const double v ) const;
87+
QgsLayoutMeasurement operator-=( const double v );
88+
QgsLayoutMeasurement operator*( const double v ) const;
89+
QgsLayoutMeasurement operator*=( const double v );
90+
QgsLayoutMeasurement operator/( const double v ) const;
91+
QgsLayoutMeasurement operator/=( const double v );
92+
93+
private:
94+
95+
double mLength;
96+
QgsUnitTypes::LayoutUnit mUnits;
97+
98+
};
99+
100+
#endif // QGSLAYOUTMEASUREMENT_H
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/***************************************************************************
2+
qgslayoutmeasurementconverter.cpp
3+
---------------------------------
4+
begin : June 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 "qgslayoutmeasurementconverter.h"
19+
20+
21+
QgsLayoutMeasurementConverter::QgsLayoutMeasurementConverter()
22+
: mDpi( 300.0 )
23+
{
24+
}
25+
26+
QgsLayoutMeasurementConverter::~QgsLayoutMeasurementConverter()
27+
{
28+
}
29+
30+
QgsLayoutMeasurement QgsLayoutMeasurementConverter::convert( const QgsLayoutMeasurement &measurement, const QgsUnitTypes::LayoutUnit targetUnits ) const
31+
{
32+
if ( measurement.units() == targetUnits )
33+
{
34+
return measurement;
35+
}
36+
37+
switch ( targetUnits )
38+
{
39+
case QgsUnitTypes::LayoutMillimeters:
40+
return QgsLayoutMeasurement( convertToMillimeters( measurement ), QgsUnitTypes::LayoutMillimeters );
41+
case QgsUnitTypes::LayoutCentimeters:
42+
return QgsLayoutMeasurement( convertToCentimeters( measurement ), QgsUnitTypes::LayoutCentimeters );
43+
case QgsUnitTypes::LayoutMeters:
44+
return QgsLayoutMeasurement( convertToMeters( measurement ), QgsUnitTypes::LayoutMeters );
45+
case QgsUnitTypes::LayoutInches:
46+
return QgsLayoutMeasurement( convertToInches( measurement ), QgsUnitTypes::LayoutInches );
47+
case QgsUnitTypes::LayoutFeet:
48+
return QgsLayoutMeasurement( convertToFeet( measurement ), QgsUnitTypes::LayoutFeet );
49+
case QgsUnitTypes::LayoutPoints:
50+
return QgsLayoutMeasurement( convertToPoints( measurement ), QgsUnitTypes::LayoutPoints );
51+
case QgsUnitTypes::LayoutPicas:
52+
return QgsLayoutMeasurement( convertToPicas( measurement ), QgsUnitTypes::LayoutPicas );
53+
case QgsUnitTypes::LayoutPixels:
54+
return QgsLayoutMeasurement( convertToPixels( measurement ), QgsUnitTypes::LayoutPixels );
55+
}
56+
57+
//will never be reached, but required to prevent warnings
58+
return QgsLayoutMeasurement( convertToMillimeters( measurement ), QgsUnitTypes::LayoutMillimeters );
59+
}
60+
61+
QgsLayoutSize QgsLayoutMeasurementConverter::convert( const QgsLayoutSize &size, const QgsUnitTypes::LayoutUnit targetUnits ) const
62+
{
63+
if ( size.units() == targetUnits )
64+
{
65+
return size;
66+
}
67+
68+
QgsLayoutSize result( size );
69+
result.setUnits( targetUnits );
70+
QgsLayoutMeasurement width = QgsLayoutMeasurement( size.width(), size.units() );
71+
QgsLayoutMeasurement height = QgsLayoutMeasurement( size.height(), size.units() );
72+
switch ( targetUnits )
73+
{
74+
case QgsUnitTypes::LayoutMillimeters:
75+
result.setSize( convertToMillimeters( width ), convertToMillimeters( height ) );
76+
break;
77+
case QgsUnitTypes::LayoutCentimeters:
78+
result.setSize( convertToCentimeters( width ), convertToCentimeters( height ) );
79+
break;
80+
case QgsUnitTypes::LayoutMeters:
81+
result.setSize( convertToMeters( width ), convertToMeters( height ) );
82+
break;
83+
case QgsUnitTypes::LayoutInches:
84+
result.setSize( convertToInches( width ), convertToInches( height ) );
85+
break;
86+
case QgsUnitTypes::LayoutFeet:
87+
result.setSize( convertToFeet( width ), convertToFeet( height ) );
88+
break;
89+
case QgsUnitTypes::LayoutPoints:
90+
result.setSize( convertToPoints( width ), convertToPoints( height ) );
91+
break;
92+
case QgsUnitTypes::LayoutPicas:
93+
result.setSize( convertToPicas( width ), convertToPicas( height ) );
94+
break;
95+
case QgsUnitTypes::LayoutPixels:
96+
result.setSize( convertToPixels( width ), convertToPixels( height ) );
97+
break;
98+
}
99+
return result;
100+
}
101+
102+
QgsLayoutPoint QgsLayoutMeasurementConverter::convert( const QgsLayoutPoint &point, const QgsUnitTypes::LayoutUnit targetUnits ) const
103+
{
104+
if ( point.units() == targetUnits )
105+
{
106+
return point;
107+
}
108+
109+
QgsLayoutPoint result( point );
110+
result.setUnits( targetUnits );
111+
QgsLayoutMeasurement x = QgsLayoutMeasurement( point.x(), point.units() );
112+
QgsLayoutMeasurement y = QgsLayoutMeasurement( point.y(), point.units() );
113+
switch ( targetUnits )
114+
{
115+
case QgsUnitTypes::LayoutMillimeters:
116+
result.setPoint( convertToMillimeters( x ), convertToMillimeters( y ) );
117+
break;
118+
case QgsUnitTypes::LayoutCentimeters:
119+
result.setPoint( convertToCentimeters( x ), convertToCentimeters( y ) );
120+
break;
121+
case QgsUnitTypes::LayoutMeters:
122+
result.setPoint( convertToMeters( x ), convertToMeters( y ) );
123+
break;
124+
case QgsUnitTypes::LayoutInches:
125+
result.setPoint( convertToInches( x ), convertToInches( y ) );
126+
break;
127+
case QgsUnitTypes::LayoutFeet:
128+
result.setPoint( convertToFeet( x ), convertToFeet( y ) );
129+
break;
130+
case QgsUnitTypes::LayoutPoints:
131+
result.setPoint( convertToPoints( x ), convertToPoints( y ) );
132+
break;
133+
case QgsUnitTypes::LayoutPicas:
134+
result.setPoint( convertToPicas( x ), convertToPicas( y ) );
135+
break;
136+
case QgsUnitTypes::LayoutPixels:
137+
result.setPoint( convertToPixels( x ), convertToPixels( y ) );
138+
break;
139+
}
140+
return result;
141+
}
142+
143+
double QgsLayoutMeasurementConverter::convertToMillimeters( const QgsLayoutMeasurement &measurement ) const
144+
{
145+
switch ( measurement.units() )
146+
{
147+
case QgsUnitTypes::LayoutMillimeters:
148+
return measurement.length();
149+
case QgsUnitTypes::LayoutCentimeters:
150+
return measurement.length() * 10.0;
151+
case QgsUnitTypes::LayoutMeters:
152+
return measurement.length() * 1000.0;
153+
case QgsUnitTypes::LayoutInches:
154+
return measurement.length() * 25.4;
155+
case QgsUnitTypes::LayoutFeet:
156+
return measurement.length() * 304.8;
157+
case QgsUnitTypes::LayoutPoints:
158+
return measurement.length() * 0.352777778;
159+
case QgsUnitTypes::LayoutPicas:
160+
return measurement.length() * 4.23333333;
161+
case QgsUnitTypes::LayoutPixels:
162+
return measurement.length() * 25.4 / mDpi;
163+
}
164+
165+
//will never be reached, but required to prevent warnings
166+
return measurement.length();
167+
}
168+
169+
double QgsLayoutMeasurementConverter::convertToCentimeters( const QgsLayoutMeasurement &measurement ) const
170+
{
171+
return convertToMillimeters( measurement ) / 10.0;
172+
}
173+
174+
double QgsLayoutMeasurementConverter::convertToMeters( const QgsLayoutMeasurement &measurement ) const
175+
{
176+
return convertToMillimeters( measurement ) / 1000.0;
177+
}
178+
179+
double QgsLayoutMeasurementConverter::convertToInches( const QgsLayoutMeasurement &measurement ) const
180+
{
181+
return convertToMillimeters( measurement ) / 25.4;
182+
}
183+
184+
double QgsLayoutMeasurementConverter::convertToFeet( const QgsLayoutMeasurement &measurement ) const
185+
{
186+
return convertToMillimeters( measurement ) / 304.8;
187+
}
188+
189+
double QgsLayoutMeasurementConverter::convertToPoints( const QgsLayoutMeasurement &measurement ) const
190+
{
191+
return convertToMillimeters( measurement ) * 2.83464567;
192+
}
193+
194+
double QgsLayoutMeasurementConverter::convertToPicas( const QgsLayoutMeasurement &measurement ) const
195+
{
196+
return convertToMillimeters( measurement ) * 0.236220472;
197+
}
198+
199+
double QgsLayoutMeasurementConverter::convertToPixels( const QgsLayoutMeasurement &measurement ) const
200+
{
201+
return convertToMillimeters( measurement ) * mDpi / 25.4;
202+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/***************************************************************************
2+
qgslayoutmeasurementconverter.h
3+
-------------------------------
4+
begin : June 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+
#ifndef QGSLAYOUTMEASUREMENTCONVERTER_H
19+
#define QGSLAYOUTMEASUREMENTCONVERTER_H
20+
21+
#include "qgis_core.h"
22+
#include "qgsunittypes.h"
23+
#include "qgslayoutmeasurement.h"
24+
#include "qgslayoutsize.h"
25+
#include "qgslayoutpoint.h"
26+
#include <QSizeF>
27+
#include <QPointF>
28+
29+
30+
/**
31+
* \ingroup Layout
32+
* \class QgsLayoutMeasurementConverter
33+
* \brief This class provides a method of converting QgsLayoutMeasurements from
34+
* one unit to another. Conversion to or from pixel units utilizes a specified
35+
* dots per inch (DPI) property for the converter. Converters default to using
36+
* 300 DPI.
37+
* \see QgsLayoutMeasurement
38+
* \since QGIS 3.0
39+
*/
40+
class CORE_EXPORT QgsLayoutMeasurementConverter
41+
{
42+
public:
43+
44+
QgsLayoutMeasurementConverter();
45+
46+
~QgsLayoutMeasurementConverter();
47+
48+
/**
49+
* Sets the dots per inch (\a dpi) for the measurement converter. This is used
50+
* when converting measurements to and from pixels.
51+
* \see dpi()
52+
*/
53+
void setDpi( const double dpi ) { mDpi = dpi; }
54+
55+
/**
56+
* Returns the Dots per inch (DPI) of the measurement converter. This is used
57+
* when converting measurements to and from pixels.
58+
* \see setDpi()
59+
*/
60+
double dpi() const { return mDpi; }
61+
62+
/**
63+
* Converts a measurement from one unit to another.
64+
* \param measurement measurement to convert
65+
* \param targetUnits units to convert measurement into
66+
* \returns measurement converted to target units
67+
*/
68+
QgsLayoutMeasurement convert( const QgsLayoutMeasurement &measurement, const QgsUnitTypes::LayoutUnit targetUnits ) const;
69+
70+
/**
71+
* Converts a layout size from one unit to another.
72+
* \param size layout size to convert
73+
* \param targetUnits units to convert size into
74+
* \returns size converted to target units
75+
*/
76+
QgsLayoutSize convert( const QgsLayoutSize &size, const QgsUnitTypes::LayoutUnit targetUnits ) const;
77+
78+
/**
79+
* Converts a layout point from one unit to another.
80+
* \param point layout point to convert
81+
* \param targetUnits units to convert point into
82+
* \returns point converted to target units
83+
*/
84+
QgsLayoutPoint convert( const QgsLayoutPoint &point, const QgsUnitTypes::LayoutUnit targetUnits ) const;
85+
86+
private:
87+
88+
double mDpi;
89+
90+
double convertToMillimeters( const QgsLayoutMeasurement &measurement ) const;
91+
double convertToCentimeters( const QgsLayoutMeasurement &measurement ) const;
92+
double convertToMeters( const QgsLayoutMeasurement &measurement ) const;
93+
double convertToInches( const QgsLayoutMeasurement &measurement ) const;
94+
double convertToFeet( const QgsLayoutMeasurement &measurement ) const;
95+
double convertToPoints( const QgsLayoutMeasurement &measurement ) const;
96+
double convertToPicas( const QgsLayoutMeasurement &measurement ) const;
97+
double convertToPixels( const QgsLayoutMeasurement &measurement ) const;
98+
99+
};
100+
101+
#endif // QGSLAYOUTMEASUREMENTCONVERTER_H

‎src/core/layout/qgslayoutpoint.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/***************************************************************************
2+
qgslayoutpoint.cpp
3+
------------------
4+
begin : June 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 "qgslayoutpoint.h"
19+
#include "qgis.h"
20+
21+
#include <QStringList>
22+
23+
QgsLayoutPoint::QgsLayoutPoint( const double x, const double y, const QgsUnitTypes::LayoutUnit units )
24+
: mX( x )
25+
, mY( y )
26+
, mUnits( units )
27+
{
28+
29+
}
30+
31+
QgsLayoutPoint::QgsLayoutPoint( const QgsUnitTypes::LayoutUnit units )
32+
: mX( 0.0 )
33+
, mY( 0.0 )
34+
, mUnits( units )
35+
{
36+
37+
}
38+
39+
QgsLayoutPoint::~QgsLayoutPoint()
40+
{
41+
42+
}
43+
44+
bool QgsLayoutPoint::isNull() const
45+
{
46+
return qgsDoubleNear( mX, 0 ) && qgsDoubleNear( mY, 0 );
47+
}
48+
49+
QPointF QgsLayoutPoint::toQPointF() const
50+
{
51+
return QPointF( mX, mY );
52+
}
53+
54+
QString QgsLayoutPoint::encodePoint() const
55+
{
56+
return QStringLiteral( "%1,%2,%3" ).arg( mX ).arg( mY ).arg( QgsUnitTypes::encodeUnit( mUnits ) );
57+
}
58+
59+
QgsLayoutPoint QgsLayoutPoint::decodePoint( const QString &string )
60+
{
61+
QStringList parts = string.split( ',' );
62+
if ( parts.count() != 3 )
63+
{
64+
return QgsLayoutPoint();
65+
}
66+
return QgsLayoutPoint( parts[0].toDouble(), parts[1].toDouble(), QgsUnitTypes::decodeLayoutUnit( parts[2] ) );
67+
}
68+
69+
bool QgsLayoutPoint::operator==( const QgsLayoutPoint &other ) const
70+
{
71+
return other.units() == mUnits && other.x() == mX && other.y() == mY;
72+
}
73+
74+
bool QgsLayoutPoint::operator!=( const QgsLayoutPoint &other ) const
75+
{
76+
return ( ! operator==( other ) );
77+
}
78+
79+
QgsLayoutPoint QgsLayoutPoint::operator*( const double v ) const
80+
{
81+
return QgsLayoutPoint( mX * v, mY * v, mUnits );
82+
}
83+
84+
QgsLayoutPoint QgsLayoutPoint::operator*=( const double v )
85+
{
86+
*this = *this * v;
87+
return *this;
88+
}
89+
90+
QgsLayoutPoint QgsLayoutPoint::operator/( const double v ) const
91+
{
92+
return QgsLayoutPoint( mX / v, mY / v, mUnits );
93+
}
94+
95+
QgsLayoutPoint QgsLayoutPoint::operator/=( const double v )
96+
{
97+
*this = *this / v;
98+
return *this;
99+
}

‎src/core/layout/qgslayoutpoint.h

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/***************************************************************************
2+
qgslayoutpoint.h
3+
----------------
4+
begin : June 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+
#ifndef QGSLAYOUTPOINT_H
19+
#define QGSLAYOUTPOINT_H
20+
21+
#include "qgis_core.h"
22+
#include "qgsunittypes.h"
23+
#include <QPointF>
24+
25+
/** \ingroup Layout
26+
* \class QgsLayoutPoint
27+
* \brief This class provides a method of storing points, consisting of an x and y coordinate,
28+
* for use in QGIS layouts. Measurement units are stored alongside the position.
29+
*
30+
* \see QgsLayoutMeasurementConverter
31+
* \since QGIS 3.0
32+
* \note This class does not inherit from QPointF since QPointF includes methods which should not apply
33+
* to positions with with units. For instance, the + and - operators would mislead users of this class
34+
* to believe that addition of two QgsLayoutPoints with different unit types would automatically convert
35+
* units. Instead, all unit conversion must be handled by a QgsLayoutMeasurementConverter so that
36+
* conversion between paper and screen units can be correctly performed.
37+
*/
38+
class CORE_EXPORT QgsLayoutPoint
39+
{
40+
public:
41+
42+
/**
43+
* Constructor for QgsLayoutPoint.
44+
* \param x x coordinate
45+
* \param x y coordinate
46+
* \param units units for x and y
47+
*/
48+
QgsLayoutPoint( const double x, const double y, const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
49+
50+
/**
51+
* Constructor for an empty point, where both x and y are set to 0.
52+
* \param units units for measurement
53+
*/
54+
explicit QgsLayoutPoint( const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
55+
56+
~QgsLayoutPoint();
57+
58+
/**
59+
* Sets new x and y coordinates for the point.
60+
* \see setX()
61+
* \see setY()
62+
* \see setUnits()
63+
*/
64+
void setPoint( const double x, const double y ) { mX = x; mY = y; }
65+
66+
/**
67+
* Returns x coordinate of point.
68+
* \see setX()
69+
* \see y()
70+
*/
71+
double x() const { return mX; }
72+
73+
/**
74+
* Sets the x coordinate of point.
75+
* \see x()
76+
* \see setY()
77+
*/
78+
void setX( const double x ) { mX = x; }
79+
80+
/**
81+
* Returns y coordinate of point.
82+
* \see setY()
83+
* \see x()
84+
*/
85+
double y() const { return mY; }
86+
87+
/**
88+
* Sets y coordinate of point.
89+
* \see y()
90+
* \see setX()
91+
*/
92+
void setY( const double y ) { mY = y; }
93+
94+
/**
95+
* Returns the units for the point.
96+
* \see setUnits()
97+
*/
98+
QgsUnitTypes::LayoutUnit units() const { return mUnits; }
99+
100+
/**
101+
* Sets the \a units for the point. Does not alter the stored coordinates,
102+
* ie. no conversion is done.
103+
* \see units()
104+
*/
105+
void setUnits( const QgsUnitTypes::LayoutUnit units ) { mUnits = units; }
106+
107+
/**
108+
* Tests whether the position is null, ie both its x and y coordinates
109+
* are zero.
110+
* \returns true if point is null
111+
*/
112+
bool isNull() const;
113+
114+
/**
115+
* Converts the layout point to a QPointF. The unit information is discarded
116+
* during this operation.
117+
* \returns QPointF with same x and y coordinates as layout point
118+
*/
119+
QPointF toQPointF() const;
120+
121+
/**
122+
* Encodes the layout point to a string
123+
* \see decodePoint()
124+
*/
125+
QString encodePoint() const;
126+
127+
/**
128+
* Decodes a point from a \a string.
129+
* \see encodePoint()
130+
*/
131+
static QgsLayoutPoint decodePoint( const QString &string );
132+
133+
bool operator==( const QgsLayoutPoint &other ) const;
134+
bool operator!=( const QgsLayoutPoint &other ) const;
135+
QgsLayoutPoint operator*( const double v ) const;
136+
QgsLayoutPoint operator*=( const double v );
137+
QgsLayoutPoint operator/( const double v ) const;
138+
QgsLayoutPoint operator/=( const double v );
139+
140+
private:
141+
142+
double mX;
143+
double mY;
144+
QgsUnitTypes::LayoutUnit mUnits;
145+
146+
};
147+
148+
#endif // QGSLAYOUTPOINT_H

‎src/core/layout/qgslayoutsize.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/***************************************************************************
2+
qgslayoutsize.cpp
3+
-----------------
4+
begin : June 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 "qgslayoutsize.h"
19+
#include "qgis.h"
20+
#include <QStringList>
21+
22+
QgsLayoutSize::QgsLayoutSize( const double width, const double height, const QgsUnitTypes::LayoutUnit units )
23+
: mWidth( width )
24+
, mHeight( height )
25+
, mUnits( units )
26+
{
27+
}
28+
29+
QgsLayoutSize::QgsLayoutSize( const QgsUnitTypes::LayoutUnit units )
30+
: mWidth( 0.0 )
31+
, mHeight( 0.0 )
32+
, mUnits( units )
33+
{
34+
35+
}
36+
37+
QgsLayoutSize::~QgsLayoutSize()
38+
{
39+
}
40+
41+
bool QgsLayoutSize::isEmpty() const
42+
{
43+
return qgsDoubleNear( mWidth, 0 ) && qgsDoubleNear( mHeight, 0 );
44+
}
45+
46+
QSizeF QgsLayoutSize::toQSizeF() const
47+
{
48+
return QSizeF( mWidth, mHeight );
49+
}
50+
51+
QString QgsLayoutSize::encodeSize() const
52+
{
53+
return QStringLiteral( "%1,%2,%3" ).arg( mWidth ).arg( mHeight ).arg( QgsUnitTypes::encodeUnit( mUnits ) );
54+
}
55+
56+
QgsLayoutSize QgsLayoutSize::decodeSize( const QString &string )
57+
{
58+
QStringList parts = string.split( ',' );
59+
if ( parts.count() != 3 )
60+
{
61+
return QgsLayoutSize();
62+
}
63+
return QgsLayoutSize( parts[0].toDouble(), parts[1].toDouble(), QgsUnitTypes::decodeLayoutUnit( parts[2] ) );
64+
65+
}
66+
67+
bool QgsLayoutSize::operator==( const QgsLayoutSize &other ) const
68+
{
69+
return other.units() == mUnits && other.width() == mWidth && other.height() == mHeight;
70+
}
71+
72+
bool QgsLayoutSize::operator!=( const QgsLayoutSize &other ) const
73+
{
74+
return ( ! operator==( other ) );
75+
}
76+
77+
QgsLayoutSize QgsLayoutSize::operator*( const double v ) const
78+
{
79+
return QgsLayoutSize( mWidth * v, mHeight * v, mUnits );
80+
}
81+
82+
QgsLayoutSize QgsLayoutSize::operator*=( const double v )
83+
{
84+
*this = *this * v;
85+
return *this;
86+
}
87+
88+
QgsLayoutSize QgsLayoutSize::operator/( const double v ) const
89+
{
90+
return QgsLayoutSize( mWidth / v, mHeight / v, mUnits );
91+
}
92+
93+
QgsLayoutSize QgsLayoutSize::operator/=( const double v )
94+
{
95+
*this = *this / v;
96+
return *this;
97+
}

‎src/core/layout/qgslayoutsize.h

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/***************************************************************************
2+
qgslayoutsize.h
3+
---------------
4+
begin : June 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+
#ifndef QGSLAYOUTSIZE_H
19+
#define QGSLAYOUTSIZE_H
20+
21+
#include "qgis_core.h"
22+
#include "qgsunittypes.h"
23+
#include <QSizeF>
24+
25+
26+
/**
27+
* \ingroup Layout
28+
* \class QgsLayoutSize
29+
* \brief This class provides a method of storing sizes, consisting of a width and height,
30+
* for use in QGIS layouts. Measurement units are stored alongside the size.
31+
*
32+
* \see QgsLayoutMeasurementConverter
33+
* \since QGIS 3.0
34+
* \note This class does not inherit from QSizeF since QSizeF includes methods which should not apply to sizes
35+
* with units. For instance, the + and - operators would mislead users of this class to believe that
36+
* addition of two QgsLayoutSize with different unit types would automatically convert units. Instead,
37+
* all unit conversion must be handled by a QgsLayoutMeasurementConverter so that conversion between
38+
* paper and screen units can be correctly performed.
39+
*/
40+
class CORE_EXPORT QgsLayoutSize
41+
{
42+
public:
43+
44+
/**
45+
* Constructor for QgsLayoutSize.
46+
* \param width width
47+
* \param height height
48+
* \param units units for width and height
49+
*/
50+
QgsLayoutSize( const double width, const double height, const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
51+
52+
/**
53+
* Constructor for an empty layout size
54+
* \param units units for measurement
55+
*/
56+
explicit QgsLayoutSize( const QgsUnitTypes::LayoutUnit units = QgsUnitTypes::LayoutMillimeters );
57+
58+
~QgsLayoutSize();
59+
60+
/**
61+
* Sets new \a width and \a height for the size.
62+
* \see setWidth()
63+
* \see setHeight()
64+
* \see setUnits()
65+
*/
66+
void setSize( const double width, const double height ) { mWidth = width; mHeight = height; }
67+
68+
/**
69+
* Returns the width of the size.
70+
* \see setWidth()
71+
* \see height()
72+
*/
73+
double width() const { return mWidth; }
74+
75+
/**
76+
* Sets the \a width for the size.
77+
* \see width()
78+
* \see setHeight()
79+
*/
80+
void setWidth( const double width ) { mWidth = width; }
81+
82+
/**
83+
* Returns the height of the size.
84+
* \see setHeight()
85+
* \see width()
86+
*/
87+
double height() const { return mHeight; }
88+
89+
/**
90+
* Sets the \a height for the size.
91+
* \see height()
92+
* \see setWidth()
93+
*/
94+
void setHeight( const double height ) { mHeight = height; }
95+
96+
/**
97+
* Returns the units for the size.
98+
* \see setUnits()
99+
*/
100+
QgsUnitTypes::LayoutUnit units() const { return mUnits; }
101+
102+
/**
103+
* Sets the \a units for the size. Does not alter the stored width or height,
104+
* ie. no conversion is done.
105+
* \see units()
106+
*/
107+
void setUnits( const QgsUnitTypes::LayoutUnit units ) { mUnits = units; }
108+
109+
/**
110+
* Tests whether the size is empty, ie both its width and height
111+
* are zero.
112+
* \returns true if size is empty
113+
*/
114+
bool isEmpty() const;
115+
116+
/**
117+
* Converts the layout size to a QSizeF. The unit information is discarded
118+
* during this operation.
119+
* \returns QSizeF with same dimensions as layout size
120+
*/
121+
QSizeF toQSizeF() const;
122+
123+
/**
124+
* Encodes the layout size to a string
125+
* \see decodeSize()
126+
*/
127+
QString encodeSize() const;
128+
129+
/**
130+
* Decodes a size from a \a string.
131+
* \see encodeSize()
132+
*/
133+
static QgsLayoutSize decodeSize( const QString &string );
134+
135+
bool operator==( const QgsLayoutSize &other ) const;
136+
bool operator!=( const QgsLayoutSize &other ) const;
137+
QgsLayoutSize operator*( const double v ) const;
138+
QgsLayoutSize operator*=( const double v );
139+
QgsLayoutSize operator/( const double v ) const;
140+
QgsLayoutSize operator/=( const double v );
141+
142+
private:
143+
144+
double mWidth;
145+
double mHeight;
146+
QgsUnitTypes::LayoutUnit mUnits;
147+
148+
};
149+
150+
#endif // QGSLAYOUTSIZE_H

‎src/core/qgsunittypes.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,3 +1773,80 @@ QString QgsUnitTypes::toString( QgsUnitTypes::RenderUnit unit )
17731773
}
17741774
return QString();
17751775
}
1776+
1777+
1778+
1779+
QString QgsUnitTypes::encodeUnit( QgsUnitTypes::LayoutUnit unit )
1780+
{
1781+
switch ( unit )
1782+
{
1783+
case LayoutCentimeters:
1784+
return QStringLiteral( "cm" );
1785+
case LayoutMeters:
1786+
return QStringLiteral( "m" );
1787+
case LayoutInches:
1788+
return QStringLiteral( "in" );
1789+
case LayoutFeet:
1790+
return QStringLiteral( "ft" );
1791+
case LayoutPoints:
1792+
return QStringLiteral( "pt" );
1793+
case LayoutPicas:
1794+
return QStringLiteral( "pi" );
1795+
case LayoutPixels:
1796+
return QStringLiteral( "px" );
1797+
case LayoutMillimeters:
1798+
return QStringLiteral( "mm" );
1799+
}
1800+
return QString();
1801+
}
1802+
1803+
QgsUnitTypes::LayoutUnit QgsUnitTypes::decodeLayoutUnit( const QString &string, bool *ok )
1804+
{
1805+
QString normalized = string.trimmed().toLower();
1806+
1807+
if ( ok )
1808+
*ok = true;
1809+
1810+
if ( normalized == encodeUnit( LayoutMillimeters ).toLower() )
1811+
return LayoutMillimeters;
1812+
if ( normalized == encodeUnit( LayoutCentimeters ).toLower() )
1813+
return LayoutCentimeters;
1814+
if ( normalized == encodeUnit( LayoutMeters ).toLower() )
1815+
return LayoutMeters;
1816+
if ( normalized == encodeUnit( LayoutInches ).toLower() )
1817+
return LayoutInches;
1818+
if ( normalized == encodeUnit( LayoutFeet ).toLower() )
1819+
return LayoutFeet;
1820+
if ( normalized == encodeUnit( LayoutPoints ).toLower() )
1821+
return LayoutPoints;
1822+
if ( normalized == encodeUnit( LayoutPicas ).toLower() )
1823+
return LayoutPicas;
1824+
if ( normalized == encodeUnit( LayoutPixels ).toLower() )
1825+
return LayoutPixels;
1826+
1827+
if ( ok )
1828+
*ok = false;
1829+
1830+
// millimeters are default
1831+
return LayoutMillimeters;
1832+
}
1833+
1834+
QgsUnitTypes::LayoutUnitType QgsUnitTypes::unitType( const QgsUnitTypes::LayoutUnit units )
1835+
{
1836+
switch ( units )
1837+
{
1838+
case LayoutPixels:
1839+
return LayoutScreenUnits;
1840+
case LayoutMillimeters:
1841+
case LayoutCentimeters:
1842+
case LayoutMeters:
1843+
case LayoutInches:
1844+
case LayoutFeet:
1845+
case LayoutPoints:
1846+
case LayoutPicas:
1847+
return LayoutPaperUnits;
1848+
}
1849+
1850+
// avoid warnings
1851+
return LayoutPaperUnits;
1852+
}

‎src/core/qgsunittypes.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,26 @@ class CORE_EXPORT QgsUnitTypes
103103
RenderUnknownUnit, //!< Mixed or unknown units
104104
};
105105

106+
//! Layout measurement units
107+
enum LayoutUnit
108+
{
109+
LayoutMillimeters = 0, //!< Millimeters
110+
LayoutCentimeters, //!< Centimeters
111+
LayoutMeters, //!< Meters
112+
LayoutInches, //!< Inches
113+
LayoutFeet, //!< Feet
114+
LayoutPoints, //!< Typographic points
115+
LayoutPicas, //!< Typographic picas
116+
LayoutPixels //!< Pixels
117+
};
118+
119+
//! Types of layout units
120+
enum LayoutUnitType
121+
{
122+
LayoutPaperUnits = 0, //!< Unit is a paper based measurement unit
123+
LayoutScreenUnits //!< Unit is a screen based measurement unit
124+
};
125+
106126
/**
107127
* A combination of distance value and unit.
108128
*
@@ -354,6 +374,31 @@ class CORE_EXPORT QgsUnitTypes
354374
* \since QGIS 3.0
355375
*/
356376
Q_INVOKABLE static QString toString( RenderUnit unit );
377+
378+
379+
// LAYOUT UNITS
380+
381+
/**
382+
* Encodes a layout unit to a string.
383+
* \param unit unit to encode
384+
* \returns encoded string
385+
* \see decodeLayoutUnit()
386+
*/
387+
Q_INVOKABLE static QString encodeUnit( LayoutUnit unit );
388+
389+
/** Decodes a layout unit from a string.
390+
* \param string string to decode
391+
* \param ok optional boolean, will be set to true if string was converted successfully
392+
* \returns decoded units
393+
* \see encodeUnit()
394+
*/
395+
Q_INVOKABLE static LayoutUnit decodeLayoutUnit( const QString &string, bool *ok SIP_OUT = 0 );
396+
397+
/**
398+
* Returns the type for a unit of measurement.
399+
*/
400+
Q_INVOKABLE static LayoutUnitType unitType( const LayoutUnit units );
401+
357402
};
358403

359404
#endif // QGSUNITTYPES_H

‎tests/src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
1313
${CMAKE_SOURCE_DIR}/src/core/composer
1414
${CMAKE_SOURCE_DIR}/src/core/expression
1515
${CMAKE_SOURCE_DIR}/src/core/geometry
16+
${CMAKE_SOURCE_DIR}/src/core/layout
1617
${CMAKE_SOURCE_DIR}/src/core/metadata
1718
${CMAKE_SOURCE_DIR}/src/core/effects
1819
${CMAKE_SOURCE_DIR}/src/core/layertree
@@ -124,6 +125,7 @@ SET(TESTS
124125
testqgsjsonutils.cpp
125126
testqgslabelingengine.cpp
126127
testqgslayertree.cpp
128+
testqgslayoutunits.cpp
127129
testqgslegendrenderer.cpp
128130
testqgscentroidfillsymbol.cpp
129131
testqgslinefillsymbol.cpp

‎tests/src/core/testqgslayoutunits.cpp

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

‎tests/src/python/test_qgsunittypes.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,33 @@ def testFormatAngle(self):
630630
self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.AngleTurn), '1.00 tr')
631631
self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.AngleUnknownUnit), '1.00')
632632

633+
def testEncodeDecodeLayoutUnits(self):
634+
"""Test encoding and decoding layout units"""
635+
units = [QgsUnitTypes.LayoutMillimeters,
636+
QgsUnitTypes.LayoutCentimeters,
637+
QgsUnitTypes.LayoutMeters,
638+
QgsUnitTypes.LayoutInches,
639+
QgsUnitTypes.LayoutFeet,
640+
QgsUnitTypes.LayoutPoints,
641+
QgsUnitTypes.LayoutPicas,
642+
QgsUnitTypes.LayoutPixels]
643+
644+
for u in units:
645+
res, ok = QgsUnitTypes.decodeLayoutUnit(QgsUnitTypes.encodeUnit(u))
646+
assert ok
647+
self.assertEqual(res, u)
648+
649+
# Test decoding bad units
650+
res, ok = QgsUnitTypes.decodeLayoutUnit('bad')
651+
self.assertFalse(ok)
652+
# default units should be MM
653+
self.assertEqual(res, QgsUnitTypes.LayoutMillimeters)
654+
655+
# Test that string is cleaned before decoding
656+
res, ok = QgsUnitTypes.decodeLayoutUnit(' px ')
657+
assert ok
658+
self.assertEqual(res, QgsUnitTypes.LayoutPixels)
659+
633660

634661
if __name__ == "__main__":
635662
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.