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 );