Quantum GIS API Documentation  master-ce49b66
src/core/composer/qgscomposeritem.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgscomposeritem.cpp
00003                              -------------------
00004     begin                : January 2005
00005     copyright            : (C) 2005 by Radim Blazek
00006     email                : blazek@itc.it
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 #include <QWidget>
00018 #include <QDomNode>
00019 #include <QFile>
00020 #include <QGraphicsLineItem>
00021 #include <QGraphicsScene>
00022 #include <QGraphicsSceneMouseEvent>
00023 #include <QGraphicsView>
00024 #include <QPainter>
00025 #include <QUuid>
00026 #include <QGraphicsEffect>
00027 
00028 #include "qgsproject.h"
00029 
00030 #include "qgscomposition.h"
00031 #include "qgscomposeritem.h"
00032 #include "qgscomposerframe.h"
00033 
00034 #include <limits>
00035 #include "qgsapplication.h"
00036 #include "qgsrectangle.h" //just for debugging
00037 #include "qgslogger.h"
00038 #include "qgssymbollayerv2utils.h" //for pointOnLineWithDistance
00039 #include "qgsmaprenderer.h" //for getCompositionMode
00040 
00041 #include <cmath>
00042 
00043 #define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter
00044 
00045 QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue )
00046     : QObject( 0 )
00047     , QGraphicsRectItem( 0 )
00048     , mComposition( composition )
00049     , mBoundingResizeRectangle( 0 )
00050     , mHAlignSnapItem( 0 )
00051     , mVAlignSnapItem( 0 )
00052     , mFrame( false )
00053     , mBackground( true )
00054     , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
00055     , mItemPositionLocked( false )
00056     , mLastValidViewScaleFactor( -1 )
00057     , mRotation( 0 )
00058     , mBlendMode( QPainter::CompositionMode_SourceOver )
00059     , mEffectsEnabled( true )
00060     , mTransparency( 0 )
00061     , mLastUsedPositionMode( UpperLeft )
00062     , mId( "" )
00063     , mUuid( QUuid::createUuid().toString() )
00064 {
00065   init( manageZValue );
00066 }
00067 
00068 QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, QgsComposition* composition, bool manageZValue )
00069     : QObject( 0 )
00070     , QGraphicsRectItem( 0, 0, width, height, 0 )
00071     , mComposition( composition )
00072     , mBoundingResizeRectangle( 0 )
00073     , mHAlignSnapItem( 0 )
00074     , mVAlignSnapItem( 0 )
00075     , mFrame( false )
00076     , mBackground( true )
00077     , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
00078     , mItemPositionLocked( false )
00079     , mLastValidViewScaleFactor( -1 )
00080     , mRotation( 0 )
00081     , mBlendMode( QPainter::CompositionMode_SourceOver )
00082     , mEffectsEnabled( true )
00083     , mTransparency( 0 )
00084     , mLastUsedPositionMode( UpperLeft )
00085     , mId( "" )
00086     , mUuid( QUuid::createUuid().toString() )
00087 {
00088   init( manageZValue );
00089   QTransform t;
00090   t.translate( x, y );
00091   setTransform( t );
00092 }
00093 
00094 void QgsComposerItem::init( bool manageZValue )
00095 {
00096   setFlag( QGraphicsItem::ItemIsSelectable, true );
00097   setAcceptsHoverEvents( true );
00098   //set default pen and brush
00099   setBrush( QBrush( QColor( 255, 255, 255, 255 ) ) );
00100   QPen defaultPen( QColor( 0, 0, 0 ) );
00101   defaultPen.setWidthF( 0.3 );
00102   setPen( defaultPen );
00103   //let z-Value be managed by composition
00104   if ( mComposition && manageZValue )
00105   {
00106     mComposition->addItemToZList( this );
00107   }
00108 
00109   // Setup composer effect
00110   mEffect = new QgsComposerEffect();
00111   setGraphicsEffect( mEffect );
00112 }
00113 
00114 QgsComposerItem::~QgsComposerItem()
00115 {
00116   if ( mComposition )
00117   {
00118     mComposition->removeItemFromZList( this );
00119   }
00120 
00121   delete mBoundingResizeRectangle;
00122   delete mEffect;
00123   deleteAlignItems();
00124 }
00125 
00126 void QgsComposerItem::setSelected( bool s )
00127 {
00128   QgsDebugMsg( "entered." );
00129   QGraphicsRectItem::setSelected( s );
00130   update(); //to draw selection boxes
00131 }
00132 
00133 bool QgsComposerItem::writeSettings( void )  { return true; }
00134 
00135 bool QgsComposerItem::readSettings( void )  { return true; }
00136 
00137 bool QgsComposerItem::removeSettings( void )  { return true; }
00138 
00139 bool QgsComposerItem::_writeXML( QDomElement& itemElem, QDomDocument& doc ) const
00140 {
00141   if ( itemElem.isNull() )
00142   {
00143     return false;
00144   }
00145 
00146   QDomElement composerItemElem = doc.createElement( "ComposerItem" );
00147 
00148   //frame
00149   if ( mFrame )
00150   {
00151     composerItemElem.setAttribute( "frame", "true" );
00152   }
00153   else
00154   {
00155     composerItemElem.setAttribute( "frame", "false" );
00156   }
00157 
00158   //frame
00159   if ( mBackground )
00160   {
00161     composerItemElem.setAttribute( "background", "true" );
00162   }
00163   else
00164   {
00165     composerItemElem.setAttribute( "background", "false" );
00166   }
00167 
00168   //scene rect
00169   composerItemElem.setAttribute( "x", QString::number( transform().dx() ) );
00170   composerItemElem.setAttribute( "y", QString::number( transform().dy() ) );
00171   composerItemElem.setAttribute( "width", QString::number( rect().width() ) );
00172   composerItemElem.setAttribute( "height", QString::number( rect().height() ) );
00173   composerItemElem.setAttribute( "positionMode", QString::number(( int ) mLastUsedPositionMode ) );
00174   composerItemElem.setAttribute( "zValue", QString::number( zValue() ) );
00175   composerItemElem.setAttribute( "outlineWidth", QString::number( pen().widthF() ) );
00176   composerItemElem.setAttribute( "rotation",  QString::number( mRotation ) );
00177   composerItemElem.setAttribute( "uuid", mUuid );
00178   composerItemElem.setAttribute( "id", mId );
00179   //position lock for mouse moves/resizes
00180   if ( mItemPositionLocked )
00181   {
00182     composerItemElem.setAttribute( "positionLock", "true" );
00183   }
00184   else
00185   {
00186     composerItemElem.setAttribute( "positionLock", "false" );
00187   }
00188 
00189   composerItemElem.setAttribute( "lastValidViewScaleFactor", QString::number( mLastValidViewScaleFactor ) );
00190 
00191 
00192   //frame color
00193   QDomElement frameColorElem = doc.createElement( "FrameColor" );
00194   QColor frameColor = pen().color();
00195   frameColorElem.setAttribute( "red", QString::number( frameColor.red() ) );
00196   frameColorElem.setAttribute( "green", QString::number( frameColor.green() ) );
00197   frameColorElem.setAttribute( "blue", QString::number( frameColor.blue() ) );
00198   frameColorElem.setAttribute( "alpha", QString::number( frameColor.alpha() ) );
00199   composerItemElem.appendChild( frameColorElem );
00200 
00201   //background color
00202   QDomElement bgColorElem = doc.createElement( "BackgroundColor" );
00203   QColor bgColor = brush().color();
00204   bgColorElem.setAttribute( "red", QString::number( bgColor.red() ) );
00205   bgColorElem.setAttribute( "green", QString::number( bgColor.green() ) );
00206   bgColorElem.setAttribute( "blue", QString::number( bgColor.blue() ) );
00207   bgColorElem.setAttribute( "alpha", QString::number( bgColor.alpha() ) );
00208   composerItemElem.appendChild( bgColorElem );
00209 
00210   //blend mode
00211   composerItemElem.setAttribute( "blendMode", QgsMapRenderer::getBlendModeEnum( mBlendMode ) );
00212 
00213   //transparency
00214   composerItemElem.setAttribute( "transparency", QString::number( mTransparency ) );
00215 
00216   itemElem.appendChild( composerItemElem );
00217 
00218   return true;
00219 }
00220 
00221 bool QgsComposerItem::_readXML( const QDomElement& itemElem, const QDomDocument& doc )
00222 {
00223   Q_UNUSED( doc );
00224   if ( itemElem.isNull() )
00225   {
00226     return false;
00227   }
00228 
00229   //rotation
00230   mRotation = itemElem.attribute( "rotation", "0" ).toDouble();
00231 
00232   //uuid
00233   mUuid = itemElem.attribute( "uuid", QUuid::createUuid().toString() );
00234 
00235   //id
00236   QString id = itemElem.attribute( "id", "" );
00237   setId( id );
00238 
00239   //frame
00240   QString frame = itemElem.attribute( "frame" );
00241   if ( frame.compare( "true", Qt::CaseInsensitive ) == 0 )
00242   {
00243     mFrame = true;
00244   }
00245   else
00246   {
00247     mFrame = false;
00248   }
00249 
00250   //frame
00251   QString background = itemElem.attribute( "background" );
00252   if ( background.compare( "true", Qt::CaseInsensitive ) == 0 )
00253   {
00254     mBackground = true;
00255   }
00256   else
00257   {
00258     mBackground = false;
00259   }
00260 
00261   //position lock for mouse moves/resizes
00262   QString positionLock = itemElem.attribute( "positionLock" );
00263   if ( positionLock.compare( "true", Qt::CaseInsensitive ) == 0 )
00264   {
00265     mItemPositionLocked = true;
00266   }
00267   else
00268   {
00269     mItemPositionLocked = false;
00270   }
00271 
00272   //position
00273   double x, y, width, height;
00274   bool xOk, yOk, widthOk, heightOk, positionModeOK;
00275 
00276   x = itemElem.attribute( "x" ).toDouble( &xOk );
00277   y = itemElem.attribute( "y" ).toDouble( &yOk );
00278   width = itemElem.attribute( "width" ).toDouble( &widthOk );
00279   height = itemElem.attribute( "height" ).toDouble( &heightOk );
00280   mLastUsedPositionMode = ( ItemPositionMode )itemElem.attribute( "positionMode" ).toInt( &positionModeOK );
00281   if ( !positionModeOK )
00282   {
00283     mLastUsedPositionMode = UpperLeft;
00284   }
00285 
00286   if ( !xOk || !yOk || !widthOk || !heightOk )
00287   {
00288     return false;
00289   }
00290 
00291   mLastValidViewScaleFactor = itemElem.attribute( "lastValidViewScaleFactor", "-1" ).toDouble();
00292 
00293   setSceneRect( QRectF( x, y, width, height ) );
00294   setZValue( itemElem.attribute( "zValue" ).toDouble() );
00295 
00296   //pen
00297   QDomNodeList frameColorList = itemElem.elementsByTagName( "FrameColor" );
00298   if ( frameColorList.size() > 0 )
00299   {
00300     QDomElement frameColorElem = frameColorList.at( 0 ).toElement();
00301     bool redOk, greenOk, blueOk, alphaOk, widthOk;
00302     int penRed, penGreen, penBlue, penAlpha;
00303     double penWidth;
00304 
00305     penWidth = itemElem.attribute( "outlineWidth" ).toDouble( &widthOk );
00306     penRed = frameColorElem.attribute( "red" ).toDouble( &redOk );
00307     penGreen = frameColorElem.attribute( "green" ).toDouble( &greenOk );
00308     penBlue = frameColorElem.attribute( "blue" ).toDouble( &blueOk );
00309     penAlpha = frameColorElem.attribute( "alpha" ).toDouble( &alphaOk );
00310     if ( redOk && greenOk && blueOk && alphaOk && widthOk )
00311     {
00312       QPen framePen( QColor( penRed, penGreen, penBlue, penAlpha ) );
00313       framePen.setWidthF( penWidth );
00314       setPen( framePen );
00315     }
00316   }
00317 
00318   //brush
00319   QDomNodeList bgColorList = itemElem.elementsByTagName( "BackgroundColor" );
00320   if ( bgColorList.size() > 0 )
00321   {
00322     QDomElement bgColorElem = bgColorList.at( 0 ).toElement();
00323     bool redOk, greenOk, blueOk, alphaOk;
00324     int bgRed, bgGreen, bgBlue, bgAlpha;
00325     bgRed = bgColorElem.attribute( "red" ).toDouble( &redOk );
00326     bgGreen = bgColorElem.attribute( "green" ).toDouble( &greenOk );
00327     bgBlue = bgColorElem.attribute( "blue" ).toDouble( &blueOk );
00328     bgAlpha = bgColorElem.attribute( "alpha" ).toDouble( &alphaOk );
00329     if ( redOk && greenOk && blueOk && alphaOk )
00330     {
00331       QColor brushColor( bgRed, bgGreen, bgBlue, bgAlpha );
00332       setBackgroundColor( brushColor );
00333     }
00334   }
00335 
00336   //blend mode
00337   setBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) itemElem.attribute( "blendMode", "0" ).toUInt() ) );
00338 
00339   //transparency
00340   setTransparency( itemElem.attribute( "transparency" , "0" ).toInt() );
00341 
00342   return true;
00343 }
00344 
00345 void QgsComposerItem::beginCommand( const QString& commandText, QgsComposerMergeCommand::Context c )
00346 {
00347   if ( mComposition )
00348   {
00349     mComposition->beginCommand( this, commandText, c );
00350   }
00351 }
00352 
00353 void QgsComposerItem::endCommand()
00354 {
00355   if ( mComposition )
00356   {
00357     mComposition->endCommand();
00358   }
00359 }
00360 
00361 void QgsComposerItem::cancelCommand()
00362 {
00363   if ( mComposition )
00364   {
00365     mComposition->cancelCommand();
00366   }
00367 }
00368 
00369 void QgsComposerItem::mouseMoveEvent( QGraphicsSceneMouseEvent * event )
00370 {
00371   if ( mItemPositionLocked )
00372   {
00373     return;
00374   }
00375 
00376   if ( !isSelected() )
00377   {
00378     return;
00379   }
00380 
00381   if ( mBoundingResizeRectangle )
00382   {
00383     double diffX = event->lastScenePos().x() - mLastMouseEventPos.x();
00384     double diffY = event->lastScenePos().y() - mLastMouseEventPos.y();
00385 
00386     changeItemRectangle( event->lastScenePos(), mMouseMoveStartPos, this, diffX, diffY, mBoundingResizeRectangle );
00387   }
00388   mLastMouseEventPos = event->lastScenePos();
00389 }
00390 
00391 void QgsComposerItem::mousePressEvent( QGraphicsSceneMouseEvent * event )
00392 {
00393   if ( mItemPositionLocked )
00394   {
00395     return;
00396   }
00397 
00398   if ( !isSelected() )
00399   {
00400     return;
00401   }
00402 
00403   //set current position and type of mouse move action
00404   mMouseMoveStartPos = event->lastScenePos();
00405   mLastMouseEventPos = event->lastScenePos();
00406   mCurrentMouseMoveAction = mouseMoveActionForPosition( event->pos() );
00407 
00408   //remove the old rubber band item if it is still there
00409   if ( mBoundingResizeRectangle )
00410   {
00411     scene()->removeItem( mBoundingResizeRectangle );
00412     delete mBoundingResizeRectangle;
00413     mBoundingResizeRectangle = 0;
00414   }
00415   deleteAlignItems();
00416 
00417   //create and show bounding rectangle
00418   mBoundingResizeRectangle = new QGraphicsRectItem( 0 );
00419   scene()->addItem( mBoundingResizeRectangle );
00420   mBoundingResizeRectangle->setRect( QRectF( 0, 0, rect().width(), rect().height() ) );
00421   QTransform resizeTransform;
00422   resizeTransform.translate( transform().dx(), transform().dy() );
00423   mBoundingResizeRectangle->setTransform( resizeTransform );
00424 
00425   mBoundingResizeRectangle->setBrush( Qt::NoBrush );
00426   mBoundingResizeRectangle->setPen( QPen( QColor( 0, 0, 0 ), 0 ) );
00427   mBoundingResizeRectangle->setZValue( 90 );
00428   mBoundingResizeRectangle->show();
00429 }
00430 
00431 void QgsComposerItem::mouseReleaseEvent( QGraphicsSceneMouseEvent * event )
00432 {
00433 
00434   if ( mItemPositionLocked )
00435   {
00436     return;
00437   }
00438 
00439   if ( !isSelected() )
00440   {
00441     return;
00442   }
00443 
00444   //delete frame rectangle
00445   if ( mBoundingResizeRectangle )
00446   {
00447     scene()->removeItem( mBoundingResizeRectangle );
00448     delete mBoundingResizeRectangle;
00449     mBoundingResizeRectangle = 0;
00450   }
00451 
00452   QPointF mouseMoveStopPoint = event->lastScenePos();
00453   double diffX = mouseMoveStopPoint.x() - mMouseMoveStartPos.x();
00454   double diffY = mouseMoveStopPoint.y() - mMouseMoveStartPos.y();
00455 
00456   //it was only a click
00457   if ( qAbs( diffX ) < std::numeric_limits<double>::min() && qAbs( diffY ) < std::numeric_limits<double>::min() )
00458   {
00459     return;
00460   }
00461 
00462   beginItemCommand( tr( "Change item position" ) );
00463   changeItemRectangle( mouseMoveStopPoint, mMouseMoveStartPos, this, diffX, diffY, this );
00464   endItemCommand();
00465 
00466   deleteAlignItems();
00467 
00468   //reset default action
00469   mCurrentMouseMoveAction = QgsComposerItem::MoveItem;
00470   setCursor( Qt::ArrowCursor );
00471 }
00472 
00473 Qt::CursorShape QgsComposerItem::cursorForPosition( const QPointF& itemCoordPos )
00474 {
00475   QgsComposerItem::MouseMoveAction mouseAction = mouseMoveActionForPosition( itemCoordPos );
00476   switch ( mouseAction )
00477   {
00478     case NoAction:
00479       return Qt::ForbiddenCursor;
00480     case MoveItem:
00481       return Qt::SizeAllCursor;
00482     case ResizeUp:
00483     case ResizeDown:
00484       return Qt::SizeVerCursor;
00485     case ResizeLeft:
00486     case ResizeRight:
00487       return Qt::SizeHorCursor;
00488     case ResizeLeftUp:
00489     case ResizeRightDown:
00490       return Qt::SizeFDiagCursor;
00491     case ResizeRightUp:
00492     case ResizeLeftDown:
00493       return Qt::SizeBDiagCursor;
00494     default:
00495       return Qt::ArrowCursor;
00496   }
00497 }
00498 
00499 QgsComposerItem::MouseMoveAction QgsComposerItem::mouseMoveActionForPosition( const QPointF& itemCoordPos )
00500 {
00501 
00502   //no action at all if item position is locked for mouse
00503   if ( mItemPositionLocked )
00504   {
00505     return QgsComposerItem::NoAction;
00506   }
00507 
00508   bool nearLeftBorder = false;
00509   bool nearRightBorder = false;
00510   bool nearLowerBorder = false;
00511   bool nearUpperBorder = false;
00512 
00513   double borderTolerance = rectHandlerBorderTolerance();
00514 
00515   if ( itemCoordPos.x() < borderTolerance )
00516   {
00517     nearLeftBorder = true;
00518   }
00519   if ( itemCoordPos.y() < borderTolerance )
00520   {
00521     nearUpperBorder = true;
00522   }
00523   if ( itemCoordPos.x() > ( rect().width() - borderTolerance ) )
00524   {
00525     nearRightBorder = true;
00526   }
00527   if ( itemCoordPos.y() > ( rect().height() - borderTolerance ) )
00528   {
00529     nearLowerBorder = true;
00530   }
00531 
00532   if ( nearLeftBorder && nearUpperBorder )
00533   {
00534     return QgsComposerItem::ResizeLeftUp;
00535   }
00536   else if ( nearLeftBorder && nearLowerBorder )
00537   {
00538     return QgsComposerItem::ResizeLeftDown;
00539   }
00540   else if ( nearRightBorder && nearUpperBorder )
00541   {
00542     return QgsComposerItem::ResizeRightUp;
00543   }
00544   else if ( nearRightBorder && nearLowerBorder )
00545   {
00546     return QgsComposerItem::ResizeRightDown;
00547   }
00548   else if ( nearLeftBorder )
00549   {
00550     return QgsComposerItem::ResizeLeft;
00551   }
00552   else if ( nearRightBorder )
00553   {
00554     return QgsComposerItem::ResizeRight;
00555   }
00556   else if ( nearUpperBorder )
00557   {
00558     return QgsComposerItem::ResizeUp;
00559   }
00560   else if ( nearLowerBorder )
00561   {
00562     return QgsComposerItem::ResizeDown;
00563   }
00564 
00565   return QgsComposerItem::MoveItem; //default
00566 }
00567 
00568 void QgsComposerItem::changeItemRectangle( const QPointF& currentPosition,
00569     const QPointF& mouseMoveStartPos,
00570     const QGraphicsRectItem* originalItem,
00571     double dx, double dy,
00572     QGraphicsRectItem* changeItem )
00573 {
00574   Q_UNUSED( dx );
00575   Q_UNUSED( dy );
00576   if ( !changeItem || !originalItem || !mComposition )
00577   {
00578     return;
00579   }
00580 
00581   //test if change item is a composer item. If so, prefer call to  setSceneRect() instead of setTransform() and setRect()
00582   QgsComposerItem* changeComposerItem = dynamic_cast<QgsComposerItem *>( changeItem );
00583 
00584   double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
00585   QPointF snappedPosition = mComposition->snapPointToGrid( currentPosition );
00586 
00587   //snap to grid and align to other items
00588   if ( mComposition->alignmentSnap() && mCurrentMouseMoveAction != QgsComposerItem::MoveItem )
00589   {
00590     double alignX = 0;
00591     double alignY = 0;
00592     snappedPosition = mComposition->alignPos( snappedPosition, dynamic_cast<const QgsComposerItem*>( originalItem ), alignX, alignY );
00593     if ( alignX != -1 )
00594     {
00595       QGraphicsLineItem* item = hAlignSnapItem();
00596       item->setLine( QLineF( alignX, 0, alignX,  mComposition->paperHeight() ) );
00597       item->show();
00598     }
00599     else
00600     {
00601       deleteHAlignSnapItem();
00602     }
00603 
00604     if ( alignY != -1 )
00605     {
00606       QGraphicsLineItem* item = vAlignSnapItem();
00607       item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
00608       item->show();
00609     }
00610     else
00611     {
00612       deleteVAlignSnapItem();
00613     }
00614   }
00615 
00616   double diffX = 0;
00617   double diffY = 0;
00618 
00619   switch ( mCurrentMouseMoveAction )
00620   {
00621       //vertical resize
00622     case QgsComposerItem::ResizeUp:
00623       diffY = snappedPosition.y() - originalItem->transform().dy();
00624       mx = 0; my = diffY; rx = 0; ry = -diffY;
00625       break;
00626 
00627     case QgsComposerItem::ResizeDown:
00628       diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
00629       mx = 0; my = 0; rx = 0; ry = diffY;
00630       break;
00631 
00632       //horizontal resize
00633     case QgsComposerItem::ResizeLeft:
00634       diffX = snappedPosition.x() - originalItem->transform().dx();
00635       mx = diffX, my = 0; rx = -diffX; ry = 0;
00636       break;
00637 
00638     case QgsComposerItem::ResizeRight:
00639       diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
00640       mx = 0; my = 0; rx = diffX, ry = 0;
00641       break;
00642 
00643       //diagonal resize
00644     case QgsComposerItem::ResizeLeftUp:
00645       diffX = snappedPosition.x() - originalItem->transform().dx();
00646       diffY = snappedPosition.y() - originalItem->transform().dy();
00647       mx = diffX, my = diffY; rx = -diffX; ry = -diffY;
00648       break;
00649 
00650     case QgsComposerItem::ResizeRightDown:
00651       diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
00652       diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
00653       mx = 0; my = 0; rx = diffX, ry = diffY;
00654       break;
00655 
00656     case QgsComposerItem::ResizeRightUp:
00657       diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
00658       diffY = snappedPosition.y() - originalItem->transform().dy();
00659       mx = 0; my = diffY, rx = diffX, ry = -diffY;
00660       break;
00661 
00662     case QgsComposerItem::ResizeLeftDown:
00663       diffX = snappedPosition.x() - originalItem->transform().dx();
00664       diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
00665       mx = diffX, my = 0; rx = -diffX; ry = diffY;
00666       break;
00667 
00668     case QgsComposerItem::MoveItem:
00669     {
00670       //calculate total move difference
00671       double moveX = currentPosition.x() - mouseMoveStartPos.x();
00672       double moveY = currentPosition.y() - mouseMoveStartPos.y();
00673 
00674       QPointF upperLeftPoint( originalItem->transform().dx() + moveX, originalItem->transform().dy() + moveY );
00675       QPointF snappedLeftPoint = mComposition->snapPointToGrid( upperLeftPoint );
00676 
00677       if ( snappedLeftPoint != upperLeftPoint ) //don't do align snap if grid snap has been done
00678       {
00679         deleteAlignItems();
00680       }
00681       else if ( mComposition->alignmentSnap() ) //align item
00682       {
00683         double alignX = 0;
00684         double alignY = 0;
00685         snappedLeftPoint = mComposition->alignItem( dynamic_cast<const QgsComposerItem*>( originalItem ), alignX, alignY, moveX, moveY );
00686         if ( alignX != -1 )
00687         {
00688           QGraphicsLineItem* item = hAlignSnapItem();
00689           int numPages = mComposition->numPages();
00690           double yLineCoord = 300; //default in case there is no single page
00691           if ( numPages > 0 )
00692           {
00693             yLineCoord = mComposition->paperHeight() * numPages + mComposition->spaceBetweenPages() * ( numPages - 1 );
00694           }
00695           item->setLine( QLineF( alignX, 0, alignX,  yLineCoord ) );
00696           item->show();
00697         }
00698         else
00699         {
00700           deleteHAlignSnapItem();
00701         }
00702         if ( alignY != -1 )
00703         {
00704           QGraphicsLineItem* item = vAlignSnapItem();
00705           item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
00706           item->show();
00707         }
00708         else
00709         {
00710           deleteVAlignSnapItem();
00711         }
00712       }
00713       double moveRectX = snappedLeftPoint.x() - originalItem->transform().dx();
00714       double moveRectY = snappedLeftPoint.y() - originalItem->transform().dy();
00715 
00716       if ( !changeComposerItem )
00717       {
00718         QTransform moveTransform;
00719         moveTransform.translate( originalItem->transform().dx() + moveRectX, originalItem->transform().dy() + moveRectY );
00720         changeItem->setTransform( moveTransform );
00721       }
00722       else  //for composer items, we prefer setSceneRect as subclasses can implement custom behaviour (e.g. item group)
00723       {
00724         changeComposerItem->setSceneRect( QRectF( originalItem->transform().dx() + moveRectX,
00725                                           originalItem->transform().dy() + moveRectY,
00726                                           originalItem->rect().width(), originalItem->rect().height() ) );
00727         changeComposerItem->updateItem();
00728       }
00729     }
00730     return;
00731     case QgsComposerItem::NoAction:
00732       break;
00733   }
00734 
00735   if ( !changeComposerItem )
00736   {
00737     QTransform itemTransform;
00738     itemTransform.translate( originalItem->transform().dx() + mx, originalItem->transform().dy() + my );
00739     changeItem->setTransform( itemTransform );
00740     QRectF itemRect( 0, 0, originalItem->rect().width() + rx,  originalItem->rect().height() + ry );
00741     changeItem->setRect( itemRect );
00742   }
00743   else //for composer items, we prefer setSceneRect as subclasses can implement custom behaviour (e.g. item group)
00744   {
00745     changeComposerItem->setSceneRect( QRectF( originalItem->transform().dx() + mx, originalItem->transform().dy() + my,
00746                                       originalItem->rect().width() + rx, originalItem->rect().height() + ry ) );
00747     changeComposerItem->updateItem();
00748   }
00749 }
00750 
00751 void QgsComposerItem::drawSelectionBoxes( QPainter* p )
00752 {
00753   if ( !mComposition )
00754   {
00755     return;
00756   }
00757 
00758   if ( mComposition->plotStyle() == QgsComposition::Preview )
00759   {
00760     //size of symbol boxes depends on zoom level in composer view
00761     double rectHandlerSize = rectHandlerBorderTolerance();
00762     double sizeLockSymbol = lockSymbolSize();
00763 
00764     if ( mItemPositionLocked )
00765     {
00766       //draw lock symbol at upper left edge. Use QImage to be independent of the graphic system
00767       QString lockIconPath = QgsApplication::activeThemePath() + "/mIconLock.png";
00768       if ( !QFile::exists( lockIconPath ) )
00769       {
00770         lockIconPath = QgsApplication::defaultThemePath() + "/mIconLock.png";
00771       }
00772 
00773       QImage lockImage( lockIconPath );
00774       if ( !lockImage.isNull() )
00775       {
00776         p->drawImage( QRectF( 0, 0, sizeLockSymbol, sizeLockSymbol ), lockImage, QRectF( 0, 0, lockImage.width(), lockImage.height() ) );
00777       }
00778     }
00779     else //draw blue squares
00780     {
00781       p->setPen( QColor( 50, 100, 120, 200 ) );
00782       p->setBrush( QColor( 200, 200, 210, 120 ) );
00783       p->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
00784       p->drawRect( QRectF( rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
00785       p->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
00786       p->drawRect( QRectF( 0, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
00787     }
00788   }
00789 }
00790 
00791 void QgsComposerItem::drawFrame( QPainter* p )
00792 {
00793   if ( mFrame && p )
00794   {
00795     p->setPen( pen() );
00796     p->setBrush( Qt::NoBrush );
00797     p->setRenderHint( QPainter::Antialiasing, true );
00798     p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
00799   }
00800 }
00801 
00802 void QgsComposerItem::move( double dx, double dy )
00803 {
00804   QTransform t = transform();
00805   QRectF newSceneRect( t.dx() + dx, t.dy() + dy, rect().width(), rect().height() );
00806   setSceneRect( newSceneRect );
00807 }
00808 
00809 void QgsComposerItem::setItemPosition( double x, double y, ItemPositionMode itemPoint )
00810 {
00811   double width = rect().width();
00812   double height = rect().height();
00813   setItemPosition( x, y, width, height, itemPoint );
00814 }
00815 
00816 void QgsComposerItem::setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint )
00817 {
00818   double upperLeftX = x;
00819   double upperLeftY = y;
00820 
00821   //store the item position mode
00822   mLastUsedPositionMode = itemPoint;
00823 
00824   //adjust x-coordinate if placement is not done to a left point
00825   if ( itemPoint == UpperMiddle || itemPoint == Middle || itemPoint == LowerMiddle )
00826   {
00827     upperLeftX -= width / 2.0;
00828   }
00829   else if ( itemPoint == UpperRight || itemPoint == MiddleRight || itemPoint == LowerRight )
00830   {
00831     upperLeftX -= width;
00832   }
00833 
00834   //adjust y-coordinate if placement is not done to an upper point
00835   if ( itemPoint == MiddleLeft || itemPoint == Middle || itemPoint == MiddleRight )
00836   {
00837     upperLeftY -= height / 2.0;
00838   }
00839   else if ( itemPoint == LowerLeft || itemPoint == LowerMiddle || itemPoint == LowerRight )
00840   {
00841     upperLeftY -= height;
00842   }
00843 
00844   setSceneRect( QRectF( upperLeftX, upperLeftY, width, height ) );
00845 }
00846 
00847 void QgsComposerItem::setSceneRect( const QRectF& rectangle )
00848 {
00849   //setRect in item coordinates
00850   double newWidth = rectangle.width();
00851   double newHeight = rectangle.height();
00852   double xTranslation = rectangle.x();
00853   double yTranslation = rectangle.y();
00854 
00855   //correction if width and/or height are negative
00856   if ( rectangle.width() < 0 )
00857   {
00858     newWidth = - rectangle.width();
00859     xTranslation -= newWidth;
00860   }
00861 
00862   if ( rectangle.height() < 0 )
00863   {
00864     newHeight = - rectangle.height();
00865     yTranslation -= newHeight;
00866   }
00867 
00868   QRectF newRect( 0, 0, newWidth, newHeight );
00869   QGraphicsRectItem::setRect( newRect );
00870 
00871   //set up transformation matrix for item coordinates
00872   QTransform t;
00873   t.translate( xTranslation, yTranslation );
00874   setTransform( t );
00875 
00876   emit sizeChanged();
00877 }
00878 
00879 void QgsComposerItem::drawBackground( QPainter* p )
00880 {
00881   if ( mBackground && p )
00882   {
00883     p->setBrush( brush() );//this causes a problem in atlas generation
00884     p->setPen( Qt::NoPen );
00885     p->setRenderHint( QPainter::Antialiasing, true );
00886     p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
00887   }
00888 }
00889 
00890 void QgsComposerItem::setBackgroundColor( const QColor& backgroundColor )
00891 {
00892   mBackgroundColor = backgroundColor;
00893   setBrush( QBrush( mBackgroundColor, Qt::SolidPattern ) );
00894 }
00895 
00896 void QgsComposerItem::setBlendMode( QPainter::CompositionMode blendMode )
00897 {
00898   mBlendMode = blendMode;
00899   // Update the composer effect to use the new blend mode
00900   mEffect->setCompositionMode( mBlendMode );
00901 }
00902 
00903 void QgsComposerItem::setTransparency( int transparency )
00904 {
00905   mTransparency = transparency;
00906   // Set the QGraphicItem's opacity
00907   setOpacity( 1. - ( transparency / 100. ) );
00908 }
00909 
00910 void QgsComposerItem::setEffectsEnabled( bool effectsEnabled )
00911 {
00912   //enable or disable the QgsComposerEffect applied to this item
00913   mEffectsEnabled = effectsEnabled;
00914   mEffect->setEnabled( effectsEnabled );
00915 }
00916 
00917 void QgsComposerItem::hoverMoveEvent( QGraphicsSceneHoverEvent * event )
00918 {
00919   if ( isSelected() )
00920   {
00921     setCursor( cursorForPosition( event->pos() ) );
00922   }
00923   else
00924   {
00925     setCursor( Qt::ArrowCursor );
00926   }
00927 }
00928 
00929 void QgsComposerItem::drawText( QPainter* p, double x, double y, const QString& text, const QFont& font ) const
00930 {
00931   QFont textFont = scaledFontPixelSize( font );
00932 
00933   p->save();
00934   p->setFont( textFont );
00935   double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
00936   p->scale( scaleFactor, scaleFactor );
00937   p->drawText( QPointF( x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE ), text );
00938   p->restore();
00939 }
00940 
00941 void QgsComposerItem::drawText( QPainter* p, const QRectF& rect, const QString& text, const QFont& font, Qt::AlignmentFlag halignment, Qt::AlignmentFlag valignment ) const
00942 {
00943   QFont textFont = scaledFontPixelSize( font );
00944 
00945   QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
00946                      rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
00947 
00948   p->save();
00949   p->setFont( textFont );
00950   double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
00951   p->scale( scaleFactor, scaleFactor );
00952   p->drawText( scaledRect, halignment | valignment | Qt::TextWordWrap, text );
00953   p->restore();
00954 }
00955 void QgsComposerItem::drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const
00956 {
00957   if ( !p )
00958   {
00959     return;
00960   }
00961   double angleRad = angle / 180.0 * M_PI;
00962   QPointF middlePoint( x, y );
00963   //rotate both arrow points
00964   QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
00965   QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
00966 
00967   QPointF p1Rotated, p2Rotated;
00968   p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
00969   p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
00970   p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
00971   p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
00972 
00973   QPolygonF arrowHeadPoly;
00974   arrowHeadPoly << middlePoint;
00975   arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
00976   arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
00977 
00978   p->save();
00979 
00980   QPen arrowPen = p->pen();
00981   arrowPen.setJoinStyle( Qt::RoundJoin );
00982   QBrush arrowBrush = p->brush();
00983   arrowBrush.setStyle( Qt::SolidPattern );
00984   p->setPen( arrowPen );
00985   p->setBrush( arrowBrush );
00986   arrowBrush.setStyle( Qt::SolidPattern );
00987   p->drawPolygon( arrowHeadPoly );
00988 
00989   p->restore();
00990 }
00991 
00992 double QgsComposerItem::textWidthMillimeters( const QFont& font, const QString& text ) const
00993 {
00994   QFont metricsFont = scaledFontPixelSize( font );
00995   QFontMetrics fontMetrics( metricsFont );
00996   return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
00997 }
00998 
00999 double QgsComposerItem::fontHeightCharacterMM( const QFont& font, const QChar& c ) const
01000 {
01001   QFont metricsFont = scaledFontPixelSize( font );
01002   QFontMetricsF fontMetrics( metricsFont );
01003   return ( fontMetrics.boundingRect( c ).height() / FONT_WORKAROUND_SCALE );
01004 }
01005 
01006 double QgsComposerItem::fontAscentMillimeters( const QFont& font ) const
01007 {
01008   QFont metricsFont = scaledFontPixelSize( font );
01009   QFontMetricsF fontMetrics( metricsFont );
01010   return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
01011 }
01012 
01013 double QgsComposerItem::fontDescentMillimeters( const QFont& font ) const
01014 {
01015   QFont metricsFont = scaledFontPixelSize( font );
01016   QFontMetricsF fontMetrics( metricsFont );
01017   return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
01018 }
01019 
01020 double QgsComposerItem::pixelFontSize( double pointSize ) const
01021 {
01022   return ( pointSize * 0.3527 );
01023 }
01024 
01025 QFont QgsComposerItem::scaledFontPixelSize( const QFont& font ) const
01026 {
01027   QFont scaledFont = font;
01028   double pixelSize = pixelFontSize( font.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
01029   scaledFont.setPixelSize( pixelSize );
01030   return scaledFont;
01031 }
01032 
01033 double QgsComposerItem::angle( const QPointF& p1, const QPointF& p2 ) const
01034 {
01035   double xDiff = p2.x() - p1.x();
01036   double yDiff = p2.y() - p1.y();
01037   double length = sqrt( xDiff * xDiff + yDiff * yDiff );
01038   if ( length <= 0 )
01039   {
01040     return 0;
01041   }
01042 
01043   double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
01044   if ( xDiff < 0 )
01045   {
01046     return ( 360 - angle );
01047   }
01048   return angle;
01049 }
01050 
01051 double QgsComposerItem::horizontalViewScaleFactor() const
01052 {
01053   double result = -1;
01054   if ( scene() )
01055   {
01056     QList<QGraphicsView*> viewList = scene()->views();
01057     if ( viewList.size() > 0 ) //if not, probably this function was called from non-gui code
01058     {
01059       QGraphicsView* currentView = viewList.at( 0 );
01060       if ( currentView->isVisible() )
01061       {
01062         result = currentView->transform().m11();
01063         mLastValidViewScaleFactor = result;
01064       }
01065     }
01066   }
01067   return result;
01068 }
01069 
01070 double QgsComposerItem::rectHandlerBorderTolerance() const
01071 {
01072   //size of symbol boxes depends on zoom level in composer view
01073   double viewScaleFactor = horizontalViewScaleFactor();
01074   double rectHandlerSize = 10.0 / viewScaleFactor;
01075 
01076   //make sure the boxes don't get too large
01077   if ( rectHandlerSize > ( rect().width() / 3 ) )
01078   {
01079     rectHandlerSize = rect().width() / 3;
01080   }
01081   if ( rectHandlerSize > ( rect().height() / 3 ) )
01082   {
01083     rectHandlerSize = rect().height() / 3;
01084   }
01085   return rectHandlerSize;
01086 }
01087 
01088 double QgsComposerItem::lockSymbolSize() const
01089 {
01090   double lockSymbolSize = 20.0 / horizontalViewScaleFactor();
01091 
01092   if ( lockSymbolSize > ( rect().width() / 3 ) )
01093   {
01094     lockSymbolSize = rect().width() / 3;
01095   }
01096   if ( lockSymbolSize > ( rect().height() / 3 ) )
01097   {
01098     lockSymbolSize = rect().height() / 3;
01099   }
01100   return lockSymbolSize;
01101 }
01102 
01103 void QgsComposerItem::updateCursor( const QPointF& itemPos )
01104 {
01105   setCursor( cursorForPosition( itemPos ) );
01106 }
01107 
01108 void QgsComposerItem::setRotation( double r )
01109 {
01110   if ( r > 360 )
01111   {
01112     mRotation = (( int )r ) % 360;
01113   }
01114   else
01115   {
01116     mRotation = r;
01117   }
01118   emit rotationChanged( r );
01119   update();
01120 }
01121 
01122 bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const
01123 {
01124   if ( qAbs( mRotation ) <= 0.0 ) //width and height stays the same if there is no rotation
01125   {
01126     return true;
01127   }
01128 
01129   if ( qgsDoubleNear( qAbs( mRotation ), 90 ) || qgsDoubleNear( qAbs( mRotation ), 270 ) )
01130   {
01131     double tmp = width;
01132     width = height;
01133     height = tmp;
01134     return true;
01135   }
01136 
01137   double x1 = 0;
01138   double y1 = 0;
01139   double x2 = width;
01140   double y2 = 0;
01141   double x3 = width;
01142   double y3 = height;
01143   double x4 = 0;
01144   double y4 = height;
01145   double midX = width / 2.0;
01146   double midY = height / 2.0;
01147 
01148   if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) )
01149   {
01150     return false;
01151   }
01152   if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) )
01153   {
01154     return false;
01155   }
01156   if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) )
01157   {
01158     return false;
01159   }
01160   if ( !cornerPointOnRotatedAndScaledRect( x4, y4, width, height ) )
01161   {
01162     return false;
01163   }
01164 
01165 
01166   //assume points 1 and 3 are on the rectangle boundaries. Calculate 2 and 4.
01167   double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) );
01168   QPointF p2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x2, y2 ), distM1 );
01169 
01170   if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 )
01171   {
01172     width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) );
01173     height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) );
01174     return true;
01175   }
01176 
01177   //else assume that points 2 and 4 are on the rectangle boundaries. Calculate 1 and 3
01178   double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) );
01179   QPointF p1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x1, y1 ), distM2 );
01180   QPointF p3 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x3, y3 ), distM2 );
01181   width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
01182   height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
01183   return true;
01184 }
01185 
01186 bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
01187 {
01188   //first rotate point clockwise
01189   double rotToRad = mRotation * M_PI / 180.0;
01190   QPointF midpoint( width / 2.0, height / 2.0 );
01191   double xVector = x - midpoint.x();
01192   double yVector = y - midpoint.y();
01193   //double xRotated = cos(rotToRad) * xVector + sin(rotToRad) * yVector;
01194   //double yRotated = -sin(rotToRad) * xVector + cos(rotToRad) * yVector;
01195   double xRotated = cos( rotToRad ) * xVector - sin( rotToRad ) * yVector;
01196   double yRotated = sin( rotToRad ) * xVector + cos( rotToRad ) * yVector;
01197 
01198   //create line from midpoint to rotated point
01199   QLineF line( midpoint.x(), midpoint.y(), midpoint.x() + xRotated, midpoint.y() + yRotated );
01200 
01201   //intersect with all four borders and return result
01202   QList<QLineF> borders;
01203   borders << QLineF( 0, 0, width, 0 );
01204   borders << QLineF( width, 0, width, height );
01205   borders << QLineF( width, height, 0, height );
01206   borders << QLineF( 0, height, 0, 0 );
01207 
01208   QList<QLineF>::const_iterator it = borders.constBegin();
01209   QPointF intersectionPoint;
01210 
01211   for ( ; it != borders.constEnd(); ++it )
01212   {
01213     if ( line.intersect( *it, &intersectionPoint ) == QLineF::BoundedIntersection )
01214     {
01215       x = intersectionPoint.x();
01216       y = intersectionPoint.y();
01217       return true;
01218     }
01219   }
01220   return false;
01221 }
01222 
01223 void QgsComposerItem::sizeChangedByRotation( double& width, double& height )
01224 {
01225   if ( mRotation == 0.0 )
01226   {
01227     return;
01228   }
01229 
01230   //vector to p1
01231   double x1 = -width / 2.0;
01232   double y1 = -height / 2.0;
01233   rotate( mRotation, x1, y1 );
01234   //vector to p2
01235   double x2 = width / 2.0;
01236   double y2 = -height / 2.0;
01237   rotate( mRotation, x2, y2 );
01238   //vector to p3
01239   double x3 = width / 2.0;
01240   double y3 = height / 2.0;
01241   rotate( mRotation, x3, y3 );
01242   //vector to p4
01243   double x4 = -width / 2.0;
01244   double y4 = height / 2.0;
01245   rotate( mRotation, x4, y4 );
01246 
01247   //double midpoint
01248   QPointF midpoint( width / 2.0, height / 2.0 );
01249 
01250   QPolygonF rotatedRectPoly;
01251   rotatedRectPoly << QPointF( midpoint.x() + x1, midpoint.y() + y1 );
01252   rotatedRectPoly << QPointF( midpoint.x() + x2, midpoint.y() + y2 );
01253   rotatedRectPoly << QPointF( midpoint.x() + x3, midpoint.y() + y3 );
01254   rotatedRectPoly << QPointF( midpoint.x() + x4, midpoint.y() + y4 );
01255   QRectF boundingRect = rotatedRectPoly.boundingRect();
01256   width = boundingRect.width();
01257   height = boundingRect.height();
01258 }
01259 
01260 void QgsComposerItem::rotate( double angle, double& x, double& y ) const
01261 {
01262   double rotToRad = angle * M_PI / 180.0;
01263   double xRot, yRot;
01264   xRot = x * cos( rotToRad ) - y * sin( rotToRad );
01265   yRot = x * sin( rotToRad ) + y * cos( rotToRad );
01266   x = xRot;
01267   y = yRot;
01268 }
01269 
01270 QGraphicsLineItem* QgsComposerItem::hAlignSnapItem()
01271 {
01272   if ( !mHAlignSnapItem )
01273   {
01274     mHAlignSnapItem = new QGraphicsLineItem( 0 );
01275     mHAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
01276     scene()->addItem( mHAlignSnapItem );
01277     mHAlignSnapItem->setZValue( 90 );
01278   }
01279   return mHAlignSnapItem;
01280 }
01281 
01282 QGraphicsLineItem* QgsComposerItem::vAlignSnapItem()
01283 {
01284   if ( !mVAlignSnapItem )
01285   {
01286     mVAlignSnapItem = new QGraphicsLineItem( 0 );
01287     mVAlignSnapItem->setPen( QPen( QColor( Qt::red ) ) );
01288     scene()->addItem( mVAlignSnapItem );
01289     mVAlignSnapItem->setZValue( 90 );
01290   }
01291   return mVAlignSnapItem;
01292 }
01293 
01294 void QgsComposerItem::deleteHAlignSnapItem()
01295 {
01296   if ( mHAlignSnapItem )
01297   {
01298     scene()->removeItem( mHAlignSnapItem );
01299     delete mHAlignSnapItem;
01300     mHAlignSnapItem = 0;
01301   }
01302 }
01303 
01304 void QgsComposerItem::deleteVAlignSnapItem()
01305 {
01306   if ( mVAlignSnapItem )
01307   {
01308     scene()->removeItem( mVAlignSnapItem );
01309     delete mVAlignSnapItem;
01310     mVAlignSnapItem = 0;
01311   }
01312 }
01313 
01314 void QgsComposerItem::deleteAlignItems()
01315 {
01316   deleteHAlignSnapItem();
01317   deleteVAlignSnapItem();
01318 }
01319 
01320 void QgsComposerItem::repaint()
01321 {
01322   update();
01323 }
01324 
01325 void QgsComposerItem::setId( const QString& id )
01326 {
01327   setToolTip( id );
01328   mId = id;
01329 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines