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 : }
|