QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
28 #include <QCoreApplication>
29 #include <QPainter>
30 #include <QWebFrame>
31 #include <QWebPage>
32 #include <QImage>
33 #include <QNetworkReply>
34 
35 QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
36  : QgsComposerMultiFrame( c, createUndoCommands )
37  , mContentMode( QgsComposerHtml::Url )
38  , mWebPage( 0 )
39  , mLoaded( false )
40  , mHtmlUnitsToMM( 1.0 )
41  , mRenderedPage( 0 )
42  , mEvaluateExpressions( true )
43  , mUseSmartBreaks( true )
44  , mMaxBreakDistance( 10 )
45  , mExpressionFeature( 0 )
46  , mExpressionLayer( 0 )
47  , mDistanceArea( 0 )
48  , mEnableUserStylesheet( false )
49  , mFetcher( 0 )
50 {
51  mDistanceArea = new QgsDistanceArea();
52  mHtmlUnitsToMM = htmlUnitsToMM();
53  mWebPage = new QWebPage();
54  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
55  mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
56 
57  //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/
58  QPalette palette = mWebPage->palette();
59  palette.setBrush( QPalette::Base, Qt::transparent );
60  mWebPage->setPalette( palette );
61 
62  mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
63  QObject::connect( mWebPage, SIGNAL( loadFinished( bool ) ), this, SLOT( frameLoaded( bool ) ) );
64  if ( mComposition )
65  {
66  QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
67  }
68 
69  // data defined strings
70  mDataDefinedNames.insert( QgsComposerObject::SourceUrl, QString( "dataDefinedSourceUrl" ) );
71 
73  {
74  //a html item added while atlas preview is enabled needs to have the expression context set,
75  //otherwise fields in the html aren't correctly evaluated until atlas preview feature changes (#9457)
77  }
78 
79  //connect to atlas feature changes
80  //to update the expression context
81  connect( &mComposition->atlasComposition(), SIGNAL( featureChanged( QgsFeature* ) ), this, SLOT( refreshExpressionContext() ) );
82 
83  mFetcher = new QgsNetworkContentFetcher();
84  connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
85 
86 }
87 
89  : QgsComposerMultiFrame( 0, false )
90  , mContentMode( QgsComposerHtml::Url )
91  , mWebPage( 0 )
92  , mLoaded( false )
93  , mHtmlUnitsToMM( 1.0 )
94  , mRenderedPage( 0 )
95  , mUseSmartBreaks( true )
96  , mMaxBreakDistance( 10 )
97  , mExpressionFeature( 0 )
98  , mExpressionLayer( 0 )
99  , mDistanceArea( 0 )
100  , mFetcher( 0 )
101 {
102  mDistanceArea = new QgsDistanceArea();
103  mFetcher = new QgsNetworkContentFetcher();
104  connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
105 }
106 
108 {
109  delete mDistanceArea;
110  delete mWebPage;
111  delete mRenderedPage;
112  mFetcher->deleteLater();
113 }
114 
115 void QgsComposerHtml::setUrl( const QUrl& url )
116 {
117  if ( !mWebPage )
118  {
119  return;
120  }
121 
122  mUrl = url;
123  loadHtml();
124  emit changed();
125 }
126 
127 void QgsComposerHtml::setHtml( const QString html )
128 {
129  mHtml = html;
130  //TODO - this signal should be emitted, but without changing the signal which sets the html
131  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
132  //ways of doing this using QScintilla widgets.
133  //emit changed();
134 }
135 
136 void QgsComposerHtml::setEvaluateExpressions( bool evaluateExpressions )
137 {
138  mEvaluateExpressions = evaluateExpressions;
139  loadHtml();
140  emit changed();
141 }
142 
144 {
145  if ( !mWebPage )
146  {
147  return;
148  }
149 
150  QString loadedHtml;
151  switch ( mContentMode )
152  {
154  {
155 
156  QString currentUrl = mUrl.toString();
157 
158  //data defined url set?
159  QVariant exprVal;
161  {
162  currentUrl = exprVal.toString().trimmed();;
163  QgsDebugMsg( QString( "exprVal Source Url:%1" ).arg( currentUrl ) );
164  }
165  if ( currentUrl.isEmpty() )
166  {
167  return;
168  }
169  if ( currentUrl != mLastFetchedUrl )
170  {
171  loadedHtml = fetchHtml( QUrl( currentUrl ) );
172  mLastFetchedUrl = currentUrl;
173  }
174  else
175  {
176  loadedHtml = mFetchedHtml;
177  }
178 
179  break;
180  }
182  loadedHtml = mHtml;
183  break;
184  }
185 
186  //evaluate expressions
187  if ( mEvaluateExpressions )
188  {
189  loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
190  }
191 
192  mLoaded = false;
193 
194  //reset page size. otherwise viewport size increases but never decreases again
195  mWebPage->setViewportSize( QSize( maxFrameWidth() * mHtmlUnitsToMM, 0 ) );
196 
197  //set html, using the specified url as base if in Url mode
198  mWebPage->mainFrame()->setHtml( loadedHtml, mContentMode == QgsComposerHtml::Url ? QUrl( mActualFetchedUrl ) : QUrl() );
199 
200  //set user stylesheet
201  QWebSettings* settings = mWebPage->settings();
202  if ( mEnableUserStylesheet && ! mUserStylesheet.isEmpty() )
203  {
204  QByteArray ba;
205  ba.append( mUserStylesheet.toUtf8() );
206  QUrl cssFileURL = QUrl( "data:text/css;charset=utf-8;base64," + ba.toBase64() );
207  settings->setUserStyleSheetUrl( cssFileURL );
208  }
209  else
210  {
211  settings->setUserStyleSheetUrl( QUrl() );
212  }
213 
214  while ( !mLoaded )
215  {
216  qApp->processEvents();
217  }
218 
220  //trigger a repaint
221  emit contentsChanged();
222 }
223 
224 void QgsComposerHtml::frameLoaded( bool ok )
225 {
226  Q_UNUSED( ok );
227  mLoaded = true;
228 }
229 
230 double QgsComposerHtml::maxFrameWidth() const
231 {
232  double maxWidth = 0;
233  QList<QgsComposerFrame*>::const_iterator frameIt = mFrameItems.constBegin();
234  for ( ; frameIt != mFrameItems.constEnd(); ++frameIt )
235  {
236  maxWidth = qMax( maxWidth, ( double )(( *frameIt )->boundingRect().width() ) );
237  }
238 
239  return maxWidth;
240 }
241 
243 {
244  if ( frameCount() < 1 ) return;
245 
246  QSize contentsSize = mWebPage->mainFrame()->contentsSize();
247 
248  //find maximum frame width
249  double maxWidth = maxFrameWidth();
250  //set content width to match maximum frame width
251  contentsSize.setWidth( maxWidth * mHtmlUnitsToMM );
252 
253  mWebPage->setViewportSize( contentsSize );
254  mSize.setWidth( contentsSize.width() / mHtmlUnitsToMM );
255  mSize.setHeight( contentsSize.height() / mHtmlUnitsToMM );
256  if ( contentsSize.isValid() )
257  {
258  renderCachedImage();
259  }
261  emit changed();
262 }
263 
264 void QgsComposerHtml::renderCachedImage()
265 {
266  //render page to cache image
267  if ( mRenderedPage )
268  {
269  delete mRenderedPage;
270  }
271  mRenderedPage = new QImage( mWebPage->viewportSize(), QImage::Format_ARGB32 );
272  if ( mRenderedPage->isNull() )
273  {
274  return;
275  }
276  QPainter painter;
277  painter.begin( mRenderedPage );
278  mWebPage->mainFrame()->render( &painter );
279  painter.end();
280 }
281 
282 QString QgsComposerHtml::fetchHtml( 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( const QPair<int, int> &c1, const 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  QRgb pixelColor;
380  QList< QPair<int, int> > candidates;
381  int minRow = qMax( idealPos - maxSearchDistance, 0 );
382  for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
383  {
384  changes = 0;
385  currentColor = qRgba( 0, 0, 0, 0 );
386  //check all pixels in this line
387  for ( int col = 0; col < mRenderedPage->width(); ++col )
388  {
389  //count how many times the pixels change color in this row
390  //eventually, we select a row to break at with the minimum number of color changes
391  //since this is likely a line break, or gap between table cells, etc
392  //but very unlikely to be midway through a text line or picture
393  pixelColor = mRenderedPage->pixel( col, candidateRow );
394  if ( pixelColor != currentColor )
395  {
396  //color has changed
397  currentColor = pixelColor;
398  changes++;
399  }
400  }
401  candidates.append( qMakePair( candidateRow, changes ) );
402  }
403 
404  //sort candidate rows by number of changes ascending, row number descending
405  qSort( candidates.begin(), candidates.end(), candidateSort );
406  //first candidate is now the largest row with smallest number of changes
407 
408  //ok, now take the mid point of the best candidate position
409  //we do this so that the spacing between text lines is likely to be split in half
410  //otherwise the html will be broken immediately above a line of text, which
411  //looks a little messy
412  int maxCandidateRow = candidates[0].first;
413  int minCandidateRow = maxCandidateRow + 1;
414  int minCandidateChanges = candidates[0].second;
415 
416  QList< QPair<int, int> >::iterator it;
417  for ( it = candidates.begin(); it != candidates.end(); ++it )
418  {
419  if (( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
420  {
421  //no longer in a consecutive block of rows of minimum pixel color changes
422  //so return the row mid-way through the block
423  //first converting back to mm
424  return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToMM();
425  }
426  minCandidateRow = ( *it ).first;
427  }
428 
429  //above loop didn't work for some reason
430  //return first candidate converted to mm
431  return candidates[0].first / htmlUnitsToMM();
432 }
433 
434 void QgsComposerHtml::setUseSmartBreaks( bool useSmartBreaks )
435 {
436  mUseSmartBreaks = useSmartBreaks;
438  emit changed();
439 }
440 
441 void QgsComposerHtml::setMaxBreakDistance( double maxBreakDistance )
442 {
443  mMaxBreakDistance = maxBreakDistance;
445  emit changed();
446 }
447 
448 void QgsComposerHtml::setUserStylesheet( const QString stylesheet )
449 {
450  mUserStylesheet = stylesheet;
451  //TODO - this signal should be emitted, but without changing the signal which sets the css
452  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
453  //ways of doing this using QScintilla widgets.
454  //emit changed();
455 }
456 
457 void QgsComposerHtml::setUserStylesheetEnabled( const bool stylesheetEnabled )
458 {
459  if ( mEnableUserStylesheet != stylesheetEnabled )
460  {
461  mEnableUserStylesheet = stylesheetEnabled;
462  loadHtml();
463  emit changed();
464  }
465 }
466 
468 {
469  return tr( "<html frame>" );
470 }
471 
472 bool QgsComposerHtml::writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames ) const
473 {
474  QDomElement htmlElem = doc.createElement( "ComposerHtml" );
475  htmlElem.setAttribute( "contentMode", QString::number(( int ) mContentMode ) );
476  htmlElem.setAttribute( "url", mUrl.toString() );
477  htmlElem.setAttribute( "html", mHtml );
478  htmlElem.setAttribute( "evaluateExpressions", mEvaluateExpressions ? "true" : "false" );
479  htmlElem.setAttribute( "useSmartBreaks", mUseSmartBreaks ? "true" : "false" );
480  htmlElem.setAttribute( "maxBreakDistance", QString::number( mMaxBreakDistance ) );
481  htmlElem.setAttribute( "stylesheet", mUserStylesheet );
482  htmlElem.setAttribute( "stylesheetEnabled", mEnableUserStylesheet ? "true" : "false" );
483 
484  bool state = _writeXML( htmlElem, doc, ignoreFrames );
485  elem.appendChild( htmlElem );
486  return state;
487 }
488 
489 bool QgsComposerHtml::readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames )
490 {
491  if ( !ignoreFrames )
492  {
493  deleteFrames();
494  }
495 
496  //first create the frames
497  if ( !_readXML( itemElem, doc, ignoreFrames ) )
498  {
499  return false;
500  }
501 
502  bool contentModeOK;
503  mContentMode = ( QgsComposerHtml::ContentMode )itemElem.attribute( "contentMode" ).toInt( &contentModeOK );
504  if ( !contentModeOK )
505  {
506  mContentMode = QgsComposerHtml::Url;
507  }
508  mEvaluateExpressions = itemElem.attribute( "evaluateExpressions", "true" ) == "true" ? true : false;
509  mUseSmartBreaks = itemElem.attribute( "useSmartBreaks", "true" ) == "true" ? true : false;
510  mMaxBreakDistance = itemElem.attribute( "maxBreakDistance", "10" ).toDouble();
511  mHtml = itemElem.attribute( "html" );
512  mUserStylesheet = itemElem.attribute( "stylesheet" );
513  mEnableUserStylesheet = itemElem.attribute( "stylesheetEnabled", "false" ) == "true" ? true : false;
514 
515  //finally load the set url
516  QString urlString = itemElem.attribute( "url" );
517  if ( !urlString.isEmpty() )
518  {
519  mUrl = urlString;
520  }
521  loadHtml();
522 
523  //since frames had to be created before, we need to emit a changed signal to refresh the widget
524  emit changed();
525  return true;
526 }
527 
528 void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer )
529 {
530  mExpressionFeature = feature;
531  mExpressionLayer = layer;
532 
533  //setup distance area conversion
534  if ( layer )
535  {
536  mDistanceArea->setSourceCrs( layer->crs().srsid() );
537  }
538  else if ( mComposition )
539  {
540  //set to composition's mapsettings' crs
541  mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
542  }
543  if ( mComposition )
544  {
546  }
547  mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
548 }
549 
551 {
552  QgsVectorLayer * vl = 0;
553  QgsFeature* feature = 0;
554 
556  {
558  }
560  {
562  }
563 
564  setExpressionContext( feature, vl );
565  loadHtml();
566 }
567 
569 {
570  //updates data defined properties and redraws item to match
571  if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
572  {
573  loadHtml();
574  }
576 }
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of it's component frames...
double findNearbyPageBreak(double yPos)
Finds the optimal position to break a frame at.
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
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.
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:113
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
virtual QString displayName() const
Get multiframe display name.
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 (...
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 render(QPainter *p, const QRectF &renderExtent, const int frameIndex)
Renders a portion of the multiframe's content into a painter.
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.
Graphics scene for map printing.
QgsFeature * currentFeature()
Returns the current atlas feature.
Frame item for a composer multiframe item.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties)
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.
void loadHtml()
Reloads the html source from the url and redraws the item.
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.
void recalculateFrameSizes()
Recalculates the frame sizes for the current viewport dimensions.
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
bool writeXML(QDomElement &elem, QDomDocument &doc, bool ignoreFrames=false) const
Stores state information about multiframe in DOM element.
double maxBreakDistance() const
Returns the maximum distance allowed when calculating where to place page breaks in the html...
void addFrame(QgsComposerFrame *frame, bool recalcFrameSizes=true)
Adds a frame to the 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()
access to canonical QgsProject instance
Definition: qgsproject.cpp:362
QSizeF totalSize() const
Returns the total size of the multiframe's content.
const CORE_EXPORT QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:73
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.
Represents a vector layer which manages a vector based data sets.
ContentMode
Source modes for the HTML content to render in the item.
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 changed()
Emitted when the properties of a multi frame have changed, and the GUI item widget must be updated...
bool readXML(const QDomElement &itemElem, const QDomDocument &doc, bool ignoreFrames=false)
Reads multiframe state information from a DOM element.
#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...