36#include <QCoreApplication> 
   40#include <QTextDocument> 
   46  mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits();
 
   50  const QString defaultFontString = settings.
value( QStringLiteral( 
"LayoutDesigner/defaultFont" ), QVariant(), 
QgsSettings::Gui ).toString();
 
   51  if ( !defaultFontString.isEmpty() )
 
   53    QFont f = mFormat.
font();
 
   54    f.setFamily( defaultFontString );
 
   67  refreshExpressionContext();
 
   90  const double penWidth = 
frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
 
   91  const double xPenAdjust = mMarginX < 0 ? -penWidth : penWidth;
 
   92  const double yPenAdjust = mMarginY < 0 ? -penWidth : penWidth;
 
   98    painterRect = QRectF( ( xPenAdjust + mMarginX ) * rectScale,
 
   99                          ( yPenAdjust + mMarginY ) * rectScale,
 
  100                          ( rect().width() - 2 * xPenAdjust - 2 * mMarginX ) * rectScale,
 
  101                          ( rect().height() - 2 * yPenAdjust - 2 * mMarginY ) * rectScale );
 
  106    const double adjustmentFactor = 3.77;
 
  109    painterRect = QRectF( 0, 0,
 
  110                          ( rect().width() ) * rectScale,
 
  111                          ( rect().height() - yPenAdjust - mMarginY ) * rectScale );
 
  120      QTextDocument document;
 
  121      document.setDocumentMargin( 0 );
 
  123      document.setDefaultStyleSheet( createStylesheet() );
 
  125      document.setDefaultFont( createDefaultFont() );
 
  127      QTextOption textOption = document.defaultTextOption();
 
  128      textOption.setAlignment( mHAlignment );
 
  129      document.setDefaultTextOption( textOption );
 
  131      document.setHtml( QStringLiteral( 
"<body>%1</body>" ).arg( 
currentText() ) );
 
  132      document.drawContents( painter, painterRect );
 
  152void QgsLayoutItemLabel::contentChanged()
 
  177    mLayout->itemsModel()->updateItemDisplayName( 
this );
 
  191  if ( 
mLayout && 
id().isEmpty() )
 
  194    mLayout->itemsModel()->updateItemDisplayName( 
this );
 
  198void QgsLayoutItemLabel::refreshExpressionContext()
 
  207    mDistanceArea->setSourceCrs( layer->
crs(), 
mLayout->project()->transformContext() );
 
  214      mDistanceArea->setSourceCrs( referenceMap->
crs(), 
mLayout->project()->transformContext() );
 
  216  mDistanceArea->setEllipsoid( 
mLayout->project()->ellipsoid() );
 
  224  QString displayText = mText;
 
  225  replaceDateText( displayText );
 
  232void QgsLayoutItemLabel::replaceDateText( QString &text )
 const 
  234  const QString constant = QStringLiteral( 
"$CURRENT_DATE" );
 
  235  const int currentDatePos = 
text.indexOf( constant );
 
  236  if ( currentDatePos != -1 )
 
  240    const int openingBracketPos = 
text.indexOf( 
'(', currentDatePos );
 
  241    const int closingBracketPos = 
text.indexOf( 
')', openingBracketPos + 1 );
 
  242    if ( openingBracketPos != -1 &&
 
  243         closingBracketPos != -1 &&
 
  244         ( closingBracketPos - openingBracketPos ) > 1 &&
 
  245         openingBracketPos == currentDatePos + constant.size() )
 
  247      formatText = 
text.mid( openingBracketPos + 1, closingBracketPos - openingBracketPos - 1 );
 
  248      text.replace( currentDatePos, closingBracketPos - currentDatePos + 1, QDate::currentDate().toString( formatText ) );
 
  252      text.replace( QLatin1String( 
"$CURRENT_DATE" ), QDate::currentDate().toString() );
 
  260  if ( f.pointSizeF() > 0 )
 
  261    mFormat.
setSize( f.pointSizeF() );
 
  278  prepareGeometryChange();
 
  284  prepareGeometryChange();
 
  290  prepareGeometryChange();
 
  301  itemShiftAdjustSize( newSize.width(), newSize.height(), xShift, yShift );
 
  304  attemptSetSceneRect( QRectF( pos().x() + xShift, pos().y() + yShift, newSize.width(), newSize.height() ) );
 
  311  const QStringList lines = 
currentText().split( 
'\n' );
 
  315  const double penWidth = 
frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
 
  317  const double width = textWidth + 2 * mMarginX + 2 * penWidth;
 
  318  const double height = fontHeight + 2 * mMarginY + 2 * penWidth;
 
  320  return mLayout->convertToLayoutUnits( 
QgsLayoutSize( width, height, Qgis::LayoutUnit::Millimeters ) );
 
  325  return mFormat.
font();
 
  330  layoutLabelElem.setAttribute( QStringLiteral( 
"htmlState" ), 
static_cast< int >( mMode ) );
 
  332  layoutLabelElem.setAttribute( QStringLiteral( 
"labelText" ), mText );
 
  333  layoutLabelElem.setAttribute( QStringLiteral( 
"marginX" ), QString::number( mMarginX ) );
 
  334  layoutLabelElem.setAttribute( QStringLiteral( 
"marginY" ), QString::number( mMarginY ) );
 
  335  layoutLabelElem.setAttribute( QStringLiteral( 
"halign" ), mHAlignment );
 
  336  layoutLabelElem.setAttribute( QStringLiteral( 
"valign" ), mVAlignment );
 
  338  QDomElement textElem = mFormat.
writeXml( doc, rwContext );
 
  339  layoutLabelElem.appendChild( textElem );
 
  349  mText = itemElem.attribute( QStringLiteral( 
"labelText" ) );
 
  352  mMode = 
static_cast< Mode >( itemElem.attribute( QStringLiteral( 
"htmlState" ) ).toInt() );
 
  355  bool marginXOk = 
false;
 
  356  bool marginYOk = 
false;
 
  357  mMarginX = itemElem.attribute( QStringLiteral( 
"marginX" ) ).toDouble( &marginXOk );
 
  358  mMarginY = itemElem.attribute( QStringLiteral( 
"marginY" ) ).toDouble( &marginYOk );
 
  359  if ( !marginXOk || !marginYOk )
 
  362    const double margin = itemElem.attribute( QStringLiteral( 
"margin" ), QStringLiteral( 
"1.0" ) ).toDouble();
 
  368  mHAlignment = 
static_cast< Qt::AlignmentFlag 
>( itemElem.attribute( QStringLiteral( 
"halign" ) ).toInt() );
 
  371  mVAlignment = 
static_cast< Qt::AlignmentFlag 
>( itemElem.attribute( QStringLiteral( 
"valign" ) ).toInt() );
 
  374  QDomNodeList textFormatNodeList = itemElem.elementsByTagName( QStringLiteral( 
"text-style" ) );
 
  375  if ( !textFormatNodeList.isEmpty() )
 
  377    QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement();
 
  378    mFormat.
readXml( textFormatElem, context );
 
  385      f.fromString( itemElem.attribute( QStringLiteral( 
"font" ), QString() ) );
 
  388    if ( f.pointSizeF() > 0 )
 
  390      mFormat.
setSize( f.pointSizeF() );
 
  393    else if ( f.pixelSize() > 0 )
 
  395      mFormat.
setSize( f.pixelSize() );
 
  400    const QDomNodeList fontColorList = itemElem.elementsByTagName( QStringLiteral( 
"FontColor" ) );
 
  401    if ( !fontColorList.isEmpty() )
 
  403      const QDomElement fontColorElem = fontColorList.at( 0 ).toElement();
 
  404      const int red = fontColorElem.attribute( QStringLiteral( 
"red" ), QStringLiteral( 
"0" ) ).toInt();
 
  405      const int green = fontColorElem.attribute( QStringLiteral( 
"green" ), QStringLiteral( 
"0" ) ).toInt();
 
  406      const int blue = fontColorElem.attribute( QStringLiteral( 
"blue" ), QStringLiteral( 
"0" ) ).toInt();
 
  407      const int alpha = fontColorElem.attribute( QStringLiteral( 
"alpha" ), QStringLiteral( 
"255" ) ).toInt();
 
  408      mFormat.
setColor( QColor( red, green, blue, alpha ) );
 
  410    else if ( textFormatNodeList.isEmpty() )
 
  412      mFormat.
setColor( QColor( 0, 0, 0 ) );
 
  421  if ( !
id().isEmpty() )
 
  429      return tr( 
"<HTML Label>" );
 
  435      const QString 
text = mText;
 
  436      if ( 
text.isEmpty() )
 
  438        return tr( 
"<Label>" );
 
  440      if ( 
text.length() > 25 )
 
  442        return QString( tr( 
"%1…" ) ).arg( 
text.left( 25 ).simplified() );
 
  446        return text.simplified();
 
  455  QRectF rectangle = rect();
 
  456  const double penWidth = 
frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
 
  457  rectangle.adjust( -penWidth, -penWidth, penWidth, penWidth );
 
  461    rectangle.adjust( mMarginX, 0, -mMarginX, 0 );
 
  465    rectangle.adjust( 0, mMarginY, 0, -mMarginY );
 
  474  prepareGeometryChange();
 
  480  prepareGeometryChange();
 
  487  refreshExpressionContext();
 
  493  if ( evaluated == mText )
 
  499void QgsLayoutItemLabel::itemShiftAdjustSize( 
double newWidth, 
double newHeight, 
double &xShift, 
double &yShift )
 const 
  502  const double currentWidth = rect().width();
 
  503  const double currentHeight = rect().height();
 
  507  const double r = rotation();
 
  508  if ( r >= 0 && r < 90 )
 
  510    if ( mHAlignment == Qt::AlignHCenter )
 
  512      xShift = - ( newWidth - currentWidth ) / 2.0;
 
  514    else if ( mHAlignment == Qt::AlignRight )
 
  516      xShift = - ( newWidth - currentWidth );
 
  518    if ( mVAlignment == Qt::AlignVCenter )
 
  520      yShift = -( newHeight - currentHeight ) / 2.0;
 
  522    else if ( mVAlignment == Qt::AlignBottom )
 
  524      yShift = - ( newHeight - currentHeight );
 
  527  if ( r >= 90 && r < 180 )
 
  529    if ( mHAlignment == Qt::AlignHCenter )
 
  531      yShift = -( newHeight  - currentHeight ) / 2.0;
 
  533    else if ( mHAlignment == Qt::AlignRight )
 
  535      yShift = -( newHeight  - currentHeight );
 
  537    if ( mVAlignment == Qt::AlignTop )
 
  539      xShift = -( newWidth - currentWidth );
 
  541    else if ( mVAlignment == Qt::AlignVCenter )
 
  543      xShift = -( newWidth - currentWidth / 2.0 );
 
  546  else if ( r >= 180 && r < 270 )
 
  548    if ( mHAlignment == Qt::AlignHCenter )
 
  550      xShift = -( newWidth - currentWidth ) / 2.0;
 
  552    else if ( mHAlignment == Qt::AlignLeft )
 
  554      xShift = -( newWidth - currentWidth );
 
  556    if ( mVAlignment == Qt::AlignVCenter )
 
  558      yShift = ( newHeight - currentHeight ) / 2.0;
 
  560    else if ( mVAlignment == Qt::AlignTop )
 
  562      yShift = ( newHeight - currentHeight );
 
  565  else if ( r >= 270 && r < 360 )
 
  567    if ( mHAlignment == Qt::AlignHCenter )
 
  569      yShift = -( newHeight  - currentHeight ) / 2.0;
 
  571    else if ( mHAlignment == Qt::AlignLeft )
 
  573      yShift = -( newHeight  - currentHeight );
 
  575    if ( mVAlignment == Qt::AlignBottom )
 
  577      xShift = -( newWidth - currentWidth );
 
  579    else if ( mVAlignment == Qt::AlignVCenter )
 
  581      xShift = -( newWidth - currentWidth / 2.0 );
 
  586QFont QgsLayoutItemLabel::createDefaultFont()
 const 
  588  QFont f = mFormat.
font();
 
  591    case Qgis::RenderUnit::Millimeters:
 
  592      f.setPointSizeF( mFormat.
size() / 0.352778 );
 
  594    case Qgis::RenderUnit::Pixels:
 
  595      f.setPixelSize( mFormat.
size() );
 
  597    case Qgis::RenderUnit::Points:
 
  598      f.setPointSizeF( mFormat.
size() );
 
  600    case Qgis::RenderUnit::Inches:
 
  601      f.setPointSizeF( mFormat.
size() * 72 );
 
  603    case Qgis::RenderUnit::Unknown:
 
  604    case Qgis::RenderUnit::Percentage:
 
  605    case Qgis::RenderUnit::MetersInMapUnits:
 
  606    case Qgis::RenderUnit::MapUnits:
 
  612double QgsLayoutItemLabel::htmlUnitsToLayoutUnits()
 
  623QString QgsLayoutItemLabel::createStylesheet()
 const 
  626  stylesheet += QStringLiteral( 
"body { margin: %1 %2;" ).arg( std::max( mMarginY * mHtmlUnitsToLayoutUnits, 0.0 ) ).arg( std::max( mMarginX * mHtmlUnitsToLayoutUnits, 0.0 ) );
 
  628  QFont f = createDefaultFont();
 
  631  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 ) );
 
  632  stylesheet += QStringLiteral( 
"text-align: %1; }" ).arg( mHAlignment == Qt::AlignLeft ? QStringLiteral( 
"left" ) : mHAlignment == Qt::AlignRight ? QStringLiteral( 
"right" ) : mHAlignment == Qt::AlignHCenter ? QStringLiteral( 
"center" ) : QStringLiteral( 
"justify" ) );
 
  637QUrl QgsLayoutItemLabel::createStylesheetUrl()
 const 
  640  ba.append( createStylesheet().toUtf8() );
 
  641  QUrl cssFileURL = QUrl( QString( 
"data:text/css;charset=utf-8;base64," + ba.toBase64() ) );
 
@ 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.
 
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
 
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...
 
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.
 
QgsCoordinateReferenceSystem crs
 
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:
 
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.
 
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.