LCOV - code coverage report
Current view: top level - core/layout - qgslayoutitemlabel.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 340 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       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"
      19                 :            : #include "qgslayoutitemregistry.h"
      20                 :            : #include "qgslayout.h"
      21                 :            : #include "qgslayoututils.h"
      22                 :            : #include "qgslayoutmodel.h"
      23                 :            : #include "qgsexpression.h"
      24                 :            : #include "qgsnetworkaccessmanager.h"
      25                 :            : #include "qgsvectorlayer.h"
      26                 :            : #include "qgsproject.h"
      27                 :            : #include "qgsdistancearea.h"
      28                 :            : #include "qgsfontutils.h"
      29                 :            : #include "qgsexpressioncontext.h"
      30                 :            : #include "qgsmapsettings.h"
      31                 :            : #include "qgslayoutitemmap.h"
      32                 :            : #include "qgssettings.h"
      33                 :            : 
      34                 :            : #include "qgswebview.h"
      35                 :            : #include "qgswebframe.h"
      36                 :            : #include "qgswebpage.h"
      37                 :            : 
      38                 :            : #include <QCoreApplication>
      39                 :            : #include <QDate>
      40                 :            : #include <QDomElement>
      41                 :            : #include <QPainter>
      42                 :            : #include <QTimer>
      43                 :            : #include <QEventLoop>
      44                 :            : #include <QThread>
      45                 :            : 
      46                 :          0 : QgsLayoutItemLabel::QgsLayoutItemLabel( QgsLayout *layout )
      47                 :          0 :   : QgsLayoutItem( layout )
      48                 :          0 : {
      49                 :          0 :   mDistanceArea.reset( new QgsDistanceArea() );
      50                 :          0 :   mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits();
      51                 :            : 
      52                 :            :   //get default layout font from settings
      53                 :          0 :   QgsSettings settings;
      54                 :          0 :   QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString();
      55                 :          0 :   if ( !defaultFontString.isEmpty() )
      56                 :            :   {
      57                 :          0 :     mFont.setFamily( defaultFontString );
      58                 :          0 :   }
      59                 :            : 
      60                 :            :   //default to a 10 point font size
      61                 :          0 :   mFont.setPointSizeF( 10 );
      62                 :            : 
      63                 :            :   //default to no background
      64                 :          0 :   setBackgroundEnabled( false );
      65                 :            : 
      66                 :            :   //a label added while atlas preview is enabled needs to have the expression context set,
      67                 :            :   //otherwise fields in the label aren't correctly evaluated until atlas preview feature changes (#9457)
      68                 :          0 :   refreshExpressionContext();
      69                 :            : 
      70                 :            :   // only possible on the main thread!
      71                 :          0 :   if ( QThread::currentThread() == QApplication::instance()->thread() )
      72                 :            :   {
      73                 :          0 :     mWebPage.reset( new QgsWebPage( this ) );
      74                 :          0 :   }
      75                 :            :   else
      76                 :            :   {
      77                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Cannot load HTML based item label in background threads" ) );
      78                 :            :   }
      79                 :          0 :   if ( mWebPage )
      80                 :            :   {
      81                 :          0 :     mWebPage->setIdentifier( tr( "Layout label item" ) );
      82                 :          0 :     mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
      83                 :            : 
      84                 :            :     //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/
      85                 :          0 :     QPalette palette = mWebPage->palette();
      86                 :          0 :     palette.setBrush( QPalette::Base, Qt::transparent );
      87                 :          0 :     mWebPage->setPalette( palette );
      88                 :            : 
      89                 :          0 :     mWebPage->mainFrame()->setZoomFactor( 10.0 );
      90                 :          0 :     mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
      91                 :          0 :     mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
      92                 :            : 
      93                 :          0 :     connect( mWebPage.get(), &QWebPage::loadFinished, this, &QgsLayoutItemLabel::loadingHtmlFinished );
      94                 :          0 :   }
      95                 :          0 : }
      96                 :            : 
      97                 :          0 : QgsLayoutItemLabel *QgsLayoutItemLabel::create( QgsLayout *layout )
      98                 :            : {
      99                 :          0 :   return new QgsLayoutItemLabel( layout );
     100                 :          0 : }
     101                 :            : 
     102                 :          0 : int QgsLayoutItemLabel::type() const
     103                 :            : {
     104                 :          0 :   return QgsLayoutItemRegistry::LayoutLabel;
     105                 :            : }
     106                 :            : 
     107                 :          0 : QIcon QgsLayoutItemLabel::icon() const
     108                 :            : {
     109                 :          0 :   return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemLabel.svg" ) );
     110                 :          0 : }
     111                 :            : 
     112                 :          0 : void QgsLayoutItemLabel::draw( QgsLayoutItemRenderContext &context )
     113                 :            : {
     114                 :          0 :   QPainter *painter = context.renderContext().painter();
     115                 :          0 :   QgsScopedQPainterState painterState( painter );
     116                 :            : 
     117                 :            :   // painter is scaled to dots, so scale back to layout units
     118                 :          0 :   painter->scale( context.renderContext().scaleFactor(), context.renderContext().scaleFactor() );
     119                 :            : 
     120                 :          0 :   double penWidth = frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
     121                 :          0 :   double xPenAdjust = mMarginX < 0 ? -penWidth : penWidth;
     122                 :          0 :   double yPenAdjust = mMarginY < 0 ? -penWidth : penWidth;
     123                 :          0 :   QRectF painterRect( xPenAdjust + mMarginX, yPenAdjust + mMarginY, rect().width() - 2 * xPenAdjust - 2 * mMarginX, rect().height() - 2 * yPenAdjust - 2 * mMarginY );
     124                 :            : 
     125                 :          0 :   switch ( mMode )
     126                 :            :   {
     127                 :            :     case ModeHtml:
     128                 :            :     {
     129                 :          0 :       if ( mFirstRender )
     130                 :            :       {
     131                 :          0 :         contentChanged();
     132                 :          0 :         mFirstRender = false;
     133                 :          0 :       }
     134                 :            : 
     135                 :          0 :       if ( mWebPage )
     136                 :            :       {
     137                 :          0 :         painter->scale( 1.0 / mHtmlUnitsToLayoutUnits / 10.0, 1.0 / mHtmlUnitsToLayoutUnits / 10.0 );
     138                 :          0 :         mWebPage->setViewportSize( QSize( painterRect.width() * mHtmlUnitsToLayoutUnits * 10.0, painterRect.height() * mHtmlUnitsToLayoutUnits * 10.0 ) );
     139                 :          0 :         mWebPage->settings()->setUserStyleSheetUrl( createStylesheetUrl() );
     140                 :          0 :         mWebPage->mainFrame()->render( painter );
     141                 :          0 :       }
     142                 :          0 :       break;
     143                 :            :     }
     144                 :            : 
     145                 :            :     case ModeFont:
     146                 :            :     {
     147                 :          0 :       const QString textToDraw = currentText();
     148                 :          0 :       painter->setFont( mFont );
     149                 :          0 :       QgsLayoutUtils::drawText( painter, painterRect, textToDraw, mFont, mFontColor, mHAlignment, mVAlignment, Qt::TextWordWrap );
     150                 :            :       break;
     151                 :          0 :     }
     152                 :            :   }
     153                 :          0 : }
     154                 :            : 
     155                 :          0 : void QgsLayoutItemLabel::contentChanged()
     156                 :            : {
     157                 :          0 :   switch ( mMode )
     158                 :            :   {
     159                 :            :     case ModeHtml:
     160                 :            :     {
     161                 :          0 :       const QString textToDraw = currentText();
     162                 :          0 :       if ( !mWebPage )
     163                 :            :       {
     164                 :          0 :         mHtmlLoaded = true;
     165                 :          0 :         return;
     166                 :            :       }
     167                 :            : 
     168                 :            :       //mHtmlLoaded tracks whether the QWebPage has completed loading
     169                 :            :       //its html contents, set it initially to false. The loadingHtmlFinished slot will
     170                 :            :       //set this to true after html is loaded.
     171                 :          0 :       mHtmlLoaded = false;
     172                 :            : 
     173                 :          0 :       const QUrl baseUrl = QUrl::fromLocalFile( mLayout->project()->absoluteFilePath() );
     174                 :          0 :       mWebPage->mainFrame()->setHtml( textToDraw, baseUrl );
     175                 :            : 
     176                 :            :       //For very basic html labels with no external assets, the html load will already be
     177                 :            :       //complete before we even get a chance to start the QEventLoop. Make sure we check
     178                 :            :       //this before starting the loop
     179                 :            : 
     180                 :            :       // important -- we CAN'T do this when it's a render inside the designer, otherwise the
     181                 :            :       // event loop will mess with the paint event and cause it to be deleted, and BOOM!
     182                 :          0 :       if ( !mHtmlLoaded && ( !mLayout || !mLayout->renderContext().isPreviewRender() ) )
     183                 :            :       {
     184                 :            :         //Setup event loop and timeout for rendering html
     185                 :          0 :         QEventLoop loop;
     186                 :            : 
     187                 :            :         //Connect timeout and webpage loadFinished signals to loop
     188                 :          0 :         connect( mWebPage.get(), &QWebPage::loadFinished, &loop, &QEventLoop::quit );
     189                 :            : 
     190                 :            :         // Start a 20 second timeout in case html loading will never complete
     191                 :          0 :         QTimer timeoutTimer;
     192                 :          0 :         timeoutTimer.setSingleShot( true );
     193                 :          0 :         connect( &timeoutTimer, &QTimer::timeout, &loop, &QEventLoop::quit );
     194                 :          0 :         timeoutTimer.start( 20000 );
     195                 :            : 
     196                 :            :         // Pause until html is loaded
     197                 :          0 :         loop.exec( QEventLoop::ExcludeUserInputEvents );
     198                 :          0 :       }
     199                 :            :       break;
     200                 :          0 :     }
     201                 :            :     case ModeFont:
     202                 :          0 :       invalidateCache();
     203                 :          0 :       break;
     204                 :            :   }
     205                 :          0 : }
     206                 :            : 
     207                 :          0 : void QgsLayoutItemLabel::loadingHtmlFinished( bool result )
     208                 :            : {
     209                 :            :   Q_UNUSED( result )
     210                 :          0 :   mHtmlLoaded = true;
     211                 :          0 :   invalidateCache();
     212                 :          0 :   update();
     213                 :          0 : }
     214                 :            : 
     215                 :          0 : double QgsLayoutItemLabel::htmlUnitsToLayoutUnits()
     216                 :            : {
     217                 :          0 :   if ( !mLayout )
     218                 :            :   {
     219                 :          0 :     return 1.0;
     220                 :            :   }
     221                 :            : 
     222                 :            :   //TODO : fix this more precisely so that the label's default text size is the same with or without "display as html"
     223                 :          0 :   return mLayout->convertToLayoutUnits( QgsLayoutMeasurement( mLayout->renderContext().dpi() / 72.0, QgsUnitTypes::LayoutMillimeters ) ); //webkit seems to assume a standard dpi of 72
     224                 :          0 : }
     225                 :            : 
     226                 :          0 : void QgsLayoutItemLabel::setText( const QString &text )
     227                 :            : {
     228                 :          0 :   mText = text;
     229                 :          0 :   emit changed();
     230                 :            : 
     231                 :          0 :   contentChanged();
     232                 :            : 
     233                 :          0 :   if ( mLayout && id().isEmpty() && mMode != ModeHtml )
     234                 :          0 :   {
     235                 :            :     //notify the model that the display name has changed
     236                 :          0 :     mLayout->itemsModel()->updateItemDisplayName( this );
     237                 :          0 :   }
     238                 :          0 : }
     239                 :          0 : 
     240                 :          0 : void QgsLayoutItemLabel::setMode( Mode mode )
     241                 :            : {
     242                 :          0 :   if ( mode == mMode )
     243                 :            :   {
     244                 :          0 :     return;
     245                 :            :   }
     246                 :            : 
     247                 :          0 :   mMode = mode;
     248                 :          0 :   contentChanged();
     249                 :            : 
     250                 :          0 :   if ( mLayout && id().isEmpty() )
     251                 :            :   {
     252                 :            :     //notify the model that the display name has changed
     253                 :          0 :     mLayout->itemsModel()->updateItemDisplayName( this );
     254                 :          0 :   }
     255                 :          0 : }
     256                 :          0 : 
     257                 :          0 : void QgsLayoutItemLabel::refreshExpressionContext()
     258                 :            : {
     259                 :          0 :   if ( !mLayout )
     260                 :          0 :     return;
     261                 :            : 
     262                 :          0 :   QgsVectorLayer *layer = mLayout->reportContext().layer();
     263                 :            :   //setup distance area conversion
     264                 :          0 :   if ( layer )
     265                 :          0 :   {
     266                 :          0 :     mDistanceArea->setSourceCrs( layer->crs(), mLayout->project()->transformContext() );
     267                 :          0 :   }
     268                 :            :   else
     269                 :            :   {
     270                 :            :     //set to composition's reference map's crs
     271                 :          0 :     QgsLayoutItemMap *referenceMap = mLayout->referenceMap();
     272                 :          0 :     if ( referenceMap )
     273                 :          0 :       mDistanceArea->setSourceCrs( referenceMap->crs(), mLayout->project()->transformContext() );
     274                 :            :   }
     275                 :          0 :   mDistanceArea->setEllipsoid( mLayout->project()->ellipsoid() );
     276                 :          0 :   contentChanged();
     277                 :            : 
     278                 :          0 :   update();
     279                 :          0 : }
     280                 :            : 
     281                 :          0 : QString QgsLayoutItemLabel::currentText() const
     282                 :            : {
     283                 :          0 :   QString displayText = mText;
     284                 :          0 :   replaceDateText( displayText );
     285                 :            : 
     286                 :          0 :   QgsExpressionContext context = createExpressionContext();
     287                 :            : 
     288                 :          0 :   return QgsExpression::replaceExpressionText( displayText, &context, mDistanceArea.get() );
     289                 :          0 : }
     290                 :            : 
     291                 :          0 : void QgsLayoutItemLabel::replaceDateText( QString &text ) const
     292                 :            : {
     293                 :          0 :   QString constant = QStringLiteral( "$CURRENT_DATE" );
     294                 :          0 :   int currentDatePos = text.indexOf( constant );
     295                 :          0 :   if ( currentDatePos != -1 )
     296                 :            :   {
     297                 :            :     //check if there is a bracket just after $CURRENT_DATE
     298                 :          0 :     QString formatText;
     299                 :          0 :     int openingBracketPos = text.indexOf( '(', currentDatePos );
     300                 :          0 :     int closingBracketPos = text.indexOf( ')', openingBracketPos + 1 );
     301                 :          0 :     if ( openingBracketPos != -1 &&
     302                 :          0 :          closingBracketPos != -1 &&
     303                 :          0 :          ( closingBracketPos - openingBracketPos ) > 1 &&
     304                 :          0 :          openingBracketPos == currentDatePos + constant.size() )
     305                 :            :     {
     306                 :          0 :       formatText = text.mid( openingBracketPos + 1, closingBracketPos - openingBracketPos - 1 );
     307                 :          0 :       text.replace( currentDatePos, closingBracketPos - currentDatePos + 1, QDate::currentDate().toString( formatText ) );
     308                 :          0 :     }
     309                 :            :     else //no bracket
     310                 :            :     {
     311                 :          0 :       text.replace( QLatin1String( "$CURRENT_DATE" ), QDate::currentDate().toString() );
     312                 :            :     }
     313                 :          0 :   }
     314                 :          0 : }
     315                 :            : 
     316                 :          0 : void QgsLayoutItemLabel::setFont( const QFont &f )
     317                 :            : {
     318                 :          0 :   mFont = f;
     319                 :          0 : }
     320                 :            : 
     321                 :          0 : void QgsLayoutItemLabel::setMargin( const double m )
     322                 :            : {
     323                 :          0 :   mMarginX = m;
     324                 :          0 :   mMarginY = m;
     325                 :          0 :   prepareGeometryChange();
     326                 :          0 : }
     327                 :            : 
     328                 :          0 : void QgsLayoutItemLabel::setMarginX( const double margin )
     329                 :            : {
     330                 :          0 :   mMarginX = margin;
     331                 :          0 :   prepareGeometryChange();
     332                 :          0 : }
     333                 :            : 
     334                 :          0 : void QgsLayoutItemLabel::setMarginY( const double margin )
     335                 :            : {
     336                 :          0 :   mMarginY = margin;
     337                 :          0 :   prepareGeometryChange();
     338                 :          0 : }
     339                 :            : 
     340                 :          0 : void QgsLayoutItemLabel::adjustSizeToText()
     341                 :            : {
     342                 :          0 :   QSizeF newSize = sizeForText();
     343                 :            : 
     344                 :            :   //keep alignment point constant
     345                 :          0 :   double xShift = 0;
     346                 :          0 :   double yShift = 0;
     347                 :            : 
     348                 :          0 :   itemShiftAdjustSize( newSize.width(), newSize.height(), xShift, yShift );
     349                 :            : 
     350                 :            :   //update rect for data defined size and position
     351                 :          0 :   attemptSetSceneRect( QRectF( pos().x() + xShift, pos().y() + yShift, newSize.width(), newSize.height() ) );
     352                 :          0 : }
     353                 :            : 
     354                 :          0 : QSizeF QgsLayoutItemLabel::sizeForText() const
     355                 :            : {
     356                 :          0 :   double textWidth = QgsLayoutUtils::textWidthMM( mFont, currentText() );
     357                 :          0 :   double fontHeight = QgsLayoutUtils::fontHeightMM( mFont );
     358                 :            : 
     359                 :          0 :   double penWidth = frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
     360                 :            : 
     361                 :          0 :   double width = textWidth + 2 * mMarginX + 2 * penWidth;
     362                 :          0 :   double height = fontHeight + 2 * mMarginY + 2 * penWidth;
     363                 :            : 
     364                 :          0 :   return mLayout->convertToLayoutUnits( QgsLayoutSize( width, height, QgsUnitTypes::LayoutMillimeters ) );
     365                 :          0 : }
     366                 :            : 
     367                 :          0 : QFont QgsLayoutItemLabel::font() const
     368                 :            : {
     369                 :          0 :   return mFont;
     370                 :            : }
     371                 :            : 
     372                 :          0 : bool QgsLayoutItemLabel::writePropertiesToElement( QDomElement &layoutLabelElem, QDomDocument &doc, const QgsReadWriteContext & ) const
     373                 :            : {
     374                 :          0 :   layoutLabelElem.setAttribute( QStringLiteral( "htmlState" ), static_cast< int >( mMode ) );
     375                 :            : 
     376                 :          0 :   layoutLabelElem.setAttribute( QStringLiteral( "labelText" ), mText );
     377                 :          0 :   layoutLabelElem.setAttribute( QStringLiteral( "marginX" ), QString::number( mMarginX ) );
     378                 :          0 :   layoutLabelElem.setAttribute( QStringLiteral( "marginY" ), QString::number( mMarginY ) );
     379                 :          0 :   layoutLabelElem.setAttribute( QStringLiteral( "halign" ), mHAlignment );
     380                 :          0 :   layoutLabelElem.setAttribute( QStringLiteral( "valign" ), mVAlignment );
     381                 :            : 
     382                 :            :   //font
     383                 :          0 :   QDomElement labelFontElem = QgsFontUtils::toXmlElement( mFont, doc, QStringLiteral( "LabelFont" ) );
     384                 :          0 :   layoutLabelElem.appendChild( labelFontElem );
     385                 :            : 
     386                 :            :   //font color
     387                 :          0 :   QDomElement fontColorElem = doc.createElement( QStringLiteral( "FontColor" ) );
     388                 :          0 :   fontColorElem.setAttribute( QStringLiteral( "red" ), mFontColor.red() );
     389                 :          0 :   fontColorElem.setAttribute( QStringLiteral( "green" ), mFontColor.green() );
     390                 :          0 :   fontColorElem.setAttribute( QStringLiteral( "blue" ), mFontColor.blue() );
     391                 :          0 :   fontColorElem.setAttribute( QStringLiteral( "alpha" ), mFontColor.alpha() );
     392                 :          0 :   layoutLabelElem.appendChild( fontColorElem );
     393                 :            : 
     394                 :            :   return true;
     395                 :          0 : }
     396                 :            : 
     397                 :          0 : bool QgsLayoutItemLabel::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext & )
     398                 :            : {
     399                 :            :   //restore label specific properties
     400                 :            : 
     401                 :            :   //text
     402                 :          0 :   mText = itemElem.attribute( QStringLiteral( "labelText" ) );
     403                 :            : 
     404                 :            :   //html state
     405                 :          0 :   mMode = static_cast< Mode >( itemElem.attribute( QStringLiteral( "htmlState" ) ).toInt() );
     406                 :            : 
     407                 :            :   //margin
     408                 :          0 :   bool marginXOk = false;
     409                 :          0 :   bool marginYOk = false;
     410                 :          0 :   mMarginX = itemElem.attribute( QStringLiteral( "marginX" ) ).toDouble( &marginXOk );
     411                 :          0 :   mMarginY = itemElem.attribute( QStringLiteral( "marginY" ) ).toDouble( &marginYOk );
     412                 :          0 :   if ( !marginXOk || !marginYOk )
     413                 :            :   {
     414                 :            :     //upgrade old projects where margins where stored in a single attribute
     415                 :          0 :     double margin = itemElem.attribute( QStringLiteral( "margin" ), QStringLiteral( "1.0" ) ).toDouble();
     416                 :          0 :     mMarginX = margin;
     417                 :          0 :     mMarginY = margin;
     418                 :          0 :   }
     419                 :            : 
     420                 :            :   //Horizontal alignment
     421                 :          0 :   mHAlignment = static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "halign" ) ).toInt() );
     422                 :            : 
     423                 :            :   //Vertical alignment
     424                 :          0 :   mVAlignment = static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "valign" ) ).toInt() );
     425                 :            : 
     426                 :            :   //font
     427                 :          0 :   QgsFontUtils::setFromXmlChildNode( mFont, itemElem, QStringLiteral( "LabelFont" ) );
     428                 :            : 
     429                 :            :   //font color
     430                 :          0 :   QDomNodeList fontColorList = itemElem.elementsByTagName( QStringLiteral( "FontColor" ) );
     431                 :          0 :   if ( !fontColorList.isEmpty() )
     432                 :            :   {
     433                 :          0 :     QDomElement fontColorElem = fontColorList.at( 0 ).toElement();
     434                 :          0 :     int red = fontColorElem.attribute( QStringLiteral( "red" ), QStringLiteral( "0" ) ).toInt();
     435                 :          0 :     int green = fontColorElem.attribute( QStringLiteral( "green" ), QStringLiteral( "0" ) ).toInt();
     436                 :          0 :     int blue = fontColorElem.attribute( QStringLiteral( "blue" ), QStringLiteral( "0" ) ).toInt();
     437                 :          0 :     int alpha = fontColorElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt();
     438                 :          0 :     mFontColor = QColor( red, green, blue, alpha );
     439                 :          0 :   }
     440                 :            :   else
     441                 :            :   {
     442                 :          0 :     mFontColor = QColor( 0, 0, 0 );
     443                 :            :   }
     444                 :            : 
     445                 :            :   return true;
     446                 :          0 : }
     447                 :            : 
     448                 :          0 : QString QgsLayoutItemLabel::displayName() const
     449                 :            : {
     450                 :          0 :   if ( !id().isEmpty() )
     451                 :            :   {
     452                 :          0 :     return id();
     453                 :            :   }
     454                 :            : 
     455                 :          0 :   switch ( mMode )
     456                 :            :   {
     457                 :            :     case ModeHtml:
     458                 :          0 :       return tr( "<HTML Label>" );
     459                 :            : 
     460                 :            :     case ModeFont:
     461                 :            :     {
     462                 :            : 
     463                 :            :       //if no id, default to portion of label text
     464                 :          0 :       QString text = mText;
     465                 :          0 :       if ( text.isEmpty() )
     466                 :            :       {
     467                 :          0 :         return tr( "<Label>" );
     468                 :            :       }
     469                 :          0 :       if ( text.length() > 25 )
     470                 :            :       {
     471                 :          0 :         return QString( tr( "%1…" ) ).arg( text.left( 25 ).simplified() );
     472                 :            :       }
     473                 :            :       else
     474                 :            :       {
     475                 :          0 :         return text.simplified();
     476                 :            :       }
     477                 :          0 :     }
     478                 :            :   }
     479                 :          0 :   return QString(); // no warnings
     480                 :          0 : }
     481                 :            : 
     482                 :          0 : QRectF QgsLayoutItemLabel::boundingRect() const
     483                 :            : {
     484                 :          0 :   QRectF rectangle = rect();
     485                 :          0 :   double penWidth = frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
     486                 :          0 :   rectangle.adjust( -penWidth, -penWidth, penWidth, penWidth );
     487                 :            : 
     488                 :          0 :   if ( mMarginX < 0 )
     489                 :            :   {
     490                 :          0 :     rectangle.adjust( mMarginX, 0, -mMarginX, 0 );
     491                 :          0 :   }
     492                 :          0 :   if ( mMarginY < 0 )
     493                 :            :   {
     494                 :          0 :     rectangle.adjust( 0, mMarginY, 0, -mMarginY );
     495                 :          0 :   }
     496                 :            : 
     497                 :          0 :   return rectangle;
     498                 :          0 : }
     499                 :            : 
     500                 :          0 : void QgsLayoutItemLabel::setFrameEnabled( const bool drawFrame )
     501                 :            : {
     502                 :          0 :   QgsLayoutItem::setFrameEnabled( drawFrame );
     503                 :          0 :   prepareGeometryChange();
     504                 :          0 : }
     505                 :            : 
     506                 :          0 : void QgsLayoutItemLabel::setFrameStrokeWidth( const QgsLayoutMeasurement strokeWidth )
     507                 :            : {
     508                 :          0 :   QgsLayoutItem::setFrameStrokeWidth( strokeWidth );
     509                 :          0 :   prepareGeometryChange();
     510                 :          0 : }
     511                 :            : 
     512                 :          0 : void QgsLayoutItemLabel::refresh()
     513                 :            : {
     514                 :          0 :   invalidateCache();
     515                 :          0 :   QgsLayoutItem::refresh();
     516                 :          0 :   refreshExpressionContext();
     517                 :          0 : }
     518                 :            : 
     519                 :          0 : void QgsLayoutItemLabel::itemShiftAdjustSize( double newWidth, double newHeight, double &xShift, double &yShift ) const
     520                 :            : {
     521                 :            :   //keep alignment point constant
     522                 :          0 :   double currentWidth = rect().width();
     523                 :          0 :   double currentHeight = rect().height();
     524                 :          0 :   xShift = 0;
     525                 :          0 :   yShift = 0;
     526                 :            : 
     527                 :          0 :   double r = rotation();
     528                 :          0 :   if ( r >= 0 && r < 90 )
     529                 :            :   {
     530                 :          0 :     if ( mHAlignment == Qt::AlignHCenter )
     531                 :            :     {
     532                 :          0 :       xShift = - ( newWidth - currentWidth ) / 2.0;
     533                 :          0 :     }
     534                 :          0 :     else if ( mHAlignment == Qt::AlignRight )
     535                 :            :     {
     536                 :          0 :       xShift = - ( newWidth - currentWidth );
     537                 :          0 :     }
     538                 :          0 :     if ( mVAlignment == Qt::AlignVCenter )
     539                 :            :     {
     540                 :          0 :       yShift = -( newHeight - currentHeight ) / 2.0;
     541                 :          0 :     }
     542                 :          0 :     else if ( mVAlignment == Qt::AlignBottom )
     543                 :            :     {
     544                 :          0 :       yShift = - ( newHeight - currentHeight );
     545                 :          0 :     }
     546                 :          0 :   }
     547                 :          0 :   if ( r >= 90 && r < 180 )
     548                 :            :   {
     549                 :          0 :     if ( mHAlignment == Qt::AlignHCenter )
     550                 :            :     {
     551                 :          0 :       yShift = -( newHeight  - currentHeight ) / 2.0;
     552                 :          0 :     }
     553                 :          0 :     else if ( mHAlignment == Qt::AlignRight )
     554                 :            :     {
     555                 :          0 :       yShift = -( newHeight  - currentHeight );
     556                 :          0 :     }
     557                 :          0 :     if ( mVAlignment == Qt::AlignTop )
     558                 :            :     {
     559                 :          0 :       xShift = -( newWidth - currentWidth );
     560                 :          0 :     }
     561                 :          0 :     else if ( mVAlignment == Qt::AlignVCenter )
     562                 :            :     {
     563                 :          0 :       xShift = -( newWidth - currentWidth / 2.0 );
     564                 :          0 :     }
     565                 :          0 :   }
     566                 :          0 :   else if ( r >= 180 && r < 270 )
     567                 :            :   {
     568                 :          0 :     if ( mHAlignment == Qt::AlignHCenter )
     569                 :            :     {
     570                 :          0 :       xShift = -( newWidth - currentWidth ) / 2.0;
     571                 :          0 :     }
     572                 :          0 :     else if ( mHAlignment == Qt::AlignLeft )
     573                 :            :     {
     574                 :          0 :       xShift = -( newWidth - currentWidth );
     575                 :          0 :     }
     576                 :          0 :     if ( mVAlignment == Qt::AlignVCenter )
     577                 :            :     {
     578                 :          0 :       yShift = ( newHeight - currentHeight ) / 2.0;
     579                 :          0 :     }
     580                 :          0 :     else if ( mVAlignment == Qt::AlignTop )
     581                 :            :     {
     582                 :          0 :       yShift = ( newHeight - currentHeight );
     583                 :          0 :     }
     584                 :          0 :   }
     585                 :          0 :   else if ( r >= 270 && r < 360 )
     586                 :            :   {
     587                 :          0 :     if ( mHAlignment == Qt::AlignHCenter )
     588                 :            :     {
     589                 :          0 :       yShift = -( newHeight  - currentHeight ) / 2.0;
     590                 :          0 :     }
     591                 :          0 :     else if ( mHAlignment == Qt::AlignLeft )
     592                 :            :     {
     593                 :          0 :       yShift = -( newHeight  - currentHeight );
     594                 :          0 :     }
     595                 :          0 :     if ( mVAlignment == Qt::AlignBottom )
     596                 :            :     {
     597                 :          0 :       xShift = -( newWidth - currentWidth );
     598                 :          0 :     }
     599                 :          0 :     else if ( mVAlignment == Qt::AlignVCenter )
     600                 :            :     {
     601                 :          0 :       xShift = -( newWidth - currentWidth / 2.0 );
     602                 :          0 :     }
     603                 :          0 :   }
     604                 :          0 : }
     605                 :            : 
     606                 :          0 : QUrl QgsLayoutItemLabel::createStylesheetUrl() const
     607                 :            : {
     608                 :          0 :   QString stylesheet;
     609                 :          0 :   stylesheet += QStringLiteral( "body { margin: %1 %2;" ).arg( std::max( mMarginY * mHtmlUnitsToLayoutUnits, 0.0 ) ).arg( std::max( mMarginX * mHtmlUnitsToLayoutUnits, 0.0 ) );
     610                 :          0 :   stylesheet += QgsFontUtils::asCSS( mFont, 0.352778 * mHtmlUnitsToLayoutUnits );
     611                 :          0 :   stylesheet += QStringLiteral( "color: rgba(%1,%2,%3,%4);" ).arg( mFontColor.red() ).arg( mFontColor.green() ).arg( mFontColor.blue() ).arg( QString::number( mFontColor.alphaF(), 'f', 4 ) );
     612                 :          0 :   stylesheet += QStringLiteral( "text-align: %1; }" ).arg( mHAlignment == Qt::AlignLeft ? QStringLiteral( "left" ) : mHAlignment == Qt::AlignRight ? QStringLiteral( "right" ) : mHAlignment == Qt::AlignHCenter ? QStringLiteral( "center" ) : QStringLiteral( "justify" ) );
     613                 :            : 
     614                 :          0 :   QByteArray ba;
     615                 :          0 :   ba.append( stylesheet.toUtf8() );
     616                 :          0 :   QUrl cssFileURL = QUrl( QString( "data:text/css;charset=utf-8;base64," + ba.toBase64() ) );
     617                 :            : 
     618                 :          0 :   return cssFileURL;
     619                 :          0 : }

Generated by: LCOV version 1.14