QGIS API Documentation  2.0.1-Dufour
 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 QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue )
46  : QObject( 0 )
47  , QGraphicsRectItem( 0 )
48  , mComposition( composition )
49  , mBoundingResizeRectangle( 0 )
50  , mHAlignSnapItem( 0 )
51  , mVAlignSnapItem( 0 )
52  , mFrame( false )
53  , mBackground( true )
54  , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
55  , mItemPositionLocked( false )
56  , mLastValidViewScaleFactor( -1 )
57  , mRotation( 0 )
58  , mBlendMode( QPainter::CompositionMode_SourceOver )
59  , mEffectsEnabled( true )
60  , mTransparency( 0 )
61  , mLastUsedPositionMode( UpperLeft )
62  , mId( "" )
63  , mUuid( QUuid::createUuid().toString() )
64 {
65  init( manageZValue );
66 }
67 
68 QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, QgsComposition* composition, bool manageZValue )
69  : QObject( 0 )
70  , QGraphicsRectItem( 0, 0, width, height, 0 )
71  , mComposition( composition )
72  , mBoundingResizeRectangle( 0 )
73  , mHAlignSnapItem( 0 )
74  , mVAlignSnapItem( 0 )
75  , mFrame( false )
76  , mBackground( true )
77  , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
78  , mItemPositionLocked( false )
79  , mLastValidViewScaleFactor( -1 )
80  , mRotation( 0 )
81  , mBlendMode( QPainter::CompositionMode_SourceOver )
82  , mEffectsEnabled( true )
83  , mTransparency( 0 )
84  , mLastUsedPositionMode( UpperLeft )
85  , mId( "" )
86  , mUuid( QUuid::createUuid().toString() )
87 {
88  init( manageZValue );
89  QTransform t;
90  t.translate( x, y );
91  setTransform( t );
92 }
93 
94 void QgsComposerItem::init( bool manageZValue )
95 {
96  setFlag( QGraphicsItem::ItemIsSelectable, true );
97  setAcceptsHoverEvents( true );
98  //set default pen and brush
99  setBrush( QBrush( QColor( 255, 255, 255, 255 ) ) );
100  QPen defaultPen( QColor( 0, 0, 0 ) );
101  defaultPen.setWidthF( 0.3 );
102  setPen( defaultPen );
103  //let z-Value be managed by composition
104  if ( mComposition && manageZValue )
105  {
106  mComposition->addItemToZList( this );
107  }
108 
109  // Setup composer effect
110  mEffect = new QgsComposerEffect();
111  setGraphicsEffect( mEffect );
112 }
113 
115 {
116  if ( mComposition )
117  {
119  }
120 
122  delete mEffect;
124 }
125 
127 {
128  QgsDebugMsg( "entered." );
129  QGraphicsRectItem::setSelected( s );
130  update(); //to draw selection boxes
131 }
132 
133 bool QgsComposerItem::writeSettings( void ) { return true; }
134 
135 bool QgsComposerItem::readSettings( void ) { return true; }
136 
137 bool QgsComposerItem::removeSettings( void ) { return true; }
138 
139 bool QgsComposerItem::_writeXML( QDomElement& itemElem, QDomDocument& doc ) const
140 {
141  if ( itemElem.isNull() )
142  {
143  return false;
144  }
145 
146  QDomElement composerItemElem = doc.createElement( "ComposerItem" );
147 
148  //frame
149  if ( mFrame )
150  {
151  composerItemElem.setAttribute( "frame", "true" );
152  }
153  else
154  {
155  composerItemElem.setAttribute( "frame", "false" );
156  }
157 
158  //frame
159  if ( mBackground )
160  {
161  composerItemElem.setAttribute( "background", "true" );
162  }
163  else
164  {
165  composerItemElem.setAttribute( "background", "false" );
166  }
167 
168  //scene rect
169  composerItemElem.setAttribute( "x", QString::number( transform().dx() ) );
170  composerItemElem.setAttribute( "y", QString::number( transform().dy() ) );
171  composerItemElem.setAttribute( "width", QString::number( rect().width() ) );
172  composerItemElem.setAttribute( "height", QString::number( rect().height() ) );
173  composerItemElem.setAttribute( "positionMode", QString::number(( int ) mLastUsedPositionMode ) );
174  composerItemElem.setAttribute( "zValue", QString::number( zValue() ) );
175  composerItemElem.setAttribute( "outlineWidth", QString::number( pen().widthF() ) );
176  composerItemElem.setAttribute( "rotation", QString::number( mRotation ) );
177  composerItemElem.setAttribute( "uuid", mUuid );
178  composerItemElem.setAttribute( "id", mId );
179  //position lock for mouse moves/resizes
180  if ( mItemPositionLocked )
181  {
182  composerItemElem.setAttribute( "positionLock", "true" );
183  }
184  else
185  {
186  composerItemElem.setAttribute( "positionLock", "false" );
187  }
188 
189  composerItemElem.setAttribute( "lastValidViewScaleFactor", QString::number( mLastValidViewScaleFactor ) );
190 
191 
192  //frame color
193  QDomElement frameColorElem = doc.createElement( "FrameColor" );
194  QColor frameColor = pen().color();
195  frameColorElem.setAttribute( "red", QString::number( frameColor.red() ) );
196  frameColorElem.setAttribute( "green", QString::number( frameColor.green() ) );
197  frameColorElem.setAttribute( "blue", QString::number( frameColor.blue() ) );
198  frameColorElem.setAttribute( "alpha", QString::number( frameColor.alpha() ) );
199  composerItemElem.appendChild( frameColorElem );
200 
201  //background color
202  QDomElement bgColorElem = doc.createElement( "BackgroundColor" );
203  QColor bgColor = brush().color();
204  bgColorElem.setAttribute( "red", QString::number( bgColor.red() ) );
205  bgColorElem.setAttribute( "green", QString::number( bgColor.green() ) );
206  bgColorElem.setAttribute( "blue", QString::number( bgColor.blue() ) );
207  bgColorElem.setAttribute( "alpha", QString::number( bgColor.alpha() ) );
208  composerItemElem.appendChild( bgColorElem );
209 
210  //blend mode
211  composerItemElem.setAttribute( "blendMode", QgsMapRenderer::getBlendModeEnum( mBlendMode ) );
212 
213  //transparency
214  composerItemElem.setAttribute( "transparency", QString::number( mTransparency ) );
215 
216  itemElem.appendChild( composerItemElem );
217 
218  return true;
219 }
220 
221 bool QgsComposerItem::_readXML( const QDomElement& itemElem, const QDomDocument& doc )
222 {
223  Q_UNUSED( doc );
224  if ( itemElem.isNull() )
225  {
226  return false;
227  }
228 
229  //rotation
230  mRotation = itemElem.attribute( "rotation", "0" ).toDouble();
231 
232  //uuid
233  mUuid = itemElem.attribute( "uuid", QUuid::createUuid().toString() );
234 
235  // temporary for groups imported from templates
236  mTemplateUuid = itemElem.attribute( "templateUuid" );
237 
238  //id
239  QString id = itemElem.attribute( "id", "" );
240  setId( id );
241 
242  //frame
243  QString frame = itemElem.attribute( "frame" );
244  if ( frame.compare( "true", Qt::CaseInsensitive ) == 0 )
245  {
246  mFrame = true;
247  }
248  else
249  {
250  mFrame = false;
251  }
252 
253  //frame
254  QString background = itemElem.attribute( "background" );
255  if ( background.compare( "true", Qt::CaseInsensitive ) == 0 )
256  {
257  mBackground = true;
258  }
259  else
260  {
261  mBackground = false;
262  }
263 
264  //position lock for mouse moves/resizes
265  QString positionLock = itemElem.attribute( "positionLock" );
266  if ( positionLock.compare( "true", Qt::CaseInsensitive ) == 0 )
267  {
268  mItemPositionLocked = true;
269  }
270  else
271  {
272  mItemPositionLocked = false;
273  }
274 
275  //position
276  double x, y, width, height;
277  bool xOk, yOk, widthOk, heightOk, positionModeOK;
278 
279  x = itemElem.attribute( "x" ).toDouble( &xOk );
280  y = itemElem.attribute( "y" ).toDouble( &yOk );
281  width = itemElem.attribute( "width" ).toDouble( &widthOk );
282  height = itemElem.attribute( "height" ).toDouble( &heightOk );
283  mLastUsedPositionMode = ( ItemPositionMode )itemElem.attribute( "positionMode" ).toInt( &positionModeOK );
284  if ( !positionModeOK )
285  {
287  }
288 
289  if ( !xOk || !yOk || !widthOk || !heightOk )
290  {
291  return false;
292  }
293 
294  mLastValidViewScaleFactor = itemElem.attribute( "lastValidViewScaleFactor", "-1" ).toDouble();
295 
296  setSceneRect( QRectF( x, y, width, height ) );
297  setZValue( itemElem.attribute( "zValue" ).toDouble() );
298 
299  //pen
300  QDomNodeList frameColorList = itemElem.elementsByTagName( "FrameColor" );
301  if ( frameColorList.size() > 0 )
302  {
303  QDomElement frameColorElem = frameColorList.at( 0 ).toElement();
304  bool redOk, greenOk, blueOk, alphaOk, widthOk;
305  int penRed, penGreen, penBlue, penAlpha;
306  double penWidth;
307 
308  penWidth = itemElem.attribute( "outlineWidth" ).toDouble( &widthOk );
309  penRed = frameColorElem.attribute( "red" ).toDouble( &redOk );
310  penGreen = frameColorElem.attribute( "green" ).toDouble( &greenOk );
311  penBlue = frameColorElem.attribute( "blue" ).toDouble( &blueOk );
312  penAlpha = frameColorElem.attribute( "alpha" ).toDouble( &alphaOk );
313  if ( redOk && greenOk && blueOk && alphaOk && widthOk )
314  {
315  QPen framePen( QColor( penRed, penGreen, penBlue, penAlpha ) );
316  framePen.setWidthF( penWidth );
317  setPen( framePen );
318  }
319  }
320 
321  //brush
322  QDomNodeList bgColorList = itemElem.elementsByTagName( "BackgroundColor" );
323  if ( bgColorList.size() > 0 )
324  {
325  QDomElement bgColorElem = bgColorList.at( 0 ).toElement();
326  bool redOk, greenOk, blueOk, alphaOk;
327  int bgRed, bgGreen, bgBlue, bgAlpha;
328  bgRed = bgColorElem.attribute( "red" ).toDouble( &redOk );
329  bgGreen = bgColorElem.attribute( "green" ).toDouble( &greenOk );
330  bgBlue = bgColorElem.attribute( "blue" ).toDouble( &blueOk );
331  bgAlpha = bgColorElem.attribute( "alpha" ).toDouble( &alphaOk );
332  if ( redOk && greenOk && blueOk && alphaOk )
333  {
334  QColor brushColor( bgRed, bgGreen, bgBlue, bgAlpha );
335  setBackgroundColor( brushColor );
336  }
337  }
338 
339  //blend mode
340  setBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) itemElem.attribute( "blendMode", "0" ).toUInt() ) );
341 
342  //transparency
343  setTransparency( itemElem.attribute( "transparency" , "0" ).toInt() );
344 
345  return true;
346 }
347 
349 {
350  if ( mComposition )
351  {
352  mComposition->beginCommand( this, commandText, c );
353  }
354 }
355 
357 {
358  if ( mComposition )
359  {
361  }
362 }
363 
365 {
366  if ( mComposition )
367  {
369  }
370 }
371 
372 void QgsComposerItem::mouseMoveEvent( QGraphicsSceneMouseEvent * event )
373 {
374  if ( mItemPositionLocked )
375  {
376  return;
377  }
378 
379  if ( !isSelected() )
380  {
381  return;
382  }
383 
385  {
386  double diffX = event->lastScenePos().x() - mLastMouseEventPos.x();
387  double diffY = event->lastScenePos().y() - mLastMouseEventPos.y();
388 
389  changeItemRectangle( event->lastScenePos(), mMouseMoveStartPos, this, diffX, diffY, mBoundingResizeRectangle );
390  }
391  mLastMouseEventPos = event->lastScenePos();
392 }
393 
394 void QgsComposerItem::mousePressEvent( QGraphicsSceneMouseEvent * event )
395 {
396  if ( mItemPositionLocked )
397  {
398  return;
399  }
400 
401  if ( !isSelected() )
402  {
403  return;
404  }
405 
406  //set current position and type of mouse move action
407  mMouseMoveStartPos = event->lastScenePos();
408  mLastMouseEventPos = event->lastScenePos();
410 
411  //remove the old rubber band item if it is still there
413  {
414  scene()->removeItem( mBoundingResizeRectangle );
417  }
419 
420  //create and show bounding rectangle
421  mBoundingResizeRectangle = new QGraphicsRectItem( 0 );
422  scene()->addItem( mBoundingResizeRectangle );
423  mBoundingResizeRectangle->setRect( QRectF( 0, 0, rect().width(), rect().height() ) );
424  QTransform resizeTransform;
425  resizeTransform.translate( transform().dx(), transform().dy() );
426  mBoundingResizeRectangle->setTransform( resizeTransform );
427 
428  mBoundingResizeRectangle->setBrush( Qt::NoBrush );
429  mBoundingResizeRectangle->setPen( QPen( QColor( 0, 0, 0 ), 0 ) );
430  mBoundingResizeRectangle->setZValue( 90 );
431  mBoundingResizeRectangle->show();
432 }
433 
434 void QgsComposerItem::mouseReleaseEvent( QGraphicsSceneMouseEvent * event )
435 {
436 
437  if ( mItemPositionLocked )
438  {
439  return;
440  }
441 
442  if ( !isSelected() )
443  {
444  return;
445  }
446 
447  //delete frame rectangle
449  {
450  scene()->removeItem( mBoundingResizeRectangle );
453  }
454 
455  QPointF mouseMoveStopPoint = event->lastScenePos();
456  double diffX = mouseMoveStopPoint.x() - mMouseMoveStartPos.x();
457  double diffY = mouseMoveStopPoint.y() - mMouseMoveStartPos.y();
458 
459  //it was only a click
460  if ( qAbs( diffX ) < std::numeric_limits<double>::min() && qAbs( diffY ) < std::numeric_limits<double>::min() )
461  {
462  return;
463  }
464 
465  beginItemCommand( tr( "Change item position" ) );
466  changeItemRectangle( mouseMoveStopPoint, mMouseMoveStartPos, this, diffX, diffY, this );
467  endItemCommand();
468 
470 
471  //reset default action
473  setCursor( Qt::ArrowCursor );
474 }
475 
476 Qt::CursorShape QgsComposerItem::cursorForPosition( const QPointF& itemCoordPos )
477 {
478  QgsComposerItem::MouseMoveAction mouseAction = mouseMoveActionForPosition( itemCoordPos );
479  switch ( mouseAction )
480  {
481  case NoAction:
482  return Qt::ForbiddenCursor;
483  case MoveItem:
484  return Qt::SizeAllCursor;
485  case ResizeUp:
486  case ResizeDown:
487  return Qt::SizeVerCursor;
488  case ResizeLeft:
489  case ResizeRight:
490  return Qt::SizeHorCursor;
491  case ResizeLeftUp:
492  case ResizeRightDown:
493  return Qt::SizeFDiagCursor;
494  case ResizeRightUp:
495  case ResizeLeftDown:
496  return Qt::SizeBDiagCursor;
497  default:
498  return Qt::ArrowCursor;
499  }
500 }
501 
503 {
504 
505  //no action at all if item position is locked for mouse
506  if ( mItemPositionLocked )
507  {
509  }
510 
511  bool nearLeftBorder = false;
512  bool nearRightBorder = false;
513  bool nearLowerBorder = false;
514  bool nearUpperBorder = false;
515 
516  double borderTolerance = rectHandlerBorderTolerance();
517 
518  if ( itemCoordPos.x() < borderTolerance )
519  {
520  nearLeftBorder = true;
521  }
522  if ( itemCoordPos.y() < borderTolerance )
523  {
524  nearUpperBorder = true;
525  }
526  if ( itemCoordPos.x() > ( rect().width() - borderTolerance ) )
527  {
528  nearRightBorder = true;
529  }
530  if ( itemCoordPos.y() > ( rect().height() - borderTolerance ) )
531  {
532  nearLowerBorder = true;
533  }
534 
535  if ( nearLeftBorder && nearUpperBorder )
536  {
538  }
539  else if ( nearLeftBorder && nearLowerBorder )
540  {
542  }
543  else if ( nearRightBorder && nearUpperBorder )
544  {
546  }
547  else if ( nearRightBorder && nearLowerBorder )
548  {
550  }
551  else if ( nearLeftBorder )
552  {
554  }
555  else if ( nearRightBorder )
556  {
558  }
559  else if ( nearUpperBorder )
560  {
562  }
563  else if ( nearLowerBorder )
564  {
566  }
567 
568  return QgsComposerItem::MoveItem; //default
569 }
570 
571 void QgsComposerItem::changeItemRectangle( const QPointF& currentPosition,
572  const QPointF& mouseMoveStartPos,
573  const QGraphicsRectItem* originalItem,
574  double dx, double dy,
575  QGraphicsRectItem* changeItem )
576 {
577  Q_UNUSED( dx );
578  Q_UNUSED( dy );
579  if ( !changeItem || !originalItem || !mComposition )
580  {
581  return;
582  }
583 
584  //test if change item is a composer item. If so, prefer call to setSceneRect() instead of setTransform() and setRect()
585  QgsComposerItem* changeComposerItem = dynamic_cast<QgsComposerItem *>( changeItem );
586 
587  double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
588  QPointF snappedPosition = mComposition->snapPointToGrid( currentPosition );
589 
590  //snap to grid and align to other items
592  {
593  double alignX = 0;
594  double alignY = 0;
595  snappedPosition = mComposition->alignPos( snappedPosition, dynamic_cast<const QgsComposerItem*>( originalItem ), alignX, alignY );
596  if ( alignX != -1 )
597  {
598  QGraphicsLineItem* item = hAlignSnapItem();
599  item->setLine( QLineF( alignX, 0, alignX, mComposition->paperHeight() ) );
600  item->show();
601  }
602  else
603  {
605  }
606 
607  if ( alignY != -1 )
608  {
609  QGraphicsLineItem* item = vAlignSnapItem();
610  item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
611  item->show();
612  }
613  else
614  {
616  }
617  }
618 
619  double diffX = 0;
620  double diffY = 0;
621 
622  switch ( mCurrentMouseMoveAction )
623  {
624  //vertical resize
626  diffY = snappedPosition.y() - originalItem->transform().dy();
627  mx = 0; my = diffY; rx = 0; ry = -diffY;
628  break;
629 
631  diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
632  mx = 0; my = 0; rx = 0; ry = diffY;
633  break;
634 
635  //horizontal resize
637  diffX = snappedPosition.x() - originalItem->transform().dx();
638  mx = diffX, my = 0; rx = -diffX; ry = 0;
639  break;
640 
642  diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
643  mx = 0; my = 0; rx = diffX, ry = 0;
644  break;
645 
646  //diagonal resize
648  diffX = snappedPosition.x() - originalItem->transform().dx();
649  diffY = snappedPosition.y() - originalItem->transform().dy();
650  mx = diffX, my = diffY; rx = -diffX; ry = -diffY;
651  break;
652 
654  diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
655  diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
656  mx = 0; my = 0; rx = diffX, ry = diffY;
657  break;
658 
660  diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
661  diffY = snappedPosition.y() - originalItem->transform().dy();
662  mx = 0; my = diffY, rx = diffX, ry = -diffY;
663  break;
664 
666  diffX = snappedPosition.x() - originalItem->transform().dx();
667  diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
668  mx = diffX, my = 0; rx = -diffX; ry = diffY;
669  break;
670 
672  {
673  //calculate total move difference
674  double moveX = currentPosition.x() - mouseMoveStartPos.x();
675  double moveY = currentPosition.y() - mouseMoveStartPos.y();
676 
677  QPointF upperLeftPoint( originalItem->transform().dx() + moveX, originalItem->transform().dy() + moveY );
678  QPointF snappedLeftPoint = mComposition->snapPointToGrid( upperLeftPoint );
679 
680  if ( snappedLeftPoint != upperLeftPoint ) //don't do align snap if grid snap has been done
681  {
683  }
684  else if ( mComposition->alignmentSnap() ) //align item
685  {
686  double alignX = 0;
687  double alignY = 0;
688  snappedLeftPoint = mComposition->alignItem( dynamic_cast<const QgsComposerItem*>( originalItem ), alignX, alignY, moveX, moveY );
689  if ( alignX != -1 )
690  {
691  QGraphicsLineItem* item = hAlignSnapItem();
692  int numPages = mComposition->numPages();
693  double yLineCoord = 300; //default in case there is no single page
694  if ( numPages > 0 )
695  {
696  yLineCoord = mComposition->paperHeight() * numPages + mComposition->spaceBetweenPages() * ( numPages - 1 );
697  }
698  item->setLine( QLineF( alignX, 0, alignX, yLineCoord ) );
699  item->show();
700  }
701  else
702  {
704  }
705  if ( alignY != -1 )
706  {
707  QGraphicsLineItem* item = vAlignSnapItem();
708  item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
709  item->show();
710  }
711  else
712  {
714  }
715  }
716  double moveRectX = snappedLeftPoint.x() - originalItem->transform().dx();
717  double moveRectY = snappedLeftPoint.y() - originalItem->transform().dy();
718 
719  if ( !changeComposerItem )
720  {
721  QTransform moveTransform;
722  moveTransform.translate( originalItem->transform().dx() + moveRectX, originalItem->transform().dy() + moveRectY );
723  changeItem->setTransform( moveTransform );
724  }
725  else //for composer items, we prefer setSceneRect as subclasses can implement custom behaviour (e.g. item group)
726  {
727  changeComposerItem->setSceneRect( QRectF( originalItem->transform().dx() + moveRectX,
728  originalItem->transform().dy() + moveRectY,
729  originalItem->rect().width(), originalItem->rect().height() ) );
730  changeComposerItem->updateItem();
731  }
732  }
733  return;
735  break;
736  }
737 
738  if ( !changeComposerItem )
739  {
740  QTransform itemTransform;
741  itemTransform.translate( originalItem->transform().dx() + mx, originalItem->transform().dy() + my );
742  changeItem->setTransform( itemTransform );
743  QRectF itemRect( 0, 0, originalItem->rect().width() + rx, originalItem->rect().height() + ry );
744  changeItem->setRect( itemRect );
745  }
746  else //for composer items, we prefer setSceneRect as subclasses can implement custom behaviour (e.g. item group)
747  {
748  changeComposerItem->setSceneRect( QRectF( originalItem->transform().dx() + mx, originalItem->transform().dy() + my,
749  originalItem->rect().width() + rx, originalItem->rect().height() + ry ) );
750  changeComposerItem->updateItem();
751  }
752 }
753 
755 {
756  if ( !mComposition )
757  {
758  return;
759  }
760 
762  {
763  //size of symbol boxes depends on zoom level in composer view
764  double rectHandlerSize = rectHandlerBorderTolerance();
765  double sizeLockSymbol = lockSymbolSize();
766 
767  if ( mItemPositionLocked )
768  {
769  //draw lock symbol at upper left edge. Use QImage to be independent of the graphic system
770  QString lockIconPath = QgsApplication::activeThemePath() + "/mIconLock.png";
771  if ( !QFile::exists( lockIconPath ) )
772  {
773  lockIconPath = QgsApplication::defaultThemePath() + "/mIconLock.png";
774  }
775 
776  QImage lockImage( lockIconPath );
777  if ( !lockImage.isNull() )
778  {
779  p->drawImage( QRectF( 0, 0, sizeLockSymbol, sizeLockSymbol ), lockImage, QRectF( 0, 0, lockImage.width(), lockImage.height() ) );
780  }
781  }
782  else //draw blue squares
783  {
784  p->setPen( QColor( 50, 100, 120, 200 ) );
785  p->setBrush( QColor( 200, 200, 210, 120 ) );
786  p->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
787  p->drawRect( QRectF( rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
788  p->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
789  p->drawRect( QRectF( 0, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
790  }
791  }
792 }
793 
794 void QgsComposerItem::drawFrame( QPainter* p )
795 {
796  if ( mFrame && p )
797  {
798  p->setPen( pen() );
799  p->setBrush( Qt::NoBrush );
800  p->setRenderHint( QPainter::Antialiasing, true );
801  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
802  }
803 }
804 
805 void QgsComposerItem::move( double dx, double dy )
806 {
807  QTransform t = transform();
808  QRectF newSceneRect( t.dx() + dx, t.dy() + dy, rect().width(), rect().height() );
809  setSceneRect( newSceneRect );
810 }
811 
812 void QgsComposerItem::setItemPosition( double x, double y, ItemPositionMode itemPoint )
813 {
814  double width = rect().width();
815  double height = rect().height();
816  setItemPosition( x, y, width, height, itemPoint );
817 }
818 
819 void QgsComposerItem::setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint )
820 {
821  double upperLeftX = x;
822  double upperLeftY = y;
823 
824  //store the item position mode
825  mLastUsedPositionMode = itemPoint;
826 
827  //adjust x-coordinate if placement is not done to a left point
828  if ( itemPoint == UpperMiddle || itemPoint == Middle || itemPoint == LowerMiddle )
829  {
830  upperLeftX -= width / 2.0;
831  }
832  else if ( itemPoint == UpperRight || itemPoint == MiddleRight || itemPoint == LowerRight )
833  {
834  upperLeftX -= width;
835  }
836 
837  //adjust y-coordinate if placement is not done to an upper point
838  if ( itemPoint == MiddleLeft || itemPoint == Middle || itemPoint == MiddleRight )
839  {
840  upperLeftY -= height / 2.0;
841  }
842  else if ( itemPoint == LowerLeft || itemPoint == LowerMiddle || itemPoint == LowerRight )
843  {
844  upperLeftY -= height;
845  }
846 
847  setSceneRect( QRectF( upperLeftX, upperLeftY, width, height ) );
848 }
849 
850 void QgsComposerItem::setSceneRect( const QRectF& rectangle )
851 {
852  //setRect in item coordinates
853  double newWidth = rectangle.width();
854  double newHeight = rectangle.height();
855  double xTranslation = rectangle.x();
856  double yTranslation = rectangle.y();
857 
858  //correction if width and/or height are negative
859  if ( rectangle.width() < 0 )
860  {
861  newWidth = - rectangle.width();
862  xTranslation -= newWidth;
863  }
864 
865  if ( rectangle.height() < 0 )
866  {
867  newHeight = - rectangle.height();
868  yTranslation -= newHeight;
869  }
870 
871  QRectF newRect( 0, 0, newWidth, newHeight );
872  QGraphicsRectItem::setRect( newRect );
873 
874  //set up transformation matrix for item coordinates
875  QTransform t;
876  t.translate( xTranslation, yTranslation );
877  setTransform( t );
878 
879  emit sizeChanged();
880 }
881 
883 {
884  if ( mBackground && p )
885  {
886  p->setBrush( brush() );//this causes a problem in atlas generation
887  p->setPen( Qt::NoPen );
888  p->setRenderHint( QPainter::Antialiasing, true );
889  p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
890  }
891 }
892 
893 void QgsComposerItem::setBackgroundColor( const QColor& backgroundColor )
894 {
896  setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
897 }
898 
899 void QgsComposerItem::setBlendMode( QPainter::CompositionMode blendMode )
900 {
902  // Update the composer effect to use the new blend mode
904 }
905 
906 void QgsComposerItem::setTransparency( int transparency )
907 {
909  // Set the QGraphicItem's opacity
910  setOpacity( 1. - ( transparency / 100. ) );
911 }
912 
913 void QgsComposerItem::setEffectsEnabled( bool effectsEnabled )
914 {
915  //enable or disable the QgsComposerEffect applied to this item
917  mEffect->setEnabled( effectsEnabled );
918 }
919 
920 void QgsComposerItem::hoverMoveEvent( QGraphicsSceneHoverEvent * event )
921 {
922  if ( isSelected() )
923  {
924  setCursor( cursorForPosition( event->pos() ) );
925  }
926  else
927  {
928  setCursor( Qt::ArrowCursor );
929  }
930 }
931 
932 void QgsComposerItem::drawText( QPainter* p, double x, double y, const QString& text, const QFont& font ) const
933 {
934  QFont textFont = scaledFontPixelSize( font );
935 
936  p->save();
937  p->setFont( textFont );
938  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
939  p->scale( scaleFactor, scaleFactor );
940  p->drawText( QPointF( x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE ), text );
941  p->restore();
942 }
943 
944 void QgsComposerItem::drawText( QPainter* p, const QRectF& rect, const QString& text, const QFont& font, Qt::AlignmentFlag halignment, Qt::AlignmentFlag valignment ) const
945 {
946  QFont textFont = scaledFontPixelSize( font );
947 
948  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
949  rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
950 
951  p->save();
952  p->setFont( textFont );
953  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
954  p->scale( scaleFactor, scaleFactor );
955  p->drawText( scaledRect, halignment | valignment | Qt::TextWordWrap, text );
956  p->restore();
957 }
958 void QgsComposerItem::drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const
959 {
960  if ( !p )
961  {
962  return;
963  }
964  double angleRad = angle / 180.0 * M_PI;
965  QPointF middlePoint( x, y );
966  //rotate both arrow points
967  QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
968  QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
969 
970  QPointF p1Rotated, p2Rotated;
971  p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
972  p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
973  p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
974  p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
975 
976  QPolygonF arrowHeadPoly;
977  arrowHeadPoly << middlePoint;
978  arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
979  arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
980 
981  p->save();
982 
983  QPen arrowPen = p->pen();
984  arrowPen.setJoinStyle( Qt::RoundJoin );
985  QBrush arrowBrush = p->brush();
986  arrowBrush.setStyle( Qt::SolidPattern );
987  p->setPen( arrowPen );
988  p->setBrush( arrowBrush );
989  arrowBrush.setStyle( Qt::SolidPattern );
990  p->drawPolygon( arrowHeadPoly );
991 
992  p->restore();
993 }
994 
995 double QgsComposerItem::textWidthMillimeters( const QFont& font, const QString& text ) const
996 {
997  QFont metricsFont = scaledFontPixelSize( font );
998  QFontMetricsF fontMetrics( metricsFont );
999  return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
1000 }
1001 
1002 double QgsComposerItem::fontHeightCharacterMM( const QFont& font, const QChar& c ) const
1003 {
1004  QFont metricsFont = scaledFontPixelSize( font );
1005  QFontMetricsF fontMetrics( metricsFont );
1006  return ( fontMetrics.boundingRect( c ).height() / FONT_WORKAROUND_SCALE );
1007 }
1008 
1009 double QgsComposerItem::fontAscentMillimeters( const QFont& font ) const
1010 {
1011  QFont metricsFont = scaledFontPixelSize( font );
1012  QFontMetricsF fontMetrics( metricsFont );
1013  return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
1014 }
1015 
1016 double QgsComposerItem::fontDescentMillimeters( const QFont& font ) const
1017 {
1018  QFont metricsFont = scaledFontPixelSize( font );
1019  QFontMetricsF fontMetrics( metricsFont );
1020  return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
1021 }
1022 
1023 double QgsComposerItem::pixelFontSize( double pointSize ) const
1024 {
1025  return ( pointSize * 0.3527 );
1026 }
1027 
1028 QFont QgsComposerItem::scaledFontPixelSize( const QFont& font ) const
1029 {
1030  QFont scaledFont = font;
1031  double pixelSize = pixelFontSize( font.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
1032  scaledFont.setPixelSize( pixelSize );
1033  return scaledFont;
1034 }
1035 
1036 double QgsComposerItem::angle( const QPointF& p1, const QPointF& p2 ) const
1037 {
1038  double xDiff = p2.x() - p1.x();
1039  double yDiff = p2.y() - p1.y();
1040  double length = sqrt( xDiff * xDiff + yDiff * yDiff );
1041  if ( length <= 0 )
1042  {
1043  return 0;
1044  }
1045 
1046  double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
1047  if ( xDiff < 0 )
1048  {
1049  return ( 360 - angle );
1050  }
1051  return angle;
1052 }
1053 
1055 {
1056  double result = -1;
1057  if ( scene() )
1058  {
1059  QList<QGraphicsView*> viewList = scene()->views();
1060  if ( viewList.size() > 0 ) //if not, probably this function was called from non-gui code
1061  {
1062  QGraphicsView* currentView = viewList.at( 0 );
1063  if ( currentView->isVisible() )
1064  {
1065  result = currentView->transform().m11();
1066  mLastValidViewScaleFactor = result;
1067  }
1068  }
1069  }
1070  return result;
1071 }
1072 
1074 {
1075  //size of symbol boxes depends on zoom level in composer view
1076  double viewScaleFactor = horizontalViewScaleFactor();
1077  double rectHandlerSize = 10.0 / viewScaleFactor;
1078 
1079  //make sure the boxes don't get too large
1080  if ( rectHandlerSize > ( rect().width() / 3 ) )
1081  {
1082  rectHandlerSize = rect().width() / 3;
1083  }
1084  if ( rectHandlerSize > ( rect().height() / 3 ) )
1085  {
1086  rectHandlerSize = rect().height() / 3;
1087  }
1088  return rectHandlerSize;
1089 }
1090 
1092 {
1093  double lockSymbolSize = 20.0 / horizontalViewScaleFactor();
1094 
1095  if ( lockSymbolSize > ( rect().width() / 3 ) )
1096  {
1097  lockSymbolSize = rect().width() / 3;
1098  }
1099  if ( lockSymbolSize > ( rect().height() / 3 ) )
1100  {
1101  lockSymbolSize = rect().height() / 3;
1102  }
1103  return lockSymbolSize;
1104 }
1105 
1106 void QgsComposerItem::updateCursor( const QPointF& itemPos )
1107 {
1108  setCursor( cursorForPosition( itemPos ) );
1109 }
1110 
1112 {
1113  if ( r > 360 )
1114  {
1115  mRotation = (( int )r ) % 360;
1116  }
1117  else
1118  {
1119  mRotation = r;
1120  }
1121  emit rotationChanged( r );
1122  update();
1123 }
1124 
1125 bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const
1126 {
1127  if ( qAbs( mRotation ) <= 0.0 ) //width and height stays the same if there is no rotation
1128  {
1129  return true;
1130  }
1131 
1132  if ( qgsDoubleNear( qAbs( mRotation ), 90 ) || qgsDoubleNear( qAbs( mRotation ), 270 ) )
1133  {
1134  double tmp = width;
1135  width = height;
1136  height = tmp;
1137  return true;
1138  }
1139 
1140  double x1 = 0;
1141  double y1 = 0;
1142  double x2 = width;
1143  double y2 = 0;
1144  double x3 = width;
1145  double y3 = height;
1146  double x4 = 0;
1147  double y4 = height;
1148  double midX = width / 2.0;
1149  double midY = height / 2.0;
1150 
1151  if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) )
1152  {
1153  return false;
1154  }
1155  if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) )
1156  {
1157  return false;
1158  }
1159  if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) )
1160  {
1161  return false;
1162  }
1163  if ( !cornerPointOnRotatedAndScaledRect( x4, y4, width, height ) )
1164  {
1165  return false;
1166  }
1167 
1168 
1169  //assume points 1 and 3 are on the rectangle boundaries. Calculate 2 and 4.
1170  double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) );
1171  QPointF p2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x2, y2 ), distM1 );
1172 
1173  if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 )
1174  {
1175  width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) );
1176  height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) );
1177  return true;
1178  }
1179 
1180  //else assume that points 2 and 4 are on the rectangle boundaries. Calculate 1 and 3
1181  double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) );
1182  QPointF p1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x1, y1 ), distM2 );
1183  QPointF p3 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x3, y3 ), distM2 );
1184  width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
1185  height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
1186  return true;
1187 }
1188 
1189 bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
1190 {
1191  //first rotate point clockwise
1192  double rotToRad = mRotation * M_PI / 180.0;
1193  QPointF midpoint( width / 2.0, height / 2.0 );
1194  double xVector = x - midpoint.x();
1195  double yVector = y - midpoint.y();
1196  //double xRotated = cos(rotToRad) * xVector + sin(rotToRad) * yVector;
1197  //double yRotated = -sin(rotToRad) * xVector + cos(rotToRad) * yVector;
1198  double xRotated = cos( rotToRad ) * xVector - sin( rotToRad ) * yVector;
1199  double yRotated = sin( rotToRad ) * xVector + cos( rotToRad ) * yVector;
1200 
1201  //create line from midpoint to rotated point
1202  QLineF line( midpoint.x(), midpoint.y(), midpoint.x() + xRotated, midpoint.y() + yRotated );
1203 
1204  //intersect with all four borders and return result
1205  QList<QLineF> borders;
1206  borders << QLineF( 0, 0, width, 0 );
1207  borders << QLineF( width, 0, width, height );
1208  borders << QLineF( width, height, 0, height );
1209  borders << QLineF( 0, height, 0, 0 );
1210 
1211  QList<QLineF>::const_iterator it = borders.constBegin();
1212  QPointF intersectionPoint;
1213 
1214  for ( ; it != borders.constEnd(); ++it )
1215  {
1216  if ( line.intersect( *it, &intersectionPoint ) == QLineF::BoundedIntersection )
1217  {
1218  x = intersectionPoint.x();
1219  y = intersectionPoint.y();
1220  return true;
1221  }
1222  }
1223  return false;
1224 }
1225 
1226 void QgsComposerItem::sizeChangedByRotation( double& width, double& height )
1227 {
1228  if ( mRotation == 0.0 )
1229  {
1230  return;
1231  }
1232 
1233  //vector to p1
1234  double x1 = -width / 2.0;
1235  double y1 = -height / 2.0;
1236  rotate( mRotation, x1, y1 );
1237  //vector to p2
1238  double x2 = width / 2.0;
1239  double y2 = -height / 2.0;
1240  rotate( mRotation, x2, y2 );
1241  //vector to p3
1242  double x3 = width / 2.0;
1243  double y3 = height / 2.0;
1244  rotate( mRotation, x3, y3 );
1245  //vector to p4
1246  double x4 = -width / 2.0;
1247  double y4 = height / 2.0;
1248  rotate( mRotation, x4, y4 );
1249 
1250  //double midpoint
1251  QPointF midpoint( width / 2.0, height / 2.0 );
1252 
1253  QPolygonF rotatedRectPoly;
1254  rotatedRectPoly << QPointF( midpoint.x() + x1, midpoint.y() + y1 );
1255  rotatedRectPoly << QPointF( midpoint.x() + x2, midpoint.y() + y2 );
1256  rotatedRectPoly << QPointF( midpoint.x() + x3, midpoint.y() + y3 );
1257  rotatedRectPoly << QPointF( midpoint.x() + x4, midpoint.y() + y4 );
1258  QRectF boundingRect = rotatedRectPoly.boundingRect();
1259  width = boundingRect.width();
1260  height = boundingRect.height();
1261 }
1262 
1263 void QgsComposerItem::rotate( double angle, double& x, double& y ) const
1264 {
1265  double rotToRad = angle * M_PI / 180.0;
1266  double xRot, yRot;
1267  xRot = x * cos( rotToRad ) - y * sin( rotToRad );
1268  yRot = x * sin( rotToRad ) + y * cos( rotToRad );
1269  x = xRot;
1270  y = yRot;
1271 }
1272 
1274 {
1275  if ( !mHAlignSnapItem )
1276  {
1277  mHAlignSnapItem = new QGraphicsLineItem( 0 );
1278  mHAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
1279  scene()->addItem( mHAlignSnapItem );
1280  mHAlignSnapItem->setZValue( 90 );
1281  }
1282  return mHAlignSnapItem;
1283 }
1284 
1286 {
1287  if ( !mVAlignSnapItem )
1288  {
1289  mVAlignSnapItem = new QGraphicsLineItem( 0 );
1290  mVAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
1291  scene()->addItem( mVAlignSnapItem );
1292  mVAlignSnapItem->setZValue( 90 );
1293  }
1294  return mVAlignSnapItem;
1295 }
1296 
1298 {
1299  if ( mHAlignSnapItem )
1300  {
1301  scene()->removeItem( mHAlignSnapItem );
1302  delete mHAlignSnapItem;
1303  mHAlignSnapItem = 0;
1304  }
1305 }
1306 
1308 {
1309  if ( mVAlignSnapItem )
1310  {
1311  scene()->removeItem( mVAlignSnapItem );
1312  delete mVAlignSnapItem;
1313  mVAlignSnapItem = 0;
1314  }
1315 }
1316 
1318 {
1321 }
1322 
1324 {
1325  update();
1326 }
1327 
1328 void QgsComposerItem::setId( const QString& id )
1329 {
1330  setToolTip( id );
1331  mId = id;
1332 }
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.
double paperWidth() const
Returns width of paper item.
int mTransparency
Item transparency.
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
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.
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.
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode Added in 1.9.
void changeItemRectangle(const QPointF &currentPosition, const QPointF &mouseMoveStartPos, const QGraphicsRectItem *originalItem, double dx, double dy, QGraphicsRectItem *changeItem)
Changes the rectangle of an item depending on current mouse action (resize or move) ...
void addItemToZList(QgsComposerItem *item)
Adds item to z list.
virtual void setRotation(double r)
QgsComposerItem::MouseMoveAction mouseMoveActionForPosition(const QPointF &itemCoordPos)
Finds out which mouse move action to choose depending on the cursor position inside the widget...
QPointF mLastMouseEventPos
Position of the last mouse move event (in scene coordinates)
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
virtual void beginItemCommand(const QString &text)
virtual bool removeSettings()
delete settings from project file
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void setCompositionMode(const QPainter::CompositionMode compositionMode)
double lockSymbolSize() const
Returns the size of the lock symbol depending on the composer zoom level and the item size...
A item that forms part of a map composition.
QgsComposerItem::MouseMoveAction mCurrentMouseMoveAction
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
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.
QPointF snapPointToGrid(const QPointF &scenePoint) const
Snaps a scene coordinate point to grid.
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.
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode Added in 1.9.
QColor backgroundColor() const
Gets the background color for this item.
QPainter::CompositionMode mBlendMode
Composition blend mode for item.
double mRotation
Item rotation in degrees, clockwise.
double spaceBetweenPages() const
bool alignmentSnap() const
int numPages() const
Note: added in version 1.9.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:258
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.
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 updateItem()
Updates item, with the possibility to do custom update for subclasses.
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.
bool mFrame
True if item fram needs to be painted.
MouseMoveAction
Describes the action (move or resize in different directon) to be done during mouse move...
void endCommand()
Finish current command and push it onto the undo stack.
void rotationChanged(double newRotation)
Is emitted on rotation change to notify north arrow pictures.
#define M_PI
static const QString defaultThemePath()
Returns the path to the default theme directory.
virtual bool writeSettings()
stores state in project
virtual ~QgsComposerItem()
Qt::CursorShape cursorForPosition(const QPointF &itemCoordPos)
Finds out the appropriate cursor for the current mouse position in the widget (e.g.
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.
QPointF mMouseMoveStartPos
Start point of the last mouse move action (in scene coordinates)
QgsComposition * mComposition
Graphics scene for map printing.
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)
QPointF alignItem(const QgsComposerItem *item, double &alignX, double &alignY, double dx=0, double dy=0)
Snaps item position to align with other items (left / middle / right or top / middle / bottom...
void sizeChangedByRotation(double &width, double &height)
Calculates width / height of the bounding box of a rotated rectangle (mRotation)
QGraphicsLineItem * hAlignSnapItem()
Return horizontal align snap item.
QColor mBackgroundColor
Background color.
QGraphicsLineItem * mVAlignSnapItem
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.
virtual void endItemCommand()
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.
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...
void updateCursor(const QPointF &itemPos)
Update mouse cursor at (item) position.
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.
double paperHeight() const
Returns height of paper item.
bool imageSizeConsideringRotation(double &width, double &height) const
Calculates width and hight of the picture (in mm) such that it fits into the item frame with the give...
void setBlendMode(QPainter::CompositionMode blendMode)
Sets the item's composition blending mode.
QPointF alignPos(const QPointF &pos, const QgsComposerItem *excludeItem, double &alignX, double &alignY)
Snaps position to align with the boundaries of other items.
QgsComposerEffect * mEffect
void drawArrowHead(QPainter *p, double x, double y, double angle, double arrowHeadWidth) const
Draws arrowhead.
double ANALYSIS_EXPORT min(double x, double y)
returns the minimum of two doubles or the first argument if both are equal
QgsComposerItem(QgsComposition *composition, bool manageZValue=true)
Constructor.
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
void init(bool manageZValue)
bool cornerPointOnRotatedAndScaledRect(double &x, double &y, double width, double height) const
Calculates corner point after rotation and scaling.
QgsComposition::PlotStyle plotStyle() const
double rectHandlerBorderTolerance() const
Returns the current (zoom level dependent) tolerance to decide if mouse position is close enough to t...
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.
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 beginCommand(QgsComposerItem *item, const QString &commandText, QgsComposerMergeCommand::Context c=QgsComposerMergeCommand::Unknown)
Allocates new item command and saves initial state in it.
#define tr(sourceText)
QString id() const
Get item's id (which is not necessarly unique)