40 #include <QCoreApplication>
42 #include <QDomElement>
52 mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits();
56 const QString defaultFontString = settings.
value( QStringLiteral(
"LayoutDesigner/defaultFont" ), QVariant(),
QgsSettings::Gui ).toString();
57 if ( !defaultFontString.isEmpty() )
59 QFont f = mFormat.
font();
60 f.setFamily( defaultFontString );
73 refreshExpressionContext();
76 if ( QThread::currentThread() == QApplication::instance()->thread() )
86 mWebPage->setIdentifier( tr(
"Layout label item" ) );
90 QPalette palette = mWebPage->palette();
91 palette.setBrush( QPalette::Base, Qt::transparent );
92 mWebPage->setPalette( palette );
94 mWebPage->mainFrame()->setZoomFactor( 10.0 );
95 mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
96 mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
98 connect( mWebPage.get(), &QWebPage::loadFinished,
this, &QgsLayoutItemLabel::loadingHtmlFinished );
122 double rectScale = 1.0;
133 const double penWidth =
frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
134 const double xPenAdjust = mMarginX < 0 ? -penWidth : penWidth;
135 const double yPenAdjust = mMarginY < 0 ? -penWidth : penWidth;
136 const QRectF painterRect( ( xPenAdjust + mMarginX ) * rectScale,
137 ( yPenAdjust + mMarginY ) * rectScale,
138 ( rect().width() - 2 * xPenAdjust - 2 * mMarginX ) * rectScale,
139 ( rect().height() - 2 * yPenAdjust - 2 * mMarginY ) * rectScale );
148 mFirstRender =
false;
153 painter->scale( 1.0 / mHtmlUnitsToLayoutUnits / 10.0, 1.0 / mHtmlUnitsToLayoutUnits / 10.0 );
154 mWebPage->setViewportSize( QSize( painterRect.width() * mHtmlUnitsToLayoutUnits * 10.0, painterRect.height() * mHtmlUnitsToLayoutUnits * 10.0 ) );
155 mWebPage->settings()->setUserStyleSheetUrl( createStylesheetUrl() );
156 mWebPage->mainFrame()->render( painter );
177 void QgsLayoutItemLabel::contentChanged()
195 const QUrl baseUrl = QUrl::fromLocalFile(
mLayout->project()->absoluteFilePath() );
196 mWebPage->mainFrame()->setHtml( textToDraw, baseUrl );
204 if ( !mHtmlLoaded && ( !
mLayout || !
mLayout->renderContext().isPreviewRender() ) )
210 connect( mWebPage.get(), &QWebPage::loadFinished, &loop, &QEventLoop::quit );
214 timeoutTimer.setSingleShot(
true );
215 connect( &timeoutTimer, &QTimer::timeout, &loop, &QEventLoop::quit );
216 timeoutTimer.start( 20000 );
219 loop.exec( QEventLoop::ExcludeUserInputEvents );
229 void QgsLayoutItemLabel::loadingHtmlFinished(
bool result )
237 double QgsLayoutItemLabel::htmlUnitsToLayoutUnits()
258 mLayout->itemsModel()->updateItemDisplayName(
this );
272 if (
mLayout &&
id().isEmpty() )
275 mLayout->itemsModel()->updateItemDisplayName(
this );
279 void QgsLayoutItemLabel::refreshExpressionContext()
288 mDistanceArea->setSourceCrs( layer->
crs(),
mLayout->project()->transformContext() );
295 mDistanceArea->setSourceCrs( referenceMap->
crs(),
mLayout->project()->transformContext() );
297 mDistanceArea->setEllipsoid(
mLayout->project()->ellipsoid() );
305 QString displayText = mText;
306 replaceDateText( displayText );
313 void QgsLayoutItemLabel::replaceDateText( QString &text )
const
315 const QString constant = QStringLiteral(
"$CURRENT_DATE" );
316 const int currentDatePos =
text.indexOf( constant );
317 if ( currentDatePos != -1 )
321 const int openingBracketPos =
text.indexOf(
'(', currentDatePos );
322 const int closingBracketPos =
text.indexOf(
')', openingBracketPos + 1 );
323 if ( openingBracketPos != -1 &&
324 closingBracketPos != -1 &&
325 ( closingBracketPos - openingBracketPos ) > 1 &&
326 openingBracketPos == currentDatePos + constant.size() )
328 formatText =
text.mid( openingBracketPos + 1, closingBracketPos - openingBracketPos - 1 );
329 text.replace( currentDatePos, closingBracketPos - currentDatePos + 1, QDate::currentDate().toString( formatText ) );
333 text.replace( QLatin1String(
"$CURRENT_DATE" ), QDate::currentDate().toString() );
341 if ( f.pointSizeF() > 0 )
342 mFormat.
setSize( f.pointSizeF() );
359 prepareGeometryChange();
365 prepareGeometryChange();
371 prepareGeometryChange();
382 itemShiftAdjustSize( newSize.width(), newSize.height(), xShift, yShift );
385 attemptSetSceneRect( QRectF( pos().x() + xShift, pos().y() + yShift, newSize.width(), newSize.height() ) );
392 const QStringList lines =
currentText().split(
'\n' );
396 const double penWidth =
frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
398 const double width = textWidth + 2 * mMarginX + 2 * penWidth;
399 const double height = fontHeight + 2 * mMarginY + 2 * penWidth;
406 return mFormat.
font();
411 layoutLabelElem.setAttribute( QStringLiteral(
"htmlState" ),
static_cast< int >( mMode ) );
413 layoutLabelElem.setAttribute( QStringLiteral(
"labelText" ), mText );
414 layoutLabelElem.setAttribute( QStringLiteral(
"marginX" ), QString::number( mMarginX ) );
415 layoutLabelElem.setAttribute( QStringLiteral(
"marginY" ), QString::number( mMarginY ) );
416 layoutLabelElem.setAttribute( QStringLiteral(
"halign" ), mHAlignment );
417 layoutLabelElem.setAttribute( QStringLiteral(
"valign" ), mVAlignment );
419 QDomElement textElem = mFormat.
writeXml( doc, rwContext );
420 layoutLabelElem.appendChild( textElem );
430 mText = itemElem.attribute( QStringLiteral(
"labelText" ) );
433 mMode =
static_cast< Mode >( itemElem.attribute( QStringLiteral(
"htmlState" ) ).toInt() );
436 bool marginXOk =
false;
437 bool marginYOk =
false;
438 mMarginX = itemElem.attribute( QStringLiteral(
"marginX" ) ).toDouble( &marginXOk );
439 mMarginY = itemElem.attribute( QStringLiteral(
"marginY" ) ).toDouble( &marginYOk );
440 if ( !marginXOk || !marginYOk )
443 const double margin = itemElem.attribute( QStringLiteral(
"margin" ), QStringLiteral(
"1.0" ) ).toDouble();
449 mHAlignment =
static_cast< Qt::AlignmentFlag
>( itemElem.attribute( QStringLiteral(
"halign" ) ).toInt() );
452 mVAlignment =
static_cast< Qt::AlignmentFlag
>( itemElem.attribute( QStringLiteral(
"valign" ) ).toInt() );
455 QDomNodeList textFormatNodeList = itemElem.elementsByTagName( QStringLiteral(
"text-style" ) );
456 if ( !textFormatNodeList.isEmpty() )
458 QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement();
459 mFormat.
readXml( textFormatElem, context );
466 f.fromString( itemElem.attribute( QStringLiteral(
"font" ), QString() ) );
469 if ( f.pointSizeF() > 0 )
471 mFormat.
setSize( f.pointSizeF() );
474 else if ( f.pixelSize() > 0 )
476 mFormat.
setSize( f.pixelSize() );
481 const QDomNodeList fontColorList = itemElem.elementsByTagName( QStringLiteral(
"FontColor" ) );
482 if ( !fontColorList.isEmpty() )
484 const QDomElement fontColorElem = fontColorList.at( 0 ).toElement();
485 const int red = fontColorElem.attribute( QStringLiteral(
"red" ), QStringLiteral(
"0" ) ).toInt();
486 const int green = fontColorElem.attribute( QStringLiteral(
"green" ), QStringLiteral(
"0" ) ).toInt();
487 const int blue = fontColorElem.attribute( QStringLiteral(
"blue" ), QStringLiteral(
"0" ) ).toInt();
488 const int alpha = fontColorElem.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"255" ) ).toInt();
489 mFormat.
setColor( QColor( red, green, blue, alpha ) );
491 else if ( textFormatNodeList.isEmpty() )
493 mFormat.
setColor( QColor( 0, 0, 0 ) );
502 if ( !
id().isEmpty() )
510 return tr(
"<HTML Label>" );
516 const QString
text = mText;
517 if (
text.isEmpty() )
519 return tr(
"<Label>" );
521 if (
text.length() > 25 )
523 return QString( tr(
"%1…" ) ).arg(
text.left( 25 ).simplified() );
527 return text.simplified();
536 QRectF rectangle = rect();
537 const double penWidth =
frameEnabled() ? ( pen().widthF() / 2.0 ) : 0;
538 rectangle.adjust( -penWidth, -penWidth, penWidth, penWidth );
542 rectangle.adjust( mMarginX, 0, -mMarginX, 0 );
546 rectangle.adjust( 0, mMarginY, 0, -mMarginY );
555 prepareGeometryChange();
561 prepareGeometryChange();
568 refreshExpressionContext();
574 if ( evaluated == mText )
580 void QgsLayoutItemLabel::itemShiftAdjustSize(
double newWidth,
double newHeight,
double &xShift,
double &yShift )
const
583 const double currentWidth = rect().width();
584 const double currentHeight = rect().height();
588 const double r = rotation();
589 if ( r >= 0 && r < 90 )
591 if ( mHAlignment == Qt::AlignHCenter )
593 xShift = - ( newWidth - currentWidth ) / 2.0;
595 else if ( mHAlignment == Qt::AlignRight )
597 xShift = - ( newWidth - currentWidth );
599 if ( mVAlignment == Qt::AlignVCenter )
601 yShift = -( newHeight - currentHeight ) / 2.0;
603 else if ( mVAlignment == Qt::AlignBottom )
605 yShift = - ( newHeight - currentHeight );
608 if ( r >= 90 && r < 180 )
610 if ( mHAlignment == Qt::AlignHCenter )
612 yShift = -( newHeight - currentHeight ) / 2.0;
614 else if ( mHAlignment == Qt::AlignRight )
616 yShift = -( newHeight - currentHeight );
618 if ( mVAlignment == Qt::AlignTop )
620 xShift = -( newWidth - currentWidth );
622 else if ( mVAlignment == Qt::AlignVCenter )
624 xShift = -( newWidth - currentWidth / 2.0 );
627 else if ( r >= 180 && r < 270 )
629 if ( mHAlignment == Qt::AlignHCenter )
631 xShift = -( newWidth - currentWidth ) / 2.0;
633 else if ( mHAlignment == Qt::AlignLeft )
635 xShift = -( newWidth - currentWidth );
637 if ( mVAlignment == Qt::AlignVCenter )
639 yShift = ( newHeight - currentHeight ) / 2.0;
641 else if ( mVAlignment == Qt::AlignTop )
643 yShift = ( newHeight - currentHeight );
646 else if ( r >= 270 && r < 360 )
648 if ( mHAlignment == Qt::AlignHCenter )
650 yShift = -( newHeight - currentHeight ) / 2.0;
652 else if ( mHAlignment == Qt::AlignLeft )
654 yShift = -( newHeight - currentHeight );
656 if ( mVAlignment == Qt::AlignBottom )
658 xShift = -( newWidth - currentWidth );
660 else if ( mVAlignment == Qt::AlignVCenter )
662 xShift = -( newWidth - currentWidth / 2.0 );
667 QUrl QgsLayoutItemLabel::createStylesheetUrl()
const
670 stylesheet += QStringLiteral(
"body { margin: %1 %2;" ).arg( std::max( mMarginY * mHtmlUnitsToLayoutUnits, 0.0 ) ).arg( std::max( mMarginX * mHtmlUnitsToLayoutUnits, 0.0 ) );
671 QFont f = mFormat.
font();
675 f.setPointSizeF( mFormat.
size() / 0.352778 );
678 f.setPixelSize( mFormat.
size() );
681 f.setPointSizeF( mFormat.
size() );
684 f.setPointSizeF( mFormat.
size() * 72 );
694 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 ) );
695 stylesheet += QStringLiteral(
"text-align: %1; }" ).arg( mHAlignment == Qt::AlignLeft ? QStringLiteral(
"left" ) : mHAlignment == Qt::AlignRight ? QStringLiteral(
"right" ) : mHAlignment == Qt::AlignHCenter ? QStringLiteral(
"center" ) : QStringLiteral(
"justify" ) );
698 ba.append( stylesheet.toUtf8() );
699 QUrl cssFileURL = QUrl( QString(
"data:text/css;charset=utf-8;base64," + ba.toBase64() ) );