28 #include <QCoreApplication> 33 #include <QNetworkReply> 40 , mHtmlUnitsToMM( 1.0 )
42 , mEvaluateExpressions( true )
43 , mUseSmartBreaks( true )
44 , mMaxBreakDistance( 10 )
45 , mExpressionFeature( 0 )
46 , mExpressionLayer( 0 )
48 , mEnableUserStylesheet( false )
52 mHtmlUnitsToMM = htmlUnitsToMM();
53 mWebPage =
new QWebPage();
54 mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
55 mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
58 QPalette palette = mWebPage->palette();
59 palette.setBrush( QPalette::Base, Qt::transparent );
60 mWebPage->setPalette( palette );
63 QObject::connect( mWebPage, SIGNAL( loadFinished(
bool ) ),
this, SLOT( frameLoaded(
bool ) ) );
84 connect( mFetcher, SIGNAL( finished() ),
this, SLOT( frameLoaded() ) );
93 , mHtmlUnitsToMM( 1.0 )
95 , mEvaluateExpressions( true )
96 , mUseSmartBreaks( true )
97 , mMaxBreakDistance( 10 )
98 , mExpressionFeature( 0 )
99 , mExpressionLayer( 0 )
101 , mEnableUserStylesheet( false )
106 connect( mFetcher, SIGNAL( finished() ),
this, SLOT( frameLoaded() ) );
111 delete mDistanceArea;
113 delete mRenderedPage;
114 mFetcher->deleteLater();
153 switch ( mContentMode )
158 QString currentUrl = mUrl.toString();
164 currentUrl = exprVal.toString().trimmed();;
165 QgsDebugMsg( QString(
"exprVal Source Url:%1" ).arg( currentUrl ) );
167 if ( currentUrl.isEmpty() )
171 if ( !( useCache && currentUrl == mLastFetchedUrl ) )
173 loadedHtml = fetchHtml( QUrl( currentUrl ) );
174 mLastFetchedUrl = currentUrl;
178 loadedHtml = mFetchedHtml;
189 if ( mEvaluateExpressions )
197 mWebPage->setViewportSize( QSize( maxFrameWidth() * mHtmlUnitsToMM, 0 ) );
200 mWebPage->mainFrame()->setHtml( loadedHtml, mContentMode ==
QgsComposerHtml::Url ? QUrl( mActualFetchedUrl ) : QUrl() );
203 QWebSettings* settings = mWebPage->settings();
204 if ( mEnableUserStylesheet && ! mUserStylesheet.isEmpty() )
207 ba.append( mUserStylesheet.toUtf8() );
208 QUrl cssFileURL = QUrl(
"data:text/css;charset=utf-8;base64," + ba.toBase64() );
209 settings->setUserStyleSheetUrl( cssFileURL );
213 settings->setUserStyleSheetUrl( QUrl() );
218 qApp->processEvents();
226 void QgsComposerHtml::frameLoaded(
bool ok )
232 double QgsComposerHtml::maxFrameWidth()
const 235 QList<QgsComposerFrame*>::const_iterator frameIt =
mFrameItems.constBegin();
236 for ( ; frameIt !=
mFrameItems.constEnd(); ++frameIt )
238 maxWidth = qMax( maxWidth, (
double )(( *frameIt )->boundingRect().width() ) );
248 QSize contentsSize = mWebPage->mainFrame()->contentsSize();
251 double maxWidth = maxFrameWidth();
253 contentsSize.setWidth( maxWidth * mHtmlUnitsToMM );
255 mWebPage->setViewportSize( contentsSize );
256 mSize.setWidth( contentsSize.width() / mHtmlUnitsToMM );
257 mSize.setHeight( contentsSize.height() / mHtmlUnitsToMM );
258 if ( contentsSize.isValid() )
266 void QgsComposerHtml::renderCachedImage()
271 delete mRenderedPage;
273 mRenderedPage =
new QImage( mWebPage->viewportSize(), QImage::Format_ARGB32 );
274 if ( mRenderedPage->isNull() )
278 mRenderedPage->fill( Qt::transparent );
280 painter.begin( mRenderedPage );
281 mWebPage->mainFrame()->render( &painter );
285 QString QgsComposerHtml::fetchHtml( QUrl
url )
293 qApp->processEvents();
297 mActualFetchedUrl = mFetcher->
reply()->url().toString();
308 Q_UNUSED( frameIndex );
316 p->setRenderHint( QPainter::Antialiasing );
317 p->scale( 1.0 / mHtmlUnitsToMM, 1.0 / mHtmlUnitsToMM );
318 p->translate( 0.0, -renderExtent.top() * mHtmlUnitsToMM );
319 mWebPage->mainFrame()->render( p, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToMM, renderExtent.width() * mHtmlUnitsToMM, renderExtent.height() * mHtmlUnitsToMM ) );
323 double QgsComposerHtml::htmlUnitsToMM()
342 if ( recalcFrameSizes )
350 if ( c1.second < c2.second )
352 else if ( c1.second > c2.second )
354 else if ( c1.first > c2.first )
362 if ( !mWebPage || !mRenderedPage || !mUseSmartBreaks )
368 int idealPos = yPos * htmlUnitsToMM();
371 if ( idealPos >= mRenderedPage->height() )
376 int maxSearchDistance = mMaxBreakDistance * htmlUnitsToMM();
382 bool currentPixelTransparent =
false;
383 bool previousPixelTransparent =
false;
385 QList< QPair<int, int> > candidates;
386 int minRow = qMax( idealPos - maxSearchDistance, 0 );
387 for (
int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
390 currentColor = qRgba( 0, 0, 0, 0 );
392 for (
int col = 0; col < mRenderedPage->width(); ++col )
398 pixelColor = mRenderedPage->pixel( col, candidateRow );
399 currentPixelTransparent = qAlpha( pixelColor ) == 0;
400 if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) )
403 currentColor = pixelColor;
406 previousPixelTransparent = currentPixelTransparent;
408 candidates.append( qMakePair( candidateRow, changes ) );
412 qSort( candidates.begin(), candidates.end(),
candidateSort );
419 int maxCandidateRow = candidates[0].first;
420 int minCandidateRow = maxCandidateRow + 1;
421 int minCandidateChanges = candidates[0].second;
423 QList< QPair<int, int> >::iterator it;
424 for ( it = candidates.begin(); it != candidates.end(); ++it )
426 if (( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
431 return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToMM();
433 minCandidateRow = ( *it ).first;
438 return candidates[0].first / htmlUnitsToMM();
457 mUserStylesheet = stylesheet;
466 if ( mEnableUserStylesheet != stylesheetEnabled )
468 mEnableUserStylesheet = stylesheetEnabled;
476 return tr(
"<html frame>" );
481 QDomElement htmlElem = doc.createElement(
"ComposerHtml" );
482 htmlElem.setAttribute(
"contentMode", QString::number((
int ) mContentMode ) );
483 htmlElem.setAttribute(
"url", mUrl.toString() );
484 htmlElem.setAttribute(
"html", mHtml );
485 htmlElem.setAttribute(
"evaluateExpressions", mEvaluateExpressions ?
"true" :
"false" );
486 htmlElem.setAttribute(
"useSmartBreaks", mUseSmartBreaks ?
"true" :
"false" );
487 htmlElem.setAttribute(
"maxBreakDistance", QString::number( mMaxBreakDistance ) );
488 htmlElem.setAttribute(
"stylesheet", mUserStylesheet );
489 htmlElem.setAttribute(
"stylesheetEnabled", mEnableUserStylesheet ?
"true" :
"false" );
491 bool state =
_writeXML( htmlElem, doc, ignoreFrames );
492 elem.appendChild( htmlElem );
504 if ( !
_readXML( itemElem, doc, ignoreFrames ) )
511 if ( !contentModeOK )
515 mEvaluateExpressions = itemElem.attribute(
"evaluateExpressions",
"true" ) ==
"true" ?
true :
false;
516 mUseSmartBreaks = itemElem.attribute(
"useSmartBreaks",
"true" ) ==
"true" ?
true :
false;
517 mMaxBreakDistance = itemElem.attribute(
"maxBreakDistance",
"10" ).toDouble();
518 mHtml = itemElem.attribute(
"html" );
519 mUserStylesheet = itemElem.attribute(
"stylesheet" );
520 mEnableUserStylesheet = itemElem.attribute(
"stylesheetEnabled",
"false" ) ==
"true" ?
true :
false;
523 QString urlString = itemElem.attribute(
"url" );
524 if ( !urlString.isEmpty() )
537 mExpressionFeature = feature;
538 mExpressionLayer = layer;
571 setExpressionContext( feature, vl );
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of it's component frames...
QgsComposition::AtlasMode atlasMode() const
Returns the current atlas mode of the composition.
QString contentAsString() const
Returns the fetched content as a string.
bool writeXML(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const override
Stores state information about multiframe in DOM element.
virtual QString displayName() const override
Get multiframe display name.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
void setHtml(const QString html)
Sets the HTML to display in the item when the item is using the QgsComposerHtml::ManualHtml mode...
void setUserStylesheet(const QString stylesheet)
Sets the user stylesheet CSS rules to use while rendering the HTML content.
QMap< QgsComposerObject::DataDefinedProperty, QString > mDataDefinedNames
Map of data defined properties for the item to string name to use when exporting item to xml...
static QgsNetworkAccessManager * instance()
A item that forms part of a map composition.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties) override
bool enabled() const
Returns whether the atlas generation is enabled.
void fetchContent(const QUrl url)
Fetches content from a remote URL and handles redirects.
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
QNetworkReply * reply()
Returns a reference to the network reply.
bool setEllipsoid(const QString &ellipsoid)
sets ellipsoid by its acronym
void setEvaluateExpressions(bool evaluateExpressions)
Sets whether the html item will evaluate QGIS expressions prior to rendering the HTML content...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
DataDefinedProperty
Data defined properties for different item types.
QSizeF totalSize() const override
Returns the total size of the multiframe's content.
bool dataDefinedEvaluate(const QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue)
Evaluate a data defined property and return the calculated value.
bool useSmartBreaks() const
Returns whether html item is using smart breaks.
QString html() const
Returns the HTML source displayed in the item if the item is using the QgsComposerHtml::ManualHtml mo...
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false)
Restores state information about base multiframe object from a DOM element.
HTTP network content fetcher.
int printResolution() const
void recalculateFrameSizes() override
Recalculates the frame sizes for the current viewport dimensions.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
Abstract base class for composer items with the ability to distribute the content to several frames (...
void addFrame(QgsComposerFrame *frame, bool recalcFrameSizes=true) override
Adds a frame to the multiframe.
QList< QgsComposerFrame * > mFrameItems
bool _writeXML(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const
Stores state information about base multiframe object in DOM element.
void setMaxBreakDistance(double maxBreakDistance)
Sets the maximum distance allowed when calculating where to place page breaks in the html...
bool evaluateExpressions() const
Returns whether html item will evaluate QGIS expressions prior to rendering the HTML content...
void setUseSmartBreaks(bool useSmartBreaks)
Sets whether the html item should use smart breaks.
int frameCount() const
Returns the number of frames associated with this multiframe.
void loadHtml(const bool useCache=false)
Reloads the html source from the url and redraws the item.
Graphics scene for map printing.
QgsFeature * currentFeature()
Returns the current atlas feature.
Frame item for a composer multiframe item.
const QUrl & url() const
Returns the URL of the content displayed in the item if the item is using the QgsComposerHtml::Url mo...
General purpose distance and area calculator.
QgsComposition * mComposition
void deleteFrames()
Removes and deletes all child frames.
void refreshExpressionContext()
void contentsChanged()
Emitted when the contents of the multi frame have changed and the frames must be redrawn.
double maxBreakDistance() const
Returns the maximum distance allowed when calculating where to place page breaks in the html...
void addComposerHtmlFrame(QgsComposerHtml *html, QgsComposerFrame *frame)
Adds composer html frame and advises composer to create a widget for it (through signal) ...
void setUrl(const QUrl &url)
Sets the URL for content to display in the item when the item is using the QgsComposerHtml::Url mode...
static QgsProject * instance()
access to canonical QgsProject instance
const CORE_EXPORT QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
int frameIndex(QgsComposerFrame *frame) const
Returns the index of a frame within the multiframe.
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
QgsAtlasComposition & atlasComposition()
QgsComposerFrame * frame(int i) const
Returns a child frame from the multiframe.
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
void setUserStylesheetEnabled(const bool stylesheetEnabled)
Sets whether user stylesheets are enabled for the HTML content.
bool readXML(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false) override
Reads multiframe state information from a DOM element.
Represents a vector layer which manages a vector based data sets.
ContentMode
Source modes for the HTML content to render in the item.
double findNearbyPageBreak(double yPos) override
Finds the optimal position to break a frame at.
void handleFrameRemoval(QgsComposerItem *item)
Called before a frame is going to be removed.
bool candidateSort(const QPair< int, int > &c1, const QPair< int, int > &c2)
virtual void refreshDataDefinedProperty(const DataDefinedProperty property=AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
void render(QPainter *p, const QRectF &renderExtent, const int frameIndex) override
Renders a portion of the multiframe's content into a painter.
void changed()
Emitted when the properties of a multi frame have changed, and the GUI item widget must be updated...
static QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0, const QgsDistanceArea *distanceArea=0)
This function currently replaces each expression between [% and %] in the string with the result of i...