QGIS API Documentation  2.3.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscomposeritem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposeritem.cpp
3  -------------------
4  begin : January 2005
5  copyright : (C) 2005 by Radim Blazek
6  email : blazek@itc.it
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 #include <QWidget>
18 #include <QDomNode>
19 #include <QFile>
20 #include <QGraphicsLineItem>
21 #include <QGraphicsScene>
22 #include <QGraphicsSceneMouseEvent>
23 #include <QGraphicsView>
24 #include <QPainter>
25 #include <QUuid>
26 #include <QGraphicsEffect>
27 
28 #include "qgsproject.h"
29 
30 #include "qgscomposition.h"
31 #include "qgscomposeritem.h"
32 #include "qgscomposerframe.h"
33 
34 #include <limits>
35 #include "qgsapplication.h"
36 #include "qgsrectangle.h" //just for debugging
37 #include "qgslogger.h"
38 #include "qgssymbollayerv2utils.h" //for pointOnLineWithDistance
39 #include "qgsmaprenderer.h" //for getCompositionMode
40 
41 #include <cmath>
42 
43 #define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter
44 
45 #ifndef M_DEG2RAD
46 #define M_DEG2RAD 0.0174532925
47 #endif
48 
49 QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue )
50  : QObject( 0 )
51  , QGraphicsRectItem( 0 )
52  , mComposition( composition )
53  , mBoundingResizeRectangle( 0 )
54  , mHAlignSnapItem( 0 )
55  , mVAlignSnapItem( 0 )
56  , mFrame( false )
57  , mBackground( true )
58  , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
59  , mFrameJoinStyle( Qt::MiterJoin )
60  , mItemPositionLocked( false )
61  , mLastValidViewScaleFactor( -1 )
62  , mItemRotation( 0 )
63  , mBlendMode( QPainter::CompositionMode_SourceOver )
64  , mEffectsEnabled( true )
65  , mTransparency( 0 )
66  , mLastUsedPositionMode( UpperLeft )
67  , mCurrentExportLayer( -1 )
68  , mId( "" )
69  , mUuid( QUuid::createUuid().toString() )
70 {
71  init( manageZValue );
72 }
73 
74 QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, QgsComposition* composition, bool manageZValue )
75  : QObject( 0 )
76  , QGraphicsRectItem( 0, 0, width, height, 0 )
77  , mComposition( composition )
78  , mBoundingResizeRectangle( 0 )
79  , mHAlignSnapItem( 0 )
80  , mVAlignSnapItem( 0 )
81  , mFrame( false )
82  , mBackground( true )
83  , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
84  , mFrameJoinStyle( Qt::MiterJoin )
85  , mItemPositionLocked( false )
86  , mLastValidViewScaleFactor( -1 )
87  , mItemRotation( 0 )
88  , mBlendMode( QPainter::CompositionMode_SourceOver )
89  , mEffectsEnabled( true )
90  , mTransparency( 0 )
91  , mLastUsedPositionMode( UpperLeft )
92  , mCurrentExportLayer( -1 )
93  , mId( "" )
94  , mUuid( QUuid::createUuid().toString() )
95 {
96  init( manageZValue );
97  setPos( x, y );
98 }
99 
100 void QgsComposerItem::init( bool manageZValue )
101 {
102  setFlag( QGraphicsItem::ItemIsSelectable, true );
103  //set default pen and brush
104  setBrush( QBrush( QColor( 255, 255, 255, 255 ) ) );
105  QPen defaultPen( QColor( 0, 0, 0 ) );
106  defaultPen.setWidthF( 0.3 );
107  defaultPen.setJoinStyle( mFrameJoinStyle );
108  setPen( defaultPen );
109  //let z-Value be managed by composition
110  if ( mComposition && manageZValue )
111  {
112  mComposition->addItemToZList( this );
113  }
114 
115  // Setup composer effect
116  mEffect = new QgsComposerEffect();
117  setGraphicsEffect( mEffect );
118 }
119 
121 {
122  if ( mComposition )
123  {
125  }
126 
128  delete mEffect;
130 }
131 
133 {
134  QgsDebugMsg( "entered." );
135  QGraphicsRectItem::setSelected( s );
136  update(); //to draw selection boxes
137 }
138 
139 bool QgsComposerItem::writeSettings( void ) { return true; }
140 
141 bool QgsComposerItem::readSettings( void ) { return true; }
142 
143 bool QgsComposerItem::removeSettings( void ) { return true; }
144 
145 bool QgsComposerItem::_writeXML( QDomElement& itemElem, QDomDocument& doc ) const
146 {
147  if ( itemElem.isNull() )
148  {
149  return false;
150  }
151 
152  QDomElement composerItemElem = doc.createElement( "ComposerItem" );
153 
154  //frame
155  if ( mFrame )
156  {
157  composerItemElem.setAttribute( "frame", "true" );
158  }
159  else
160  {
161  composerItemElem.setAttribute( "frame", "false" );
162  }
163 
164  //frame
165  if ( mBackground )
166  {
167  composerItemElem.setAttribute( "background", "true" );
168  }
169  else
170  {
171  composerItemElem.setAttribute( "background", "false" );
172  }
173 
174  //scene rect
175  composerItemElem.setAttribute( "x", QString::number( pos().x() ) );
176  composerItemElem.setAttribute( "y", QString::number( pos().y() ) );
177  composerItemElem.setAttribute( "width", QString::number( rect().width() ) );
178  composerItemElem.setAttribute( "height", QString::number( rect().height() ) );
179  composerItemElem.setAttribute( "positionMode", QString::number(( int ) mLastUsedPositionMode ) );
180  composerItemElem.setAttribute( "zValue", QString::number( zValue() ) );
181  composerItemElem.setAttribute( "outlineWidth", QString::number( pen().widthF() ) );
182  composerItemElem.setAttribute( "frameJoinStyle", QgsSymbolLayerV2Utils::encodePenJoinStyle( mFrameJoinStyle ) );
183  composerItemElem.setAttribute( "itemRotation", QString::number( mItemRotation ) );
184  composerItemElem.setAttribute( "uuid", mUuid );
185  composerItemElem.setAttribute( "id", mId );
186  //position lock for mouse moves/resizes
187  if ( mItemPositionLocked )
188  {
189  composerItemElem.setAttribute( "positionLock", "true" );
190  }
191  else
192  {
193  composerItemElem.setAttribute( "positionLock", "false" );
194  }
195 
196  composerItemElem.setAttribute( "lastValidViewScaleFactor", QString::number( mLastValidViewScaleFactor ) );
197 
198 
199  //frame color
200  QDomElement frameColorElem = doc.createElement( "FrameColor" );
201  QColor frameColor = pen().color();
202  frameColorElem.setAttribute( "red", QString::number( frameColor.red() ) );
203  frameColorElem.setAttribute( "green", QString::number( frameColor.green() ) );
204  frameColorElem.setAttribute( "blue", QString::number( frameColor.blue() ) );
205  frameColorElem.setAttribute( "alpha", QString::number( frameColor.alpha() ) );
206  composerItemElem.appendChild( frameColorElem );
207 
208  //background color
209  QDomElement bgColorElem = doc.createElement( "BackgroundColor" );
210  QColor bgColor = brush().color();
211  bgColorElem.setAttribute( "red", QString::number( bgColor.red() ) );
212  bgColorElem.setAttribute( "green", QString::number( bgColor.green() ) );
213  bgColorElem.setAttribute( "blue", QString::number( bgColor.blue() ) );
214  bgColorElem.setAttribute( "alpha", QString::number( bgColor.alpha() ) );
215  composerItemElem.appendChild( bgColorElem );
216 
217  //blend mode
218  composerItemElem.setAttribute( "blendMode", QgsMapRenderer::getBlendModeEnum( mBlendMode ) );
219 
220  //transparency
221  composerItemElem.setAttribute( "transparency", QString::number( mTransparency ) );
222 
223  itemElem.appendChild( composerItemElem );
224 
225  return true;
226 }
227 
228 bool QgsComposerItem::_readXML( const QDomElement& itemElem, const QDomDocument& doc )
229 {
230  Q_UNUSED( doc );
231  if ( itemElem.isNull() )
232  {
233  return false;
234  }
235 
236  //rotation
237  setItemRotation( itemElem.attribute( "itemRotation", "0" ).toDouble() );
238 
239  //uuid
240  mUuid = itemElem.attribute( "uuid", QUuid::createUuid().toString() );
241 
242  // temporary for groups imported from templates
243  mTemplateUuid = itemElem.attribute( "templateUuid" );
244 
245  //id
246  QString id = itemElem.attribute( "id", "" );
247  setId( id );
248 
249  //frame
250  QString frame = itemElem.attribute( "frame" );
251  if ( frame.compare( "true", Qt::CaseInsensitive ) == 0 )
252  {
253  mFrame = true;
254  }
255  else
256  {
257  mFrame = false;
258  }
259 
260  //frame
261  QString background = itemElem.attribute( "background" );
262  if ( background.compare( "true", Qt::CaseInsensitive ) == 0 )
263  {
264  mBackground = true;
265  }
266  else
267  {
268  mBackground = false;
269  }
270 
271  //position lock for mouse moves/resizes
272  QString positionLock = itemElem.attribute( "positionLock" );
273  if ( positionLock.compare( "true", Qt::CaseInsensitive ) == 0 )
274  {
275  setPositionLock( true );
276  }
277  else
278  {
279  setPositionLock( false );
280  }
281 
282  //position
283  double x, y, width, height;
284  bool xOk, yOk, widthOk, heightOk, positionModeOK;
285 
286  x = itemElem.attribute( "x" ).toDouble( &xOk );
287  y = itemElem.attribute( "y" ).toDouble( &yOk );
288  width = itemElem.attribute( "width" ).toDouble( &widthOk );
289  height = itemElem.attribute( "height" ).toDouble( &heightOk );
290  mLastUsedPositionMode = ( ItemPositionMode )itemElem.attribute( "positionMode" ).toInt( &positionModeOK );
291  if ( !positionModeOK )
292  {
294  }
295 
296  if ( !xOk || !yOk || !widthOk || !heightOk )
297  {
298  return false;
299  }
300 
301  mLastValidViewScaleFactor = itemElem.attribute( "lastValidViewScaleFactor", "-1" ).toDouble();
302 
303  setSceneRect( QRectF( x, y, width, height ) );
304  setZValue( itemElem.attribute( "zValue" ).toDouble() );
305 
306  //pen
307  QDomNodeList frameColorList = itemElem.elementsByTagName( "FrameColor" );
308  if ( frameColorList.size() > 0 )
309  {
310  QDomElement frameColorElem = frameColorList.at( 0 ).toElement();
311  bool redOk, greenOk, blueOk, alphaOk, widthOk;
312  int penRed, penGreen, penBlue, penAlpha;
313  double penWidth;
314 
315  penWidth = itemElem.attribute( "outlineWidth" ).toDouble( &widthOk );
316  penRed = frameColorElem.attribute( "red" ).toDouble( &redOk );
317  penGreen = frameColorElem.attribute( "green" ).toDouble( &greenOk );
318  penBlue = frameColorElem.attribute( "blue" ).toDouble( &blueOk );
319  penAlpha = frameColorElem.attribute( "alpha" ).toDouble( &alphaOk );
320  mFrameJoinStyle = QgsSymbolLayerV2Utils::decodePenJoinStyle( itemElem.attribute( "frameJoinStyle", "miter" ) );
321 
322  if ( redOk && greenOk && blueOk && alphaOk && widthOk )
323  {
324  QPen framePen( QColor( penRed, penGreen, penBlue, penAlpha ) );
325  framePen.setWidthF( penWidth );
326  framePen.setJoinStyle( mFrameJoinStyle );
327  setPen( framePen );
328  }
329  }
330 
331  //brush
332  QDomNodeList bgColorList = itemElem.elementsByTagName( "BackgroundColor" );
333  if ( bgColorList.size() > 0 )
334  {
335  QDomElement bgColorElem = bgColorList.at( 0 ).toElement();
336  bool redOk, greenOk, blueOk, alphaOk;
337  int bgRed, bgGreen, bgBlue, bgAlpha;
338  bgRed = bgColorElem.attribute( "red" ).toDouble( &redOk );
339  bgGreen = bgColorElem.attribute( "green" ).toDouble( &greenOk );
340  bgBlue = bgColorElem.attribute( "blue" ).toDouble( &blueOk );
341  bgAlpha = bgColorElem.attribute( "alpha" ).toDouble( &alphaOk );
342  if ( redOk && greenOk && blueOk && alphaOk )
343  {
344  QColor brushColor( bgRed, bgGreen, bgBlue, bgAlpha );
345  setBackgroundColor( brushColor );
346  }
347  }
348 
349  //blend mode
350  setBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) itemElem.attribute( "blendMode", "0" ).toUInt() ) );
351 
352  //transparency
353  setTransparency( itemElem.attribute( "transparency" , "0" ).toInt() );
354 
355  return true;
356 }
357 
358 void QgsComposerItem::setFrameEnabled( bool drawFrame )
359 {
360  mFrame = drawFrame;
361  emit frameChanged();
362 }
363 
365 {
366  QPen itemPen = pen();
367  if ( itemPen.widthF() == outlineWidth )
368  {
369  //no change
370  return;
371  }
372  itemPen.setWidthF( outlineWidth );
373  setPen( itemPen );
374  emit frameChanged();
375 }
376 
377 void QgsComposerItem::setFrameJoinStyle( Qt::PenJoinStyle style )
378 {
379  if ( mFrameJoinStyle == style )
380  {
381  //no change
382  return;
383  }
384  mFrameJoinStyle = style;
385 
386  QPen itemPen = pen();
387  itemPen.setJoinStyle( mFrameJoinStyle );
388  setPen( itemPen );
389  emit frameChanged();
390 }
391 
393 {
394  if ( !hasFrame() )
395  {
396  return 0;
397  }
398 
399  return pen().widthF() / 2.0;
400 }
401 
403 {
404  double frameBleed = estimatedFrameBleed();
405  return rect().adjusted( -frameBleed, -frameBleed, frameBleed, frameBleed );
406 }
407 
409 {
410  if ( mComposition )
411  {
412  mComposition->beginCommand( this, commandText, c );
413  }
414 }
415 
417 {
418  if ( mComposition )
419  {
421  }
422 }
423 
425 {
426  if ( mComposition )
427  {
429  }
430 }
431 
433 {
434 
435  if ( !mComposition )
436  {
437  return;
438  }
439 
441  {
442  double sizeLockSymbol = lockSymbolSize();
443 
444  if ( mItemPositionLocked )
445  {
446  //draw lock symbol at upper left edge. Use QImage to be independent of the graphic system
447  QString lockIconPath = QgsApplication::activeThemePath() + "/mIconLock.png";
448  if ( !QFile::exists( lockIconPath ) )
449  {
450  lockIconPath = QgsApplication::defaultThemePath() + "/mIconLock.png";
451  }
452 
453  QImage lockImage( lockIconPath );
454  if ( !lockImage.isNull() )
455  {
456  p->drawImage( QRectF( 0, 0, sizeLockSymbol, sizeLockSymbol ), lockImage, QRectF( 0, 0, lockImage.width(), lockImage.height() ) );
457  }
458  }
459  }
460 }
461 
462 void QgsComposerItem::drawFrame( QPainter* p )
463 {
464  if ( mFrame && p )
465  {
466  p->setPen( pen() );
467  p->setBrush( Qt::NoBrush );
468  p->setRenderHint( QPainter::Antialiasing, true );
469  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
470  }
471 }
472 
474 {
475  mItemPositionLocked = lock;
476 }
477 
478 void QgsComposerItem::move( double dx, double dy )
479 {
480  QRectF newSceneRect( pos().x() + dx, pos().y() + dy, rect().width(), rect().height() );
481  setSceneRect( newSceneRect );
482 }
483 
484 void QgsComposerItem::setItemPosition( double x, double y, ItemPositionMode itemPoint )
485 {
486  double width = rect().width();
487  double height = rect().height();
488  setItemPosition( x, y, width, height, itemPoint );
489 }
490 
491 void QgsComposerItem::setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint, bool posIncludesFrame )
492 {
493  double upperLeftX = x;
494  double upperLeftY = y;
495 
496  //store the item position mode
497  mLastUsedPositionMode = itemPoint;
498 
499  //adjust x-coordinate if placement is not done to a left point
500  if ( itemPoint == UpperMiddle || itemPoint == Middle || itemPoint == LowerMiddle )
501  {
502  upperLeftX -= width / 2.0;
503  }
504  else if ( itemPoint == UpperRight || itemPoint == MiddleRight || itemPoint == LowerRight )
505  {
506  upperLeftX -= width;
507  }
508 
509  //adjust y-coordinate if placement is not done to an upper point
510  if ( itemPoint == MiddleLeft || itemPoint == Middle || itemPoint == MiddleRight )
511  {
512  upperLeftY -= height / 2.0;
513  }
514  else if ( itemPoint == LowerLeft || itemPoint == LowerMiddle || itemPoint == LowerRight )
515  {
516  upperLeftY -= height;
517  }
518 
519  if ( posIncludesFrame )
520  {
521  //adjust position to account for frame size
522 
523  if ( mItemRotation == 0 )
524  {
525  upperLeftX += estimatedFrameBleed();
526  upperLeftY += estimatedFrameBleed();
527  }
528  else
529  {
530  //adjust position for item rotation
531  QLineF lineToItemOrigin = QLineF( 0, 0, estimatedFrameBleed(), estimatedFrameBleed() );
532  lineToItemOrigin.setAngle( -45 - mItemRotation );
533  upperLeftX += lineToItemOrigin.x2();
534  upperLeftY += lineToItemOrigin.y2();
535  }
536 
537  width -= 2 * estimatedFrameBleed();
538  height -= 2 * estimatedFrameBleed();
539  }
540 
541  setSceneRect( QRectF( upperLeftX, upperLeftY, width, height ) );
542 }
543 
544 void QgsComposerItem::setSceneRect( const QRectF& rectangle )
545 {
546  //setRect in item coordinates
547  double newWidth = rectangle.width();
548  double newHeight = rectangle.height();
549  double xTranslation = rectangle.x();
550  double yTranslation = rectangle.y();
551 
552  //correction if width and/or height are negative
553  if ( rectangle.width() < 0 )
554  {
555  newWidth = - rectangle.width();
556  xTranslation -= newWidth;
557  }
558 
559  if ( rectangle.height() < 0 )
560  {
561  newHeight = - rectangle.height();
562  yTranslation -= newHeight;
563  }
564 
565  QRectF newRect( 0, 0, newWidth, newHeight );
566  QGraphicsRectItem::setRect( newRect );
567  setPos( xTranslation, yTranslation );
568 
569  emit sizeChanged();
570 }
571 
573 {
574  if ( mBackground && p )
575  {
576  p->setBrush( brush() );//this causes a problem in atlas generation
577  p->setPen( Qt::NoPen );
578  p->setRenderHint( QPainter::Antialiasing, true );
579  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
580  }
581 }
582 
583 void QgsComposerItem::setBackgroundColor( const QColor& backgroundColor )
584 {
586  setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
587 }
588 
589 void QgsComposerItem::setBlendMode( QPainter::CompositionMode blendMode )
590 {
592  // Update the composer effect to use the new blend mode
594 }
595 
596 void QgsComposerItem::setTransparency( int transparency )
597 {
599  // Set the QGraphicItem's opacity
600  setOpacity( 1. - ( transparency / 100. ) );
601 }
602 
603 void QgsComposerItem::setEffectsEnabled( bool effectsEnabled )
604 {
605  //enable or disable the QgsComposerEffect applied to this item
607  mEffect->setEnabled( effectsEnabled );
608 }
609 
610 void QgsComposerItem::drawText( QPainter* p, double x, double y, const QString& text, const QFont& font ) const
611 {
612  QFont textFont = scaledFontPixelSize( font );
613 
614  p->save();
615  p->setFont( textFont );
616  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
617  p->scale( scaleFactor, scaleFactor );
618  p->drawText( QPointF( x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE ), text );
619  p->restore();
620 }
621 
622 void QgsComposerItem::drawText( QPainter* p, const QRectF& rect, const QString& text, const QFont& font, Qt::AlignmentFlag halignment, Qt::AlignmentFlag valignment ) const
623 {
624  QFont textFont = scaledFontPixelSize( font );
625 
626  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
627  rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
628 
629  p->save();
630  p->setFont( textFont );
631  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
632  p->scale( scaleFactor, scaleFactor );
633  p->drawText( scaledRect, halignment | valignment | Qt::TextWordWrap, text );
634  p->restore();
635 }
636 void QgsComposerItem::drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const
637 {
638  if ( !p )
639  {
640  return;
641  }
642  double angleRad = angle / 180.0 * M_PI;
643  QPointF middlePoint( x, y );
644  //rotate both arrow points
645  QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
646  QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
647 
648  QPointF p1Rotated, p2Rotated;
649  p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
650  p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
651  p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
652  p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
653 
654  QPolygonF arrowHeadPoly;
655  arrowHeadPoly << middlePoint;
656  arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
657  arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
658 
659  p->save();
660 
661  QPen arrowPen = p->pen();
662  arrowPen.setJoinStyle( Qt::RoundJoin );
663  QBrush arrowBrush = p->brush();
664  arrowBrush.setStyle( Qt::SolidPattern );
665  p->setPen( arrowPen );
666  p->setBrush( arrowBrush );
667  arrowBrush.setStyle( Qt::SolidPattern );
668  p->drawPolygon( arrowHeadPoly );
669 
670  p->restore();
671 }
672 
673 double QgsComposerItem::textWidthMillimeters( const QFont& font, const QString& text ) const
674 {
675  QFont metricsFont = scaledFontPixelSize( font );
676  QFontMetricsF fontMetrics( metricsFont );
677  return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
678 }
679 
680 double QgsComposerItem::fontHeightCharacterMM( const QFont& font, const QChar& c ) const
681 {
682  QFont metricsFont = scaledFontPixelSize( font );
683  QFontMetricsF fontMetrics( metricsFont );
684  return ( fontMetrics.boundingRect( c ).height() / FONT_WORKAROUND_SCALE );
685 }
686 
687 double QgsComposerItem::fontAscentMillimeters( const QFont& font ) const
688 {
689  QFont metricsFont = scaledFontPixelSize( font );
690  QFontMetricsF fontMetrics( metricsFont );
691  return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
692 }
693 
694 double QgsComposerItem::fontDescentMillimeters( const QFont& font ) const
695 {
696  QFont metricsFont = scaledFontPixelSize( font );
697  QFontMetricsF fontMetrics( metricsFont );
698  return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
699 }
700 
701 double QgsComposerItem::pixelFontSize( double pointSize ) const
702 {
703  return ( pointSize * 0.3527 );
704 }
705 
706 QFont QgsComposerItem::scaledFontPixelSize( const QFont& font ) const
707 {
708  QFont scaledFont = font;
709  double pixelSize = pixelFontSize( font.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
710  scaledFont.setPixelSize( pixelSize );
711  return scaledFont;
712 }
713 
714 double QgsComposerItem::angle( const QPointF& p1, const QPointF& p2 ) const
715 {
716  double xDiff = p2.x() - p1.x();
717  double yDiff = p2.y() - p1.y();
718  double length = sqrt( xDiff * xDiff + yDiff * yDiff );
719  if ( length <= 0 )
720  {
721  return 0;
722  }
723 
724  double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
725  if ( xDiff < 0 )
726  {
727  return ( 360 - angle );
728  }
729  return angle;
730 }
731 
733 {
734  double result = -1;
735  if ( scene() )
736  {
737  QList<QGraphicsView*> viewList = scene()->views();
738  if ( viewList.size() > 0 ) //if not, probably this function was called from non-gui code
739  {
740  QGraphicsView* currentView = viewList.at( 0 );
741  if ( currentView->isVisible() )
742  {
743  result = currentView->transform().m11();
744  mLastValidViewScaleFactor = result;
745  }
746  }
747  }
748  return result;
749 }
750 
752 {
753  //size of symbol boxes depends on zoom level in composer view
754  double viewScaleFactor = horizontalViewScaleFactor();
755  double rectHandlerSize = 10.0 / viewScaleFactor;
756 
757  //make sure the boxes don't get too large
758  if ( rectHandlerSize > ( rect().width() / 3 ) )
759  {
760  rectHandlerSize = rect().width() / 3;
761  }
762  if ( rectHandlerSize > ( rect().height() / 3 ) )
763  {
764  rectHandlerSize = rect().height() / 3;
765  }
766  return rectHandlerSize;
767 }
768 
770 {
771  double lockSymbolSize = 20.0 / horizontalViewScaleFactor();
772 
773  if ( lockSymbolSize > ( rect().width() / 3 ) )
774  {
775  lockSymbolSize = rect().width() / 3;
776  }
777  if ( lockSymbolSize > ( rect().height() / 3 ) )
778  {
779  lockSymbolSize = rect().height() / 3;
780  }
781  return lockSymbolSize;
782 }
783 
785 {
786  //kept for api compatibility with QGIS 2.0
787  //remove after 2.0 series
788  setItemRotation( r, true );
789 }
790 
791 void QgsComposerItem::setItemRotation( double r, bool adjustPosition )
792 {
793  if ( adjustPosition )
794  {
795  //adjustPosition set, so shift the position of the item so that rotation occurs around item center
796  //create a line from the centrepoint of the rect() to its origin, in scene coordinates
797  QLineF refLine = QLineF( mapToScene( QPointF( rect().width() / 2.0, rect().height() / 2.0 ) ) , mapToScene( QPointF( 0 , 0 ) ) );
798  //rotate this line by the current rotation angle
799  refLine.setAngle( refLine.angle() - r + mItemRotation );
800  //get new end point of line - this is the new item position
801  QPointF rotatedReferencePoint = refLine.p2();
802  setPos( rotatedReferencePoint );
803  emit sizeChanged();
804  }
805 
806  if ( r > 360 )
807  {
808  mItemRotation = (( int )r ) % 360;
809  }
810  else
811  {
812  mItemRotation = r;
813  }
814 
815  setTransformOriginPoint( 0, 0 );
816  QGraphicsItem::setRotation( mItemRotation );
817 
818  emit itemRotationChanged( r );
819  update();
820 }
821 
822 bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const
823 {
824  //kept for api compatibility with QGIS 2.0, use item rotation
825  return imageSizeConsideringRotation( width, height, mItemRotation );
826 }
827 
828 QRectF QgsComposerItem::largestRotatedRectWithinBounds( QRectF originalRect, QRectF boundsRect, double rotation ) const
829 {
830  double originalWidth = originalRect.width();
831  double originalHeight = originalRect.height();
832  double boundsWidth = boundsRect.width();
833  double boundsHeight = boundsRect.height();
834  double ratioBoundsRect = boundsWidth / boundsHeight;
835 
836  //shortcut for some rotation values
837  if ( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 )
838  {
839  double originalRatio = originalWidth / originalHeight;
840  double rectScale = originalRatio > ratioBoundsRect ? boundsWidth / originalWidth : boundsHeight / originalHeight;
841  double rectScaledWidth = rectScale * originalWidth;
842  double rectScaledHeight = rectScale * originalHeight;
843 
844  if ( rotation == 0 || rotation == 180 )
845  {
846  return QRectF(( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
847  }
848  else
849  {
850  return QRectF(( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledHeight, rectScaledWidth );
851  }
852  }
853 
854  //convert angle to radians and flip
855  double angleRad = -rotation * M_DEG2RAD;
856  double cosAngle = cos( angleRad );
857  double sinAngle = sin( angleRad );
858 
859  //calculate size of bounds of rotated rectangle
860  double widthBoundsRotatedRect = originalWidth * fabs( cosAngle ) + originalHeight * fabs( sinAngle );
861  double heightBoundsRotatedRect = originalHeight * fabs( cosAngle ) + originalWidth * fabs( sinAngle );
862 
863  //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
864  //rect to fit within bounds
865  double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
866  double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
867  double rectScaledWidth = rectScale * originalWidth;
868  double rectScaledHeight = rectScale * originalHeight;
869 
870  //now calculate offset so that rotated rectangle is centered within bounds
871  //first calculate min x and y coordinates
872  double currentCornerX = 0;
873  double minX = 0;
874  currentCornerX += rectScaledWidth * cosAngle;
875  minX = minX < currentCornerX ? minX : currentCornerX;
876  currentCornerX += rectScaledHeight * sinAngle;
877  minX = minX < currentCornerX ? minX : currentCornerX;
878  currentCornerX -= rectScaledWidth * cosAngle;
879  minX = minX < currentCornerX ? minX : currentCornerX;
880 
881  double currentCornerY = 0;
882  double minY = 0;
883  currentCornerY -= rectScaledWidth * sinAngle;
884  minY = minY < currentCornerY ? minY : currentCornerY;
885  currentCornerY += rectScaledHeight * cosAngle;
886  minY = minY < currentCornerY ? minY : currentCornerY;
887  currentCornerY += rectScaledWidth * sinAngle;
888  minY = minY < currentCornerY ? minY : currentCornerY;
889 
890  //now calculate offset position of rotated rectangle
891  double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
892  offsetX += fabs( minX );
893  double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
894  offsetY += fabs( minY );
895 
896  return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
897 }
898 
899 bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height, double rotation ) const
900 {
901  if ( qAbs( rotation ) <= 0.0 ) //width and height stays the same if there is no rotation
902  {
903  return true;
904  }
905 
906  if ( qgsDoubleNear( qAbs( rotation ), 90 ) || qgsDoubleNear( qAbs( rotation ), 270 ) )
907  {
908  double tmp = width;
909  width = height;
910  height = tmp;
911  return true;
912  }
913 
914  double x1 = 0;
915  double y1 = 0;
916  double x2 = width;
917  double y2 = 0;
918  double x3 = width;
919  double y3 = height;
920  double x4 = 0;
921  double y4 = height;
922  double midX = width / 2.0;
923  double midY = height / 2.0;
924 
925  if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height, rotation ) )
926  {
927  return false;
928  }
929  if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height, rotation ) )
930  {
931  return false;
932  }
933  if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height, rotation ) )
934  {
935  return false;
936  }
937  if ( !cornerPointOnRotatedAndScaledRect( x4, y4, width, height, rotation ) )
938  {
939  return false;
940  }
941 
942 
943  //assume points 1 and 3 are on the rectangle boundaries. Calculate 2 and 4.
944  double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) );
945  QPointF p2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x2, y2 ), distM1 );
946 
947  if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 )
948  {
949  width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) );
950  height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) );
951  return true;
952  }
953 
954  //else assume that points 2 and 4 are on the rectangle boundaries. Calculate 1 and 3
955  double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) );
956  QPointF p1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x1, y1 ), distM2 );
957  QPointF p3 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x3, y3 ), distM2 );
958  width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
959  height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
960  return true;
961 }
962 
963 bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
964 {
965  //kept for api compatibility with QGIS 2.0, use item rotation
966  return cornerPointOnRotatedAndScaledRect( x, y, width, height, mItemRotation );
967 }
968 
969 bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height, double rotation ) const
970 {
971  //first rotate point clockwise
972  double rotToRad = rotation * M_PI / 180.0;
973  QPointF midpoint( width / 2.0, height / 2.0 );
974  double xVector = x - midpoint.x();
975  double yVector = y - midpoint.y();
976  //double xRotated = cos(rotToRad) * xVector + sin(rotToRad) * yVector;
977  //double yRotated = -sin(rotToRad) * xVector + cos(rotToRad) * yVector;
978  double xRotated = cos( rotToRad ) * xVector - sin( rotToRad ) * yVector;
979  double yRotated = sin( rotToRad ) * xVector + cos( rotToRad ) * yVector;
980 
981  //create line from midpoint to rotated point
982  QLineF line( midpoint.x(), midpoint.y(), midpoint.x() + xRotated, midpoint.y() + yRotated );
983 
984  //intersect with all four borders and return result
985  QList<QLineF> borders;
986  borders << QLineF( 0, 0, width, 0 );
987  borders << QLineF( width, 0, width, height );
988  borders << QLineF( width, height, 0, height );
989  borders << QLineF( 0, height, 0, 0 );
990 
991  QList<QLineF>::const_iterator it = borders.constBegin();
992  QPointF intersectionPoint;
993 
994  for ( ; it != borders.constEnd(); ++it )
995  {
996  if ( line.intersect( *it, &intersectionPoint ) == QLineF::BoundedIntersection )
997  {
998  x = intersectionPoint.x();
999  y = intersectionPoint.y();
1000  return true;
1001  }
1002  }
1003  return false;
1004 }
1005 
1006 void QgsComposerItem::sizeChangedByRotation( double& width, double& height )
1007 {
1008  //kept for api compatibility with QGIS 2.0, use item rotation
1009  return sizeChangedByRotation( width, height, mItemRotation );
1010 }
1011 
1012 void QgsComposerItem::sizeChangedByRotation( double& width, double& height, double rotation )
1013 {
1014  if ( rotation == 0.0 )
1015  {
1016  return;
1017  }
1018 
1019  //vector to p1
1020  double x1 = -width / 2.0;
1021  double y1 = -height / 2.0;
1022  rotate( rotation, x1, y1 );
1023  //vector to p2
1024  double x2 = width / 2.0;
1025  double y2 = -height / 2.0;
1026  rotate( rotation, x2, y2 );
1027  //vector to p3
1028  double x3 = width / 2.0;
1029  double y3 = height / 2.0;
1030  rotate( rotation, x3, y3 );
1031  //vector to p4
1032  double x4 = -width / 2.0;
1033  double y4 = height / 2.0;
1034  rotate( rotation, x4, y4 );
1035 
1036  //double midpoint
1037  QPointF midpoint( width / 2.0, height / 2.0 );
1038 
1039  QPolygonF rotatedRectPoly;
1040  rotatedRectPoly << QPointF( midpoint.x() + x1, midpoint.y() + y1 );
1041  rotatedRectPoly << QPointF( midpoint.x() + x2, midpoint.y() + y2 );
1042  rotatedRectPoly << QPointF( midpoint.x() + x3, midpoint.y() + y3 );
1043  rotatedRectPoly << QPointF( midpoint.x() + x4, midpoint.y() + y4 );
1044  QRectF boundingRect = rotatedRectPoly.boundingRect();
1045  width = boundingRect.width();
1046  height = boundingRect.height();
1047 }
1048 
1049 void QgsComposerItem::rotate( double angle, double& x, double& y ) const
1050 {
1051  double rotToRad = angle * M_PI / 180.0;
1052  double xRot, yRot;
1053  xRot = x * cos( rotToRad ) - y * sin( rotToRad );
1054  yRot = x * sin( rotToRad ) + y * cos( rotToRad );
1055  x = xRot;
1056  y = yRot;
1057 }
1058 
1060 {
1061  if ( !mHAlignSnapItem )
1062  {
1063  mHAlignSnapItem = new QGraphicsLineItem( 0 );
1064  mHAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
1065  scene()->addItem( mHAlignSnapItem );
1066  mHAlignSnapItem->setZValue( 90 );
1067  }
1068  return mHAlignSnapItem;
1069 }
1070 
1072 {
1073  if ( !mVAlignSnapItem )
1074  {
1075  mVAlignSnapItem = new QGraphicsLineItem( 0 );
1076  mVAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
1077  scene()->addItem( mVAlignSnapItem );
1078  mVAlignSnapItem->setZValue( 90 );
1079  }
1080  return mVAlignSnapItem;
1081 }
1082 
1084 {
1085  if ( mHAlignSnapItem )
1086  {
1087  scene()->removeItem( mHAlignSnapItem );
1088  delete mHAlignSnapItem;
1089  mHAlignSnapItem = 0;
1090  }
1091 }
1092 
1094 {
1095  if ( mVAlignSnapItem )
1096  {
1097  scene()->removeItem( mVAlignSnapItem );
1098  delete mVAlignSnapItem;
1099  mVAlignSnapItem = 0;
1100  }
1101 }
1102 
1104 {
1107 }
1108 
1110 {
1111  update();
1112 }
1113 
1114 void QgsComposerItem::setId( const QString& id )
1115 {
1116  setToolTip( id );
1117  mId = id;
1118 }
bool positionLock() const
Returns position lock for mouse drags (true means locked)
bool effectsEnabled() const
Returns true if effects (eg blend modes) are enabled for the item.
bool imageSizeConsideringRotation(double &width, double &height, double rotation) const
Calculates width and hight of the picture (in mm) such that it fits into the item frame with the give...
double outlineWidth
Definition: qgssvgcache.cpp:78
int mTransparency
Item transparency.
void setEffectsEnabled(bool effectsEnabled)
Sets whether effects (eg blend modes) are enabled for the item.
double fontHeightCharacterMM(const QFont &font, const QChar &c) const
Returns the font height of a character in millimeters.
void itemRotationChanged(double newRotation)
Is emitted on item rotation change.
static const QString activeThemePath()
Returns the path to the currently active theme directory.
double pixelFontSize(double pointSize) const
Calculates font to from point size to pixel size.
void addItemToZList(QgsComposerItem *item)
Adds item to z list.
virtual void setRotation(double r)
Sets the item rotation.
virtual double estimatedFrameBleed() const
Returns the estimated amount the item's frame bleeds outside the item's actual rectangle.
virtual bool removeSettings()
delete settings from project file
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
double lockSymbolSize() const
Returns the size of the lock symbol depending on the composer zoom level and the item size...
void removeItemFromZList(QgsComposerItem *item)
Removes item from z list.
#define FONT_WORKAROUND_SCALE
double mLastValidViewScaleFactor
Backup to restore item appearance if no view scale factor is available.
ItemPositionMode mLastUsedPositionMode
The item's position mode.
virtual void setSelected(bool s)
Set selected, selected item should be highlighted.
void setItemPosition(double x, double y, ItemPositionMode itemPoint=UpperLeft)
Moves the item to a new position (in canvas coordinates)
virtual void drawFrame(QPainter *p)
Draw black frame around item.
QColor backgroundColor() const
Gets the background color for this item.
QPainter::CompositionMode mBlendMode
Composition blend mode for item.
void setCompositionMode(const QPainter::CompositionMode &compositionMode)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:324
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
double fontDescentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
void setTransparency(int transparency)
Sets the item's transparency.
void frameChanged()
Emitted if the item's frame style changes.
double horizontalViewScaleFactor() const
Returns the zoom factor of the graphics view.
void cancelCommand()
Deletes current command.
QFont scaledFontPixelSize(const QFont &font) const
Returns a font where size is in pixel and font size is upscaled with FONT_WORKAROUND_SCALE.
int transparency() const
Returns the item's transparency.
virtual void drawSelectionBoxes(QPainter *p)
Draw selection boxes around item.
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
void rotate(double angle, double &x, double &y) const
Rotates a point / vector.
void endCommand()
Saves end state of item and pushes command to the undo history.
QGraphicsRectItem * mBoundingResizeRectangle
Rectangle used during move and resize actions.
QRectF largestRotatedRectWithinBounds(QRectF originalRect, QRectF boundsRect, double rotation) const
Calculates the largest scaled version of originalRect which fits within boundsRect, when it is rotated by a specified amount.
bool mFrame
True if item fram needs to be painted.
void endCommand()
Finish current command and push it onto the undo stack.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
virtual void setFrameOutlineWidth(double outlineWidth)
Sets frame outline width.
#define M_PI
static const QString defaultThemePath()
Returns the path to the default theme directory.
virtual bool writeSettings()
stores state in project
virtual ~QgsComposerItem()
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
void beginCommand(const QString &commandText, QgsComposerMergeCommand::Context c=QgsComposerMergeCommand::Unknown)
Starts new composer undo command.
void setFrameJoinStyle(Qt::PenJoinStyle style)
Sets join style used when drawing the item's frame.
QgsComposition * mComposition
Graphics scene for map printing.
virtual void setItemRotation(double r, bool adjustPosition=false)
Sets the item rotation.
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
void setPositionLock(bool lock)
Locks / unlocks the item position for mouse drags.
virtual QRectF rectWithFrame() const
Returns the item's rectangular bounds, including any bleed caused by the item's frame.
QGraphicsLineItem * hAlignSnapItem()
Return horizontal align snap item.
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode &blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode Added in 1.9.
Qt::PenJoinStyle mFrameJoinStyle
Frame join style.
QColor mBackgroundColor
Background color.
QGraphicsLineItem * mVAlignSnapItem
bool cornerPointOnRotatedAndScaledRect(double &x, double &y, double width, double height, double rotation) const
Calculates corner point after rotation and scaling.
QGraphicsLineItem * mHAlignSnapItem
virtual bool readSettings()
read state from project
void setBackgroundColor(const QColor &backgroundColor)
Sets the background color for this item.
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
bool mItemPositionLocked
True if item position and size cannot be changed with mouse move.
QPainter::CompositionMode blendMode() const
Returns the item's composition blending mode.
virtual void drawBackground(QPainter *p)
Draw background.
bool hasFrame() const
Whether this item has a frame or not.
virtual void setId(const QString &id)
Set item's id (which is not necessarly unique)
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
double angle(const QPointF &p1, const QPointF &p2) const
Returns angle of the line from p1 to p2 (clockwise, starting at N)
void sizeChanged()
Emitted if the rectangle changes.
static Qt::PenJoinStyle decodePenJoinStyle(QString str)
void setBlendMode(QPainter::CompositionMode blendMode)
Sets the item's composition blending mode.
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode &blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode Added in 1.9.
QgsComposerEffect * mEffect
void drawArrowHead(QPainter *p, double x, double y, double angle, double arrowHeadWidth) const
Draws arrowhead.
QgsComposerItem(QgsComposition *composition, bool manageZValue=true)
Constructor.
void init(bool manageZValue)
QgsComposition::PlotStyle plotStyle() const
double rectHandlerBorderTolerance() const
Returns the current (zoom level dependent) tolerance to decide if mouse position is close enough to t...
#define M_DEG2RAD
void setFrameEnabled(bool drawFrame)
Set whether this item has a frame drawn around it or not.
static QPointF pointOnLineWithDistance(const QPointF &startPoint, const QPointF &directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
bool mBackground
True if item background needs to be painted.
void move(double dx, double dy)
Moves item in canvas coordinates.
double mItemRotation
Item rotation in degrees, clockwise.
QGraphicsLineItem * vAlignSnapItem()
Return vertical align snap item.
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
void sizeChangedByRotation(double &width, double &height, double rotation)
Calculates width / height of the bounding box of a rotated rectangle.
void beginCommand(QgsComposerItem *item, const QString &commandText, QgsComposerMergeCommand::Context c=QgsComposerMergeCommand::Unknown)
Allocates new item command and saves initial state in it.
QString id() const
Get item's id (which is not necessarly unique)