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