QGIS API Documentation  2.4.0-Chugiak
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  QPointF pagepos = pagePos();
176  composerItemElem.setAttribute( "x", QString::number( pos().x() ) );
177  composerItemElem.setAttribute( "y", QString::number( pos().y() ) );
178  composerItemElem.setAttribute( "page", page() );
179  composerItemElem.setAttribute( "pagex", QString::number( pagepos.x() ) );
180  composerItemElem.setAttribute( "pagey", QString::number( pagepos.y() ) );
181  composerItemElem.setAttribute( "width", QString::number( rect().width() ) );
182  composerItemElem.setAttribute( "height", QString::number( rect().height() ) );
183  composerItemElem.setAttribute( "positionMode", QString::number(( int ) mLastUsedPositionMode ) );
184  composerItemElem.setAttribute( "zValue", QString::number( zValue() ) );
185  composerItemElem.setAttribute( "outlineWidth", QString::number( pen().widthF() ) );
186  composerItemElem.setAttribute( "frameJoinStyle", QgsSymbolLayerV2Utils::encodePenJoinStyle( mFrameJoinStyle ) );
187  composerItemElem.setAttribute( "itemRotation", QString::number( mItemRotation ) );
188  composerItemElem.setAttribute( "uuid", mUuid );
189  composerItemElem.setAttribute( "id", mId );
190  //position lock for mouse moves/resizes
191  if ( mItemPositionLocked )
192  {
193  composerItemElem.setAttribute( "positionLock", "true" );
194  }
195  else
196  {
197  composerItemElem.setAttribute( "positionLock", "false" );
198  }
199 
200  composerItemElem.setAttribute( "lastValidViewScaleFactor", QString::number( mLastValidViewScaleFactor ) );
201 
202 
203  //frame color
204  QDomElement frameColorElem = doc.createElement( "FrameColor" );
205  QColor frameColor = pen().color();
206  frameColorElem.setAttribute( "red", QString::number( frameColor.red() ) );
207  frameColorElem.setAttribute( "green", QString::number( frameColor.green() ) );
208  frameColorElem.setAttribute( "blue", QString::number( frameColor.blue() ) );
209  frameColorElem.setAttribute( "alpha", QString::number( frameColor.alpha() ) );
210  composerItemElem.appendChild( frameColorElem );
211 
212  //background color
213  QDomElement bgColorElem = doc.createElement( "BackgroundColor" );
214  QColor bgColor = brush().color();
215  bgColorElem.setAttribute( "red", QString::number( bgColor.red() ) );
216  bgColorElem.setAttribute( "green", QString::number( bgColor.green() ) );
217  bgColorElem.setAttribute( "blue", QString::number( bgColor.blue() ) );
218  bgColorElem.setAttribute( "alpha", QString::number( bgColor.alpha() ) );
219  composerItemElem.appendChild( bgColorElem );
220 
221  //blend mode
222  composerItemElem.setAttribute( "blendMode", QgsMapRenderer::getBlendModeEnum( mBlendMode ) );
223 
224  //transparency
225  composerItemElem.setAttribute( "transparency", QString::number( mTransparency ) );
226 
227  itemElem.appendChild( composerItemElem );
228 
229  return true;
230 }
231 
232 bool QgsComposerItem::_readXML( const QDomElement& itemElem, const QDomDocument& doc )
233 {
234  Q_UNUSED( doc );
235  if ( itemElem.isNull() )
236  {
237  return false;
238  }
239 
240  //rotation
241  setItemRotation( itemElem.attribute( "itemRotation", "0" ).toDouble() );
242 
243  //uuid
244  mUuid = itemElem.attribute( "uuid", QUuid::createUuid().toString() );
245 
246  // temporary for groups imported from templates
247  mTemplateUuid = itemElem.attribute( "templateUuid" );
248 
249  //id
250  QString id = itemElem.attribute( "id", "" );
251  setId( id );
252 
253  //frame
254  QString frame = itemElem.attribute( "frame" );
255  if ( frame.compare( "true", Qt::CaseInsensitive ) == 0 )
256  {
257  mFrame = true;
258  }
259  else
260  {
261  mFrame = false;
262  }
263 
264  //frame
265  QString background = itemElem.attribute( "background" );
266  if ( background.compare( "true", Qt::CaseInsensitive ) == 0 )
267  {
268  mBackground = true;
269  }
270  else
271  {
272  mBackground = false;
273  }
274 
275  //position lock for mouse moves/resizes
276  QString positionLock = itemElem.attribute( "positionLock" );
277  if ( positionLock.compare( "true", Qt::CaseInsensitive ) == 0 )
278  {
279  setPositionLock( true );
280  }
281  else
282  {
283  setPositionLock( false );
284  }
285 
286  //position
287  int page;
288  double x, y, pagex, pagey, width, height;
289  bool xOk, yOk, pageOk, pagexOk, pageyOk, widthOk, heightOk, positionModeOK;
290 
291  x = itemElem.attribute( "x" ).toDouble( &xOk );
292  y = itemElem.attribute( "y" ).toDouble( &yOk );
293  page = itemElem.attribute( "page" ).toInt( &pageOk );
294  pagex = itemElem.attribute( "pagex" ).toDouble( &pagexOk );
295  pagey = itemElem.attribute( "pagey" ).toDouble( &pageyOk );
296  width = itemElem.attribute( "width" ).toDouble( &widthOk );
297  height = itemElem.attribute( "height" ).toDouble( &heightOk );
298  mLastUsedPositionMode = ( ItemPositionMode )itemElem.attribute( "positionMode" ).toInt( &positionModeOK );
299  if ( !positionModeOK )
300  {
302  }
303  if ( pageOk && pagexOk && pageyOk )
304  {
305  xOk = true;
306  yOk = true;
307  x = pagex;
308  y = ( page - 1 ) * ( mComposition->paperHeight() + composition()->spaceBetweenPages() ) + pagey;
309  }
310 
311  if ( !xOk || !yOk || !widthOk || !heightOk )
312  {
313  return false;
314  }
315 
316  mLastValidViewScaleFactor = itemElem.attribute( "lastValidViewScaleFactor", "-1" ).toDouble();
317 
318  setSceneRect( QRectF( x, y, width, height ) );
319  setZValue( itemElem.attribute( "zValue" ).toDouble() );
320 
321  //pen
322  QDomNodeList frameColorList = itemElem.elementsByTagName( "FrameColor" );
323  if ( frameColorList.size() > 0 )
324  {
325  QDomElement frameColorElem = frameColorList.at( 0 ).toElement();
326  bool redOk, greenOk, blueOk, alphaOk, widthOk;
327  int penRed, penGreen, penBlue, penAlpha;
328  double penWidth;
329 
330  penWidth = itemElem.attribute( "outlineWidth" ).toDouble( &widthOk );
331  penRed = frameColorElem.attribute( "red" ).toDouble( &redOk );
332  penGreen = frameColorElem.attribute( "green" ).toDouble( &greenOk );
333  penBlue = frameColorElem.attribute( "blue" ).toDouble( &blueOk );
334  penAlpha = frameColorElem.attribute( "alpha" ).toDouble( &alphaOk );
335  mFrameJoinStyle = QgsSymbolLayerV2Utils::decodePenJoinStyle( itemElem.attribute( "frameJoinStyle", "miter" ) );
336 
337  if ( redOk && greenOk && blueOk && alphaOk && widthOk )
338  {
339  QPen framePen( QColor( penRed, penGreen, penBlue, penAlpha ) );
340  framePen.setWidthF( penWidth );
341  framePen.setJoinStyle( mFrameJoinStyle );
342  setPen( framePen );
343  }
344  }
345 
346  //brush
347  QDomNodeList bgColorList = itemElem.elementsByTagName( "BackgroundColor" );
348  if ( bgColorList.size() > 0 )
349  {
350  QDomElement bgColorElem = bgColorList.at( 0 ).toElement();
351  bool redOk, greenOk, blueOk, alphaOk;
352  int bgRed, bgGreen, bgBlue, bgAlpha;
353  bgRed = bgColorElem.attribute( "red" ).toDouble( &redOk );
354  bgGreen = bgColorElem.attribute( "green" ).toDouble( &greenOk );
355  bgBlue = bgColorElem.attribute( "blue" ).toDouble( &blueOk );
356  bgAlpha = bgColorElem.attribute( "alpha" ).toDouble( &alphaOk );
357  if ( redOk && greenOk && blueOk && alphaOk )
358  {
359  QColor brushColor( bgRed, bgGreen, bgBlue, bgAlpha );
360  setBackgroundColor( brushColor );
361  }
362  }
363 
364  //blend mode
365  setBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) itemElem.attribute( "blendMode", "0" ).toUInt() ) );
366 
367  //transparency
368  setTransparency( itemElem.attribute( "transparency" , "0" ).toInt() );
369 
370  return true;
371 }
372 
373 void QgsComposerItem::setFrameEnabled( bool drawFrame )
374 {
375  mFrame = drawFrame;
376  emit frameChanged();
377 }
378 
380 {
381  QPen itemPen = pen();
382  if ( itemPen.widthF() == outlineWidth )
383  {
384  //no change
385  return;
386  }
387  itemPen.setWidthF( outlineWidth );
388  setPen( itemPen );
389  emit frameChanged();
390 }
391 
392 void QgsComposerItem::setFrameJoinStyle( Qt::PenJoinStyle style )
393 {
394  if ( mFrameJoinStyle == style )
395  {
396  //no change
397  return;
398  }
399  mFrameJoinStyle = style;
400 
401  QPen itemPen = pen();
402  itemPen.setJoinStyle( mFrameJoinStyle );
403  setPen( itemPen );
404  emit frameChanged();
405 }
406 
408 {
409  if ( !hasFrame() )
410  {
411  return 0;
412  }
413 
414  return pen().widthF() / 2.0;
415 }
416 
418 {
419  double frameBleed = estimatedFrameBleed();
420  return rect().adjusted( -frameBleed, -frameBleed, frameBleed, frameBleed );
421 }
422 
424 {
425  if ( mComposition )
426  {
427  mComposition->beginCommand( this, commandText, c );
428  }
429 }
430 
432 {
433  if ( mComposition )
434  {
436  }
437 }
438 
440 {
441  if ( mComposition )
442  {
444  }
445 }
446 
448 {
449 
450  if ( !mComposition )
451  {
452  return;
453  }
454 
456  {
457  double sizeLockSymbol = lockSymbolSize();
458 
459  if ( mItemPositionLocked )
460  {
461  //draw lock symbol at upper left edge. Use QImage to be independent of the graphic system
462  QString lockIconPath = QgsApplication::activeThemePath() + "/mIconLock.png";
463  if ( !QFile::exists( lockIconPath ) )
464  {
465  lockIconPath = QgsApplication::defaultThemePath() + "/mIconLock.png";
466  }
467 
468  QImage lockImage( lockIconPath );
469  if ( !lockImage.isNull() )
470  {
471  p->drawImage( QRectF( 0, 0, sizeLockSymbol, sizeLockSymbol ), lockImage, QRectF( 0, 0, lockImage.width(), lockImage.height() ) );
472  }
473  }
474  }
475 }
476 
477 void QgsComposerItem::drawFrame( QPainter* p )
478 {
479  if ( mFrame && p )
480  {
481  p->setPen( pen() );
482  p->setBrush( Qt::NoBrush );
483  p->setRenderHint( QPainter::Antialiasing, true );
484  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
485  }
486 }
487 
489 {
490  mItemPositionLocked = lock;
491 }
492 
493 void QgsComposerItem::move( double dx, double dy )
494 {
495  QRectF newSceneRect( pos().x() + dx, pos().y() + dy, rect().width(), rect().height() );
496  setSceneRect( newSceneRect );
497 }
498 
500 {
501  double y = pos().y();
502  double h = composition()->paperHeight() + composition()->spaceBetweenPages();
503  int page = 1;
504  while ( y - h >= 0. )
505  {
506  y -= h;
507  ++page;
508  }
509  return page;
510 }
511 
513 {
514  QPointF p = pos();
515  double h = composition()->paperHeight() + composition()->spaceBetweenPages();
516  p.ry() -= ( page() - 1 ) * h;
517  return p;
518 }
519 
520 void QgsComposerItem::updatePagePos( double newPageWidth, double newPageHeight )
521 {
522  Q_UNUSED( newPageWidth )
523  QPointF curPagePos = pagePos();
524  int curPage = page() - 1;
525  setY( curPage * ( newPageHeight + composition()->spaceBetweenPages() ) + curPagePos.y() );
526  emit sizeChanged();
527 }
528 
529 void QgsComposerItem::setItemPosition( double x, double y, ItemPositionMode itemPoint, int page )
530 {
531  double width = rect().width();
532  double height = rect().height();
533  setItemPosition( x, y, width, height, itemPoint, false, page );
534 }
535 
536 void QgsComposerItem::setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint, bool posIncludesFrame, int page )
537 {
538  double upperLeftX = x;
539  double upperLeftY = y;
540 
541  if ( page > 0 )
542  {
543  double h = composition()->paperHeight() + composition()->spaceBetweenPages();
544  upperLeftY += ( page - 1 ) * h;
545  }
546 
547  //store the item position mode
548  mLastUsedPositionMode = itemPoint;
549 
550  //adjust x-coordinate if placement is not done to a left point
551  if ( itemPoint == UpperMiddle || itemPoint == Middle || itemPoint == LowerMiddle )
552  {
553  upperLeftX -= width / 2.0;
554  }
555  else if ( itemPoint == UpperRight || itemPoint == MiddleRight || itemPoint == LowerRight )
556  {
557  upperLeftX -= width;
558  }
559 
560  //adjust y-coordinate if placement is not done to an upper point
561  if ( itemPoint == MiddleLeft || itemPoint == Middle || itemPoint == MiddleRight )
562  {
563  upperLeftY -= height / 2.0;
564  }
565  else if ( itemPoint == LowerLeft || itemPoint == LowerMiddle || itemPoint == LowerRight )
566  {
567  upperLeftY -= height;
568  }
569 
570  if ( posIncludesFrame )
571  {
572  //adjust position to account for frame size
573 
574  if ( mItemRotation == 0 )
575  {
576  upperLeftX += estimatedFrameBleed();
577  upperLeftY += estimatedFrameBleed();
578  }
579  else
580  {
581  //adjust position for item rotation
582  QLineF lineToItemOrigin = QLineF( 0, 0, estimatedFrameBleed(), estimatedFrameBleed() );
583  lineToItemOrigin.setAngle( -45 - mItemRotation );
584  upperLeftX += lineToItemOrigin.x2();
585  upperLeftY += lineToItemOrigin.y2();
586  }
587 
588  width -= 2 * estimatedFrameBleed();
589  height -= 2 * estimatedFrameBleed();
590  }
591 
592  setSceneRect( QRectF( upperLeftX, upperLeftY, width, height ) );
593 }
594 
595 void QgsComposerItem::setSceneRect( const QRectF& rectangle )
596 {
597  //setRect in item coordinates
598  double newWidth = rectangle.width();
599  double newHeight = rectangle.height();
600  double xTranslation = rectangle.x();
601  double yTranslation = rectangle.y();
602 
603  //correction if width and/or height are negative
604  if ( rectangle.width() < 0 )
605  {
606  newWidth = - rectangle.width();
607  xTranslation -= newWidth;
608  }
609 
610  if ( rectangle.height() < 0 )
611  {
612  newHeight = - rectangle.height();
613  yTranslation -= newHeight;
614  }
615 
616  QRectF newRect( 0, 0, newWidth, newHeight );
617  QGraphicsRectItem::setRect( newRect );
618  setPos( xTranslation, yTranslation );
619 
620  emit sizeChanged();
621 }
622 
624 {
625  if ( mBackground && p )
626  {
627  p->setBrush( brush() );//this causes a problem in atlas generation
628  p->setPen( Qt::NoPen );
629  p->setRenderHint( QPainter::Antialiasing, true );
630  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
631  }
632 }
633 
634 void QgsComposerItem::setBackgroundColor( const QColor& backgroundColor )
635 {
637  setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
638 }
639 
640 void QgsComposerItem::setBlendMode( QPainter::CompositionMode blendMode )
641 {
643  // Update the composer effect to use the new blend mode
645 }
646 
647 void QgsComposerItem::setTransparency( int transparency )
648 {
650  // Set the QGraphicItem's opacity
651  setOpacity( 1. - ( transparency / 100. ) );
652 }
653 
654 void QgsComposerItem::setEffectsEnabled( bool effectsEnabled )
655 {
656  //enable or disable the QgsComposerEffect applied to this item
658  mEffect->setEnabled( effectsEnabled );
659 }
660 
661 void QgsComposerItem::drawText( QPainter* p, double x, double y, const QString& text, const QFont& font ) const
662 {
663  QFont textFont = scaledFontPixelSize( font );
664 
665  p->save();
666  p->setFont( textFont );
667  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
668  p->scale( scaleFactor, scaleFactor );
669  p->drawText( QPointF( x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE ), text );
670  p->restore();
671 }
672 
673 void QgsComposerItem::drawText( QPainter* p, const QRectF& rect, const QString& text, const QFont& font, Qt::AlignmentFlag halignment, Qt::AlignmentFlag valignment, int flags ) const
674 {
675  QFont textFont = scaledFontPixelSize( font );
676 
677  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
678  rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
679 
680  p->save();
681  p->setFont( textFont );
682  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
683  p->scale( scaleFactor, scaleFactor );
684  p->drawText( scaledRect, halignment | valignment | flags, text );
685  p->restore();
686 }
687 void QgsComposerItem::drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const
688 {
689  if ( !p )
690  {
691  return;
692  }
693  double angleRad = angle / 180.0 * M_PI;
694  QPointF middlePoint( x, y );
695  //rotate both arrow points
696  QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
697  QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
698 
699  QPointF p1Rotated, p2Rotated;
700  p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
701  p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
702  p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
703  p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
704 
705  QPolygonF arrowHeadPoly;
706  arrowHeadPoly << middlePoint;
707  arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
708  arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
709 
710  p->save();
711 
712  QPen arrowPen = p->pen();
713  arrowPen.setJoinStyle( Qt::RoundJoin );
714  QBrush arrowBrush = p->brush();
715  arrowBrush.setStyle( Qt::SolidPattern );
716  p->setPen( arrowPen );
717  p->setBrush( arrowBrush );
718  arrowBrush.setStyle( Qt::SolidPattern );
719  p->drawPolygon( arrowHeadPoly );
720 
721  p->restore();
722 }
723 
724 double QgsComposerItem::textWidthMillimeters( const QFont& font, const QString& text ) const
725 {
726  QFont metricsFont = scaledFontPixelSize( font );
727  QFontMetricsF fontMetrics( metricsFont );
728  return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
729 }
730 
731 double QgsComposerItem::fontHeightCharacterMM( const QFont& font, const QChar& c ) const
732 {
733  QFont metricsFont = scaledFontPixelSize( font );
734  QFontMetricsF fontMetrics( metricsFont );
735  return ( fontMetrics.boundingRect( c ).height() / FONT_WORKAROUND_SCALE );
736 }
737 
738 double QgsComposerItem::fontAscentMillimeters( const QFont& font ) const
739 {
740  QFont metricsFont = scaledFontPixelSize( font );
741  QFontMetricsF fontMetrics( metricsFont );
742  return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
743 }
744 
745 double QgsComposerItem::fontDescentMillimeters( const QFont& font ) const
746 {
747  QFont metricsFont = scaledFontPixelSize( font );
748  QFontMetricsF fontMetrics( metricsFont );
749  return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
750 }
751 
752 double QgsComposerItem::fontHeightMillimeters( const QFont& font ) const
753 {
754  QFont metricsFont = scaledFontPixelSize( font );
755  QFontMetricsF fontMetrics( metricsFont );
756  return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
757 }
758 
759 double QgsComposerItem::pixelFontSize( double pointSize ) const
760 {
761  return ( pointSize * 0.3527 );
762 }
763 
764 QFont QgsComposerItem::scaledFontPixelSize( const QFont& font ) const
765 {
766  QFont scaledFont = font;
767  double pixelSize = pixelFontSize( font.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
768  scaledFont.setPixelSize( pixelSize );
769  return scaledFont;
770 }
771 
772 double QgsComposerItem::angle( const QPointF& p1, const QPointF& p2 ) const
773 {
774  double xDiff = p2.x() - p1.x();
775  double yDiff = p2.y() - p1.y();
776  double length = sqrt( xDiff * xDiff + yDiff * yDiff );
777  if ( length <= 0 )
778  {
779  return 0;
780  }
781 
782  double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
783  if ( xDiff < 0 )
784  {
785  return ( 360 - angle );
786  }
787  return angle;
788 }
789 
791 {
792  double result = -1;
793  if ( scene() )
794  {
795  QList<QGraphicsView*> viewList = scene()->views();
796  if ( viewList.size() > 0 ) //if not, probably this function was called from non-gui code
797  {
798  QGraphicsView* currentView = viewList.at( 0 );
799  if ( currentView->isVisible() )
800  {
801  result = currentView->transform().m11();
802  mLastValidViewScaleFactor = result;
803  }
804  }
805  }
806  return result;
807 }
808 
810 {
811  //size of symbol boxes depends on zoom level in composer view
812  double viewScaleFactor = horizontalViewScaleFactor();
813  double rectHandlerSize = 10.0 / viewScaleFactor;
814 
815  //make sure the boxes don't get too large
816  if ( rectHandlerSize > ( rect().width() / 3 ) )
817  {
818  rectHandlerSize = rect().width() / 3;
819  }
820  if ( rectHandlerSize > ( rect().height() / 3 ) )
821  {
822  rectHandlerSize = rect().height() / 3;
823  }
824  return rectHandlerSize;
825 }
826 
828 {
829  double lockSymbolSize = 20.0 / horizontalViewScaleFactor();
830 
831  if ( lockSymbolSize > ( rect().width() / 3 ) )
832  {
833  lockSymbolSize = rect().width() / 3;
834  }
835  if ( lockSymbolSize > ( rect().height() / 3 ) )
836  {
837  lockSymbolSize = rect().height() / 3;
838  }
839  return lockSymbolSize;
840 }
841 
843 {
844  //kept for api compatibility with QGIS 2.0
845  //remove after 2.0 series
846  setItemRotation( r, true );
847 }
848 
849 void QgsComposerItem::setItemRotation( double r, bool adjustPosition )
850 {
851  if ( adjustPosition )
852  {
853  //adjustPosition set, so shift the position of the item so that rotation occurs around item center
854  //create a line from the centrepoint of the rect() to its origin, in scene coordinates
855  QLineF refLine = QLineF( mapToScene( QPointF( rect().width() / 2.0, rect().height() / 2.0 ) ) , mapToScene( QPointF( 0 , 0 ) ) );
856  //rotate this line by the current rotation angle
857  refLine.setAngle( refLine.angle() - r + mItemRotation );
858  //get new end point of line - this is the new item position
859  QPointF rotatedReferencePoint = refLine.p2();
860  setPos( rotatedReferencePoint );
861  emit sizeChanged();
862  }
863 
864  if ( r > 360 )
865  {
866  mItemRotation = (( int )r ) % 360;
867  }
868  else
869  {
870  mItemRotation = r;
871  }
872 
873  setTransformOriginPoint( 0, 0 );
874  QGraphicsItem::setRotation( mItemRotation );
875 
876  emit itemRotationChanged( r );
877  update();
878 }
879 
880 bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const
881 {
882  //kept for api compatibility with QGIS 2.0, use item rotation
883  return imageSizeConsideringRotation( width, height, mItemRotation );
884 }
885 
886 QRectF QgsComposerItem::largestRotatedRectWithinBounds( QRectF originalRect, QRectF boundsRect, double rotation ) const
887 {
888  double originalWidth = originalRect.width();
889  double originalHeight = originalRect.height();
890  double boundsWidth = boundsRect.width();
891  double boundsHeight = boundsRect.height();
892  double ratioBoundsRect = boundsWidth / boundsHeight;
893 
894  double clippedRotation = fmod( rotation, 360.0 );
895 
896  //shortcut for some rotation values
897  if ( clippedRotation == 0 || clippedRotation == 90 || clippedRotation == 180 || clippedRotation == 270 )
898  {
899  double rectScale;
900  if ( clippedRotation == 0 || clippedRotation == 180 )
901  {
902  rectScale = (( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
903  }
904  else
905  {
906  rectScale = (( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
907  }
908  double rectScaledWidth = rectScale * originalWidth;
909  double rectScaledHeight = rectScale * originalHeight;
910 
911  if ( clippedRotation == 0 || clippedRotation == 180 )
912  {
913  return QRectF(( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
914  }
915  else
916  {
917  return QRectF(( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
918  }
919  }
920 
921  //convert angle to radians and flip
922  double angleRad = -clippedRotation * M_DEG2RAD;
923  double cosAngle = cos( angleRad );
924  double sinAngle = sin( angleRad );
925 
926  //calculate size of bounds of rotated rectangle
927  double widthBoundsRotatedRect = originalWidth * fabs( cosAngle ) + originalHeight * fabs( sinAngle );
928  double heightBoundsRotatedRect = originalHeight * fabs( cosAngle ) + originalWidth * fabs( sinAngle );
929 
930  //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
931  //rect to fit within bounds
932  double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
933  double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
934  double rectScaledWidth = rectScale * originalWidth;
935  double rectScaledHeight = rectScale * originalHeight;
936 
937  //now calculate offset so that rotated rectangle is centered within bounds
938  //first calculate min x and y coordinates
939  double currentCornerX = 0;
940  double minX = 0;
941  currentCornerX += rectScaledWidth * cosAngle;
942  minX = minX < currentCornerX ? minX : currentCornerX;
943  currentCornerX += rectScaledHeight * sinAngle;
944  minX = minX < currentCornerX ? minX : currentCornerX;
945  currentCornerX -= rectScaledWidth * cosAngle;
946  minX = minX < currentCornerX ? minX : currentCornerX;
947 
948  double currentCornerY = 0;
949  double minY = 0;
950  currentCornerY -= rectScaledWidth * sinAngle;
951  minY = minY < currentCornerY ? minY : currentCornerY;
952  currentCornerY += rectScaledHeight * cosAngle;
953  minY = minY < currentCornerY ? minY : currentCornerY;
954  currentCornerY += rectScaledWidth * sinAngle;
955  minY = minY < currentCornerY ? minY : currentCornerY;
956 
957  //now calculate offset position of rotated rectangle
958  double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
959  offsetX += fabs( minX );
960  double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
961  offsetY += fabs( minY );
962 
963  return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
964 }
965 
966 bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height, double rotation ) const
967 {
968  if ( qAbs( rotation ) <= 0.0 ) //width and height stays the same if there is no rotation
969  {
970  return true;
971  }
972 
973  if ( qgsDoubleNear( qAbs( rotation ), 90 ) || qgsDoubleNear( qAbs( rotation ), 270 ) )
974  {
975  double tmp = width;
976  width = height;
977  height = tmp;
978  return true;
979  }
980 
981  double x1 = 0;
982  double y1 = 0;
983  double x2 = width;
984  double y2 = 0;
985  double x3 = width;
986  double y3 = height;
987  double x4 = 0;
988  double y4 = height;
989  double midX = width / 2.0;
990  double midY = height / 2.0;
991 
992  if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height, rotation ) )
993  {
994  return false;
995  }
996  if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height, rotation ) )
997  {
998  return false;
999  }
1000  if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height, rotation ) )
1001  {
1002  return false;
1003  }
1004  if ( !cornerPointOnRotatedAndScaledRect( x4, y4, width, height, rotation ) )
1005  {
1006  return false;
1007  }
1008 
1009 
1010  //assume points 1 and 3 are on the rectangle boundaries. Calculate 2 and 4.
1011  double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) );
1012  QPointF p2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x2, y2 ), distM1 );
1013 
1014  if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 )
1015  {
1016  width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) );
1017  height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) );
1018  return true;
1019  }
1020 
1021  //else assume that points 2 and 4 are on the rectangle boundaries. Calculate 1 and 3
1022  double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) );
1023  QPointF p1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x1, y1 ), distM2 );
1024  QPointF p3 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x3, y3 ), distM2 );
1025  width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
1026  height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
1027  return true;
1028 }
1029 
1030 bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
1031 {
1032  //kept for api compatibility with QGIS 2.0, use item rotation
1033  return cornerPointOnRotatedAndScaledRect( x, y, width, height, mItemRotation );
1034 }
1035 
1036 bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height, double rotation ) const
1037 {
1038  //first rotate point clockwise
1039  double rotToRad = rotation * M_PI / 180.0;
1040  QPointF midpoint( width / 2.0, height / 2.0 );
1041  double xVector = x - midpoint.x();
1042  double yVector = y - midpoint.y();
1043  //double xRotated = cos(rotToRad) * xVector + sin(rotToRad) * yVector;
1044  //double yRotated = -sin(rotToRad) * xVector + cos(rotToRad) * yVector;
1045  double xRotated = cos( rotToRad ) * xVector - sin( rotToRad ) * yVector;
1046  double yRotated = sin( rotToRad ) * xVector + cos( rotToRad ) * yVector;
1047 
1048  //create line from midpoint to rotated point
1049  QLineF line( midpoint.x(), midpoint.y(), midpoint.x() + xRotated, midpoint.y() + yRotated );
1050 
1051  //intersect with all four borders and return result
1052  QList<QLineF> borders;
1053  borders << QLineF( 0, 0, width, 0 );
1054  borders << QLineF( width, 0, width, height );
1055  borders << QLineF( width, height, 0, height );
1056  borders << QLineF( 0, height, 0, 0 );
1057 
1058  QList<QLineF>::const_iterator it = borders.constBegin();
1059  QPointF intersectionPoint;
1060 
1061  for ( ; it != borders.constEnd(); ++it )
1062  {
1063  if ( line.intersect( *it, &intersectionPoint ) == QLineF::BoundedIntersection )
1064  {
1065  x = intersectionPoint.x();
1066  y = intersectionPoint.y();
1067  return true;
1068  }
1069  }
1070  return false;
1071 }
1072 
1073 void QgsComposerItem::sizeChangedByRotation( double& width, double& height )
1074 {
1075  //kept for api compatibility with QGIS 2.0, use item rotation
1076  return sizeChangedByRotation( width, height, mItemRotation );
1077 }
1078 
1079 void QgsComposerItem::sizeChangedByRotation( double& width, double& height, double rotation )
1080 {
1081  if ( rotation == 0.0 )
1082  {
1083  return;
1084  }
1085 
1086  //vector to p1
1087  double x1 = -width / 2.0;
1088  double y1 = -height / 2.0;
1089  rotate( rotation, x1, y1 );
1090  //vector to p2
1091  double x2 = width / 2.0;
1092  double y2 = -height / 2.0;
1093  rotate( rotation, x2, y2 );
1094  //vector to p3
1095  double x3 = width / 2.0;
1096  double y3 = height / 2.0;
1097  rotate( rotation, x3, y3 );
1098  //vector to p4
1099  double x4 = -width / 2.0;
1100  double y4 = height / 2.0;
1101  rotate( rotation, x4, y4 );
1102 
1103  //double midpoint
1104  QPointF midpoint( width / 2.0, height / 2.0 );
1105 
1106  QPolygonF rotatedRectPoly;
1107  rotatedRectPoly << QPointF( midpoint.x() + x1, midpoint.y() + y1 );
1108  rotatedRectPoly << QPointF( midpoint.x() + x2, midpoint.y() + y2 );
1109  rotatedRectPoly << QPointF( midpoint.x() + x3, midpoint.y() + y3 );
1110  rotatedRectPoly << QPointF( midpoint.x() + x4, midpoint.y() + y4 );
1111  QRectF boundingRect = rotatedRectPoly.boundingRect();
1112  width = boundingRect.width();
1113  height = boundingRect.height();
1114 }
1115 
1116 void QgsComposerItem::rotate( double angle, double& x, double& y ) const
1117 {
1118  double rotToRad = angle * M_PI / 180.0;
1119  double xRot, yRot;
1120  xRot = x * cos( rotToRad ) - y * sin( rotToRad );
1121  yRot = x * sin( rotToRad ) + y * cos( rotToRad );
1122  x = xRot;
1123  y = yRot;
1124 }
1125 
1127 {
1128  if ( !mHAlignSnapItem )
1129  {
1130  mHAlignSnapItem = new QGraphicsLineItem( 0 );
1131  mHAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
1132  scene()->addItem( mHAlignSnapItem );
1133  mHAlignSnapItem->setZValue( 90 );
1134  }
1135  return mHAlignSnapItem;
1136 }
1137 
1139 {
1140  if ( !mVAlignSnapItem )
1141  {
1142  mVAlignSnapItem = new QGraphicsLineItem( 0 );
1143  mVAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
1144  scene()->addItem( mVAlignSnapItem );
1145  mVAlignSnapItem->setZValue( 90 );
1146  }
1147  return mVAlignSnapItem;
1148 }
1149 
1151 {
1152  if ( mHAlignSnapItem )
1153  {
1154  scene()->removeItem( mHAlignSnapItem );
1155  delete mHAlignSnapItem;
1156  mHAlignSnapItem = 0;
1157  }
1158 }
1159 
1161 {
1162  if ( mVAlignSnapItem )
1163  {
1164  scene()->removeItem( mVAlignSnapItem );
1165  delete mVAlignSnapItem;
1166  mVAlignSnapItem = 0;
1167  }
1168 }
1169 
1171 {
1174 }
1175 
1177 {
1178  update();
1179 }
1180 
1181 void QgsComposerItem::setId( const QString& id )
1182 {
1183  setToolTip( id );
1184  mId = id;
1185 }
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...
QPointF pagePos() const
Returns the item's position relative to its current page.
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.
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)
double spaceBetweenPages() const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:324
void setItemPosition(double x, double y, ItemPositionMode itemPoint=UpperLeft, int page=-1)
Moves the item to a new position (in canvas coordinates)
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 descent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCA...
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.
void updatePagePos(double newPageWidth, double newPageHeight)
Moves the item so that it retains its relative position on the page when the paper size changes...
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.
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
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)
double fontHeightMillimeters(const QFont &font) const
Returns the font height in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
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.
const QgsComposition * composition() const
double paperHeight() const
Returns height of paper item.
int page() const
Gets the page the item is currently on.
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)