mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-29 00:05:09 -04:00
I just can't find any other reliable way to wait until javascript execution in a web page has completed.
298 lines
10 KiB
C++
298 lines
10 KiB
C++
/***************************************************************************
|
|
qgslayoutitemhtml.h
|
|
------------------------------------------------------------
|
|
begin : October 2017
|
|
copyright : (C) 2017 by Nyall Dawson
|
|
email : nyall dot dawson at gmail dot com
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef QGSLAYOUTITEMHTML_H
|
|
#define QGSLAYOUTITEMHTML_H
|
|
|
|
#include "qgis_core.h"
|
|
#include "qgis.h"
|
|
#include "qgslayoutmultiframe.h"
|
|
#include "qgsfeature.h"
|
|
#include "qgsdistancearea.h"
|
|
#include <QUrl>
|
|
|
|
class QgsWebPage;
|
|
class QImage;
|
|
class QgsVectorLayer;
|
|
class QgsNetworkContentFetcher;
|
|
|
|
/**
|
|
* \ingroup core
|
|
* A layout multiframe subclass for HTML content.
|
|
* \since QGIS 3.0
|
|
*/
|
|
class CORE_EXPORT QgsLayoutItemHtml: public QgsLayoutMultiFrame
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
//! Source modes for the HTML content to render in the item
|
|
enum ContentMode
|
|
{
|
|
Url, //!< Using this mode item fetches its content via a url
|
|
ManualHtml //!< HTML content is manually set for the item
|
|
};
|
|
|
|
/**
|
|
* Constructor for QgsLayoutItemHtml, with the specified parent \a layout.
|
|
*
|
|
* Ownership is transferred to the layout.
|
|
*/
|
|
QgsLayoutItemHtml( QgsLayout *layout SIP_TRANSFERTHIS );
|
|
|
|
~QgsLayoutItemHtml() override;
|
|
|
|
int type() const override;
|
|
QIcon icon() const override;
|
|
|
|
/**
|
|
* Returns a new QgsLayoutItemHtml for the specified parent \a layout.
|
|
*/
|
|
static QgsLayoutItemHtml *create( QgsLayout *layout ) SIP_FACTORY;
|
|
|
|
/**
|
|
* Sets the source \a mode for item's HTML content.
|
|
* \see contentMode()
|
|
* \see setUrl()
|
|
* \see setHtml()
|
|
*/
|
|
void setContentMode( ContentMode mode ) { mContentMode = mode; }
|
|
|
|
/**
|
|
* Returns the source mode for item's HTML content.
|
|
* \see setContentMode()
|
|
* \see url()
|
|
* \see html()
|
|
*/
|
|
ContentMode contentMode() const { return mContentMode; }
|
|
|
|
/**
|
|
* Sets the \a url for content to display in the item when the item is using
|
|
* the QgsLayoutItemHtml::Url mode. Content is automatically fetched and the
|
|
* HTML item refreshed after calling this function.
|
|
* \see url()
|
|
* \see contentMode()
|
|
*/
|
|
void setUrl( const QUrl &url );
|
|
|
|
/**
|
|
* Returns the URL of the content displayed in the item if the item is using
|
|
* the QgsLayoutItemHtml::Url mode.
|
|
* \see setUrl()
|
|
* \see contentMode()
|
|
*/
|
|
QUrl url() const { return mUrl; }
|
|
|
|
/**
|
|
* Sets the \a html to display in the item when the item is using
|
|
* the QgsLayoutItemHtml::ManualHtml mode. Setting the HTML using this function
|
|
* does not automatically refresh the item's contents. Call loadHtml to trigger
|
|
* a refresh of the item after setting the HTML content.
|
|
* \see html()
|
|
* \see contentMode()
|
|
* \see loadHtml()
|
|
*/
|
|
void setHtml( const QString &html );
|
|
|
|
/**
|
|
* Returns the HTML source displayed in the item if the item is using
|
|
* the QgsLayoutItemHtml::ManualHtml mode.
|
|
* \see setHtml()
|
|
* \see contentMode()
|
|
*/
|
|
QString html() const { return mHtml; }
|
|
|
|
/**
|
|
* Returns whether html item will evaluate QGIS expressions prior to rendering
|
|
* the HTML content. If set, any content inside [% %] tags will be
|
|
* treated as a QGIS expression and evaluated against the current atlas
|
|
* feature.
|
|
* \see setEvaluateExpressions()
|
|
*/
|
|
bool evaluateExpressions() const { return mEvaluateExpressions; }
|
|
|
|
/**
|
|
* Sets whether the html item will evaluate QGIS expressions prior to rendering
|
|
* the HTML content. If set, any content inside [% %] tags will be
|
|
* treated as a QGIS expression and evaluated against the current atlas
|
|
* feature.
|
|
* \see evaluateExpressions()
|
|
*/
|
|
void setEvaluateExpressions( bool evaluateExpressions );
|
|
|
|
/**
|
|
* Returns whether html item is using smart breaks. Smart breaks prevent
|
|
* the html frame contents from breaking mid-way though a line of text.
|
|
* \see setUseSmartBreaks()
|
|
*/
|
|
bool useSmartBreaks() const { return mUseSmartBreaks; }
|
|
|
|
/**
|
|
* Sets whether the html item should use smart breaks. Smart breaks prevent
|
|
* the html frame contents from breaking mid-way though a line of text.
|
|
* \see useSmartBreaks()
|
|
*/
|
|
void setUseSmartBreaks( bool useSmartBreaks );
|
|
|
|
/**
|
|
* Sets the maximum \a distance allowed when calculating where to place page breaks
|
|
* in the html. This distance is the maximum amount of empty space allowed
|
|
* at the bottom of a frame after calculating the optimum break location. Setting
|
|
* a larger value will result in better choice of page break location, but more
|
|
* wasted space at the bottom of frames. This setting is only effective if
|
|
* useSmartBreaks is true.
|
|
* \see maxBreakDistance()
|
|
* \see setUseSmartBreaks()
|
|
*/
|
|
void setMaxBreakDistance( double distance );
|
|
|
|
/**
|
|
* Returns the maximum distance allowed when calculating where to place page breaks
|
|
* in the html. This distance is the maximum amount of empty space allowed
|
|
* at the bottom of a frame after calculating the optimum break location. This setting
|
|
* is only effective if useSmartBreaks is true.
|
|
* \see setMaxBreakDistance()
|
|
* \see useSmartBreaks()
|
|
*/
|
|
double maxBreakDistance() const { return mMaxBreakDistance; }
|
|
|
|
/**
|
|
* Sets the user \a stylesheet CSS rules to use while rendering the HTML content. These
|
|
* allow for overriding the styles specified within the HTML source. Setting the stylesheet
|
|
* using this function does not automatically refresh the item's contents. Call loadHtml
|
|
* to trigger a refresh of the item after setting the stylesheet rules.
|
|
* \see userStylesheet()
|
|
* \see setUserStylesheetEnabled()
|
|
* \see loadHtml()
|
|
*/
|
|
void setUserStylesheet( const QString &stylesheet );
|
|
|
|
/**
|
|
* Returns the user stylesheet CSS rules used while rendering the HTML content. These
|
|
* overriding the styles specified within the HTML source.
|
|
* \see setUserStylesheet()
|
|
* \see userStylesheetEnabled()
|
|
*/
|
|
QString userStylesheet() const { return mUserStylesheet; }
|
|
|
|
/**
|
|
* Sets whether user stylesheets are \a enabled for the HTML content.
|
|
* \see userStylesheetEnabled()
|
|
* \see setUserStylesheet()
|
|
*/
|
|
void setUserStylesheetEnabled( const bool enabled );
|
|
|
|
/**
|
|
* Returns whether user stylesheets are enabled for the HTML content.
|
|
* \see setUserStylesheetEnabled()
|
|
* \see userStylesheet()
|
|
*/
|
|
bool userStylesheetEnabled() const { return mEnableUserStylesheet; }
|
|
|
|
QString displayName() const override;
|
|
QSizeF totalSize() const override;
|
|
void render( QgsRenderContext &context, const QRectF &renderExtent, int frameIndex,
|
|
const QStyleOptionGraphicsItem *itemStyle = nullptr ) override;
|
|
|
|
//overridden to break frames without dividing lines of text
|
|
double findNearbyPageBreak( double yPos ) override;
|
|
|
|
public slots:
|
|
|
|
/**
|
|
* Reloads the html source from the url and redraws the item.
|
|
* \param useCache set to true to use a cached copy of remote html
|
|
* content
|
|
* \param context expression context for evaluating data defined urls and expressions in html
|
|
* \see setUrl
|
|
* \see url
|
|
*/
|
|
void loadHtml( const bool useCache = false, const QgsExpressionContext *context = nullptr );
|
|
|
|
//! Recalculates the frame sizes for the current viewport dimensions
|
|
void recalculateFrameSizes() override;
|
|
|
|
void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties ) override;
|
|
|
|
protected:
|
|
|
|
bool writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
|
|
bool readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context ) override;
|
|
|
|
private:
|
|
ContentMode mContentMode = QgsLayoutItemHtml::Url;
|
|
QUrl mUrl;
|
|
std::unique_ptr< QgsWebPage > mWebPage;
|
|
QString mHtml;
|
|
QString mFetchedHtml;
|
|
QString mLastFetchedUrl;
|
|
QString mActualFetchedUrl; //may be different if page was redirected
|
|
QSizeF mSize; //total size in mm
|
|
double mHtmlUnitsToLayoutUnits = 1.0;
|
|
QImage mRenderedPage;
|
|
bool mEvaluateExpressions = true;
|
|
bool mUseSmartBreaks = true;
|
|
double mMaxBreakDistance = 10.0;
|
|
|
|
QgsFeature mExpressionFeature;
|
|
QgsVectorLayer *mExpressionLayer = nullptr;
|
|
QgsDistanceArea mDistanceArea;
|
|
|
|
QString mUserStylesheet;
|
|
bool mEnableUserStylesheet = false;
|
|
|
|
//! JSON string representation of current atlas feature
|
|
QString mAtlasFeatureJSON;
|
|
|
|
QgsNetworkContentFetcher *mFetcher = nullptr;
|
|
|
|
double htmlUnitsToLayoutUnits(); //calculate scale factor
|
|
|
|
//renders a snapshot of the page to a cached image
|
|
void renderCachedImage();
|
|
|
|
//fetches html content from a url and returns it as a string
|
|
QString fetchHtml( const QUrl &url );
|
|
|
|
//! Sets the current feature, the current layer and a list of local variable substitutions for evaluating expressions
|
|
void setExpressionContext( const QgsFeature &feature, QgsVectorLayer *layer );
|
|
|
|
//! Calculates the max width of frames in the html multiframe
|
|
double maxFrameWidth() const;
|
|
|
|
void refreshExpressionContext();
|
|
};
|
|
|
|
///@cond PRIVATE
|
|
#ifndef SIP_RUN
|
|
class JavascriptExecutorLoop : public QEventLoop
|
|
{
|
|
Q_OBJECT
|
|
public slots:
|
|
|
|
void done();
|
|
void execIfNotDone();
|
|
|
|
private:
|
|
|
|
bool mDone = false;
|
|
|
|
};
|
|
#endif
|
|
///@endcond
|
|
|
|
#endif // QGSLAYOUTITEMHTML_H
|