QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgslayoutitemlabel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutitemlabel.cpp
3 -------------------
4 begin : October 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgslayoutitemlabel.h"
20#include "qgslayoututils.h"
21#include "qgslayoutmodel.h"
22#include "qgsexpression.h"
24#include "qgsvectorlayer.h"
25#include "qgsdistancearea.h"
26#include "qgsfontutils.h"
27#include "qgstextformat.h"
28#include "qgstextrenderer.h"
30#include "qgslayoutitemmap.h"
31#include "qgssettings.h"
32#include "qgslayout.h"
35
36#include "qgswebpage.h"
37#include "qgswebframe.h"
38
39#include <QCoreApplication>
40#include <QDate>
41#include <QDomElement>
42#include <QPainter>
43#include <QTimer>
44#include <QEventLoop>
45#include <QThread>
46
48 : QgsLayoutItem( layout )
49{
50 mDistanceArea.reset( new QgsDistanceArea() );
51 mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits();
52
53 //get default layout font from settings
54 const QgsSettings settings;
55 const QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString();
56 if ( !defaultFontString.isEmpty() )
57 {
58 QFont f = mFormat.font();
59 f.setFamily( defaultFontString );
60 mFormat.setFont( f );
61 }
62
63 //default to a 10 point font size
64 mFormat.setSize( 10 );
65 mFormat.setSizeUnit( Qgis::RenderUnit::Points );
66
67 //default to no background
68 setBackgroundEnabled( false );
69
70 //a label added while atlas preview is enabled needs to have the expression context set,
71 //otherwise fields in the label aren't correctly evaluated until atlas preview feature changes (#9457)
72 refreshExpressionContext();
73
74 // only possible on the main thread!
75 if ( QThread::currentThread() == QApplication::instance()->thread() )
76 {
77 mWebPage.reset( new QgsWebPage( this ) );
78 }
79 else
80 {
81 QgsMessageLog::logMessage( QObject::tr( "Cannot load HTML based item label in background threads" ) );
82 }
83 if ( mWebPage )
84 {
85 mWebPage->setIdentifier( tr( "Layout label item" ) );
86 mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
87
88 //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/
89 QPalette palette = mWebPage->palette();
90 palette.setBrush( QPalette::Base, Qt::transparent );
91 mWebPage->setPalette( palette );
92
93 mWebPage->mainFrame()->setZoomFactor( 10.0 );
94 mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
95 mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
96
97 connect( mWebPage.get(), &QWebPage::loadFinished, this, &QgsLayoutItemLabel::loadingHtmlFinished );
98 }
99}
100
102{
103 return new QgsLayoutItemLabel( layout );
104}
105
107{
109}
110
112{
113 return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemLabel.svg" ) );
114}
115
117{
118 QPainter *painter = context.renderContext().painter();
119 const QgsScopedQPainterState painterState( painter );
120
121 double rectScale = 1.0;
122 if ( mMode == QgsLayoutItemLabel::ModeFont )
123 {
124 rectScale = context.renderContext().scaleFactor();
125 }
126 else
127 {
128 // painter is scaled to dots, so scale back to layout units
129 painter->scale( context.renderContext().scaleFactor(), context.renderContext().scaleFactor() );
130 }
131
132 const double penWidth = frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
133 const double xPenAdjust = mMarginX < 0 ? -penWidth : penWidth;
134 const double yPenAdjust = mMarginY < 0 ? -penWidth : penWidth;
135 const QRectF painterRect( ( xPenAdjust + mMarginX ) * rectScale,
136 ( yPenAdjust + mMarginY ) * rectScale,
137 ( rect().width() - 2 * xPenAdjust - 2 * mMarginX ) * rectScale,
138 ( rect().height() - 2 * yPenAdjust - 2 * mMarginY ) * rectScale );
139
140 switch ( mMode )
141 {
142 case ModeHtml:
143 {
144 if ( mFirstRender )
145 {
146 contentChanged();
147 mFirstRender = false;
148 }
149
150 if ( mWebPage )
151 {
152 painter->scale( 1.0 / mHtmlUnitsToLayoutUnits / 10.0, 1.0 / mHtmlUnitsToLayoutUnits / 10.0 );
153 mWebPage->setViewportSize( QSize( painterRect.width() * mHtmlUnitsToLayoutUnits * 10.0, painterRect.height() * mHtmlUnitsToLayoutUnits * 10.0 ) );
154 mWebPage->settings()->setUserStyleSheetUrl( createStylesheetUrl() );
155 mWebPage->mainFrame()->render( painter );
156 }
157 break;
158 }
159
160 case ModeFont:
161 {
163 QgsTextRenderer::drawText( painterRect, 0,
165 currentText().split( '\n' ),
166 context.renderContext(),
167 mFormat,
168 true,
171 break;
172 }
173 }
174}
175
176void QgsLayoutItemLabel::contentChanged()
177{
178 switch ( mMode )
179 {
180 case ModeHtml:
181 {
182 const QString textToDraw = currentText();
183 if ( !mWebPage )
184 {
185 mHtmlLoaded = true;
186 return;
187 }
188
189 //mHtmlLoaded tracks whether the QWebPage has completed loading
190 //its html contents, set it initially to false. The loadingHtmlFinished slot will
191 //set this to true after html is loaded.
192 mHtmlLoaded = false;
193
194 const QUrl baseUrl = QUrl::fromLocalFile( mLayout->project()->absoluteFilePath() );
195 mWebPage->mainFrame()->setHtml( textToDraw, baseUrl );
196
197 //For very basic html labels with no external assets, the html load will already be
198 //complete before we even get a chance to start the QEventLoop. Make sure we check
199 //this before starting the loop
200
201 // important -- we CAN'T do this when it's a render inside the designer, otherwise the
202 // event loop will mess with the paint event and cause it to be deleted, and BOOM!
203 if ( !mHtmlLoaded && ( !mLayout || !mLayout->renderContext().isPreviewRender() ) )
204 {
205 //Setup event loop and timeout for rendering html
206 QEventLoop loop;
207
208 //Connect timeout and webpage loadFinished signals to loop
209 connect( mWebPage.get(), &QWebPage::loadFinished, &loop, &QEventLoop::quit );
210
211 // Start a 20 second timeout in case html loading will never complete
212 QTimer timeoutTimer;
213 timeoutTimer.setSingleShot( true );
214 connect( &timeoutTimer, &QTimer::timeout, &loop, &QEventLoop::quit );
215 timeoutTimer.start( 20000 );
216
217 // Pause until html is loaded
218 loop.exec( QEventLoop::ExcludeUserInputEvents );
219 }
220 break;
221 }
222 case ModeFont:
224 break;
225 }
226}
227
228void QgsLayoutItemLabel::loadingHtmlFinished( bool result )
229{
230 Q_UNUSED( result )
231 mHtmlLoaded = true;
233 update();
234}
235
236double QgsLayoutItemLabel::htmlUnitsToLayoutUnits()
237{
238 if ( !mLayout )
239 {
240 return 1.0;
241 }
242
243 //TODO : fix this more precisely so that the label's default text size is the same with or without "display as html"
244 return mLayout->convertToLayoutUnits( QgsLayoutMeasurement( mLayout->renderContext().dpi() / 72.0, Qgis::LayoutUnit::Millimeters ) ); //webkit seems to assume a standard dpi of 72
245}
246
247void QgsLayoutItemLabel::setText( const QString &text )
248{
249 mText = text;
250 emit changed();
251
252 contentChanged();
253
254 if ( mLayout && id().isEmpty() && mMode != ModeHtml )
255 {
256 //notify the model that the display name has changed
257 mLayout->itemsModel()->updateItemDisplayName( this );
258 }
259}
260
262{
263 if ( mode == mMode )
264 {
265 return;
266 }
267
268 mMode = mode;
269 contentChanged();
270
271 if ( mLayout && id().isEmpty() )
272 {
273 //notify the model that the display name has changed
274 mLayout->itemsModel()->updateItemDisplayName( this );
275 }
276}
277
278void QgsLayoutItemLabel::refreshExpressionContext()
279{
280 if ( !mLayout )
281 return;
282
283 QgsVectorLayer *layer = mLayout->reportContext().layer();
284 //setup distance area conversion
285 if ( layer )
286 {
287 mDistanceArea->setSourceCrs( layer->crs(), mLayout->project()->transformContext() );
288 }
289 else
290 {
291 //set to composition's reference map's crs
292 QgsLayoutItemMap *referenceMap = mLayout->referenceMap();
293 if ( referenceMap )
294 mDistanceArea->setSourceCrs( referenceMap->crs(), mLayout->project()->transformContext() );
295 }
296 mDistanceArea->setEllipsoid( mLayout->project()->ellipsoid() );
297 contentChanged();
298
299 update();
300}
301
303{
304 QString displayText = mText;
305 replaceDateText( displayText );
306
308
309 return QgsExpression::replaceExpressionText( displayText, &context, mDistanceArea.get() );
310}
311
312void QgsLayoutItemLabel::replaceDateText( QString &text ) const
313{
314 const QString constant = QStringLiteral( "$CURRENT_DATE" );
315 const int currentDatePos = text.indexOf( constant );
316 if ( currentDatePos != -1 )
317 {
318 //check if there is a bracket just after $CURRENT_DATE
319 QString formatText;
320 const int openingBracketPos = text.indexOf( '(', currentDatePos );
321 const int closingBracketPos = text.indexOf( ')', openingBracketPos + 1 );
322 if ( openingBracketPos != -1 &&
323 closingBracketPos != -1 &&
324 ( closingBracketPos - openingBracketPos ) > 1 &&
325 openingBracketPos == currentDatePos + constant.size() )
326 {
327 formatText = text.mid( openingBracketPos + 1, closingBracketPos - openingBracketPos - 1 );
328 text.replace( currentDatePos, closingBracketPos - currentDatePos + 1, QDate::currentDate().toString( formatText ) );
329 }
330 else //no bracket
331 {
332 text.replace( QLatin1String( "$CURRENT_DATE" ), QDate::currentDate().toString() );
333 }
334 }
335}
336
337void QgsLayoutItemLabel::setFont( const QFont &f )
338{
339 mFormat.setFont( f );
340 if ( f.pointSizeF() > 0 )
341 mFormat.setSize( f.pointSizeF() );
342}
343
345{
346 return mFormat;
347}
348
350{
351 mFormat = format;
352}
353
354void QgsLayoutItemLabel::setMargin( const double m )
355{
356 mMarginX = m;
357 mMarginY = m;
358 prepareGeometryChange();
359}
360
361void QgsLayoutItemLabel::setMarginX( const double margin )
362{
363 mMarginX = margin;
364 prepareGeometryChange();
365}
366
367void QgsLayoutItemLabel::setMarginY( const double margin )
368{
369 mMarginY = margin;
370 prepareGeometryChange();
371}
372
374{
375 const QSizeF newSize = sizeForText();
376
377 //keep alignment point constant
378 double xShift = 0;
379 double yShift = 0;
380
381 itemShiftAdjustSize( newSize.width(), newSize.height(), xShift, yShift );
382
383 //update rect for data defined size and position
384 attemptSetSceneRect( QRectF( pos().x() + xShift, pos().y() + yShift, newSize.width(), newSize.height() ) );
385}
386
388{
390
391 const QStringList lines = currentText().split( '\n' );
392 const double textWidth = QgsTextRenderer::textWidth( context, mFormat, lines ) / context.convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
393 const double fontHeight = QgsTextRenderer::textHeight( context, mFormat, lines ) / context.convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
394
395 const double penWidth = frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
396
397 const double width = textWidth + 2 * mMarginX + 2 * penWidth;
398 const double height = fontHeight + 2 * mMarginY + 2 * penWidth;
399
400 return mLayout->convertToLayoutUnits( QgsLayoutSize( width, height, Qgis::LayoutUnit::Millimeters ) );
401}
402
404{
405 return mFormat.font();
406}
407
408bool QgsLayoutItemLabel::writePropertiesToElement( QDomElement &layoutLabelElem, QDomDocument &doc, const QgsReadWriteContext &rwContext ) const
409{
410 layoutLabelElem.setAttribute( QStringLiteral( "htmlState" ), static_cast< int >( mMode ) );
411
412 layoutLabelElem.setAttribute( QStringLiteral( "labelText" ), mText );
413 layoutLabelElem.setAttribute( QStringLiteral( "marginX" ), QString::number( mMarginX ) );
414 layoutLabelElem.setAttribute( QStringLiteral( "marginY" ), QString::number( mMarginY ) );
415 layoutLabelElem.setAttribute( QStringLiteral( "halign" ), mHAlignment );
416 layoutLabelElem.setAttribute( QStringLiteral( "valign" ), mVAlignment );
417
418 QDomElement textElem = mFormat.writeXml( doc, rwContext );
419 layoutLabelElem.appendChild( textElem );
420
421 return true;
422}
423
424bool QgsLayoutItemLabel::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext &context )
425{
426 //restore label specific properties
427
428 //text
429 mText = itemElem.attribute( QStringLiteral( "labelText" ) );
430
431 //html state
432 mMode = static_cast< Mode >( itemElem.attribute( QStringLiteral( "htmlState" ) ).toInt() );
433
434 //margin
435 bool marginXOk = false;
436 bool marginYOk = false;
437 mMarginX = itemElem.attribute( QStringLiteral( "marginX" ) ).toDouble( &marginXOk );
438 mMarginY = itemElem.attribute( QStringLiteral( "marginY" ) ).toDouble( &marginYOk );
439 if ( !marginXOk || !marginYOk )
440 {
441 //upgrade old projects where margins where stored in a single attribute
442 const double margin = itemElem.attribute( QStringLiteral( "margin" ), QStringLiteral( "1.0" ) ).toDouble();
443 mMarginX = margin;
444 mMarginY = margin;
445 }
446
447 //Horizontal alignment
448 mHAlignment = static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "halign" ) ).toInt() );
449
450 //Vertical alignment
451 mVAlignment = static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "valign" ) ).toInt() );
452
453 //font
454 QDomNodeList textFormatNodeList = itemElem.elementsByTagName( QStringLiteral( "text-style" ) );
455 if ( !textFormatNodeList.isEmpty() )
456 {
457 QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement();
458 mFormat.readXml( textFormatElem, context );
459 }
460 else
461 {
462 QFont f;
463 if ( !QgsFontUtils::setFromXmlChildNode( f, itemElem, QStringLiteral( "LabelFont" ) ) )
464 {
465 f.fromString( itemElem.attribute( QStringLiteral( "font" ), QString() ) );
466 }
467 mFormat.setFont( f );
468 if ( f.pointSizeF() > 0 )
469 {
470 mFormat.setSize( f.pointSizeF() );
471 mFormat.setSizeUnit( Qgis::RenderUnit::Points );
472 }
473 else if ( f.pixelSize() > 0 )
474 {
475 mFormat.setSize( f.pixelSize() );
476 mFormat.setSizeUnit( Qgis::RenderUnit::Pixels );
477 }
478
479 //font color
480 const QDomNodeList fontColorList = itemElem.elementsByTagName( QStringLiteral( "FontColor" ) );
481 if ( !fontColorList.isEmpty() )
482 {
483 const QDomElement fontColorElem = fontColorList.at( 0 ).toElement();
484 const int red = fontColorElem.attribute( QStringLiteral( "red" ), QStringLiteral( "0" ) ).toInt();
485 const int green = fontColorElem.attribute( QStringLiteral( "green" ), QStringLiteral( "0" ) ).toInt();
486 const int blue = fontColorElem.attribute( QStringLiteral( "blue" ), QStringLiteral( "0" ) ).toInt();
487 const int alpha = fontColorElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt();
488 mFormat.setColor( QColor( red, green, blue, alpha ) );
489 }
490 else if ( textFormatNodeList.isEmpty() )
491 {
492 mFormat.setColor( QColor( 0, 0, 0 ) );
493 }
494 }
495
496 return true;
497}
498
500{
501 if ( !id().isEmpty() )
502 {
503 return id();
504 }
505
506 switch ( mMode )
507 {
508 case ModeHtml:
509 return tr( "<HTML Label>" );
510
511 case ModeFont:
512 {
513
514 //if no id, default to portion of label text
515 const QString text = mText;
516 if ( text.isEmpty() )
517 {
518 return tr( "<Label>" );
519 }
520 if ( text.length() > 25 )
521 {
522 return QString( tr( "%1…" ) ).arg( text.left( 25 ).simplified() );
523 }
524 else
525 {
526 return text.simplified();
527 }
528 }
529 }
530 return QString(); // no warnings
531}
532
534{
535 QRectF rectangle = rect();
536 const double penWidth = frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
537 rectangle.adjust( -penWidth, -penWidth, penWidth, penWidth );
538
539 if ( mMarginX < 0 )
540 {
541 rectangle.adjust( mMarginX, 0, -mMarginX, 0 );
542 }
543 if ( mMarginY < 0 )
544 {
545 rectangle.adjust( 0, mMarginY, 0, -mMarginY );
546 }
547
548 return rectangle;
549}
550
551void QgsLayoutItemLabel::setFrameEnabled( const bool drawFrame )
552{
554 prepareGeometryChange();
555}
556
558{
560 prepareGeometryChange();
561}
562
564{
567 refreshExpressionContext();
568}
569
571{
572 const QString evaluated = currentText();
573 if ( evaluated == mText )
574 return; // no changes
575
576 setText( evaluated );
577}
578
579void QgsLayoutItemLabel::itemShiftAdjustSize( double newWidth, double newHeight, double &xShift, double &yShift ) const
580{
581 //keep alignment point constant
582 const double currentWidth = rect().width();
583 const double currentHeight = rect().height();
584 xShift = 0;
585 yShift = 0;
586
587 const double r = rotation();
588 if ( r >= 0 && r < 90 )
589 {
590 if ( mHAlignment == Qt::AlignHCenter )
591 {
592 xShift = - ( newWidth - currentWidth ) / 2.0;
593 }
594 else if ( mHAlignment == Qt::AlignRight )
595 {
596 xShift = - ( newWidth - currentWidth );
597 }
598 if ( mVAlignment == Qt::AlignVCenter )
599 {
600 yShift = -( newHeight - currentHeight ) / 2.0;
601 }
602 else if ( mVAlignment == Qt::AlignBottom )
603 {
604 yShift = - ( newHeight - currentHeight );
605 }
606 }
607 if ( r >= 90 && r < 180 )
608 {
609 if ( mHAlignment == Qt::AlignHCenter )
610 {
611 yShift = -( newHeight - currentHeight ) / 2.0;
612 }
613 else if ( mHAlignment == Qt::AlignRight )
614 {
615 yShift = -( newHeight - currentHeight );
616 }
617 if ( mVAlignment == Qt::AlignTop )
618 {
619 xShift = -( newWidth - currentWidth );
620 }
621 else if ( mVAlignment == Qt::AlignVCenter )
622 {
623 xShift = -( newWidth - currentWidth / 2.0 );
624 }
625 }
626 else if ( r >= 180 && r < 270 )
627 {
628 if ( mHAlignment == Qt::AlignHCenter )
629 {
630 xShift = -( newWidth - currentWidth ) / 2.0;
631 }
632 else if ( mHAlignment == Qt::AlignLeft )
633 {
634 xShift = -( newWidth - currentWidth );
635 }
636 if ( mVAlignment == Qt::AlignVCenter )
637 {
638 yShift = ( newHeight - currentHeight ) / 2.0;
639 }
640 else if ( mVAlignment == Qt::AlignTop )
641 {
642 yShift = ( newHeight - currentHeight );
643 }
644 }
645 else if ( r >= 270 && r < 360 )
646 {
647 if ( mHAlignment == Qt::AlignHCenter )
648 {
649 yShift = -( newHeight - currentHeight ) / 2.0;
650 }
651 else if ( mHAlignment == Qt::AlignLeft )
652 {
653 yShift = -( newHeight - currentHeight );
654 }
655 if ( mVAlignment == Qt::AlignBottom )
656 {
657 xShift = -( newWidth - currentWidth );
658 }
659 else if ( mVAlignment == Qt::AlignVCenter )
660 {
661 xShift = -( newWidth - currentWidth / 2.0 );
662 }
663 }
664}
665
666QUrl QgsLayoutItemLabel::createStylesheetUrl() const
667{
668 QString stylesheet;
669 stylesheet += QStringLiteral( "body { margin: %1 %2;" ).arg( std::max( mMarginY * mHtmlUnitsToLayoutUnits, 0.0 ) ).arg( std::max( mMarginX * mHtmlUnitsToLayoutUnits, 0.0 ) );
670 QFont f = mFormat.font();
671 switch ( mFormat.sizeUnit() )
672 {
673 case Qgis::RenderUnit::Millimeters:
674 f.setPointSizeF( mFormat.size() / 0.352778 );
675 break;
676 case Qgis::RenderUnit::Pixels:
677 f.setPixelSize( mFormat.size() );
678 break;
679 case Qgis::RenderUnit::Points:
680 f.setPointSizeF( mFormat.size() );
681 break;
682 case Qgis::RenderUnit::Inches:
683 f.setPointSizeF( mFormat.size() * 72 );
684 break;
685 case Qgis::RenderUnit::Unknown:
686 case Qgis::RenderUnit::Percentage:
687 case Qgis::RenderUnit::MetersInMapUnits:
688 case Qgis::RenderUnit::MapUnits:
689 break;
690 }
691
692 stylesheet += QgsFontUtils::asCSS( f, 0.352778 * mHtmlUnitsToLayoutUnits );
693 stylesheet += QStringLiteral( "color: rgba(%1,%2,%3,%4);" ).arg( mFormat.color().red() ).arg( mFormat.color().green() ).arg( mFormat.color().blue() ).arg( QString::number( mFormat.color().alphaF(), 'f', 4 ) );
694 stylesheet += QStringLiteral( "text-align: %1; }" ).arg( mHAlignment == Qt::AlignLeft ? QStringLiteral( "left" ) : mHAlignment == Qt::AlignRight ? QStringLiteral( "right" ) : mHAlignment == Qt::AlignHCenter ? QStringLiteral( "center" ) : QStringLiteral( "justify" ) );
695
696 QByteArray ba;
697 ba.append( stylesheet.toUtf8() );
698 QUrl cssFileURL = QUrl( QString( "data:text/css;charset=utf-8;base64," + ba.toBase64() ) );
699
700 return cssFileURL;
701}
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
@ WrapLines
Automatically wrap long lines of text.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
static QString asCSS(const QFont &font, double pointToPixelMultiplier=1.0)
Returns a CSS string representing the specified font as closely as possible.
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
A layout item subclass for text labels.
Mode mode() const
Returns the label's current mode.
void setMarginX(double margin)
Sets the horizontal margin between the edge of the frame and the label contents, in layout units.
void setFrameEnabled(bool drawFrame) override
Sets whether this item has a frame drawn around it or not.
QRectF boundingRect() const override
QSizeF sizeForText() const
Returns the required item size (in layout units) for the label's text to fill the item.
void setMargin(double margin)
Sets the margin between the edge of the frame and the label contents.
int type() const override
static QgsLayoutItemLabel * create(QgsLayout *layout)
Returns a new label item for the specified layout.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Q_DECL_DEPRECATED QFont font() const
Returns the label's current font.
QgsLayoutItemLabel(QgsLayout *layout)
Constructor for QgsLayoutItemLabel, with the specified parent layout.
void setText(const QString &text)
Sets the label's preset text.
void setFrameStrokeWidth(QgsLayoutMeasurement strokeWidth) override
Sets the frame stroke width.
void setMarginY(double margin)
Sets the vertical margin between the edge of the frame and the label contents, in layout units.
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
Q_DECL_DEPRECATED void setFont(const QFont &font)
Sets the label's current font.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void setMode(Mode mode)
Sets the label's current mode, allowing the label to switch between font based and HTML based renderi...
QString displayName() const override
Gets item display name.
QString text() const
Returns the label's preset text.
void convertToStaticText()
Converts the label's text() to a static string, by evaluating any expressions included in the text an...
QgsTextFormat textFormat() const
Returns the text format used for drawing text in the label.
void setTextFormat(const QgsTextFormat &format)
Sets the text format used for drawing text in the label.
QString currentText() const
Returns the text as it appears on the label (with evaluated expressions and other dynamic content).
QIcon icon() const override
Returns the item's icon.
void adjustSizeToText()
Resizes the item so that the label's text fits to the item.
@ ModeHtml
Label displays rendered HTML content.
@ ModeFont
Label displays text rendered using a single font.
Layout graphical items for displaying a map.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Contains settings and helpers relating to a render of a QgsLayoutItem.
Definition: qgslayoutitem.h:44
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgslayoutitem.h:71
Base class for graphical items within a QgsLayout.
virtual void drawFrame(QgsRenderContext &context)
Draws the frame around the item.
virtual void setFrameStrokeWidth(QgsLayoutMeasurement width)
Sets the frame stroke width.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
virtual void invalidateCache()
Forces a deferred update of any cached image the item uses.
QString id() const
Returns the item's ID name.
bool frameEnabled() const
Returns true if the item includes a frame.
void refresh() override
Refreshes the item, causing a recalculation of any property overrides and recalculation of its positi...
void attemptSetSceneRect(const QRectF &rect, bool includesFrame=false)
Attempts to update the item's position and size to match the passed rect in layout coordinates.
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
QPointer< QgsLayout > mLayout
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:41
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
The class is used as a container of context for various read/write operations on other objects.
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Scoped object for saving and restoring a QPainter object's state.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:63
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the size of rendered text.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
Qgis::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
double size() const
Returns the size for rendered text.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
QColor color() const
Returns the color that text will be rendered in.
QFont font() const
Returns the font used for rendering text.
static Qgis::TextVerticalAlignment convertQtVAlignment(Qt::Alignment alignment)
Converts a Qt vertical alignment flag to a Qgis::TextVerticalAlignment value.
static double textWidth(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics=nullptr)
Returns the width of a text based on a given format.
static void drawText(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, Qgis::TextVerticalAlignment vAlignment=Qgis::TextVerticalAlignment::Top, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle)
Draws text within a rectangle using the specified settings.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Point, QFontMetricsF *fontMetrics=nullptr, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), double maxLineWidth=0)
Returns the height of a text based on a given format.
static Qgis::TextHorizontalAlignment convertQtHAlignment(Qt::Alignment alignment)
Converts a Qt horizontal alignment flag to a Qgis::TextHorizontalAlignment value.
Represents a vector layer which manages a vector based data sets.
QWebPage subclass which redirects JavaScript errors and console output to the QGIS message log.
Definition: qgswebpage.h:218