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( true );
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( true );
140  emit changed();
141 }
142 
143 void QgsComposerHtml::loadHtml( const bool useCache )
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 ( !( useCache && 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  mRenderedPage->fill( Qt::transparent );
277  QPainter painter;
278  painter.begin( mRenderedPage );
279  mWebPage->mainFrame()->render( &painter );
280  painter.end();
281 }
282 
283 QString QgsComposerHtml::fetchHtml( QUrl url )
284 {
285  //pause until HTML fetch
286  mLoaded = false;
287  mFetcher->fetchContent( url );
288 
289  while ( !mLoaded )
290  {
291  qApp->processEvents();
292  }
293 
294  mFetchedHtml = mFetcher->contentAsString();
295  mActualFetchedUrl = mFetcher->reply()->url().toString();
296  return mFetchedHtml;
297 }
298 
300 {
301  return mSize;
302 }
303 
304 void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent, const int frameIndex )
305 {
306  Q_UNUSED( frameIndex );
307 
308  if ( !mWebPage )
309  {
310  return;
311  }
312 
313  p->save();
314  p->setRenderHint( QPainter::Antialiasing );
315  p->scale( 1.0 / mHtmlUnitsToMM, 1.0 / mHtmlUnitsToMM );
316  p->translate( 0.0, -renderExtent.top() * mHtmlUnitsToMM );
317  mWebPage->mainFrame()->render( p, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToMM, renderExtent.width() * mHtmlUnitsToMM, renderExtent.height() * mHtmlUnitsToMM ) );
318  p->restore();
319 }
320 
321 double QgsComposerHtml::htmlUnitsToMM()
322 {
323  if ( !mComposition )
324  {
325  return 1.0;
326  }
327 
328  return ( mComposition->printResolution() / 72.0 ); //webkit seems to assume a standard dpi of 96
329 }
330 
331 void QgsComposerHtml::addFrame( QgsComposerFrame* frame, bool recalcFrameSizes )
332 {
333  mFrameItems.push_back( frame );
334  QObject::connect( frame, SIGNAL( sizeChanged() ), this, SLOT( recalculateFrameSizes() ) );
335  if ( mComposition )
336  {
337  mComposition->addComposerHtmlFrame( this, frame );
338  }
339 
340  if ( recalcFrameSizes )
341  {
343  }
344 }
345 
346 bool candidateSort( const QPair<int, int> &c1, const QPair<int, int> &c2 )
347 {
348  if ( c1.second < c2.second )
349  return true;
350  else if ( c1.second > c2.second )
351  return false;
352  else if ( c1.first > c2.first )
353  return true;
354  else
355  return false;
356 }
357 
359 {
360  if ( !mWebPage || !mRenderedPage || !mUseSmartBreaks )
361  {
362  return yPos;
363  }
364 
365  //convert yPos to pixels
366  int idealPos = yPos * htmlUnitsToMM();
367 
368  //if ideal break pos is past end of page, there's nothing we need to do
369  if ( idealPos >= mRenderedPage->height() )
370  {
371  return yPos;
372  }
373 
374  int maxSearchDistance = mMaxBreakDistance * htmlUnitsToMM();
375 
376  //loop through all lines just before ideal break location, up to max distance
377  //of maxSearchDistance
378  int changes = 0;
379  QRgb currentColor;
380  bool currentPixelTransparent = false;
381  bool previousPixelTransparent = false;
382  QRgb pixelColor;
383  QList< QPair<int, int> > candidates;
384  int minRow = qMax( idealPos - maxSearchDistance, 0 );
385  for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow )
386  {
387  changes = 0;
388  currentColor = qRgba( 0, 0, 0, 0 );
389  //check all pixels in this line
390  for ( int col = 0; col < mRenderedPage->width(); ++col )
391  {
392  //count how many times the pixels change color in this row
393  //eventually, we select a row to break at with the minimum number of color changes
394  //since this is likely a line break, or gap between table cells, etc
395  //but very unlikely to be midway through a text line or picture
396  pixelColor = mRenderedPage->pixel( col, candidateRow );
397  currentPixelTransparent = qAlpha( pixelColor ) == 0;
398  if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) )
399  {
400  //color has changed
401  currentColor = pixelColor;
402  changes++;
403  }
404  previousPixelTransparent = currentPixelTransparent;
405  }
406  candidates.append( qMakePair( candidateRow, changes ) );
407  }
408 
409  //sort candidate rows by number of changes ascending, row number descending
410  qSort( candidates.begin(), candidates.end(), candidateSort );
411  //first candidate is now the largest row with smallest number of changes
412 
413  //ok, now take the mid point of the best candidate position
414  //we do this so that the spacing between text lines is likely to be split in half
415  //otherwise the html will be broken immediately above a line of text, which
416  //looks a little messy
417  int maxCandidateRow = candidates[0].first;
418  int minCandidateRow = maxCandidateRow + 1;
419  int minCandidateChanges = candidates[0].second;
420 
421  QList< QPair<int, int> >::iterator it;
422  for ( it = candidates.begin(); it != candidates.end(); ++it )
423  {
424  if (( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 )
425  {
426  //no longer in a consecutive block of rows of minimum pixel color changes
427  //so return the row mid-way through the block
428  //first converting back to mm
429  return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToMM();
430  }
431  minCandidateRow = ( *it ).first;
432  }
433 
434  //above loop didn't work for some reason
435  //return first candidate converted to mm
436  return candidates[0].first / htmlUnitsToMM();
437 }
438 
439 void QgsComposerHtml::setUseSmartBreaks( bool useSmartBreaks )
440 {
441  mUseSmartBreaks = useSmartBreaks;
443  emit changed();
444 }
445 
446 void QgsComposerHtml::setMaxBreakDistance( double maxBreakDistance )
447 {
448  mMaxBreakDistance = maxBreakDistance;
450  emit changed();
451 }
452 
453 void QgsComposerHtml::setUserStylesheet( const QString stylesheet )
454 {
455  mUserStylesheet = stylesheet;
456  //TODO - this signal should be emitted, but without changing the signal which sets the css
457  //to an equivalent of editingFinished it causes a lot of problems. Need to investigate
458  //ways of doing this using QScintilla widgets.
459  //emit changed();
460 }
461 
462 void QgsComposerHtml::setUserStylesheetEnabled( const bool stylesheetEnabled )
463 {
464  if ( mEnableUserStylesheet != stylesheetEnabled )
465  {
466  mEnableUserStylesheet = stylesheetEnabled;
467  loadHtml( true );
468  emit changed();
469  }
470 }
471 
473 {
474  return tr( "<html frame>" );
475 }
476 
477 bool QgsComposerHtml::writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames ) const
478 {
479  QDomElement htmlElem = doc.createElement( "ComposerHtml" );
480  htmlElem.setAttribute( "contentMode", QString::number(( int ) mContentMode ) );
481  htmlElem.setAttribute( "url", mUrl.toString() );
482  htmlElem.setAttribute( "html", mHtml );
483  htmlElem.setAttribute( "evaluateExpressions", mEvaluateExpressions ? "true" : "false" );
484  htmlElem.setAttribute( "useSmartBreaks", mUseSmartBreaks ? "true" : "false" );
485  htmlElem.setAttribute( "maxBreakDistance", QString::number( mMaxBreakDistance ) );
486  htmlElem.setAttribute( "stylesheet", mUserStylesheet );
487  htmlElem.setAttribute( "stylesheetEnabled", mEnableUserStylesheet ? "true" : "false" );
488 
489  bool state = _writeXML( htmlElem, doc, ignoreFrames );
490  elem.appendChild( htmlElem );
491  return state;
492 }
493 
494 bool QgsComposerHtml::readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames )
495 {
496  if ( !ignoreFrames )
497  {
498  deleteFrames();
499  }
500 
501  //first create the frames
502  if ( !_readXML( itemElem, doc, ignoreFrames ) )
503  {
504  return false;
505  }
506 
507  bool contentModeOK;
508  mContentMode = ( QgsComposerHtml::ContentMode )itemElem.attribute( "contentMode" ).toInt( &contentModeOK );
509  if ( !contentModeOK )
510  {
511  mContentMode = QgsComposerHtml::Url;
512  }
513  mEvaluateExpressions = itemElem.attribute( "evaluateExpressions", "true" ) == "true" ? true : false;
514  mUseSmartBreaks = itemElem.attribute( "useSmartBreaks", "true" ) == "true" ? true : false;
515  mMaxBreakDistance = itemElem.attribute( "maxBreakDistance", "10" ).toDouble();
516  mHtml = itemElem.attribute( "html" );
517  mUserStylesheet = itemElem.attribute( "stylesheet" );
518  mEnableUserStylesheet = itemElem.attribute( "stylesheetEnabled", "false" ) == "true" ? true : false;
519 
520  //finally load the set url
521  QString urlString = itemElem.attribute( "url" );
522  if ( !urlString.isEmpty() )
523  {
524  mUrl = urlString;
525  }
526  loadHtml( true );
527 
528  //since frames had to be created before, we need to emit a changed signal to refresh the widget
529  emit changed();
530  return true;
531 }
532 
533 void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer )
534 {
535  mExpressionFeature = feature;
536  mExpressionLayer = layer;
537 
538  //setup distance area conversion
539  if ( layer )
540  {
541  mDistanceArea->setSourceCrs( layer->crs().srsid() );
542  }
543  else if ( mComposition )
544  {
545  //set to composition's mapsettings' crs
546  mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
547  }
548  if ( mComposition )
549  {
551  }
552  mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
553 }
554 
556 {
557  QgsVectorLayer * vl = 0;
558  QgsFeature* feature = 0;
559 
561  {
563  }
565  {
567  }
568 
569  setExpressionContext( feature, vl );
570  loadHtml( true );
571 }
572 
574 {
575  //updates data defined properties and redraws item to match
576  if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
577  {
578  loadHtml( true );
579  }
581 }
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...
static QgsNetworkAccessManager * instance()
Definition: qgssingleton.h:23
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.
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.
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.
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.
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...