|
QGIS API Documentation
master-59fd5e0
|
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 }