QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgslayoutitemhtml.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutitemhtml.cpp
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 #include "qgslayoutitemhtml.h"
17 #include "qgslayoutframe.h"
18 #include "qgslayout.h"
20 #include "qgsmessagelog.h"
21 #include "qgsexpression.h"
22 #include "qgslogger.h"
24 #include "qgsvectorlayer.h"
25 #include "qgsproject.h"
26 #include "qgsdistancearea.h"
27 #include "qgsjsonutils.h"
28 #include "qgsmapsettings.h"
29 #include "qgswebpage.h"
30 #include "qgswebframe.h"
31 #include "qgslayoutitemmap.h"
32 
33 #include <QCoreApplication>
34 #include <QPainter>
35 #include <QImage>
36 #include <QNetworkReply>
37 
38 // clazy:excludeall=lambda-in-connect
39 
41  : QgsLayoutMultiFrame( layout )
42 {
43  mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits();
44 
45  // only possible on the main thread!
46  if ( QThread::currentThread() == QApplication::instance()->thread() )
47  {
48  mWebPage = qgis::make_unique< QgsWebPage >();
49  }
50  else
51  {
52  QgsMessageLog::logMessage( QObject::tr( "Cannot load HTML content in background threads" ) );
53  }
54 
55  if ( mWebPage )
56  {
57  mWebPage->setIdentifier( tr( "Layout HTML item" ) );
58  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
59  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
60 
61  //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/
62  QPalette palette = mWebPage->palette();
63  palette.setBrush( QPalette::Base, Qt::transparent );
64  mWebPage->setPalette( palette );
65 
66  mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
67  }
68 
69  //a html item added to a layout needs to have the initial expression context set,
70  //otherwise fields in the html aren't correctly evaluated until atlas preview feature changes (#9457)
71  setExpressionContext( mLayout->reportContext().feature(), mLayout->reportContext().layer() );
72 
73  connect( &mLayout->reportContext(), &QgsLayoutReportContext::changed, this, &QgsLayoutItemHtml::refreshExpressionContext );
74 
75  mFetcher = new QgsNetworkContentFetcher();
76 }
77 
79 {
80  mFetcher->deleteLater();
81 }
82 
84 {
86 }
87 
89 {
90  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemHtml.svg" ) );
91 }
92 
94 {
95  return new QgsLayoutItemHtml( layout );
96 }
97 
98 void QgsLayoutItemHtml::setUrl( const QUrl &url )
99 {
100  if ( !mWebPage )
101  {
102  return;
103  }
104 
105  mUrl = url;
106  loadHtml( true );
107  emit changed();
108 }
109 
110 void QgsLayoutItemHtml::setHtml( const QString &html )
111 {
112  mHtml = html;
113  //TODO - this signal should be emitted, but without changing the signal which sets the html
114  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
115  //ways of doing this using QScintilla widgets.
116  //emit changed();
117 }
118 
119 void QgsLayoutItemHtml::setEvaluateExpressions( bool evaluateExpressions )
120 {
121  mEvaluateExpressions = evaluateExpressions;
122  loadHtml( true );
123  emit changed();
124 }
125 
126 void QgsLayoutItemHtml::loadHtml( const bool useCache, const QgsExpressionContext *context )
127 {
128  if ( !mWebPage )
129  {
130  return;
131  }
132 
134  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
135 
136  QString loadedHtml;
137  switch ( mContentMode )
138  {
140  {
141 
142  QString currentUrl = mUrl.toString();
143 
144  //data defined url set?
145  bool ok = false;
146  currentUrl = mDataDefinedProperties.valueAsString( QgsLayoutObject::SourceUrl, *evalContext, currentUrl, &ok );
147  if ( ok )
148  {
149  currentUrl = currentUrl.trimmed();
150  QgsDebugMsg( QStringLiteral( "exprVal Source Url:%1" ).arg( currentUrl ) );
151  }
152  if ( currentUrl.isEmpty() )
153  {
154  return;
155  }
156  if ( !( useCache && currentUrl == mLastFetchedUrl ) )
157  {
158  loadedHtml = fetchHtml( QUrl( currentUrl ) );
159  mLastFetchedUrl = currentUrl;
160  }
161  else
162  {
163  loadedHtml = mFetchedHtml;
164  }
165 
166  break;
167  }
169  loadedHtml = mHtml;
170  break;
171  }
172 
173  //evaluate expressions
174  if ( mEvaluateExpressions )
175  {
176  loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, evalContext, &mDistanceArea );
177  }
178 
179  bool loaded = false;
180 
181  QEventLoop loop;
182  connect( mWebPage.get(), &QWebPage::loadFinished, &loop, [&loaded, &loop ] { loaded = true; loop.quit(); } );
183  connect( mFetcher, &QgsNetworkContentFetcher::finished, &loop, [&loaded, &loop ] { loaded = true; loop.quit(); } );
184 
185  //reset page size. otherwise viewport size increases but never decreases again
186  mWebPage->setViewportSize( QSize( maxFrameWidth() * mHtmlUnitsToLayoutUnits, 0 ) );
187 
188  //set html, using the specified url as base if in Url mode or the project file if in manual mode
189  const QUrl baseUrl = mContentMode == QgsLayoutItemHtml::Url ?
190  QUrl( mActualFetchedUrl ) :
191  QUrl::fromLocalFile( mLayout->project()->absoluteFilePath() );
192 
193  mWebPage->mainFrame()->setHtml( loadedHtml, baseUrl );
194 
195  //set user stylesheet
196  QWebSettings *settings = mWebPage->settings();
197  if ( mEnableUserStylesheet && ! mUserStylesheet.isEmpty() )
198  {
199  QByteArray ba;
200  ba.append( mUserStylesheet.toUtf8() );
201  QUrl cssFileURL = QUrl( "data:text/css;charset=utf-8;base64," + ba.toBase64() );
202  settings->setUserStyleSheetUrl( cssFileURL );
203  }
204  else
205  {
206  settings->setUserStyleSheetUrl( QUrl() );
207  }
208 
209  if ( !loaded )
210  loop.exec( QEventLoop::ExcludeUserInputEvents );
211 
212  //inject JSON feature
213  if ( !mAtlasFeatureJSON.isEmpty() )
214  {
215  JavascriptExecutorLoop jsLoop;
216 
217  mWebPage->mainFrame()->addToJavaScriptWindowObject( QStringLiteral( "loop" ), &jsLoop );
218  mWebPage->mainFrame()->evaluateJavaScript( QStringLiteral( "if ( typeof setFeature === \"function\" ) { try{ setFeature(%1); } catch (err) { loop.reportError(err.message); } }; loop.done();" ).arg( mAtlasFeatureJSON ) );
219 
220  jsLoop.execIfNotDone();
221  }
222 
224  //trigger a repaint
225  emit contentsChanged();
226 }
227 
228 double QgsLayoutItemHtml::maxFrameWidth() const
229 {
230  double maxWidth = 0;
231  for ( QgsLayoutFrame *frame : mFrameItems )
232  {
233  maxWidth = std::max( maxWidth, static_cast< double >( frame->boundingRect().width() ) );
234  }
235 
236  return maxWidth;
237 }
238 
240 {
241  if ( frameCount() < 1 )
242  return;
243 
244  if ( !mWebPage )
245  return;
246 
247  QSize contentsSize = mWebPage->mainFrame()->contentsSize();
248 
249  //find maximum frame width
250  double maxWidth = maxFrameWidth();
251  //set content width to match maximum frame width
252  contentsSize.setWidth( maxWidth * mHtmlUnitsToLayoutUnits );
253 
254  mWebPage->setViewportSize( contentsSize );
255  mSize.setWidth( contentsSize.width() / mHtmlUnitsToLayoutUnits );
256  mSize.setHeight( contentsSize.height() / mHtmlUnitsToLayoutUnits );
257  if ( contentsSize.isValid() )
258  {
259  renderCachedImage();
260  }
262  emit changed();
263 }
264 
265 void QgsLayoutItemHtml::renderCachedImage()
266 {
267  if ( !mWebPage )
268  return;
269 
270  //render page to cache image
271  mRenderedPage = QImage( mWebPage->viewportSize(), QImage::Format_ARGB32 );
272  if ( mRenderedPage.isNull() )
273  {
274  return;
275  }
276  mRenderedPage.fill( Qt::transparent );
277  QPainter painter;
278  painter.begin( &mRenderedPage );
279  mWebPage->mainFrame()->render( &painter );
280  painter.end();
281 }
282 
283 QString QgsLayoutItemHtml::fetchHtml( const QUrl &url )
284 {
285  //pause until HTML fetch
286  bool loaded = false;
287  QEventLoop loop;
288  connect( mFetcher, &QgsNetworkContentFetcher::finished, &loop, [&loaded, &loop ] { loaded = true; loop.quit(); } );
289  mFetcher->fetchContent( url );
290 
291  if ( !loaded )
292  loop.exec( QEventLoop::ExcludeUserInputEvents );
293 
294  mFetchedHtml = mFetcher->contentAsString();
295  mActualFetchedUrl = mFetcher->reply()->url().toString();
296  return mFetchedHtml;
297 }
298 
300 {
301  return mSize;
302 }
303 
304 void QgsLayoutItemHtml::render( QgsLayoutItemRenderContext &context, const QRectF &renderExtent, const int )
305 {
306  if ( !mWebPage )
307  return;
308 
309  QPainter *painter = context.renderContext().painter();
310  painter->save();
311  // painter is scaled to dots, so scale back to layout units
312  painter->scale( context.renderContext().scaleFactor() / mHtmlUnitsToLayoutUnits, context.renderContext().scaleFactor() / mHtmlUnitsToLayoutUnits );
313  painter->translate( 0.0, -renderExtent.top() * mHtmlUnitsToLayoutUnits );
314  mWebPage->mainFrame()->render( painter, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToLayoutUnits, renderExtent.width() * mHtmlUnitsToLayoutUnits, renderExtent.height() * mHtmlUnitsToLayoutUnits ) );
315  painter->restore();
316 }
317 
318 double QgsLayoutItemHtml::htmlUnitsToLayoutUnits()
319 {
320  if ( !mLayout )
321  {
322  return 1.0;
323  }
324 
325  return mLayout->convertToLayoutUnits( QgsLayoutMeasurement( mLayout->renderContext().dpi() / 72.0, QgsUnitTypes::LayoutMillimeters ) ); //webkit seems to assume a standard dpi of 96
326 }
327 
328 bool candidateSort( QPair<int, int> c1, QPair<int, int> c2 )
329 {
330  if ( c1.second < c2.second )
331  return true;
332  else if ( c1.second > c2.second )
333  return false;
334  else if ( c1.first > c2.first )
335  return true;
336  else
337  return false;
338 }
339 
341 {
342  if ( !mWebPage || mRenderedPage.isNull() || !mUseSmartBreaks )
343  {
344  return yPos;
345  }
346 
347  //convert yPos to pixels
348  int idealPos = yPos * htmlUnitsToLayoutUnits();
349 
350  //if ideal break pos is past end of page, there's nothing we need to do
351  if ( idealPos >= mRenderedPage.height() )
352  {
353  return yPos;
354  }
355 
356  int maxSearchDistance = mMaxBreakDistance * htmlUnitsToLayoutUnits();
357 
358  //loop through all lines just before ideal break location, up to max distance
359  //of maxSearchDistance
360  int changes = 0;
361  QRgb currentColor;
362  bool currentPixelTransparent = false;
363  bool previousPixelTransparent = false;
364  QRgb pixelColor;
365  QList< QPair<int, int> > candidates;
366  int minRow = std::max( idealPos - maxSearchDistance, 0 );
367  for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
368  {
369  changes = 0;
370  currentColor = qRgba( 0, 0, 0, 0 );
371  //check all pixels in this line
372  for ( int col = 0; col < mRenderedPage.width(); ++col )
373  {
374  //count how many times the pixels change color in this row
375  //eventually, we select a row to break at with the minimum number of color changes
376  //since this is likely a line break, or gap between table cells, etc
377  //but very unlikely to be midway through a text line or picture
378  pixelColor = mRenderedPage.pixel( col, candidateRow );
379  currentPixelTransparent = qAlpha( pixelColor ) == 0;
380  if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) )
381  {
382  //color has changed
383  currentColor = pixelColor;
384  changes++;
385  }
386  previousPixelTransparent = currentPixelTransparent;
387  }
388  candidates.append( qMakePair( candidateRow, changes ) );
389  }
390 
391  //sort candidate rows by number of changes ascending, row number descending
392  std::sort( candidates.begin(), candidates.end(), candidateSort );
393  //first candidate is now the largest row with smallest number of changes
394 
395  //OK, now take the mid point of the best candidate position
396  //we do this so that the spacing between text lines is likely to be split in half
397  //otherwise the html will be broken immediately above a line of text, which
398  //looks a little messy
399  int maxCandidateRow = candidates[0].first;
400  int minCandidateRow = maxCandidateRow + 1;
401  int minCandidateChanges = candidates[0].second;
402 
403  QList< QPair<int, int> >::iterator it;
404  for ( it = candidates.begin(); it != candidates.end(); ++it )
405  {
406  if ( ( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
407  {
408  //no longer in a consecutive block of rows of minimum pixel color changes
409  //so return the row mid-way through the block
410  //first converting back to mm
411  return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToLayoutUnits();
412  }
413  minCandidateRow = ( *it ).first;
414  }
415 
416  //above loop didn't work for some reason
417  //return first candidate converted to mm
418  return candidates[0].first / htmlUnitsToLayoutUnits();
419 }
420 
421 void QgsLayoutItemHtml::setUseSmartBreaks( bool useSmartBreaks )
422 {
423  mUseSmartBreaks = useSmartBreaks;
425  emit changed();
426 }
427 
428 void QgsLayoutItemHtml::setMaxBreakDistance( double maxBreakDistance )
429 {
430  mMaxBreakDistance = maxBreakDistance;
432  emit changed();
433 }
434 
435 void QgsLayoutItemHtml::setUserStylesheet( const QString &stylesheet )
436 {
437  mUserStylesheet = stylesheet;
438  //TODO - this signal should be emitted, but without changing the signal which sets the css
439  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
440  //ways of doing this using QScintilla widgets.
441  //emit changed();
442 }
443 
444 void QgsLayoutItemHtml::setUserStylesheetEnabled( const bool stylesheetEnabled )
445 {
446  if ( mEnableUserStylesheet != stylesheetEnabled )
447  {
448  mEnableUserStylesheet = stylesheetEnabled;
449  loadHtml( true );
450  emit changed();
451  }
452 }
453 
455 {
456  return tr( "<HTML frame>" );
457 }
458 
459 bool QgsLayoutItemHtml::writePropertiesToElement( QDomElement &htmlElem, QDomDocument &, const QgsReadWriteContext & ) const
460 {
461  htmlElem.setAttribute( QStringLiteral( "contentMode" ), QString::number( static_cast< int >( mContentMode ) ) );
462  htmlElem.setAttribute( QStringLiteral( "url" ), mUrl.toString() );
463  htmlElem.setAttribute( QStringLiteral( "html" ), mHtml );
464  htmlElem.setAttribute( QStringLiteral( "evaluateExpressions" ), mEvaluateExpressions ? "true" : "false" );
465  htmlElem.setAttribute( QStringLiteral( "useSmartBreaks" ), mUseSmartBreaks ? "true" : "false" );
466  htmlElem.setAttribute( QStringLiteral( "maxBreakDistance" ), QString::number( mMaxBreakDistance ) );
467  htmlElem.setAttribute( QStringLiteral( "stylesheet" ), mUserStylesheet );
468  htmlElem.setAttribute( QStringLiteral( "stylesheetEnabled" ), mEnableUserStylesheet ? "true" : "false" );
469  return true;
470 }
471 
472 bool QgsLayoutItemHtml::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext & )
473 {
474  bool contentModeOK;
475  mContentMode = static_cast< QgsLayoutItemHtml::ContentMode >( itemElem.attribute( QStringLiteral( "contentMode" ) ).toInt( &contentModeOK ) );
476  if ( !contentModeOK )
477  {
478  mContentMode = QgsLayoutItemHtml::Url;
479  }
480  mEvaluateExpressions = itemElem.attribute( QStringLiteral( "evaluateExpressions" ), QStringLiteral( "true" ) ) == QLatin1String( "true" );
481  mUseSmartBreaks = itemElem.attribute( QStringLiteral( "useSmartBreaks" ), QStringLiteral( "true" ) ) == QLatin1String( "true" );
482  mMaxBreakDistance = itemElem.attribute( QStringLiteral( "maxBreakDistance" ), QStringLiteral( "10" ) ).toDouble();
483  mHtml = itemElem.attribute( QStringLiteral( "html" ) );
484  mUserStylesheet = itemElem.attribute( QStringLiteral( "stylesheet" ) );
485  mEnableUserStylesheet = itemElem.attribute( QStringLiteral( "stylesheetEnabled" ), QStringLiteral( "false" ) ) == QLatin1String( "true" );
486 
487  //finally load the set url
488  QString urlString = itemElem.attribute( QStringLiteral( "url" ) );
489  if ( !urlString.isEmpty() )
490  {
491  mUrl = urlString;
492  }
493  loadHtml( true );
494 
495  //since frames had to be created before, we need to emit a changed signal to refresh the widget
496  emit changed();
497  return true;
498 }
499 
500 void QgsLayoutItemHtml::setExpressionContext( const QgsFeature &feature, QgsVectorLayer *layer )
501 {
502  mExpressionFeature = feature;
503  mExpressionLayer = layer;
504 
505  //setup distance area conversion
506  if ( layer )
507  {
508  mDistanceArea.setSourceCrs( layer->crs(), mLayout->project()->transformContext() );
509  }
510  else if ( mLayout )
511  {
512  //set to composition's mapsettings' crs
513  QgsLayoutItemMap *referenceMap = mLayout->referenceMap();
514  if ( referenceMap )
515  mDistanceArea.setSourceCrs( referenceMap->crs(), mLayout->project()->transformContext() );
516  }
517  if ( mLayout )
518  {
519  mDistanceArea.setEllipsoid( mLayout->project()->ellipsoid() );
520  }
521 
522  if ( feature.isValid() )
523  {
524  // create JSON representation of feature
525  QgsJsonExporter exporter( layer );
526  exporter.setIncludeRelated( true );
527  mAtlasFeatureJSON = exporter.exportFeature( feature );
528  }
529  else
530  {
531  mAtlasFeatureJSON.clear();
532  }
533 }
534 
535 void QgsLayoutItemHtml::refreshExpressionContext()
536 {
537  QgsVectorLayer *vl = nullptr;
538  QgsFeature feature;
539 
540  if ( mLayout )
541  {
542  vl = mLayout->reportContext().layer();
543  feature = mLayout->reportContext().feature();
544  }
545 
546  setExpressionContext( feature, vl );
547  loadHtml( true );
548 }
549 
551 {
553 
554  //updates data defined properties and redraws item to match
555  if ( property == QgsLayoutObject::SourceUrl || property == QgsLayoutObject::AllProperties )
556  {
557  loadHtml( true, &context );
558  }
559 }
560 
561 //JavascriptExecutorLoop
563 
564 void JavascriptExecutorLoop::done()
565 {
566  mDone = true;
567  quit();
568 }
569 
570 void JavascriptExecutorLoop::execIfNotDone()
571 {
572  if ( !mDone )
573  exec( QEventLoop::ExcludeUserInputEvents );
574 
575  // gross, but nothing else works, so f*** it.. it's not worth spending a day trying to find a non-hacky way
576  // to force the web page to update following the js execution
577  for ( int i = 0; i < 100; i++ )
578  qApp->processEvents();
579 }
580 
581 void JavascriptExecutorLoop::reportError( const QString &error )
582 {
583  mDone = true;
584  QgsMessageLog::logMessage( tr( "HTML setFeature function error: %1" ).arg( error ), tr( "Layout" ) );
585  quit();
586 }
587 
QgsLayoutMultiFrame::frame
QgsLayoutFrame * frame(int index) const
Returns the child frame at a specified index from the multiframe.
Definition: qgslayoutmultiframe.cpp:469
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:88
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:118
QgsLayoutMultiFrame::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgslayoutmultiframe.cpp:283
QgsLayoutItemHtml::evaluateExpressions
bool evaluateExpressions() const
Returns whether html item will evaluate QGIS expressions prior to rendering the HTML content.
Definition: qgslayoutitemhtml.h:125
QgsLayoutItemHtml::setUserStylesheetEnabled
void setUserStylesheetEnabled(bool enabled)
Sets whether user stylesheets are enabled for the HTML content.
Definition: qgslayoutitemhtml.cpp:444
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
QgsLayoutItemHtml::render
void render(QgsLayoutItemRenderContext &context, const QRectF &renderExtent, int frameIndex) override
Renders a portion of the multiframe's content into a render context.
Definition: qgslayoutitemhtml.cpp:304
QgsLayoutItemHtml::setUseSmartBreaks
void setUseSmartBreaks(bool useSmartBreaks)
Sets whether the html item should use smart breaks.
Definition: qgslayoutitemhtml.cpp:421
QgsReadWriteContext
Definition: qgsreadwritecontext.h:34
qgsexpression.h
qgswebframe.h
QgsLayoutItemHtml::setHtml
void setHtml(const QString &html)
Sets the html to display in the item when the item is using the QgsLayoutItemHtml::ManualHtml mode.
Definition: qgslayoutitemhtml.cpp:110
QWebSettings
The QWebSettings class is a collection of stubs to mimic the API of a QWebSettings on systems where Q...
Definition: qgswebpage.h:42
QgsLayoutItemRenderContext
Definition: qgslayoutitem.h:44
QgsLayoutItemHtml
Definition: qgslayoutitemhtml.h:36
QgsLayoutObject::mDataDefinedProperties
QgsPropertyCollection mDataDefinedProperties
Definition: qgslayoutobject.h:337
QgsLayoutItemHtml::totalSize
QSizeF totalSize() const override
Returns the total size of the multiframe's content, in layout units.
Definition: qgslayoutitemhtml.cpp:299
QgsLayoutItemHtml::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets multiframe state from a DOM element.
Definition: qgslayoutitemhtml.cpp:472
QgsLayoutItemHtml::QgsLayoutItemHtml
QgsLayoutItemHtml(QgsLayout *layout)
Constructor for QgsLayoutItemHtml, with the specified parent layout.
Definition: qgslayoutitemhtml.cpp:40
QgsLayoutItemHtml::refreshDataDefinedProperty
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties) override
Definition: qgslayoutitemhtml.cpp:550
QgsLayoutItemHtml::setUserStylesheet
void setUserStylesheet(const QString &stylesheet)
Sets the user stylesheet CSS rules to use while rendering the HTML content.
Definition: qgslayoutitemhtml.cpp:435
QgsLayoutItemHtml::icon
QIcon icon() const override
Returns the item's icon.
Definition: qgslayoutitemhtml.cpp:88
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsLayoutMultiFrame
Definition: qgslayoutmultiframe.h:48
qgsmapsettings.h
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:317
QgsLayoutItemHtml::setUrl
void setUrl(const QUrl &url)
Sets the url for content to display in the item when the item is using the QgsLayoutItemHtml::Url mod...
Definition: qgslayoutitemhtml.cpp:98
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsLayoutMultiFrame::mFrameItems
QList< QgsLayoutFrame * > mFrameItems
Definition: qgslayoutmultiframe.h:408
qgslayoutframe.h
qgswebpage.h
QgsDistanceArea::setEllipsoid
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Definition: qgsdistancearea.cpp:66
QgsLayoutItemHtml::loadHtml
void loadHtml(bool useCache=false, const QgsExpressionContext *context=nullptr)
Reloads the html source from the url and redraws the item.
Definition: qgslayoutitemhtml.cpp:126
QgsLayoutItemHtml::ContentMode
ContentMode
Source modes for the HTML content to render in the item.
Definition: qgslayoutitemhtml.h:43
QgsLayoutObject::AllProperties
@ AllProperties
All properties for item.
Definition: qgslayoutobject.h:135
QgsNetworkContentFetcher
HTTP network content fetcher. A simple method for fetching remote HTTP content and converting the con...
Definition: qgsnetworkcontentfetcher.h:37
QgsLayoutFrame
Definition: qgslayoutframe.h:31
QgsFeature::isValid
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
QgsNetworkContentFetcher::fetchContent
void fetchContent(const QUrl &url, const QString &authcfg=QString())
Fetches content from a remote URL and handles redirects.
Definition: qgsnetworkcontentfetcher.cpp:40
QgsLayoutItemHtml::maxBreakDistance
double maxBreakDistance() const
Returns the maximum distance allowed when calculating where to place page breaks in the html.
Definition: qgslayoutitemhtml.h:170
qgsnetworkaccessmanager.h
candidateSort
bool candidateSort(QPair< int, int > c1, QPair< int, int > c2)
Definition: qgslayoutitemhtml.cpp:328
QgsLayoutItemHtml::useSmartBreaks
bool useSmartBreaks() const
Returns whether html item is using smart breaks.
Definition: qgslayoutitemhtml.h:141
QgsNetworkContentFetcher::reply
QNetworkReply * reply()
Returns a reference to the network reply.
Definition: qgsnetworkcontentfetcher.cpp:79
QgsLayoutItemHtml::setEvaluateExpressions
void setEvaluateExpressions(bool evaluateExpressions)
Sets whether the html item will evaluate QGIS expressions prior to rendering the HTML content.
Definition: qgslayoutitemhtml.cpp:119
QgsLayoutItemHtml::html
QString html() const
Returns the HTML source displayed in the item if the item is using the QgsLayoutItemHtml::ManualHtml ...
Definition: qgslayoutitemhtml.h:116
QgsLayoutItemHtml::recalculateFrameSizes
void recalculateFrameSizes() override
Recalculates the frame sizes for the current viewport dimensions.
Definition: qgslayoutitemhtml.cpp:239
QgsDistanceArea::setSourceCrs
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
Definition: qgsdistancearea.cpp:60
QgsLayoutMultiFrame::contentsChanged
void contentsChanged()
Emitted when the contents of the multi frame have changed and the frames must be redrawn.
QgsLayoutItemHtml::writePropertiesToElement
bool writePropertiesToElement(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Stores multiframe state within an XML DOM element.
Definition: qgslayoutitemhtml.cpp:459
QgsLayoutReportContext::changed
void changed()
Emitted certain settings in the context is changed, e.g.
qgslayout.h
QgsLayoutItemMap::crs
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Definition: qgslayoutitemmap.cpp:264
QgsNetworkAccessManager::instance
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
Definition: qgsnetworkaccessmanager.cpp:121
QgsAbstractPropertyCollection::valueAsString
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
Definition: qgspropertycollection.cpp:42
qgsvectorlayer.h
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:39
QgsJsonExporter
Handles exporting QgsFeature features to GeoJSON features.
Definition: qgsjsonutils.h:45
QgsLayoutItemRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgslayoutitem.h:72
QgsLayoutItemHtml::ManualHtml
@ ManualHtml
HTML content is manually set for the item.
Definition: qgslayoutitemhtml.h:46
QgsLayoutItemHtml::type
int type() const override
Returns unique multiframe type id.
Definition: qgslayoutitemhtml.cpp:83
QgsLayoutItemHtml::displayName
QString displayName() const override
Returns the multiframe display name.
Definition: qgslayoutitemhtml.cpp:454
QgsLayoutObject::mLayout
QPointer< QgsLayout > mLayout
Definition: qgslayoutobject.h:335
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsLayoutItemHtml::setMaxBreakDistance
void setMaxBreakDistance(double distance)
Sets the maximum distance allowed when calculating where to place page breaks in the html.
Definition: qgslayoutitemhtml.cpp:428
QgsLayoutItemHtml::~QgsLayoutItemHtml
~QgsLayoutItemHtml() override
Definition: qgslayoutitemhtml.cpp:78
QgsNetworkContentFetcher::contentAsString
QString contentAsString() const
Returns the fetched content as a string.
Definition: qgsnetworkcontentfetcher.cpp:89
QgsNetworkContentFetcher::finished
void finished()
Emitted when content has loaded.
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsLayoutItemHtml::url
QUrl url() const
Returns the URL of the content displayed in the item if the item is using the QgsLayoutItemHtml::Url ...
Definition: qgslayoutitemhtml.h:97
qgsdistancearea.h
QgsLayoutMultiFrame::recalculateFrameSizes
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of its component frames.
Definition: qgslayoutmultiframe.cpp:96
QgsFeature
Definition: qgsfeature.h:55
qgsnetworkcontentfetcher.h
QgsLayoutItemRegistry::LayoutHtml
@ LayoutHtml
Html multiframe item.
Definition: qgslayoutitemregistry.h:332
QgsUnitTypes::LayoutMillimeters
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:182
qgsjsonutils.h
qgslogger.h
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:174
QgsLayoutItemHtml::create
static QgsLayoutItemHtml * create(QgsLayout *layout)
Returns a new QgsLayoutItemHtml for the specified parent layout.
Definition: qgslayoutitemhtml.cpp:93
QgsLayoutObject::SourceUrl
@ SourceUrl
Html source url.
Definition: qgslayoutobject.h:183
QgsExpression::replaceExpressionText
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
Definition: qgsexpression.cpp:430
qgsproject.h
QgsLayoutMeasurement
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
Definition: qgslayoutmeasurement.h:33
QgsLayoutMultiFrame::frameCount
int frameCount() const
Returns the number of frames associated with this multiframe.
Definition: qgslayoutmultiframe.h:265
qgslayoutitemhtml.h
QgsLayoutObject::DataDefinedProperty
DataDefinedProperty
Data defined properties for different item types.
Definition: qgslayoutobject.h:132
QgsLayoutItemHtml::findNearbyPageBreak
double findNearbyPageBreak(double yPos) override
Finds the optimal position to break a frame at.
Definition: qgslayoutitemhtml.cpp:340
qgslayoutitemmap.h
qgsmessagelog.h
QgsLayoutItemHtml::Url
@ Url
Using this mode item fetches its content via a url.
Definition: qgslayoutitemhtml.h:45