20 #include <QGraphicsLineItem>
21 #include <QGraphicsScene>
22 #include <QGraphicsSceneMouseEvent>
23 #include <QGraphicsView>
26 #include <QGraphicsEffect>
43 #define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter
46 #define M_DEG2RAD 0.0174532925
51 , QGraphicsRectItem( 0 )
52 , mComposition( composition )
53 , mBoundingResizeRectangle( 0 )
54 , mHAlignSnapItem( 0 )
55 , mVAlignSnapItem( 0 )
58 , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
59 , mItemPositionLocked( false )
60 , mLastValidViewScaleFactor( -1 )
62 , mBlendMode( QPainter::CompositionMode_SourceOver )
63 , mEffectsEnabled( true )
65 , mLastUsedPositionMode( UpperLeft )
67 , mUuid( QUuid::createUuid().toString() )
74 , QGraphicsRectItem( 0, 0, width, height, 0 )
75 , mComposition( composition )
76 , mBoundingResizeRectangle( 0 )
77 , mHAlignSnapItem( 0 )
78 , mVAlignSnapItem( 0 )
81 , mBackgroundColor( QColor( 255, 255, 255, 255 ) )
82 , mItemPositionLocked( false )
83 , mLastValidViewScaleFactor( -1 )
85 , mBlendMode( QPainter::CompositionMode_SourceOver )
86 , mEffectsEnabled( true )
88 , mLastUsedPositionMode( UpperLeft )
90 , mUuid( QUuid::createUuid().toString() )
98 setFlag( QGraphicsItem::ItemIsSelectable,
true );
100 setBrush( QBrush( QColor( 255, 255, 255, 255 ) ) );
101 QPen defaultPen( QColor( 0, 0, 0 ) );
102 defaultPen.setWidthF( 0.3 );
103 defaultPen.setJoinStyle( Qt::MiterJoin );
104 setPen( defaultPen );
143 if ( itemElem.isNull() )
148 QDomElement composerItemElem = doc.createElement(
"ComposerItem" );
153 composerItemElem.setAttribute(
"frame",
"true" );
157 composerItemElem.setAttribute(
"frame",
"false" );
163 composerItemElem.setAttribute(
"background",
"true" );
167 composerItemElem.setAttribute(
"background",
"false" );
171 composerItemElem.setAttribute(
"x", QString::number( pos().x() ) );
172 composerItemElem.setAttribute(
"y", QString::number( pos().y() ) );
173 composerItemElem.setAttribute(
"width", QString::number( rect().width() ) );
174 composerItemElem.setAttribute(
"height", QString::number( rect().height() ) );
176 composerItemElem.setAttribute(
"zValue", QString::number( zValue() ) );
177 composerItemElem.setAttribute(
"outlineWidth", QString::number( pen().widthF() ) );
178 composerItemElem.setAttribute(
"itemRotation", QString::number(
mItemRotation ) );
179 composerItemElem.setAttribute(
"uuid",
mUuid );
180 composerItemElem.setAttribute(
"id",
mId );
184 composerItemElem.setAttribute(
"positionLock",
"true" );
188 composerItemElem.setAttribute(
"positionLock",
"false" );
195 QDomElement frameColorElem = doc.createElement(
"FrameColor" );
196 QColor frameColor = pen().color();
197 frameColorElem.setAttribute(
"red", QString::number( frameColor.red() ) );
198 frameColorElem.setAttribute(
"green", QString::number( frameColor.green() ) );
199 frameColorElem.setAttribute(
"blue", QString::number( frameColor.blue() ) );
200 frameColorElem.setAttribute(
"alpha", QString::number( frameColor.alpha() ) );
201 composerItemElem.appendChild( frameColorElem );
204 QDomElement bgColorElem = doc.createElement(
"BackgroundColor" );
205 QColor bgColor = brush().color();
206 bgColorElem.setAttribute(
"red", QString::number( bgColor.red() ) );
207 bgColorElem.setAttribute(
"green", QString::number( bgColor.green() ) );
208 bgColorElem.setAttribute(
"blue", QString::number( bgColor.blue() ) );
209 bgColorElem.setAttribute(
"alpha", QString::number( bgColor.alpha() ) );
210 composerItemElem.appendChild( bgColorElem );
216 composerItemElem.setAttribute(
"transparency", QString::number(
mTransparency ) );
218 itemElem.appendChild( composerItemElem );
226 if ( itemElem.isNull() )
232 if ( itemElem.attribute(
"itemRotation",
"0" ).toDouble() != 0 )
234 setItemRotation( itemElem.attribute(
"itemRotation",
"0" ).toDouble() );
238 mUuid = itemElem.attribute(
"uuid", QUuid::createUuid().toString() );
244 QString
id = itemElem.attribute(
"id",
"" );
248 QString frame = itemElem.attribute(
"frame" );
249 if ( frame.compare(
"true", Qt::CaseInsensitive ) == 0 )
259 QString background = itemElem.attribute(
"background" );
260 if ( background.compare(
"true", Qt::CaseInsensitive ) == 0 )
270 QString
positionLock = itemElem.attribute(
"positionLock" );
271 if ( positionLock.compare(
"true", Qt::CaseInsensitive ) == 0 )
281 double x, y, width, height;
282 bool xOk, yOk, widthOk, heightOk, positionModeOK;
284 x = itemElem.attribute(
"x" ).toDouble( &xOk );
285 y = itemElem.attribute(
"y" ).toDouble( &yOk );
286 width = itemElem.attribute(
"width" ).toDouble( &widthOk );
287 height = itemElem.attribute(
"height" ).toDouble( &heightOk );
289 if ( !positionModeOK )
294 if ( !xOk || !yOk || !widthOk || !heightOk )
302 setZValue( itemElem.attribute(
"zValue" ).toDouble() );
305 QDomNodeList frameColorList = itemElem.elementsByTagName(
"FrameColor" );
306 if ( frameColorList.size() > 0 )
308 QDomElement frameColorElem = frameColorList.at( 0 ).toElement();
309 bool redOk, greenOk, blueOk, alphaOk, widthOk;
310 int penRed, penGreen, penBlue, penAlpha;
313 penWidth = itemElem.attribute(
"outlineWidth" ).toDouble( &widthOk );
314 penRed = frameColorElem.attribute(
"red" ).toDouble( &redOk );
315 penGreen = frameColorElem.attribute(
"green" ).toDouble( &greenOk );
316 penBlue = frameColorElem.attribute(
"blue" ).toDouble( &blueOk );
317 penAlpha = frameColorElem.attribute(
"alpha" ).toDouble( &alphaOk );
318 if ( redOk && greenOk && blueOk && alphaOk && widthOk )
320 QPen framePen( QColor( penRed, penGreen, penBlue, penAlpha ) );
321 framePen.setWidthF( penWidth );
322 framePen.setJoinStyle( Qt::MiterJoin );
328 QDomNodeList bgColorList = itemElem.elementsByTagName(
"BackgroundColor" );
329 if ( bgColorList.size() > 0 )
331 QDomElement bgColorElem = bgColorList.at( 0 ).toElement();
332 bool redOk, greenOk, blueOk, alphaOk;
333 int bgRed, bgGreen, bgBlue, bgAlpha;
334 bgRed = bgColorElem.attribute(
"red" ).toDouble( &redOk );
335 bgGreen = bgColorElem.attribute(
"green" ).toDouble( &greenOk );
336 bgBlue = bgColorElem.attribute(
"blue" ).toDouble( &blueOk );
337 bgAlpha = bgColorElem.attribute(
"alpha" ).toDouble( &alphaOk );
338 if ( redOk && greenOk && blueOk && alphaOk )
340 QColor brushColor( bgRed, bgGreen, bgBlue, bgAlpha );
362 QPen itemPen = pen();
368 itemPen.setWidthF( outlineWidth );
380 return pen().widthF() / 2.0;
386 return rect().adjusted( -frameBleed, -frameBleed, frameBleed, frameBleed );
429 if ( !QFile::exists( lockIconPath ) )
434 QImage lockImage( lockIconPath );
435 if ( !lockImage.isNull() )
437 p->drawImage( QRectF( 0, 0, sizeLockSymbol, sizeLockSymbol ), lockImage, QRectF( 0, 0, lockImage.width(), lockImage.height() ) );
448 p->setBrush( Qt::NoBrush );
449 p->setRenderHint( QPainter::Antialiasing,
true );
450 p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
461 QRectF newSceneRect( pos().x() + dx, pos().y() + dy, rect().width(), rect().height() );
467 double width = rect().width();
468 double height = rect().height();
474 double upperLeftX = x;
475 double upperLeftY = y;
483 upperLeftX -= width / 2.0;
493 upperLeftY -= height / 2.0;
497 upperLeftY -= height;
500 if ( posIncludesFrame )
514 upperLeftX += lineToItemOrigin.x2();
515 upperLeftY += lineToItemOrigin.y2();
522 setSceneRect( QRectF( upperLeftX, upperLeftY, width, height ) );
528 double newWidth = rectangle.width();
529 double newHeight = rectangle.height();
530 double xTranslation = rectangle.x();
531 double yTranslation = rectangle.y();
534 if ( rectangle.width() < 0 )
536 newWidth = - rectangle.width();
537 xTranslation -= newWidth;
540 if ( rectangle.height() < 0 )
542 newHeight = - rectangle.height();
543 yTranslation -= newHeight;
546 QRectF newRect( 0, 0, newWidth, newHeight );
547 QGraphicsRectItem::setRect( newRect );
548 setPos( xTranslation, yTranslation );
557 p->setBrush( brush() );
558 p->setPen( Qt::NoPen );
559 p->setRenderHint( QPainter::Antialiasing,
true );
560 p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
581 setOpacity( 1. - ( transparency / 100. ) );
588 mEffect->setEnabled( effectsEnabled );
596 p->setFont( textFont );
598 p->scale( scaleFactor, scaleFactor );
603 void QgsComposerItem::drawText( QPainter* p,
const QRectF& rect,
const QString& text,
const QFont& font, Qt::AlignmentFlag halignment, Qt::AlignmentFlag valignment )
const
611 p->setFont( textFont );
613 p->scale( scaleFactor, scaleFactor );
614 p->drawText( scaledRect, halignment | valignment | Qt::TextWordWrap, text );
623 double angleRad = angle / 180.0 *
M_PI;
624 QPointF middlePoint( x, y );
626 QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
627 QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
629 QPointF p1Rotated, p2Rotated;
630 p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
631 p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
632 p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
633 p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
635 QPolygonF arrowHeadPoly;
636 arrowHeadPoly << middlePoint;
637 arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
638 arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
642 QPen arrowPen = p->pen();
643 arrowPen.setJoinStyle( Qt::RoundJoin );
644 QBrush arrowBrush = p->brush();
645 arrowBrush.setStyle( Qt::SolidPattern );
646 p->setPen( arrowPen );
647 p->setBrush( arrowBrush );
648 arrowBrush.setStyle( Qt::SolidPattern );
649 p->drawPolygon( arrowHeadPoly );
657 QFontMetricsF fontMetrics( metricsFont );
664 QFontMetricsF fontMetrics( metricsFont );
671 QFontMetricsF fontMetrics( metricsFont );
678 QFontMetricsF fontMetrics( metricsFont );
684 return ( pointSize * 0.3527 );
689 QFont scaledFont = font;
691 scaledFont.setPixelSize( pixelSize );
697 double xDiff = p2.x() - p1.x();
698 double yDiff = p2.y() - p1.y();
699 double length = sqrt( xDiff * xDiff + yDiff * yDiff );
705 double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 /
M_PI;
708 return ( 360 - angle );
718 QList<QGraphicsView*> viewList = scene()->views();
719 if ( viewList.size() > 0 )
721 QGraphicsView* currentView = viewList.at( 0 );
722 if ( currentView->isVisible() )
724 result = currentView->transform().m11();
736 double rectHandlerSize = 10.0 / viewScaleFactor;
739 if ( rectHandlerSize > ( rect().width() / 3 ) )
741 rectHandlerSize = rect().width() / 3;
743 if ( rectHandlerSize > ( rect().height() / 3 ) )
745 rectHandlerSize = rect().height() / 3;
747 return rectHandlerSize;
754 if ( lockSymbolSize > ( rect().width() / 3 ) )
756 lockSymbolSize = rect().width() / 3;
758 if ( lockSymbolSize > ( rect().height() / 3 ) )
760 lockSymbolSize = rect().height() / 3;
774 if ( adjustPosition )
778 QLineF refLine = QLineF( mapToScene( QPointF( rect().width() / 2.0, rect().height() / 2.0 ) ) , mapToScene( QPointF( 0 , 0 ) ) );
782 QPointF rotatedReferencePoint = refLine.p2();
783 setPos( rotatedReferencePoint );
796 setTransformOriginPoint( 0, 0 );
811 double originalWidth = originalRect.width();
812 double originalHeight = originalRect.height();
813 double boundsWidth = boundsRect.width();
814 double boundsHeight = boundsRect.height();
815 double ratioBoundsRect = boundsWidth / boundsHeight;
818 if ( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 )
820 double originalRatio = originalWidth / originalHeight;
821 double rectScale = originalRatio > ratioBoundsRect ? boundsWidth / originalWidth : boundsHeight / originalHeight;
822 double rectScaledWidth = rectScale * originalWidth;
823 double rectScaledHeight = rectScale * originalHeight;
825 if ( rotation == 0 || rotation == 180 )
827 return QRectF(( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
831 return QRectF(( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledHeight, rectScaledWidth );
837 double cosAngle = cos( angleRad );
838 double sinAngle = sin( angleRad );
841 double widthBoundsRotatedRect = originalWidth * fabs( cosAngle ) + originalHeight * fabs( sinAngle );
842 double heightBoundsRotatedRect = originalHeight * fabs( cosAngle ) + originalWidth * fabs( sinAngle );
846 double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
847 double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
848 double rectScaledWidth = rectScale * originalWidth;
849 double rectScaledHeight = rectScale * originalHeight;
853 double currentCornerX = 0;
855 currentCornerX += rectScaledWidth * cosAngle;
856 minX = minX < currentCornerX ? minX : currentCornerX;
857 currentCornerX += rectScaledHeight * sinAngle;
858 minX = minX < currentCornerX ? minX : currentCornerX;
859 currentCornerX -= rectScaledWidth * cosAngle;
860 minX = minX < currentCornerX ? minX : currentCornerX;
862 double currentCornerY = 0;
864 currentCornerY -= rectScaledWidth * sinAngle;
865 minY = minY < currentCornerY ? minY : currentCornerY;
866 currentCornerY += rectScaledHeight * cosAngle;
867 minY = minY < currentCornerY ? minY : currentCornerY;
868 currentCornerY += rectScaledWidth * sinAngle;
869 minY = minY < currentCornerY ? minY : currentCornerY;
872 double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
873 offsetX += fabs( minX );
874 double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
875 offsetY += fabs( minY );
877 return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
882 if ( qAbs( rotation ) <= 0.0 )
903 double midX = width / 2.0;
904 double midY = height / 2.0;
925 double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) );
928 if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 )
930 width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) );
931 height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) );
936 double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) );
939 width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
940 height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
953 double rotToRad = rotation *
M_PI / 180.0;
954 QPointF midpoint( width / 2.0, height / 2.0 );
955 double xVector = x - midpoint.x();
956 double yVector = y - midpoint.y();
959 double xRotated = cos( rotToRad ) * xVector - sin( rotToRad ) * yVector;
960 double yRotated = sin( rotToRad ) * xVector + cos( rotToRad ) * yVector;
963 QLineF line( midpoint.x(), midpoint.y(), midpoint.x() + xRotated, midpoint.y() + yRotated );
966 QList<QLineF> borders;
967 borders << QLineF( 0, 0, width, 0 );
968 borders << QLineF( width, 0, width, height );
969 borders << QLineF( width, height, 0, height );
970 borders << QLineF( 0, height, 0, 0 );
972 QList<QLineF>::const_iterator it = borders.constBegin();
973 QPointF intersectionPoint;
975 for ( ; it != borders.constEnd(); ++it )
977 if ( line.intersect( *it, &intersectionPoint ) == QLineF::BoundedIntersection )
979 x = intersectionPoint.x();
980 y = intersectionPoint.y();
995 if ( rotation == 0.0 )
1001 double x1 = -width / 2.0;
1002 double y1 = -height / 2.0;
1003 rotate( rotation, x1, y1 );
1005 double x2 = width / 2.0;
1006 double y2 = -height / 2.0;
1007 rotate( rotation, x2, y2 );
1009 double x3 = width / 2.0;
1010 double y3 = height / 2.0;
1011 rotate( rotation, x3, y3 );
1013 double x4 = -width / 2.0;
1014 double y4 = height / 2.0;
1015 rotate( rotation, x4, y4 );
1018 QPointF midpoint( width / 2.0, height / 2.0 );
1020 QPolygonF rotatedRectPoly;
1021 rotatedRectPoly << QPointF( midpoint.x() + x1, midpoint.y() + y1 );
1022 rotatedRectPoly << QPointF( midpoint.x() + x2, midpoint.y() + y2 );
1023 rotatedRectPoly << QPointF( midpoint.x() + x3, midpoint.y() + y3 );
1024 rotatedRectPoly << QPointF( midpoint.x() + x4, midpoint.y() + y4 );
1025 QRectF boundingRect = rotatedRectPoly.boundingRect();
1026 width = boundingRect.width();
1027 height = boundingRect.height();
1032 double rotToRad = angle *
M_PI / 180.0;
1034 xRot = x * cos( rotToRad ) - y * sin( rotToRad );
1035 yRot = x * sin( rotToRad ) + y * cos( rotToRad );