QGIS API Documentation  2.99.0-Master (8ec3eaf)
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 
31 #include "qgswebpage.h"
32 #include "qgswebframe.h"
33 
34 #include <QCoreApplication>
35 #include <QPainter>
36 #include <QImage>
37 #include <QNetworkReply>
38 
39 QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
40  : QgsComposerMultiFrame( c, createUndoCommands )
41  , mContentMode( QgsComposerHtml::Url )
42  , mWebPage( nullptr )
43  , mLoaded( false )
44  , mHtmlUnitsToMM( 1.0 )
45  , mRenderedPage( nullptr )
46  , mEvaluateExpressions( true )
47  , mUseSmartBreaks( true )
48  , mMaxBreakDistance( 10 )
49  , mExpressionLayer( nullptr )
50  , mDistanceArea( nullptr )
51  , mEnableUserStylesheet( false )
52  , mFetcher( nullptr )
53 {
54  mDistanceArea = new QgsDistanceArea();
55  mHtmlUnitsToMM = htmlUnitsToMM();
56  mWebPage = new QgsWebPage();
57  mWebPage->setIdentifier( tr( "Composer 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  QObject::connect( mWebPage, SIGNAL( loadFinished( bool ) ), this, SLOT( frameLoaded( bool ) ) );
68  if ( mComposition )
69  {
70  QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
71  }
72 
73  // data defined strings
74  mDataDefinedNames.insert( QgsComposerObject::SourceUrl, QStringLiteral( "dataDefinedSourceUrl" ) );
75 
77  {
78  //a html item added while atlas preview is enabled needs to have the expression context set,
79  //otherwise fields in the html aren't correctly evaluated until atlas preview feature changes (#9457)
81  }
82 
83  //connect to atlas feature changes
84  //to update the expression context
85  connect( &mComposition->atlasComposition(), SIGNAL( featureChanged( QgsFeature* ) ), this, SLOT( refreshExpressionContext() ) );
86 
87  mFetcher = new QgsNetworkContentFetcher();
88  connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
89 
90 }
91 
93 {
94  delete mDistanceArea;
95  delete mWebPage;
96  delete mRenderedPage;
97  mFetcher->deleteLater();
98 }
99 
100 void QgsComposerHtml::setUrl( const QUrl& url )
101 {
102  if ( !mWebPage )
103  {
104  return;
105  }
106 
107  mUrl = url;
108  loadHtml( true );
109  emit changed();
110 }
111 
112 void QgsComposerHtml::setHtml( const QString& html )
113 {
114  mHtml = html;
115  //TODO - this signal should be emitted, but without changing the signal which sets the html
116  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
117  //ways of doing this using QScintilla widgets.
118  //emit changed();
119 }
120 
122 {
123  mEvaluateExpressions = evaluateExpressions;
124  loadHtml( true );
125  emit changed();
126 }
127 
128 void QgsComposerHtml::loadHtml( const bool useCache, const QgsExpressionContext *context )
129 {
130  if ( !mWebPage )
131  {
132  return;
133  }
134 
136  const QgsExpressionContext* evalContext = context ? context : &scopedContext;
137 
138  QString loadedHtml;
139  switch ( mContentMode )
140  {
142  {
143 
144  QString currentUrl = mUrl.toString();
145 
146  //data defined url set?
147  QVariant exprVal;
148  if ( dataDefinedEvaluate( QgsComposerObject::SourceUrl, exprVal, *evalContext ) )
149  {
150  currentUrl = exprVal.toString().trimmed();
151  QgsDebugMsg( QString( "exprVal Source Url:%1" ).arg( currentUrl ) );
152  }
153  if ( currentUrl.isEmpty() )
154  {
155  return;
156  }
157  if ( !( useCache && currentUrl == mLastFetchedUrl ) )
158  {
159  loadedHtml = fetchHtml( QUrl( currentUrl ) );
160  mLastFetchedUrl = currentUrl;
161  }
162  else
163  {
164  loadedHtml = mFetchedHtml;
165  }
166 
167  break;
168  }
170  loadedHtml = mHtml;
171  break;
172  }
173 
174  //evaluate expressions
175  if ( mEvaluateExpressions )
176  {
177  loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, evalContext, mDistanceArea );
178  }
179 
180  mLoaded = false;
181 
182  //reset page size. otherwise viewport size increases but never decreases again
183  mWebPage->setViewportSize( QSize( maxFrameWidth() * mHtmlUnitsToMM, 0 ) );
184 
185  //set html, using the specified url as base if in Url mode or the project file if in manual mode
186  const QUrl baseUrl = mContentMode == QgsComposerHtml::Url ?
187  QUrl( mActualFetchedUrl ) :
188  QUrl::fromLocalFile( QgsProject::instance()->fileInfo().absoluteFilePath() );
189  mWebPage->mainFrame()->setHtml( loadedHtml, baseUrl );
190 
191  //set user stylesheet
192  QWebSettings* settings = mWebPage->settings();
193  if ( mEnableUserStylesheet && ! mUserStylesheet.isEmpty() )
194  {
195  QByteArray ba;
196  ba.append( mUserStylesheet.toUtf8() );
197  QUrl cssFileURL = QUrl( "data:text/css;charset=utf-8;base64," + ba.toBase64() );
198  settings->setUserStyleSheetUrl( cssFileURL );
199  }
200  else
201  {
202  settings->setUserStyleSheetUrl( QUrl() );
203  }
204 
205  while ( !mLoaded )
206  {
207  qApp->processEvents();
208  }
209 
210  //inject JSON feature
211  if ( !mAtlasFeatureJSON.isEmpty() )
212  {
213  mWebPage->mainFrame()->evaluateJavaScript( QStringLiteral( "if ( typeof setFeature === \"function\" ) { setFeature(%1); }" ).arg( mAtlasFeatureJSON ) );
214  //needs an extra process events here to give javascript a chance to execute
215  qApp->processEvents();
216  }
217 
219  //trigger a repaint
220  emit contentsChanged();
221 }
222 
223 void QgsComposerHtml::frameLoaded( bool ok )
224 {
225  Q_UNUSED( ok );
226  mLoaded = true;
227 }
228 
229 double QgsComposerHtml::maxFrameWidth() const
230 {
231  double maxWidth = 0;
232  QList<QgsComposerFrame*>::const_iterator frameIt = mFrameItems.constBegin();
233  for ( ; frameIt != mFrameItems.constEnd(); ++frameIt )
234  {
235  maxWidth = qMax( maxWidth, static_cast< double >(( *frameIt )->boundingRect().width() ) );
236  }
237 
238  return maxWidth;
239 }
240 
242 {
243  if ( frameCount() < 1 ) return;
244 
245  QSize contentsSize = mWebPage->mainFrame()->contentsSize();
246 
247  //find maximum frame width
248  double maxWidth = maxFrameWidth();
249  //set content width to match maximum frame width
250  contentsSize.setWidth( maxWidth * mHtmlUnitsToMM );
251 
252  mWebPage->setViewportSize( contentsSize );
253  mSize.setWidth( contentsSize.width() / mHtmlUnitsToMM );
254  mSize.setHeight( contentsSize.height() / mHtmlUnitsToMM );
255  if ( contentsSize.isValid() )
256  {
257  renderCachedImage();
258  }
260  emit changed();
261 }
262 
263 void QgsComposerHtml::renderCachedImage()
264 {
265  //render page to cache image
266  if ( mRenderedPage )
267  {
268  delete mRenderedPage;
269  }
270  mRenderedPage = new QImage( mWebPage->viewportSize(), QImage::Format_ARGB32 );
271  if ( mRenderedPage->isNull() )
272  {
273  return;
274  }
275  mRenderedPage->fill( Qt::transparent );
276  QPainter painter;
277  painter.begin( mRenderedPage );
278  mWebPage->mainFrame()->render( &painter );
279  painter.end();
280 }
281 
282 QString QgsComposerHtml::fetchHtml( const QUrl& url )
283 {
284  //pause until HTML fetch
285  mLoaded = false;
286  mFetcher->fetchContent( url );
287 
288  while ( !mLoaded )
289  {
290  qApp->processEvents();
291  }
292 
293  mFetchedHtml = mFetcher->contentAsString();
294  mActualFetchedUrl = mFetcher->reply()->url().toString();
295  return mFetchedHtml;
296 }
297 
299 {
300  return mSize;
301 }
302 
303 void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent, const int frameIndex )
304 {
305  Q_UNUSED( frameIndex );
306 
307  if ( !mWebPage )
308  {
309  return;
310  }
311 
312  p->save();
313  p->setRenderHint( QPainter::Antialiasing );
314  p->scale( 1.0 / mHtmlUnitsToMM, 1.0 / mHtmlUnitsToMM );
315  p->translate( 0.0, -renderExtent.top() * mHtmlUnitsToMM );
316  mWebPage->mainFrame()->render( p, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToMM, renderExtent.width() * mHtmlUnitsToMM, renderExtent.height() * mHtmlUnitsToMM ) );
317  p->restore();
318 }
319 
320 double QgsComposerHtml::htmlUnitsToMM()
321 {
322  if ( !mComposition )
323  {
324  return 1.0;
325  }
326 
327  return ( mComposition->printResolution() / 72.0 ); //webkit seems to assume a standard dpi of 96
328 }
329 
330 void QgsComposerHtml::addFrame( QgsComposerFrame* frame, bool recalcFrameSizes )
331 {
332  mFrameItems.push_back( frame );
333  QObject::connect( frame, SIGNAL( sizeChanged() ), this, SLOT( recalculateFrameSizes() ) );
334  if ( mComposition )
335  {
336  mComposition->addComposerHtmlFrame( this, frame );
337  }
338 
339  if ( recalcFrameSizes )
340  {
342  }
343 }
344 
345 bool candidateSort( QPair<int, int> c1, QPair<int, int> c2 )
346 {
347  if ( c1.second < c2.second )
348  return true;
349  else if ( c1.second > c2.second )
350  return false;
351  else if ( c1.first > c2.first )
352  return true;
353  else
354  return false;
355 }
356 
358 {
359  if ( !mWebPage || !mRenderedPage || !mUseSmartBreaks )
360  {
361  return yPos;
362  }
363 
364  //convert yPos to pixels
365  int idealPos = yPos * htmlUnitsToMM();
366 
367  //if ideal break pos is past end of page, there's nothing we need to do
368  if ( idealPos >= mRenderedPage->height() )
369  {
370  return yPos;
371  }
372 
373  int maxSearchDistance = mMaxBreakDistance * htmlUnitsToMM();
374 
375  //loop through all lines just before ideal break location, up to max distance
376  //of maxSearchDistance
377  int changes = 0;
378  QRgb currentColor;
379  bool currentPixelTransparent = false;
380  bool previousPixelTransparent = false;
381  QRgb pixelColor;
382  QList< QPair<int, int> > candidates;
383  int minRow = qMax( idealPos - maxSearchDistance, 0 );
384  for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
385  {
386  changes = 0;
387  currentColor = qRgba( 0, 0, 0, 0 );
388  //check all pixels in this line
389  for ( int col = 0; col < mRenderedPage->width(); ++col )
390  {
391  //count how many times the pixels change color in this row
392  //eventually, we select a row to break at with the minimum number of color changes
393  //since this is likely a line break, or gap between table cells, etc
394  //but very unlikely to be midway through a text line or picture
395  pixelColor = mRenderedPage->pixel( col, candidateRow );
396  currentPixelTransparent = qAlpha( pixelColor ) == 0;
397  if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) )
398  {
399  //color has changed
400  currentColor = pixelColor;
401  changes++;
402  }
403  previousPixelTransparent = currentPixelTransparent;
404  }
405  candidates.append( qMakePair( candidateRow, changes ) );
406  }
407 
408  //sort candidate rows by number of changes ascending, row number descending
409  qSort( candidates.begin(), candidates.end(), candidateSort );
410  //first candidate is now the largest row with smallest number of changes
411 
412  //ok, now take the mid point of the best candidate position
413  //we do this so that the spacing between text lines is likely to be split in half
414  //otherwise the html will be broken immediately above a line of text, which
415  //looks a little messy
416  int maxCandidateRow = candidates[0].first;
417  int minCandidateRow = maxCandidateRow + 1;
418  int minCandidateChanges = candidates[0].second;
419 
420  QList< QPair<int, int> >::iterator it;
421  for ( it = candidates.begin(); it != candidates.end(); ++it )
422  {
423  if (( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
424  {
425  //no longer in a consecutive block of rows of minimum pixel color changes
426  //so return the row mid-way through the block
427  //first converting back to mm
428  return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToMM();
429  }
430  minCandidateRow = ( *it ).first;
431  }
432 
433  //above loop didn't work for some reason
434  //return first candidate converted to mm
435  return candidates[0].first / htmlUnitsToMM();
436 }
437 
439 {
440  mUseSmartBreaks = useSmartBreaks;
442  emit changed();
443 }
444 
446 {
447  mMaxBreakDistance = maxBreakDistance;
449  emit changed();
450 }
451 
452 void QgsComposerHtml::setUserStylesheet( const QString& stylesheet )
453 {
454  mUserStylesheet = stylesheet;
455  //TODO - this signal should be emitted, but without changing the signal which sets the css
456  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
457  //ways of doing this using QScintilla widgets.
458  //emit changed();
459 }
460 
461 void QgsComposerHtml::setUserStylesheetEnabled( const bool stylesheetEnabled )
462 {
463  if ( mEnableUserStylesheet != stylesheetEnabled )
464  {
465  mEnableUserStylesheet = stylesheetEnabled;
466  loadHtml( true );
467  emit changed();
468  }
469 }
470 
472 {
473  return tr( "<HTML frame>" );
474 }
475 
476 bool QgsComposerHtml::writeXml( QDomElement& elem, QDomDocument & doc, bool ignoreFrames ) const
477 {
478  QDomElement htmlElem = doc.createElement( QStringLiteral( "ComposerHtml" ) );
479  htmlElem.setAttribute( QStringLiteral( "contentMode" ), QString::number( static_cast< int >( mContentMode ) ) );
480  htmlElem.setAttribute( QStringLiteral( "url" ), mUrl.toString() );
481  htmlElem.setAttribute( QStringLiteral( "html" ), mHtml );
482  htmlElem.setAttribute( QStringLiteral( "evaluateExpressions" ), mEvaluateExpressions ? "true" : "false" );
483  htmlElem.setAttribute( QStringLiteral( "useSmartBreaks" ), mUseSmartBreaks ? "true" : "false" );
484  htmlElem.setAttribute( QStringLiteral( "maxBreakDistance" ), QString::number( mMaxBreakDistance ) );
485  htmlElem.setAttribute( QStringLiteral( "stylesheet" ), mUserStylesheet );
486  htmlElem.setAttribute( QStringLiteral( "stylesheetEnabled" ), mEnableUserStylesheet ? "true" : "false" );
487 
488  bool state = _writeXml( htmlElem, doc, ignoreFrames );
489  elem.appendChild( htmlElem );
490  return state;
491 }
492 
493 bool QgsComposerHtml::readXml( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames )
494 {
495  if ( !ignoreFrames )
496  {
497  deleteFrames();
498  }
499 
500  //first create the frames
501  if ( !_readXml( itemElem, doc, ignoreFrames ) )
502  {
503  return false;
504  }
505 
506  bool contentModeOK;
507  mContentMode = static_cast< QgsComposerHtml::ContentMode >( itemElem.attribute( QStringLiteral( "contentMode" ) ).toInt( &contentModeOK ) );
508  if ( !contentModeOK )
509  {
510  mContentMode = QgsComposerHtml::Url;
511  }
512  mEvaluateExpressions = itemElem.attribute( QStringLiteral( "evaluateExpressions" ), QStringLiteral( "true" ) ) == QLatin1String( "true" ) ? true : false;
513  mUseSmartBreaks = itemElem.attribute( QStringLiteral( "useSmartBreaks" ), QStringLiteral( "true" ) ) == QLatin1String( "true" ) ? true : false;
514  mMaxBreakDistance = itemElem.attribute( QStringLiteral( "maxBreakDistance" ), QStringLiteral( "10" ) ).toDouble();
515  mHtml = itemElem.attribute( QStringLiteral( "html" ) );
516  mUserStylesheet = itemElem.attribute( QStringLiteral( "stylesheet" ) );
517  mEnableUserStylesheet = itemElem.attribute( QStringLiteral( "stylesheetEnabled" ), QStringLiteral( "false" ) ) == QLatin1String( "true" ) ? true : false;
518 
519  //finally load the set url
520  QString urlString = itemElem.attribute( QStringLiteral( "url" ) );
521  if ( !urlString.isEmpty() )
522  {
523  mUrl = urlString;
524  }
525  loadHtml( true );
526 
527  //since frames had to be created before, we need to emit a changed signal to refresh the widget
528  emit changed();
529  return true;
530 }
531 
532 void QgsComposerHtml::setExpressionContext( const QgsFeature &feature, QgsVectorLayer* layer )
533 {
534  mExpressionFeature = feature;
535  mExpressionLayer = layer;
536 
537  //setup distance area conversion
538  if ( layer )
539  {
540  mDistanceArea->setSourceCrs( layer->crs().srsid() );
541  }
542  else if ( mComposition )
543  {
544  //set to composition's mapsettings' crs
545  mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
546  }
547  if ( mComposition )
548  {
550  }
551  mDistanceArea->setEllipsoid( QgsProject::instance()->ellipsoid() );
552 
553  // create JSON representation of feature
554  QgsJSONExporter exporter( layer );
555  exporter.setIncludeRelated( true );
556  mAtlasFeatureJSON = exporter.exportFeature( feature );
557 }
558 
560 {
561  QgsVectorLayer * vl = nullptr;
562  QgsFeature feature;
563 
565  {
567  }
569  {
570  feature = mComposition->atlasComposition().feature();
571  }
572 
573  setExpressionContext( feature, vl );
574  loadHtml( true );
575 }
576 
578 {
580  const QgsExpressionContext* evalContext = context ? context : &scopedContext;
581 
582 
583  //updates data defined properties and redraws item to match
584  if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
585  {
586  loadHtml( true, evalContext );
587  }
589 }
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:226
HTML content is manually set for the item.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual QString displayName() const override
Get multiframe display name.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
int printResolution() const
QMap< QgsComposerObject::DataDefinedProperty, QString > mDataDefinedNames
Map of data defined properties for the item to string name to use when exporting item to xml...
A item that forms part of a map composition.
The QWebSettings class is a collection of stubs to mimic the API of a QWebSettings on systems where Q...
Definition: qgswebpage.h:38
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...
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
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:135
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:85
QString contentAsString() const
Returns the fetched content as a string.
Handles exporting QgsFeature features to GeoJSON features.
Definition: qgsjsonutils.h:36
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.
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
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.
const QUrl & url() const
Returns the URL of the content displayed in the item if the item is using the QgsComposerHtml::Url mo...
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.
QList< QgsComposerFrame * > mFrameItems
void setMaxBreakDistance(double maxBreakDistance)
Sets the maximum distance allowed when calculating where to place page breaks in the html...
bool dataDefinedEvaluate(const QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue, const QgsExpressionContext &context=QgsExpressionContext()) const
Evaluate a data defined property and return the calculated value.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
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.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
Frame item for a composer multiframe item.
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.
void refreshExpressionContext()
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.
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()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:348
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.
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:207
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...