QGIS API Documentation  2.99.0-Master (b8fd1fd)
qgscomposerhtml.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerhtml.cpp
3  ------------------------------------------------------------
4  begin : July 2012
5  copyright : (C) 2012 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
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 "qgscomposerhtml.h"
17 #include "qgscomposerframe.h"
18 #include "qgscomposition.h"
21 #include "qgsmessagelog.h"
22 #include "qgsexpression.h"
23 #include "qgslogger.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsproject.h"
27 #include "qgsdistancearea.h"
28 #include "qgsjsonutils.h"
29 #include "qgsmapsettings.h"
30 #include "qgscomposermap.h"
31 
32 #include "qgswebpage.h"
33 #include "qgswebframe.h"
34 
35 #include <QCoreApplication>
36 #include <QPainter>
37 #include <QImage>
38 #include <QNetworkReply>
39 
40 QgsComposerHtml::QgsComposerHtml( QgsComposition *c, bool createUndoCommands )
41  : QgsComposerMultiFrame( c, createUndoCommands )
42  , mContentMode( QgsComposerHtml::Url )
43  , mWebPage( nullptr )
44  , mLoaded( false )
45  , mHtmlUnitsToMM( 1.0 )
46  , mRenderedPage( nullptr )
47  , mEvaluateExpressions( true )
48  , mUseSmartBreaks( true )
49  , mMaxBreakDistance( 10 )
50  , mExpressionLayer( nullptr )
51  , mDistanceArea( nullptr )
52  , mEnableUserStylesheet( false )
53  , mFetcher( nullptr )
54 {
55  mDistanceArea = new QgsDistanceArea();
56  mHtmlUnitsToMM = htmlUnitsToMM();
57  mWebPage = new QgsWebPage();
58  mWebPage->setIdentifier( tr( "Composer HTML item" ) );
59  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
60  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
61 
62  //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/
63  QPalette palette = mWebPage->palette();
64  palette.setBrush( QPalette::Base, Qt::transparent );
65  mWebPage->setPalette( palette );
66 
67  mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
68  connect( mWebPage, &QWebPage::loadFinished, this, &QgsComposerHtml::frameLoaded );
69  if ( mComposition )
70  {
72  }
73 
75  {
76  //a html item added while atlas preview is enabled needs to have the expression context set,
77  //otherwise fields in the html aren't correctly evaluated until atlas preview feature changes (#9457)
79  }
80 
81  //connect to atlas feature changes
82  //to update the expression context
84 
85  mFetcher = new QgsNetworkContentFetcher();
86  connect( mFetcher, &QgsNetworkContentFetcher::finished, this, [ = ] { frameLoaded(); } );
87 
88 }
89 
91 {
92  delete mDistanceArea;
93  delete mWebPage;
94  delete mRenderedPage;
95  mFetcher->deleteLater();
96 }
97 
98 void QgsComposerHtml::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 QgsComposerHtml::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 
120 {
121  mEvaluateExpressions = evaluateExpressions;
122  loadHtml( true );
123  emit changed();
124 }
125 
126 void QgsComposerHtml::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( QgsComposerObject::SourceUrl, *evalContext, currentUrl, &ok );
147  if ( ok )
148  {
149  currentUrl = currentUrl.trimmed();
150  QgsDebugMsg( QString( "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  mLoaded = false;
180 
181  //reset page size. otherwise viewport size increases but never decreases again
182  mWebPage->setViewportSize( QSize( maxFrameWidth() * mHtmlUnitsToMM, 0 ) );
183 
184  //set html, using the specified url as base if in Url mode or the project file if in manual mode
185  const QUrl baseUrl = mContentMode == QgsComposerHtml::Url ?
186  QUrl( mActualFetchedUrl ) :
187  QUrl::fromLocalFile( mComposition->project()->fileInfo().absoluteFilePath() );
188  mWebPage->mainFrame()->setHtml( loadedHtml, baseUrl );
189 
190  //set user stylesheet
191  QWebSettings *settings = mWebPage->settings();
192  if ( mEnableUserStylesheet && ! mUserStylesheet.isEmpty() )
193  {
194  QByteArray ba;
195  ba.append( mUserStylesheet.toUtf8() );
196  QUrl cssFileURL = QUrl( "data:text/css;charset=utf-8;base64," + ba.toBase64() );
197  settings->setUserStyleSheetUrl( cssFileURL );
198  }
199  else
200  {
201  settings->setUserStyleSheetUrl( QUrl() );
202  }
203 
204  while ( !mLoaded )
205  {
206  qApp->processEvents();
207  }
208 
209  //inject JSON feature
210  if ( !mAtlasFeatureJSON.isEmpty() )
211  {
212  mWebPage->mainFrame()->evaluateJavaScript( QStringLiteral( "if ( typeof setFeature === \"function\" ) { setFeature(%1); }" ).arg( mAtlasFeatureJSON ) );
213  //needs an extra process events here to give javascript a chance to execute
214  qApp->processEvents();
215  }
216 
218  //trigger a repaint
219  emit contentsChanged();
220 }
221 
222 void QgsComposerHtml::frameLoaded( bool ok )
223 {
224  Q_UNUSED( ok );
225  mLoaded = true;
226 }
227 
228 double QgsComposerHtml::maxFrameWidth() const
229 {
230  double maxWidth = 0;
231  QList<QgsComposerFrame *>::const_iterator frameIt = mFrameItems.constBegin();
232  for ( ; frameIt != mFrameItems.constEnd(); ++frameIt )
233  {
234  maxWidth = qMax( maxWidth, static_cast< double >( ( *frameIt )->boundingRect().width() ) );
235  }
236 
237  return maxWidth;
238 }
239 
241 {
242  if ( frameCount() < 1 ) return;
243 
244  QSize contentsSize = mWebPage->mainFrame()->contentsSize();
245 
246  //find maximum frame width
247  double maxWidth = maxFrameWidth();
248  //set content width to match maximum frame width
249  contentsSize.setWidth( maxWidth * mHtmlUnitsToMM );
250 
251  mWebPage->setViewportSize( contentsSize );
252  mSize.setWidth( contentsSize.width() / mHtmlUnitsToMM );
253  mSize.setHeight( contentsSize.height() / mHtmlUnitsToMM );
254  if ( contentsSize.isValid() )
255  {
256  renderCachedImage();
257  }
259  emit changed();
260 }
261 
262 void QgsComposerHtml::renderCachedImage()
263 {
264  //render page to cache image
265  if ( mRenderedPage )
266  {
267  delete mRenderedPage;
268  }
269  mRenderedPage = new QImage( mWebPage->viewportSize(), QImage::Format_ARGB32 );
270  if ( mRenderedPage->isNull() )
271  {
272  return;
273  }
274  mRenderedPage->fill( Qt::transparent );
275  QPainter painter;
276  painter.begin( mRenderedPage );
277  mWebPage->mainFrame()->render( &painter );
278  painter.end();
279 }
280 
281 QString QgsComposerHtml::fetchHtml( const QUrl &url )
282 {
283  //pause until HTML fetch
284  mLoaded = false;
285  mFetcher->fetchContent( url );
286 
287  while ( !mLoaded )
288  {
289  qApp->processEvents();
290  }
291 
292  mFetchedHtml = mFetcher->contentAsString();
293  mActualFetchedUrl = mFetcher->reply()->url().toString();
294  return mFetchedHtml;
295 }
296 
298 {
299  return mSize;
300 }
301 
302 void QgsComposerHtml::render( QPainter *p, const QRectF &renderExtent, const int frameIndex )
303 {
304  Q_UNUSED( frameIndex );
305 
306  if ( !mWebPage )
307  {
308  return;
309  }
310 
311  p->save();
312  p->setRenderHint( QPainter::Antialiasing );
313  p->scale( 1.0 / mHtmlUnitsToMM, 1.0 / mHtmlUnitsToMM );
314  p->translate( 0.0, -renderExtent.top() * mHtmlUnitsToMM );
315  mWebPage->mainFrame()->render( p, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToMM, renderExtent.width() * mHtmlUnitsToMM, renderExtent.height() * mHtmlUnitsToMM ) );
316  p->restore();
317 }
318 
319 double QgsComposerHtml::htmlUnitsToMM()
320 {
321  if ( !mComposition )
322  {
323  return 1.0;
324  }
325 
326  return ( mComposition->printResolution() / 72.0 ); //webkit seems to assume a standard dpi of 96
327 }
328 
329 void QgsComposerHtml::addFrame( QgsComposerFrame *frame, bool recalcFrameSizes )
330 {
331  mFrameItems.push_back( frame );
333  if ( mComposition )
334  {
335  mComposition->addComposerHtmlFrame( this, frame );
336  }
337 
338  if ( recalcFrameSizes )
339  {
341  }
342 }
343 
344 bool candidateSort( QPair<int, int> c1, QPair<int, int> c2 )
345 {
346  if ( c1.second < c2.second )
347  return true;
348  else if ( c1.second > c2.second )
349  return false;
350  else if ( c1.first > c2.first )
351  return true;
352  else
353  return false;
354 }
355 
357 {
358  if ( !mWebPage || !mRenderedPage || !mUseSmartBreaks )
359  {
360  return yPos;
361  }
362 
363  //convert yPos to pixels
364  int idealPos = yPos * htmlUnitsToMM();
365 
366  //if ideal break pos is past end of page, there's nothing we need to do
367  if ( idealPos >= mRenderedPage->height() )
368  {
369  return yPos;
370  }
371 
372  int maxSearchDistance = mMaxBreakDistance * htmlUnitsToMM();
373 
374  //loop through all lines just before ideal break location, up to max distance
375  //of maxSearchDistance
376  int changes = 0;
377  QRgb currentColor;
378  bool currentPixelTransparent = false;
379  bool previousPixelTransparent = false;
380  QRgb pixelColor;
381  QList< QPair<int, int> > candidates;
382  int minRow = qMax( idealPos - maxSearchDistance, 0 );
383  for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
384  {
385  changes = 0;
386  currentColor = qRgba( 0, 0, 0, 0 );
387  //check all pixels in this line
388  for ( int col = 0; col < mRenderedPage->width(); ++col )
389  {
390  //count how many times the pixels change color in this row
391  //eventually, we select a row to break at with the minimum number of color changes
392  //since this is likely a line break, or gap between table cells, etc
393  //but very unlikely to be midway through a text line or picture
394  pixelColor = mRenderedPage->pixel( col, candidateRow );
395  currentPixelTransparent = qAlpha( pixelColor ) == 0;
396  if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) )
397  {
398  //color has changed
399  currentColor = pixelColor;
400  changes++;
401  }
402  previousPixelTransparent = currentPixelTransparent;
403  }
404  candidates.append( qMakePair( candidateRow, changes ) );
405  }
406 
407  //sort candidate rows by number of changes ascending, row number descending
408  std::sort( candidates.begin(), candidates.end(), candidateSort );
409  //first candidate is now the largest row with smallest number of changes
410 
411  //ok, now take the mid point of the best candidate position
412  //we do this so that the spacing between text lines is likely to be split in half
413  //otherwise the html will be broken immediately above a line of text, which
414  //looks a little messy
415  int maxCandidateRow = candidates[0].first;
416  int minCandidateRow = maxCandidateRow + 1;
417  int minCandidateChanges = candidates[0].second;
418 
419  QList< QPair<int, int> >::iterator it;
420  for ( it = candidates.begin(); it != candidates.end(); ++it )
421  {
422  if ( ( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
423  {
424  //no longer in a consecutive block of rows of minimum pixel color changes
425  //so return the row mid-way through the block
426  //first converting back to mm
427  return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToMM();
428  }
429  minCandidateRow = ( *it ).first;
430  }
431 
432  //above loop didn't work for some reason
433  //return first candidate converted to mm
434  return candidates[0].first / htmlUnitsToMM();
435 }
436 
438 {
439  mUseSmartBreaks = useSmartBreaks;
441  emit changed();
442 }
443 
445 {
446  mMaxBreakDistance = maxBreakDistance;
448  emit changed();
449 }
450 
451 void QgsComposerHtml::setUserStylesheet( const QString &stylesheet )
452 {
453  mUserStylesheet = stylesheet;
454  //TODO - this signal should be emitted, but without changing the signal which sets the css
455  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
456  //ways of doing this using QScintilla widgets.
457  //emit changed();
458 }
459 
460 void QgsComposerHtml::setUserStylesheetEnabled( const bool stylesheetEnabled )
461 {
462  if ( mEnableUserStylesheet != stylesheetEnabled )
463  {
464  mEnableUserStylesheet = stylesheetEnabled;
465  loadHtml( true );
466  emit changed();
467  }
468 }
469 
471 {
472  return tr( "<HTML frame>" );
473 }
474 
475 bool QgsComposerHtml::writeXml( QDomElement &elem, QDomDocument &doc, bool ignoreFrames ) const
476 {
477  QDomElement htmlElem = doc.createElement( QStringLiteral( "ComposerHtml" ) );
478  htmlElem.setAttribute( QStringLiteral( "contentMode" ), QString::number( static_cast< int >( mContentMode ) ) );
479  htmlElem.setAttribute( QStringLiteral( "url" ), mUrl.toString() );
480  htmlElem.setAttribute( QStringLiteral( "html" ), mHtml );
481  htmlElem.setAttribute( QStringLiteral( "evaluateExpressions" ), mEvaluateExpressions ? "true" : "false" );
482  htmlElem.setAttribute( QStringLiteral( "useSmartBreaks" ), mUseSmartBreaks ? "true" : "false" );
483  htmlElem.setAttribute( QStringLiteral( "maxBreakDistance" ), QString::number( mMaxBreakDistance ) );
484  htmlElem.setAttribute( QStringLiteral( "stylesheet" ), mUserStylesheet );
485  htmlElem.setAttribute( QStringLiteral( "stylesheetEnabled" ), mEnableUserStylesheet ? "true" : "false" );
486 
487  bool state = _writeXml( htmlElem, doc, ignoreFrames );
488  elem.appendChild( htmlElem );
489  return state;
490 }
491 
492 bool QgsComposerHtml::readXml( const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames )
493 {
494  if ( !ignoreFrames )
495  {
496  deleteFrames();
497  }
498 
499  //first create the frames
500  if ( !_readXml( itemElem, doc, ignoreFrames ) )
501  {
502  return false;
503  }
504 
505  bool contentModeOK;
506  mContentMode = static_cast< QgsComposerHtml::ContentMode >( itemElem.attribute( QStringLiteral( "contentMode" ) ).toInt( &contentModeOK ) );
507  if ( !contentModeOK )
508  {
509  mContentMode = QgsComposerHtml::Url;
510  }
511  mEvaluateExpressions = itemElem.attribute( QStringLiteral( "evaluateExpressions" ), QStringLiteral( "true" ) ) == QLatin1String( "true" );
512  mUseSmartBreaks = itemElem.attribute( QStringLiteral( "useSmartBreaks" ), QStringLiteral( "true" ) ) == QLatin1String( "true" );
513  mMaxBreakDistance = itemElem.attribute( QStringLiteral( "maxBreakDistance" ), QStringLiteral( "10" ) ).toDouble();
514  mHtml = itemElem.attribute( QStringLiteral( "html" ) );
515  mUserStylesheet = itemElem.attribute( QStringLiteral( "stylesheet" ) );
516  mEnableUserStylesheet = itemElem.attribute( QStringLiteral( "stylesheetEnabled" ), QStringLiteral( "false" ) ) == QLatin1String( "true" );
517 
518  //finally load the set url
519  QString urlString = itemElem.attribute( QStringLiteral( "url" ) );
520  if ( !urlString.isEmpty() )
521  {
522  mUrl = urlString;
523  }
524  loadHtml( true );
525 
526  //since frames had to be created before, we need to emit a changed signal to refresh the widget
527  emit changed();
528  return true;
529 }
530 
531 void QgsComposerHtml::setExpressionContext( const QgsFeature &feature, QgsVectorLayer *layer )
532 {
533  mExpressionFeature = feature;
534  mExpressionLayer = layer;
535 
536  //setup distance area conversion
537  if ( layer )
538  {
539  mDistanceArea->setSourceCrs( layer->crs().srsid() );
540  }
541  else if ( mComposition )
542  {
543  //set to composition's mapsettings' crs
544  QgsComposerMap *referenceMap = mComposition->referenceMap();
545  if ( referenceMap )
546  mDistanceArea->setSourceCrs( referenceMap->crs().srsid() );
547  }
548  if ( mComposition )
549  {
550  mDistanceArea->setEllipsoidalMode( true );
551  mDistanceArea->setEllipsoid( mComposition->project()->ellipsoid() );
552  }
553 
554  // create JSON representation of feature
555  QgsJSONExporter exporter( layer );
556  exporter.setIncludeRelated( true );
557  mAtlasFeatureJSON = exporter.exportFeature( feature );
558 }
559 
561 {
562  QgsVectorLayer *vl = nullptr;
563  QgsFeature feature;
564 
566  {
568  }
570  {
571  feature = mComposition->atlasComposition().feature();
572  }
573 
574  setExpressionContext( feature, vl );
575  loadHtml( true );
576 }
577 
579 {
581  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
582 
583 
584  //updates data defined properties and redraws item to match
585  if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
586  {
587  loadHtml( true, evalContext );
588  }
590 }
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of it&#39;s component frames...
virtual QgsExpressionContext createExpressionContext() const
Creates an expression context relating to the objects&#39; current state.
void setIdentifier(const QString &identifier)
Sets an identifier for the QgsWebPage.
Definition: qgswebpage.h:227
HTML content is manually set for the item.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
virtual QString displayName() const override
Get multiframe display name.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
int printResolution() const
The QWebSettings class is a collection of stubs to mimic the API of a QWebSettings on systems where Q...
Definition: qgswebpage.h:39
virtual void refreshDataDefinedProperty(const DataDefinedProperty property=AllProperties, const QgsExpressionContext *context=nullptr)
Refreshes a data defined property for the item by reevaluating the property&#39;s value and redrawing the...
QUrl url() const
Returns the URL of the content displayed in the item if the item is using the QgsComposerHtml::Url mo...
bool writeXml(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const override
Stores state information about multiframe in DOM element.
Using this mode item fetches its content via a url.
QgsComposerHtml(QgsComposition *c, bool createUndoCommands)
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...
Definition: qgsfeature.h:136
double maxBreakDistance() const
Returns the maximum distance allowed when calculating where to place page breaks in the html...
void setIncludeRelated(bool includeRelated)
Sets whether to include attributes of features linked via references in the JSON exports.
Definition: qgsjsonutils.h:88
QString contentAsString() const
Returns the fetched content as a string.
Handles exporting QgsFeature features to GeoJSON features.
Definition: qgsjsonutils.h:37
QgsComposition::AtlasMode atlasMode() const
Returns the current atlas mode of the composition.
DataDefinedProperty
Data defined properties for different item types.
QSizeF totalSize() const override
Returns the total size of the multiframe&#39;s content.
void loadHtml(const bool useCache=false, const QgsExpressionContext *context=nullptr)
Reloads the html source from the url and redraws the item.
void setHtml(const QString &html)
Sets the HTML to display in the item when the item is using the QgsComposerHtml::ManualHtml mode...
HTTP network content fetcher.
bool _readXml(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false)
Restores state information about base multiframe object from a DOM element.
void itemRemoved(QgsComposerItem *)
Is emitted when a composer item has been removed from the scene.
QgsComposerMap * referenceMap() const
Returns the map item which will be used to generate corresponding world files when the composition is...
bool useSmartBreaks() const
Returns whether html item is using smart breaks.
void recalculateFrameSizes() override
Recalculates the frame sizes for the current viewport dimensions.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
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.
void setMaxBreakDistance(double maxBreakDistance)
Sets the maximum distance allowed when calculating where to place page breaks in the html...
void finished()
Emitted when content has loaded.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
QgsPropertyCollection mDataDefinedProperties
void setUseSmartBreaks(bool useSmartBreaks)
Sets whether the html item should use smart breaks.
bool evaluateExpressions() const
Returns whether html item will evaluate QGIS expressions prior to rendering the HTML content...
QString html() const
Returns the HTML source displayed in the item if the item is using the QgsComposerHtml::ManualHtml mo...
Graphics scene for map printing.
bool readXml(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false) override
Reads multiframe state information from a DOM element.
Object representing map window.
Frame item for a composer multiframe item.
void featureChanged(QgsFeature *feature)
Is emitted when the current atlas feature changes.
bool _writeXml(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const
Stores state information about base multiframe object in DOM element.
General purpose distance and area calculator.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties, const QgsExpressionContext *context=nullptr) override
QgsComposition * mComposition
void deleteFrames()
Removes and deletes all child frames.
void setUserStylesheet(const QString &stylesheet)
Sets the user stylesheet CSS rules to use while rendering the HTML content.
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...
void refreshExpressionContext()
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
QFileInfo fileInfo() const
Returns QFileInfo object for the project&#39;s associated file.
Definition: qgsproject.cpp:417
void contentsChanged()
Emitted when the contents of the multi frame have changed and the frames must be redrawn.
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
int frameCount() const
Returns the number of frames associated with this multiframe.
QgsProject * project() const
The project associated with the composition.
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...
void sizeChanged()
Emitted if the rectangle changes.
QList< QgsComposerFrame * > mFrameItems
bool candidateSort(QPair< int, int > c1, QPair< int, int > c2)
int frameIndex(QgsComposerFrame *frame) const
Returns the index of a frame within the multiframe.
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
QgsAtlasComposition & atlasComposition()
QgsFeature feature() const
Returns the current atlas feature.
QString ellipsoid() const
Returns a proj string representing the project&#39;s ellipsoid setting, e.g., "WGS84".
Definition: qgsproject.cpp:438
void setUserStylesheetEnabled(const bool stylesheetEnabled)
Sets whether user stylesheets are enabled for the HTML content.
long srsid() const
Returns the internal CRS ID, if available.
void fetchContent(const QUrl &url)
Fetches content from a remote URL and handles redirects.
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.
QgsComposerFrame * frame(int i) const
Returns a child frame from the multiframe.
QString exportFeature(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant()) const
Returns a GeoJSON string representation of a feature.
void handleFrameRemoval(QgsComposerItem *item)
Called before a frame is going to be removed.
QWebPage subclass which redirects JavaScript errors and console output to the QGIS message log...
Definition: qgswebpage.h:208
bool enabled() const
Returns whether the atlas generation is enabled.
void setEllipsoidalMode(bool flag)
Sets whether coordinates must be projected to ellipsoid before measuring.
All properties for item.
void render(QPainter *p, const QRectF &renderExtent, const int frameIndex) override
Renders a portion of the multiframe&#39;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 QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...