Skip to content

Commit f1d1e45

Browse files
committedNov 24, 2017
Begin port of HTML item
1 parent 0e71505 commit f1d1e45

File tree

7 files changed

+1079
-13
lines changed

7 files changed

+1079
-13
lines changed
 

‎python/core/core_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@
409409
%Include layout/qgslayoutframe.sip
410410
%Include layout/qgslayoutitem.sip
411411
%Include layout/qgslayoutitemgroup.sip
412+
%Include layout/qgslayoutitemhtml.sip
412413
%Include layout/qgslayoutitemlabel.sip
413414
%Include layout/qgslayoutitemlegend.sip
414415
%Include layout/qgslayoutitemmap.sip
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/layout/qgslayoutitemhtml.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsLayoutItemHtml: QgsLayoutMultiFrame
13+
{
14+
%Docstring
15+
A layout multiframe subclass for HTML content.
16+
.. versionadded:: 3.0
17+
%End
18+
19+
%TypeHeaderCode
20+
#include "qgslayoutitemhtml.h"
21+
%End
22+
public:
23+
24+
enum ContentMode
25+
{
26+
Url,
27+
ManualHtml
28+
};
29+
30+
QgsLayoutItemHtml( QgsLayout *layout );
31+
%Docstring
32+
Constructor for QgsLayoutItemHtml, with the specified parent ``layout``.
33+
%End
34+
35+
~QgsLayoutItemHtml();
36+
37+
void setContentMode( ContentMode mode );
38+
%Docstring
39+
Sets the source ``mode`` for item's HTML content.
40+
.. seealso:: contentMode()
41+
.. seealso:: setUrl()
42+
.. seealso:: setHtml()
43+
%End
44+
45+
ContentMode contentMode() const;
46+
%Docstring
47+
Returns the source mode for item's HTML content.
48+
.. seealso:: setContentMode()
49+
.. seealso:: url()
50+
.. seealso:: html()
51+
:rtype: ContentMode
52+
%End
53+
54+
void setUrl( const QUrl &url );
55+
%Docstring
56+
Sets the ``url`` for content to display in the item when the item is using
57+
the QgsLayoutItemHtml.Url mode. Content is automatically fetched and the
58+
HTML item refreshed after calling this function.
59+
.. seealso:: url()
60+
.. seealso:: contentMode()
61+
%End
62+
63+
QUrl url() const;
64+
%Docstring
65+
Returns the URL of the content displayed in the item if the item is using
66+
the QgsLayoutItemHtml.Url mode.
67+
.. seealso:: setUrl()
68+
.. seealso:: contentMode()
69+
:rtype: QUrl
70+
%End
71+
72+
void setHtml( const QString &html );
73+
%Docstring
74+
Sets the ``html`` to display in the item when the item is using
75+
the QgsLayoutItemHtml.ManualHtml mode. Setting the HTML using this function
76+
does not automatically refresh the item's contents. Call loadHtml to trigger
77+
a refresh of the item after setting the HTML content.
78+
.. seealso:: html()
79+
.. seealso:: contentMode()
80+
.. seealso:: loadHtml()
81+
%End
82+
83+
QString html() const;
84+
%Docstring
85+
Returns the HTML source displayed in the item if the item is using
86+
the QgsLayoutItemHtml.ManualHtml mode.
87+
.. seealso:: setHtml()
88+
.. seealso:: contentMode()
89+
:rtype: str
90+
%End
91+
92+
bool evaluateExpressions() const;
93+
%Docstring
94+
Returns whether html item will evaluate QGIS expressions prior to rendering
95+
the HTML content. If set, any content inside [% %] tags will be
96+
treated as a QGIS expression and evaluated against the current atlas
97+
feature.
98+
.. seealso:: setEvaluateExpressions()
99+
:rtype: bool
100+
%End
101+
102+
void setEvaluateExpressions( bool evaluateExpressions );
103+
%Docstring
104+
Sets whether the html item will evaluate QGIS expressions prior to rendering
105+
the HTML content. If set, any content inside [% %] tags will be
106+
treated as a QGIS expression and evaluated against the current atlas
107+
feature.
108+
.. seealso:: evaluateExpressions()
109+
%End
110+
111+
bool useSmartBreaks() const;
112+
%Docstring
113+
Returns whether html item is using smart breaks. Smart breaks prevent
114+
the html frame contents from breaking mid-way though a line of text.
115+
.. seealso:: setUseSmartBreaks()
116+
:rtype: bool
117+
%End
118+
119+
void setUseSmartBreaks( bool useSmartBreaks );
120+
%Docstring
121+
Sets whether the html item should use smart breaks. Smart breaks prevent
122+
the html frame contents from breaking mid-way though a line of text.
123+
.. seealso:: useSmartBreaks()
124+
%End
125+
126+
void setMaxBreakDistance( double distance );
127+
%Docstring
128+
Sets the maximum ``distance`` allowed when calculating where to place page breaks
129+
in the html. This distance is the maximum amount of empty space allowed
130+
at the bottom of a frame after calculating the optimum break location. Setting
131+
a larger value will result in better choice of page break location, but more
132+
wasted space at the bottom of frames. This setting is only effective if
133+
useSmartBreaks is true.
134+
.. seealso:: maxBreakDistance()
135+
.. seealso:: setUseSmartBreaks()
136+
%End
137+
138+
double maxBreakDistance() const;
139+
%Docstring
140+
Returns the maximum distance allowed when calculating where to place page breaks
141+
in the html. This distance is the maximum amount of empty space allowed
142+
at the bottom of a frame after calculating the optimum break location. This setting
143+
is only effective if useSmartBreaks is true.
144+
.. seealso:: setMaxBreakDistance()
145+
.. seealso:: useSmartBreaks()
146+
:rtype: float
147+
%End
148+
149+
void setUserStylesheet( const QString &stylesheet );
150+
%Docstring
151+
Sets the user ``stylesheet`` CSS rules to use while rendering the HTML content. These
152+
allow for overriding the styles specified within the HTML source. Setting the stylesheet
153+
using this function does not automatically refresh the item's contents. Call loadHtml
154+
to trigger a refresh of the item after setting the stylesheet rules.
155+
.. seealso:: userStylesheet()
156+
.. seealso:: setUserStylesheetEnabled()
157+
.. seealso:: loadHtml()
158+
%End
159+
160+
QString userStylesheet() const;
161+
%Docstring
162+
Returns the user stylesheet CSS rules used while rendering the HTML content. These
163+
overriding the styles specified within the HTML source.
164+
.. seealso:: setUserStylesheet()
165+
.. seealso:: userStylesheetEnabled()
166+
:rtype: str
167+
%End
168+
169+
void setUserStylesheetEnabled( const bool enabled );
170+
%Docstring
171+
Sets whether user stylesheets are ``enabled`` for the HTML content.
172+
.. seealso:: userStylesheetEnabled()
173+
.. seealso:: setUserStylesheet()
174+
%End
175+
176+
bool userStylesheetEnabled() const;
177+
%Docstring
178+
Returns whether user stylesheets are enabled for the HTML content.
179+
.. seealso:: setUserStylesheetEnabled()
180+
.. seealso:: userStylesheet()
181+
:rtype: bool
182+
%End
183+
184+
virtual QString displayName() const;
185+
186+
virtual QSizeF totalSize() const;
187+
188+
virtual void render( QgsRenderContext &context, const QRectF &renderExtent, const int frameIndex,
189+
const QStyleOptionGraphicsItem *itemStyle = 0 );
190+
191+
virtual bool writeXml( QDomElement &elem, QDomDocument &doc, bool ignoreFrames = false ) const;
192+
193+
virtual bool readXml( const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames = false );
194+
195+
virtual double findNearbyPageBreak( double yPos );
196+
197+
198+
public slots:
199+
200+
void loadHtml( const bool useCache = false, const QgsExpressionContext *context = 0 );
201+
%Docstring
202+
Reloads the html source from the url and redraws the item.
203+
\param useCache set to true to use a cached copy of remote html
204+
content
205+
\param context expression context for evaluating data defined urls and expressions in html
206+
.. seealso:: setUrl
207+
.. seealso:: url
208+
%End
209+
210+
virtual void recalculateFrameSizes();
211+
212+
%Docstring
213+
Recalculates the frame sizes for the current viewport dimensions
214+
%End
215+
void refreshExpressionContext();
216+
217+
void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );
218+
219+
};
220+
221+
/************************************************************************
222+
* This file has been generated automatically from *
223+
* *
224+
* src/core/layout/qgslayoutitemhtml.h *
225+
* *
226+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
227+
************************************************************************/

‎src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ SET(QGIS_CORE_SRCS
373373
layout/qgslayoutitem.cpp
374374
layout/qgslayoutitemgroup.cpp
375375
layout/qgslayoutitemgroupundocommand.cpp
376+
layout/qgslayoutitemhtml.cpp
376377
layout/qgslayoutitemlabel.cpp
377378
layout/qgslayoutitemlegend.cpp
378379
layout/qgslayoutitemmap.cpp
@@ -735,6 +736,7 @@ SET(QGIS_CORE_MOC_HDRS
735736
layout/qgslayoutitem.h
736737
layout/qgslayoutitemgroup.h
737738
layout/qgslayoutitemgroupundocommand.h
739+
layout/qgslayoutitemhtml.h
738740
layout/qgslayoutitemlabel.h
739741
layout/qgslayoutitemlegend.h
740742
layout/qgslayoutitemmap.h

‎src/core/composer/qgscomposerhtml.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,6 @@ void QgsComposerHtml::addFrame( QgsComposerFrame *frame, bool recalcFrameSizes )
336336
}
337337
}
338338

339-
bool candidateSort( QPair<int, int> c1, QPair<int, int> c2 )
340-
{
341-
if ( c1.second < c2.second )
342-
return true;
343-
else if ( c1.second > c2.second )
344-
return false;
345-
else if ( c1.first > c2.first )
346-
return true;
347-
else
348-
return false;
349-
}
350-
351339
double QgsComposerHtml::findNearbyPageBreak( double yPos )
352340
{
353341
if ( !mWebPage || !mRenderedPage || !mUseSmartBreaks )
@@ -400,7 +388,18 @@ double QgsComposerHtml::findNearbyPageBreak( double yPos )
400388
}
401389

402390
//sort candidate rows by number of changes ascending, row number descending
403-
std::sort( candidates.begin(), candidates.end(), candidateSort );
391+
std::sort( candidates.begin(), candidates.end(),
392+
[]( QPair<int, int> c1, QPair<int, int> c2 )->bool
393+
{
394+
if ( c1.second < c2.second )
395+
return true;
396+
else if ( c1.second > c2.second )
397+
return false;
398+
else if ( c1.first > c2.first )
399+
return true;
400+
else
401+
return false;
402+
} );
404403
//first candidate is now the largest row with smallest number of changes
405404

406405
//OK, now take the mid point of the best candidate position

‎src/core/layout/qgslayoutitemhtml.cpp

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

‎src/core/layout/qgslayoutitemhtml.h

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/***************************************************************************
2+
qgslayoutitemhtml.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+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSLAYOUTITEMHTML_H
17+
#define QGSLAYOUTITEMHTML_H
18+
19+
#include "qgis_core.h"
20+
#include "qgis.h"
21+
#include "qgslayoutmultiframe.h"
22+
#include "qgsfeature.h"
23+
#include <QUrl>
24+
25+
class QgsWebPage;
26+
class QImage;
27+
class QgsVectorLayer;
28+
class QgsNetworkContentFetcher;
29+
class QgsDistanceArea;
30+
31+
/**
32+
* \ingroup core
33+
* A layout multiframe subclass for HTML content.
34+
* \since QGIS 3.0
35+
*/
36+
class CORE_EXPORT QgsLayoutItemHtml: public QgsLayoutMultiFrame
37+
{
38+
Q_OBJECT
39+
40+
public:
41+
42+
//! Source modes for the HTML content to render in the item
43+
enum ContentMode
44+
{
45+
Url, //!< Using this mode item fetches its content via a url
46+
ManualHtml //!< HTML content is manually set for the item
47+
};
48+
49+
/**
50+
* Constructor for QgsLayoutItemHtml, with the specified parent \a layout.
51+
*/
52+
QgsLayoutItemHtml( QgsLayout *layout );
53+
54+
~QgsLayoutItemHtml();
55+
56+
/**
57+
* Sets the source \a mode for item's HTML content.
58+
* \see contentMode()
59+
* \see setUrl()
60+
* \see setHtml()
61+
*/
62+
void setContentMode( ContentMode mode ) { mContentMode = mode; }
63+
64+
/**
65+
* Returns the source mode for item's HTML content.
66+
* \see setContentMode()
67+
* \see url()
68+
* \see html()
69+
*/
70+
ContentMode contentMode() const { return mContentMode; }
71+
72+
/**
73+
* Sets the \a url for content to display in the item when the item is using
74+
* the QgsLayoutItemHtml::Url mode. Content is automatically fetched and the
75+
* HTML item refreshed after calling this function.
76+
* \see url()
77+
* \see contentMode()
78+
*/
79+
void setUrl( const QUrl &url );
80+
81+
/**
82+
* Returns the URL of the content displayed in the item if the item is using
83+
* the QgsLayoutItemHtml::Url mode.
84+
* \see setUrl()
85+
* \see contentMode()
86+
*/
87+
QUrl url() const { return mUrl; }
88+
89+
/**
90+
* Sets the \a html to display in the item when the item is using
91+
* the QgsLayoutItemHtml::ManualHtml mode. Setting the HTML using this function
92+
* does not automatically refresh the item's contents. Call loadHtml to trigger
93+
* a refresh of the item after setting the HTML content.
94+
* \see html()
95+
* \see contentMode()
96+
* \see loadHtml()
97+
*/
98+
void setHtml( const QString &html );
99+
100+
/**
101+
* Returns the HTML source displayed in the item if the item is using
102+
* the QgsLayoutItemHtml::ManualHtml mode.
103+
* \see setHtml()
104+
* \see contentMode()
105+
*/
106+
QString html() const { return mHtml; }
107+
108+
/**
109+
* Returns whether html item will evaluate QGIS expressions prior to rendering
110+
* the HTML content. If set, any content inside [% %] tags will be
111+
* treated as a QGIS expression and evaluated against the current atlas
112+
* feature.
113+
* \see setEvaluateExpressions()
114+
*/
115+
bool evaluateExpressions() const { return mEvaluateExpressions; }
116+
117+
/**
118+
* Sets whether the html item will evaluate QGIS expressions prior to rendering
119+
* the HTML content. If set, any content inside [% %] tags will be
120+
* treated as a QGIS expression and evaluated against the current atlas
121+
* feature.
122+
* \see evaluateExpressions()
123+
*/
124+
void setEvaluateExpressions( bool evaluateExpressions );
125+
126+
/**
127+
* Returns whether html item is using smart breaks. Smart breaks prevent
128+
* the html frame contents from breaking mid-way though a line of text.
129+
* \see setUseSmartBreaks()
130+
*/
131+
bool useSmartBreaks() const { return mUseSmartBreaks; }
132+
133+
/**
134+
* Sets whether the html item should use smart breaks. Smart breaks prevent
135+
* the html frame contents from breaking mid-way though a line of text.
136+
* \see useSmartBreaks()
137+
*/
138+
void setUseSmartBreaks( bool useSmartBreaks );
139+
140+
/**
141+
* Sets the maximum \a distance allowed when calculating where to place page breaks
142+
* in the html. This distance is the maximum amount of empty space allowed
143+
* at the bottom of a frame after calculating the optimum break location. Setting
144+
* a larger value will result in better choice of page break location, but more
145+
* wasted space at the bottom of frames. This setting is only effective if
146+
* useSmartBreaks is true.
147+
* \see maxBreakDistance()
148+
* \see setUseSmartBreaks()
149+
*/
150+
void setMaxBreakDistance( double distance );
151+
152+
/**
153+
* Returns the maximum distance allowed when calculating where to place page breaks
154+
* in the html. This distance is the maximum amount of empty space allowed
155+
* at the bottom of a frame after calculating the optimum break location. This setting
156+
* is only effective if useSmartBreaks is true.
157+
* \see setMaxBreakDistance()
158+
* \see useSmartBreaks()
159+
*/
160+
double maxBreakDistance() const { return mMaxBreakDistance; }
161+
162+
/**
163+
* Sets the user \a stylesheet CSS rules to use while rendering the HTML content. These
164+
* allow for overriding the styles specified within the HTML source. Setting the stylesheet
165+
* using this function does not automatically refresh the item's contents. Call loadHtml
166+
* to trigger a refresh of the item after setting the stylesheet rules.
167+
* \see userStylesheet()
168+
* \see setUserStylesheetEnabled()
169+
* \see loadHtml()
170+
*/
171+
void setUserStylesheet( const QString &stylesheet );
172+
173+
/**
174+
* Returns the user stylesheet CSS rules used while rendering the HTML content. These
175+
* overriding the styles specified within the HTML source.
176+
* \see setUserStylesheet()
177+
* \see userStylesheetEnabled()
178+
*/
179+
QString userStylesheet() const { return mUserStylesheet; }
180+
181+
/**
182+
* Sets whether user stylesheets are \a enabled for the HTML content.
183+
* \see userStylesheetEnabled()
184+
* \see setUserStylesheet()
185+
*/
186+
void setUserStylesheetEnabled( const bool enabled );
187+
188+
/**
189+
* Returns whether user stylesheets are enabled for the HTML content.
190+
* \see setUserStylesheetEnabled()
191+
* \see userStylesheet()
192+
*/
193+
bool userStylesheetEnabled() const { return mEnableUserStylesheet; }
194+
195+
QString displayName() const override;
196+
QSizeF totalSize() const override;
197+
void render( QgsRenderContext &context, const QRectF &renderExtent, const int frameIndex,
198+
const QStyleOptionGraphicsItem *itemStyle = nullptr ) override;
199+
200+
bool writeXml( QDomElement &elem, QDomDocument &doc, bool ignoreFrames = false ) const override;
201+
bool readXml( const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames = false ) override;
202+
//overridden to break frames without dividing lines of text
203+
double findNearbyPageBreak( double yPos ) override;
204+
205+
public slots:
206+
207+
/**
208+
* Reloads the html source from the url and redraws the item.
209+
* \param useCache set to true to use a cached copy of remote html
210+
* content
211+
* \param context expression context for evaluating data defined urls and expressions in html
212+
* \see setUrl
213+
* \see url
214+
*/
215+
void loadHtml( const bool useCache = false, const QgsExpressionContext *context = nullptr );
216+
217+
//! Recalculates the frame sizes for the current viewport dimensions
218+
void recalculateFrameSizes() override;
219+
void refreshExpressionContext();
220+
221+
void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );
222+
223+
private slots:
224+
void frameLoaded( bool ok = true );
225+
226+
private:
227+
ContentMode mContentMode;
228+
QUrl mUrl;
229+
QgsWebPage *mWebPage = nullptr;
230+
QString mHtml;
231+
QString mFetchedHtml;
232+
QString mLastFetchedUrl;
233+
QString mActualFetchedUrl; //may be different if page was redirected
234+
bool mLoaded;
235+
QSizeF mSize; //total size in mm
236+
double mHtmlUnitsToLayoutUnits;
237+
QImage *mRenderedPage = nullptr;
238+
bool mEvaluateExpressions;
239+
bool mUseSmartBreaks;
240+
double mMaxBreakDistance;
241+
242+
QgsFeature mExpressionFeature;
243+
QgsVectorLayer *mExpressionLayer = nullptr;
244+
QgsDistanceArea *mDistanceArea = nullptr;
245+
246+
QString mUserStylesheet;
247+
bool mEnableUserStylesheet;
248+
249+
//! JSON string representation of current atlas feature
250+
QString mAtlasFeatureJSON;
251+
252+
QgsNetworkContentFetcher *mFetcher = nullptr;
253+
254+
double htmlUnitsToLayoutUnits(); //calculate scale factor
255+
256+
//renders a snapshot of the page to a cached image
257+
void renderCachedImage();
258+
259+
//fetches html content from a url and returns it as a string
260+
QString fetchHtml( const QUrl &url );
261+
262+
//! Sets the current feature, the current layer and a list of local variable substitutions for evaluating expressions
263+
void setExpressionContext( const QgsFeature &feature, QgsVectorLayer *layer );
264+
265+
//! Calculates the max width of frames in the html multiframe
266+
double maxFrameWidth() const;
267+
};
268+
269+
#endif // QGSLAYOUTITEMHTML_H

‎src/core/layout/qgslayoutmultiframe.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void QgsLayoutMultiFrame::addFrame( QgsLayoutFrame *frame, bool recalcFrameSizes
5555

5656
mFrameItems.push_back( frame );
5757
frame->mMultiFrame = this;
58+
connect( frame, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutMultiFrame::recalculateFrameSizes );
5859
connect( frame, &QgsLayoutFrame::destroyed, this, &QgsLayoutMultiFrame::handleFrameRemoval );
5960
if ( mLayout )
6061
{

0 commit comments

Comments
 (0)
Please sign in to comment.