QGIS API Documentation  2.9.0-Master
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 
29 #include "qgswebpage.h"
30 #include "qgswebframe.h"
31 
32 #include <QCoreApplication>
33 #include <QPainter>
34 #include <QImage>
35 #include <QNetworkReply>
36 
37 QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
38  : QgsComposerMultiFrame( c, createUndoCommands )
39  , mContentMode( QgsComposerHtml::Url )
40  , mWebPage( 0 )
41  , mLoaded( false )
42  , mHtmlUnitsToMM( 1.0 )
43  , mRenderedPage( 0 )
44  , mEvaluateExpressions( true )
45  , mUseSmartBreaks( true )
46  , mMaxBreakDistance( 10 )
47  , mExpressionFeature( 0 )
48  , mExpressionLayer( 0 )
49  , mDistanceArea( 0 )
50  , mEnableUserStylesheet( false )
51  , mFetcher( 0 )
52 {
53  mDistanceArea = new QgsDistanceArea();
54  mHtmlUnitsToMM = htmlUnitsToMM();
55  mWebPage = new QWebPage();
56  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
57  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
58 
59  //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/
60  QPalette palette = mWebPage->palette();
61  palette.setBrush( QPalette::Base, Qt::transparent );
62  mWebPage->setPalette( palette );
63 
64  mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
65  QObject::connect( mWebPage, SIGNAL( loadFinished( bool ) ), this, SLOT( frameLoaded( bool ) ) );
66  if ( mComposition )
67  {
68  QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
69  }
70 
71  // data defined strings
72  mDataDefinedNames.insert( QgsComposerObject::SourceUrl, QString( "dataDefinedSourceUrl" ) );
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
83  connect( &mComposition->atlasComposition(), SIGNAL( featureChanged( QgsFeature* ) ), this, SLOT( refreshExpressionContext() ) );
84 
85  mFetcher = new QgsNetworkContentFetcher();
86  connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
87 
88 }
89 
91  : QgsComposerMultiFrame( 0, false )
92  , mContentMode( QgsComposerHtml::Url )
93  , mWebPage( 0 )
94  , mLoaded( false )
95  , mHtmlUnitsToMM( 1.0 )
96  , mRenderedPage( 0 )
97  , mEvaluateExpressions( true )
98  , mUseSmartBreaks( true )
99  , mMaxBreakDistance( 10 )
100  , mExpressionFeature( 0 )
101  , mExpressionLayer( 0 )
102  , mDistanceArea( 0 )
103  , mEnableUserStylesheet( false )
104  , mFetcher( 0 )
105 {
106  mDistanceArea = new QgsDistanceArea();
107  mFetcher = new QgsNetworkContentFetcher();
108  connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
109 }
110 
112 {
113  delete mDistanceArea;
114  delete mWebPage;
115  delete mRenderedPage;
116  mFetcher->deleteLater();
117 }
118 
119 void QgsComposerHtml::setUrl( const QUrl& url )
120 {
121  if ( !mWebPage )
122  {
123  return;
124  }
125 
126  mUrl = url;
127  loadHtml( true );
128  emit changed();
129 }
130 
131 void QgsComposerHtml::setHtml( const QString html )
132 {
133  mHtml = html;
134  //TODO - this signal should be emitted, but without changing the signal which sets the html
135  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
136  //ways of doing this using QScintilla widgets.
137  //emit changed();
138 }
139 
140 void QgsComposerHtml::setEvaluateExpressions( bool evaluateExpressions )
141 {
142  mEvaluateExpressions = evaluateExpressions;
143  loadHtml( true );
144  emit changed();
145 }
146 
147 void QgsComposerHtml::loadHtml( const bool useCache )
148 {
149  if ( !mWebPage )
150  {
151  return;
152  }
153 
154  QString loadedHtml;
155  switch ( mContentMode )
156  {
158  {
159 
160  QString currentUrl = mUrl.toString();
161 
162  //data defined url set?
163  QVariant exprVal;
165  {
166  currentUrl = exprVal.toString().trimmed();;
167  QgsDebugMsg( QString( "exprVal Source Url:%1" ).arg( currentUrl ) );
168  }
169  if ( currentUrl.isEmpty() )
170  {
171  return;
172  }
173  if ( !( useCache && currentUrl == mLastFetchedUrl ) )
174  {
175  loadedHtml = fetchHtml( QUrl( currentUrl ) );
176  mLastFetchedUrl = currentUrl;
177  }
178  else
179  {
180  loadedHtml = mFetchedHtml;
181  }
182 
183  break;
184  }
186  loadedHtml = mHtml;
187  break;
188  }
189 
190  //evaluate expressions
191  if ( mEvaluateExpressions )
192  {
193  loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
194  }
195 
196  mLoaded = false;
197 
198  //reset page size. otherwise viewport size increases but never decreases again
199  mWebPage->setViewportSize( QSize( maxFrameWidth() * mHtmlUnitsToMM, 0 ) );
200 
201  //set html, using the specified url as base if in Url mode
202  mWebPage->mainFrame()->setHtml( loadedHtml, mContentMode == QgsComposerHtml::Url ? QUrl( mActualFetchedUrl ) : QUrl() );
203 
204  //set user stylesheet
205  QWebSettings* settings = mWebPage->settings();
206  if ( mEnableUserStylesheet && ! mUserStylesheet.isEmpty() )
207  {
208  QByteArray ba;
209  ba.append( mUserStylesheet.toUtf8() );
210  QUrl cssFileURL = QUrl( "data:text/css;charset=utf-8;base64," + ba.toBase64() );
211  settings->setUserStyleSheetUrl( cssFileURL );
212  }
213  else
214  {
215  settings->setUserStyleSheetUrl( QUrl() );
216  }
217 
218  while ( !mLoaded )
219  {
220  qApp->processEvents();
221  }
222 
224  //trigger a repaint
225  emit contentsChanged();
226 }
227 
228 void QgsComposerHtml::frameLoaded( bool ok )
229 {
230  Q_UNUSED( ok );
231  mLoaded = true;
232 }
233 
234 double QgsComposerHtml::maxFrameWidth() const
235 {
236  double maxWidth = 0;
237  QList<QgsComposerFrame*>::const_iterator frameIt = mFrameItems.constBegin();
238  for ( ; frameIt != mFrameItems.constEnd(); ++frameIt )
239  {
240  maxWidth = qMax( maxWidth, ( double )(( *frameIt )->boundingRect().width() ) );
241  }
242 
243  return maxWidth;
244 }
245 
247 {
248  if ( frameCount() < 1 ) return;
249 
250  QSize contentsSize = mWebPage->mainFrame()->contentsSize();
251 
252  //find maximum frame width
253  double maxWidth = maxFrameWidth();
254  //set content width to match maximum frame width
255  contentsSize.setWidth( maxWidth * mHtmlUnitsToMM );
256 
257  mWebPage->setViewportSize( contentsSize );
258  mSize.setWidth( contentsSize.width() / mHtmlUnitsToMM );
259  mSize.setHeight( contentsSize.height() / mHtmlUnitsToMM );
260  if ( contentsSize.isValid() )
261  {
262  renderCachedImage();
263  }
265  emit changed();
266 }
267 
268 void QgsComposerHtml::renderCachedImage()
269 {
270  //render page to cache image
271  if ( mRenderedPage )
272  {
273  delete mRenderedPage;
274  }
275  mRenderedPage = new QImage( mWebPage->viewportSize(), QImage::Format_ARGB32 );
276  if ( mRenderedPage->isNull() )
277  {
278  return;
279  }
280  mRenderedPage->fill( Qt::transparent );
281  QPainter painter;
282  painter.begin( mRenderedPage );
283  mWebPage->mainFrame()->render( &painter );
284  painter.end();
285 }
286 
287 QString QgsComposerHtml::fetchHtml( QUrl url )
288 {
289  //pause until HTML fetch
290  mLoaded = false;
291  mFetcher->fetchContent( url );
292 
293  while ( !mLoaded )
294  {
295  qApp->processEvents();
296  }
297 
298  mFetchedHtml = mFetcher->contentAsString();
299  mActualFetchedUrl = mFetcher->reply()->url().toString();
300  return mFetchedHtml;
301 }
302 
304 {
305  return mSize;
306 }
307 
308 void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent, const int frameIndex )
309 {
310  Q_UNUSED( frameIndex );
311 
312  if ( !mWebPage )
313  {
314  return;
315  }
316 
317  p->save();
318  p->setRenderHint( QPainter::Antialiasing );
319  p->scale( 1.0 / mHtmlUnitsToMM, 1.0 / mHtmlUnitsToMM );
320  p->translate( 0.0, -renderExtent.top() * mHtmlUnitsToMM );
321  mWebPage->mainFrame()->render( p, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToMM, renderExtent.width() * mHtmlUnitsToMM, renderExtent.height() * mHtmlUnitsToMM ) );
322  p->restore();
323 }
324 
325 double QgsComposerHtml::htmlUnitsToMM()
326 {
327  if ( !mComposition )
328  {
329  return 1.0;
330  }
331 
332  return ( mComposition->printResolution() / 72.0 ); //webkit seems to assume a standard dpi of 96
333 }
334 
335 void QgsComposerHtml::addFrame( QgsComposerFrame* frame, bool recalcFrameSizes )
336 {
337  mFrameItems.push_back( frame );
338  QObject::connect( frame, SIGNAL( sizeChanged() ), this, SLOT( recalculateFrameSizes() ) );
339  if ( mComposition )
340  {
341  mComposition->addComposerHtmlFrame( this, frame );
342  }
343 
344  if ( recalcFrameSizes )
345  {
347  }
348 }
349 
350 bool candidateSort( const QPair<int, int> &c1, const QPair<int, int> &c2 )
351 {
352  if ( c1.second < c2.second )
353  return true;
354  else if ( c1.second > c2.second )
355  return false;
356  else if ( c1.first > c2.first )
357  return true;
358  else
359  return false;
360 }
361 
363 {
364  if ( !mWebPage || !mRenderedPage || !mUseSmartBreaks )
365  {
366  return yPos;
367  }
368 
369  //convert yPos to pixels
370  int idealPos = yPos * htmlUnitsToMM();
371 
372  //if ideal break pos is past end of page, there's nothing we need to do
373  if ( idealPos >= mRenderedPage->height() )
374  {
375  return yPos;
376  }
377 
378  int maxSearchDistance = mMaxBreakDistance * htmlUnitsToMM();
379 
380  //loop through all lines just before ideal break location, up to max distance
381  //of maxSearchDistance
382  int changes = 0;
383  QRgb currentColor;
384  bool currentPixelTransparent = false;
385  bool previousPixelTransparent = false;
386  QRgb pixelColor;
387  QList< QPair<int, int> > candidates;
388  int minRow = qMax( idealPos - maxSearchDistance, 0 );
389  for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
390  {
391  changes = 0;
392  currentColor = qRgba( 0, 0, 0, 0 );
393  //check all pixels in this line
394  for ( int col = 0; col < mRenderedPage->width(); ++col )
395  {
396  //count how many times the pixels change color in this row
397  //eventually, we select a row to break at with the minimum number of color changes
398  //since this is likely a line break, or gap between table cells, etc
399  //but very unlikely to be midway through a text line or picture
400  pixelColor = mRenderedPage->pixel( col, candidateRow );
401  currentPixelTransparent = qAlpha( pixelColor ) == 0;
402  if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) )
403  {
404  //color has changed
405  currentColor = pixelColor;
406  changes++;
407  }
408  previousPixelTransparent = currentPixelTransparent;
409  }
410  candidates.append( qMakePair( candidateRow, changes ) );
411  }
412 
413  //sort candidate rows by number of changes ascending, row number descending
414  qSort( candidates.begin(), candidates.end(), candidateSort );
415  //first candidate is now the largest row with smallest number of changes
416 
417  //ok, now take the mid point of the best candidate position
418  //we do this so that the spacing between text lines is likely to be split in half
419  //otherwise the html will be broken immediately above a line of text, which
420  //looks a little messy
421  int maxCandidateRow = candidates[0].first;
422  int minCandidateRow = maxCandidateRow + 1;
423  int minCandidateChanges = candidates[0].second;
424 
425  QList< QPair<int, int> >::iterator it;
426  for ( it = candidates.begin(); it != candidates.end(); ++it )
427  {
428  if (( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
429  {
430  //no longer in a consecutive block of rows of minimum pixel color changes
431  //so return the row mid-way through the block
432  //first converting back to mm
433  return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToMM();
434  }
435  minCandidateRow = ( *it ).first;
436  }
437 
438  //above loop didn't work for some reason
439  //return first candidate converted to mm
440  return candidates[0].first / htmlUnitsToMM();
441 }
442 
443 void QgsComposerHtml::setUseSmartBreaks( bool useSmartBreaks )
444 {
445  mUseSmartBreaks = useSmartBreaks;
447  emit changed();
448 }
449 
450 void QgsComposerHtml::setMaxBreakDistance( double maxBreakDistance )
451 {
452  mMaxBreakDistance = maxBreakDistance;
454  emit changed();
455 }
456 
457 void QgsComposerHtml::setUserStylesheet( const QString stylesheet )
458 {
459  mUserStylesheet = stylesheet;
460  //TODO - this signal should be emitted, but without changing the signal which sets the css
461  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
462  //ways of doing this using QScintilla widgets.
463  //emit changed();
464 }
465 
466 void QgsComposerHtml::setUserStylesheetEnabled( const bool stylesheetEnabled )
467 {
468  if ( mEnableUserStylesheet != stylesheetEnabled )
469  {
470  mEnableUserStylesheet = stylesheetEnabled;
471  loadHtml( true );
472  emit changed();
473  }
474 }
475 
477 {
478  return tr( "<html frame>" );
479 }
480 
481 bool QgsComposerHtml::writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames ) const
482 {
483  QDomElement htmlElem = doc.createElement( "ComposerHtml" );
484  htmlElem.setAttribute( "contentMode", QString::number(( int ) mContentMode ) );
485  htmlElem.setAttribute( "url", mUrl.toString() );
486  htmlElem.setAttribute( "html", mHtml );
487  htmlElem.setAttribute( "evaluateExpressions", mEvaluateExpressions ? "true" : "false" );
488  htmlElem.setAttribute( "useSmartBreaks", mUseSmartBreaks ? "true" : "false" );
489  htmlElem.setAttribute( "maxBreakDistance", QString::number( mMaxBreakDistance ) );
490  htmlElem.setAttribute( "stylesheet", mUserStylesheet );
491  htmlElem.setAttribute( "stylesheetEnabled", mEnableUserStylesheet ? "true" : "false" );
492 
493  bool state = _writeXML( htmlElem, doc, ignoreFrames );
494  elem.appendChild( htmlElem );
495  return state;
496 }
497 
498 bool QgsComposerHtml::readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames )
499 {
500  if ( !ignoreFrames )
501  {
502  deleteFrames();
503  }
504 
505  //first create the frames
506  if ( !_readXML( itemElem, doc, ignoreFrames ) )
507  {
508  return false;
509  }
510 
511  bool contentModeOK;
512  mContentMode = ( QgsComposerHtml::ContentMode )itemElem.attribute( "contentMode" ).toInt( &contentModeOK );
513  if ( !contentModeOK )
514  {
515  mContentMode = QgsComposerHtml::Url;
516  }
517  mEvaluateExpressions = itemElem.attribute( "evaluateExpressions", "true" ) == "true" ? true : false;
518  mUseSmartBreaks = itemElem.attribute( "useSmartBreaks", "true" ) == "true" ? true : false;
519  mMaxBreakDistance = itemElem.attribute( "maxBreakDistance", "10" ).toDouble();
520  mHtml = itemElem.attribute( "html" );
521  mUserStylesheet = itemElem.attribute( "stylesheet" );
522  mEnableUserStylesheet = itemElem.attribute( "stylesheetEnabled", "false" ) == "true" ? true : false;
523 
524  //finally load the set url
525  QString urlString = itemElem.attribute( "url" );
526  if ( !urlString.isEmpty() )
527  {
528  mUrl = urlString;
529  }
530  loadHtml( true );
531 
532  //since frames had to be created before, we need to emit a changed signal to refresh the widget
533  emit changed();
534  return true;
535 }
536 
537 void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer )
538 {
539  mExpressionFeature = feature;
540  mExpressionLayer = layer;
541 
542  //setup distance area conversion
543  if ( layer )
544  {
545  mDistanceArea->setSourceCrs( layer->crs().srsid() );
546  }
547  else if ( mComposition )
548  {
549  //set to composition's mapsettings' crs
550  mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
551  }
552  if ( mComposition )
553  {
555  }
556  mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
557 }
558 
560 {
561  QgsVectorLayer * vl = 0;
562  QgsFeature* feature = 0;
563 
565  {
567  }
569  {
571  }
572 
573  setExpressionContext( feature, vl );
574  loadHtml( true );
575 }
576 
578 {
579  //updates data defined properties and redraws item to match
580  if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
581  {
582  loadHtml( true );
583  }
585 }
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of it's component frames...
QgsComposition::AtlasMode atlasMode() const
Returns the current atlas mode of the composition.
QString contentAsString() const
Returns the fetched content as a string.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
bool writeXML(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const override
Stores state information about multiframe in DOM element.
virtual QString displayName() const override
Get multiframe display name.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
void setHtml(const QString html)
Sets the HTML to display in the item when the item is using the QgsComposerHtml::ManualHtml mode...
void setUserStylesheet(const QString stylesheet)
Sets the user stylesheet CSS rules to use while rendering the HTML content.
QMap< QgsComposerObject::DataDefinedProperty, QString > mDataDefinedNames
Map of data defined properties for the item to string name to use when exporting item to xml...
A item that forms part of a map composition.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties) override
The QWebSettings class is a collection of stubs to mimic the API of a QWebSettings on systems where Q...
Definition: qgswebpage.h:36
bool enabled() const
Returns whether the atlas generation is enabled.
void fetchContent(const QUrl url)
Fetches content from a remote URL and handles redirects.
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
QNetworkReply * reply()
Returns a reference to the network reply.
DataDefinedProperty
Data defined properties for different item types.
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:119
QSizeF totalSize() const override
Returns the total size of the multiframe's content.
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:74
bool dataDefinedEvaluate(const QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue)
Evaluate a data defined property and return the calculated value.
bool useSmartBreaks() const
Returns whether html item is using smart breaks.
QString html() const
Returns the HTML source displayed in the item if the item is using the QgsComposerHtml::ManualHtml mo...
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false)
Restores state information about base multiframe object from a DOM element.
HTTP network content fetcher.
int printResolution() const
void recalculateFrameSizes() override
Recalculates the frame sizes for the current viewport dimensions.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
Abstract base class for composer items with the ability to distribute the content to several frames (...
void addFrame(QgsComposerFrame *frame, bool recalcFrameSizes=true) override
Adds a frame to the multiframe.
QList< QgsComposerFrame * > mFrameItems
bool _writeXML(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const
Stores state information about base multiframe object in DOM element.
void setMaxBreakDistance(double maxBreakDistance)
Sets the maximum distance allowed when calculating where to place page breaks in the html...
bool evaluateExpressions() const
Returns whether html item will evaluate QGIS expressions prior to rendering the HTML content...
void setUseSmartBreaks(bool useSmartBreaks)
Sets whether the html item should use smart breaks.
int frameCount() const
Returns the number of frames associated with this multiframe.
void loadHtml(const bool useCache=false)
Reloads the html source from the url and redraws the item.
Graphics scene for map printing.
QgsFeature * currentFeature()
Returns the current atlas feature.
Frame item for a composer multiframe item.
const QUrl & url() const
Returns the URL of the content displayed in the item if the item is using the QgsComposerHtml::Url mo...
General purpose distance and area calculator.
QgsComposition * mComposition
void deleteFrames()
Removes and deletes all child frames.
void refreshExpressionContext()
void contentsChanged()
Emitted when the contents of the multi frame have changed and the frames must be redrawn.
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
double maxBreakDistance() const
Returns the maximum distance allowed when calculating where to place page breaks in the html...
void addComposerHtmlFrame(QgsComposerHtml *html, QgsComposerFrame *frame)
Adds composer html frame and advises composer to create a widget for it (through signal) ...
void setUrl(const QUrl &url)
Sets the URL for content to display in the item when the item is using the QgsComposerHtml::Url mode...
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:351
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
QgsAtlasComposition & atlasComposition()
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
void setUserStylesheetEnabled(const bool stylesheetEnabled)
Sets whether user stylesheets are enabled for the HTML content.
bool readXML(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false) override
Reads multiframe state information from a DOM element.
The QWebPage class is a collection of stubs to mimic the API of a QWebPage on systems where QtWebkit ...
Definition: qgswebpage.h:99
Represents a vector layer which manages a vector based data sets.
ContentMode
Source modes for the HTML content to render in the item.
double findNearbyPageBreak(double yPos) override
Finds the optimal position to break a frame at.
void handleFrameRemoval(QgsComposerItem *item)
Called before a frame is going to be removed.
bool candidateSort(const QPair< int, int > &c1, const QPair< int, int > &c2)
virtual void refreshDataDefinedProperty(const DataDefinedProperty property=AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
void render(QPainter *p, const QRectF &renderExtent, const int frameIndex) override
Renders a portion of the multiframe's content into a painter.
void changed()
Emitted when the properties of a multi frame have changed, and the GUI item widget must be updated...
#define tr(sourceText)
static QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0, const QgsDistanceArea *distanceArea=0)
This function currently replaces each expression between [% and %] in the string with the result of i...