26#include <QGraphicsSceneHoverEvent>
27#include <QGraphicsView>
32#include "moc_qgsgraphicsviewmousehandles.cpp"
34using namespace Qt::StringLiterals;
38QgsGraphicsViewMouseHandles::QgsGraphicsViewMouseHandles( QGraphicsView *view )
40 , QGraphicsRectItem( nullptr )
44 setAcceptHoverEvents(
true );
47 mRotationHandlePath.moveTo( 0, 14 );
48 mRotationHandlePath.lineTo( 6, 20 );
49 mRotationHandlePath.lineTo( 12, 14 );
50 mRotationHandlePath.arcTo( 8, 8, 12, 12, 180, -90 );
51 mRotationHandlePath.lineTo( 14, 12 );
52 mRotationHandlePath.lineTo( 20, 6 );
53 mRotationHandlePath.lineTo( 14, 0 );
54 mRotationHandlePath.arcTo( 4, 4, 20, 20, 90, 90 );
55 mRotationHandlePath.lineTo( 0, 14 );
58void QgsGraphicsViewMouseHandles::setRotationEnabled(
bool enable )
60 if ( mRotationEnabled == enable )
65 mRotationEnabled = enable;
69void QgsGraphicsViewMouseHandles::setCadMouseDigitizingModeEnabled(
bool enable )
71 if ( mCadMouseDigitizingMode == enable )
76 mCadMouseDigitizingMode = enable;
79void QgsGraphicsViewMouseHandles::setResizeEnabled(
bool enable )
81 if ( mResizeEnabled == enable )
86 mResizeEnabled = enable;
90void QgsGraphicsViewMouseHandles::paintInternal( QPainter *painter,
bool showHandles,
bool showStaticBoundingBoxes,
bool showTemporaryBoundingBoxes,
const QStyleOptionGraphicsItem *, QWidget * )
97 if ( showStaticBoundingBoxes )
100 double rectHandlerSize = rectHandlerBorderTolerance();
101 drawHandles( painter, rectHandlerSize );
104 if ( showTemporaryBoundingBoxes && ( mIsResizing || mIsDragging || showStaticBoundingBoxes ) )
107 drawSelectedItemBounds( painter );
111QRectF QgsGraphicsViewMouseHandles::storedItemRect( QGraphicsItem *item )
const
113 return itemRect( item );
116void QgsGraphicsViewMouseHandles::rotateItem( QGraphicsItem *,
double,
double,
double )
118 QgsDebugError( u
"Rotation is not implemented for this class"_s );
121void QgsGraphicsViewMouseHandles::previewItemMove( QGraphicsItem *,
double,
double )
124void QgsGraphicsViewMouseHandles::setItemRect( QGraphicsItem *, QRectF )
126 QgsDebugError( u
"Resize is not implemented for this class"_s );
129QRectF QgsGraphicsViewMouseHandles::previewSetItemRect( QGraphicsItem *, QRectF )
134void QgsGraphicsViewMouseHandles::startMacroCommand(
const QString & )
137void QgsGraphicsViewMouseHandles::endMacroCommand()
140void QgsGraphicsViewMouseHandles::endItemCommand( QGraphicsItem * )
143void QgsGraphicsViewMouseHandles::createItemCommand( QGraphicsItem * )
146QPointF QgsGraphicsViewMouseHandles::snapPoint( QPointF originalPoint, QgsGraphicsViewMouseHandles::SnapGuideMode,
bool,
bool )
148 return originalPoint;
151void QgsGraphicsViewMouseHandles::expandItemList(
const QList<QGraphicsItem *> &items, QList<QGraphicsItem *> &collected )
const
156void QgsGraphicsViewMouseHandles::drawHandles( QPainter *painter,
double rectHandlerSize )
159 QPen handlePen = QPen( QColor( 55, 140, 195, 255 ) );
160 handlePen.setWidth( 0 );
161 painter->setPen( handlePen );
164 painter->setBrush( Qt::NoBrush );
165 painter->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
167 if ( isResizeEnabled() )
170 painter->setBrush( QColor( 255, 255, 255, 255 ) );
172 painter->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
174 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, 0, rectHandlerSize, rectHandlerSize ) );
176 painter->drawRect( QRectF( rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
178 painter->drawRect( QRectF( 0, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
180 painter->drawRect( QRectF( rect().width() - rectHandlerSize, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
182 painter->drawRect( QRectF( 0, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
184 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
186 painter->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
189 if ( isRotationEnabled() )
192 const double scale = rectHandlerSize / mHandleSize;
193 const bool drawBottomRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().height();
194 const bool drawRightRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().width();
195 QTransform transform;
199 transform.translate( rectHandlerSize, rectHandlerSize );
200 transform.scale( scale, scale );
202 painter->setTransform( transform,
true );
203 painter->drawPath( mRotationHandlePath );
207 if ( drawRightRotationHandles )
210 transform.translate( rect().width() - rectHandlerSize, rectHandlerSize );
211 transform.rotate( 90 );
212 transform.scale( scale, scale );
214 painter->setTransform( transform,
true );
215 painter->drawPath( mRotationHandlePath );
219 if ( drawBottomRotationHandles )
223 transform.translate( rectHandlerSize, rect().height() - rectHandlerSize );
224 transform.rotate( 270 );
225 transform.scale( scale, scale );
227 painter->setTransform( transform,
true );
228 painter->drawPath( mRotationHandlePath );
232 if ( drawBottomRotationHandles && drawRightRotationHandles )
236 transform.translate( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize );
237 transform.rotate( 180 );
238 transform.scale( scale, scale );
240 painter->setTransform( transform,
true );
241 painter->drawPath( mRotationHandlePath );
247void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
250 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
251 if ( selectedItems.isEmpty() )
256 QList<QGraphicsItem *> itemsToDraw;
257 expandItemList( selectedItems, itemsToDraw );
259 if ( itemsToDraw.size() <= 1 )
266 QgsScopedQPainterState painterState( painter );
267 painter->setCompositionMode( QPainter::CompositionMode_Difference );
270 QPen selectedItemPen = QPen( QColor( 144, 144, 144, 255 ) );
271 selectedItemPen.setStyle( Qt::DashLine );
272 selectedItemPen.setWidth( 0 );
273 painter->setPen( selectedItemPen );
274 painter->setBrush( Qt::NoBrush );
276 for ( QGraphicsItem *item : std::as_const( itemsToDraw ) )
279 QPolygonF itemBounds;
280 if ( isDragging() && !itemIsLocked( item ) )
284 QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
287 itemSceneBounds.translate( transform().dx(), transform().dy() );
289 itemBounds = mapFromScene( itemSceneBounds );
291 else if ( isResizing() && !itemIsLocked( item ) )
295 QRectF thisItemRect = mapRectFromItem( item, itemRect( item ) );
297 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
298 itemBounds = QPolygonF( thisItemRect );
300 else if ( isRotating() && !itemIsLocked( item ) )
302 const QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
303 const QPointF rotationCenter = sceneTransform().map( rect().center() );
305 QTransform transform;
306 transform.translate( rotationCenter.x(), rotationCenter.y() );
307 transform.rotate( mRotationDelta );
308 transform.translate( -rotationCenter.x(), -rotationCenter.y() );
309 itemBounds = mapFromScene( transform.map( itemSceneBounds ) );
314 itemBounds = item->mapToItem(
this, itemRect( item ) );
320 path.addPolygon( itemBounds );
321 painter->drawPath( path );
325double QgsGraphicsViewMouseHandles::rectHandlerBorderTolerance()
const
332 double viewScaleFactor = mView->transform().m11();
335 double rectHandlerSize = mHandleSize / viewScaleFactor;
338 if ( rectHandlerSize > ( rect().width() / 3 ) )
340 rectHandlerSize = rect().width() / 3;
342 if ( rectHandlerSize > ( rect().height() / 3 ) )
344 rectHandlerSize = rect().height() / 3;
346 return rectHandlerSize;
349Qt::CursorShape QgsGraphicsViewMouseHandles::cursorForPosition( QPointF itemCoordPos )
352 double normalizedRotation = std::fmod( rotation(), 360 );
353 if ( normalizedRotation < 0 )
355 normalizedRotation += 360;
357 switch ( mouseAction )
360 return Qt::ForbiddenCursor;
362 return Qt::SizeAllCursor;
366 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
368 return Qt::SizeVerCursor;
370 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
372 return Qt::SizeBDiagCursor;
374 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
376 return Qt::SizeHorCursor;
380 return Qt::SizeFDiagCursor;
385 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
387 return Qt::SizeHorCursor;
389 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
391 return Qt::SizeFDiagCursor;
393 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
395 return Qt::SizeVerCursor;
399 return Qt::SizeBDiagCursor;
405 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
407 return Qt::SizeFDiagCursor;
409 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
411 return Qt::SizeVerCursor;
413 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
415 return Qt::SizeBDiagCursor;
419 return Qt::SizeHorCursor;
424 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
426 return Qt::SizeBDiagCursor;
428 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
430 return Qt::SizeHorCursor;
432 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
434 return Qt::SizeFDiagCursor;
438 return Qt::SizeVerCursor;
441 return Qt::ArrowCursor;
447 return Qt::PointingHandCursor;
450 return Qt::ArrowCursor;
455 bool nearLeftBorder =
false;
456 bool nearRightBorder =
false;
457 bool nearLowerBorder =
false;
458 bool nearUpperBorder =
false;
460 bool nearLeftInner =
false;
461 bool nearRightInner =
false;
462 bool nearLowerInner =
false;
463 bool nearUpperInner =
false;
465 bool withinWidth =
false;
466 bool withinHeight =
false;
468 if ( itemCoordPos.x() >= 0 && itemCoordPos.x() <= rect().width() )
472 if ( itemCoordPos.y() >= 0 && itemCoordPos.y() <= rect().height() )
477 double borderTolerance = rectHandlerBorderTolerance();
478 double innerTolerance = mRotationHandleSize * borderTolerance / mHandleSize;
480 if ( isResizeEnabled() && itemCoordPos.x() >= 0 && itemCoordPos.x() < borderTolerance )
482 nearLeftBorder =
true;
484 else if ( isRotationEnabled() && itemCoordPos.x() >= borderTolerance && itemCoordPos.x() < ( borderTolerance + innerTolerance ) )
486 nearLeftInner =
true;
488 if ( isResizeEnabled() && itemCoordPos.y() >= 0 && itemCoordPos.y() < borderTolerance )
490 nearUpperBorder =
true;
492 else if ( isRotationEnabled() && itemCoordPos.y() >= borderTolerance && itemCoordPos.y() < ( borderTolerance + innerTolerance ) )
494 nearUpperInner =
true;
496 if ( isResizeEnabled() && itemCoordPos.x() <= rect().width() && itemCoordPos.x() > ( rect().width() - borderTolerance ) )
498 nearRightBorder =
true;
500 else if ( isRotationEnabled() && itemCoordPos.x() <= ( rect().width() - borderTolerance ) && itemCoordPos.x() > ( rect().width() - borderTolerance - innerTolerance ) )
502 nearRightInner =
true;
504 if ( isResizeEnabled() && itemCoordPos.y() <= rect().height() && itemCoordPos.y() > ( rect().height() - borderTolerance ) )
506 nearLowerBorder =
true;
508 else if ( isRotationEnabled() && itemCoordPos.y() <= ( rect().height() - borderTolerance ) && itemCoordPos.y() > ( rect().height() - borderTolerance - innerTolerance ) )
510 nearLowerInner =
true;
513 if ( nearLeftBorder && nearUpperBorder )
517 else if ( nearLeftBorder && nearLowerBorder )
521 else if ( nearRightBorder && nearUpperBorder )
525 else if ( nearRightBorder && nearLowerBorder )
529 else if ( nearLeftBorder && withinHeight )
533 else if ( nearRightBorder && withinHeight )
537 else if ( nearUpperBorder && withinWidth )
541 else if ( nearLowerBorder && withinWidth )
545 else if ( nearLeftInner && nearUpperInner )
549 else if ( nearRightInner && nearUpperInner )
553 else if ( nearLeftInner && nearLowerInner )
557 else if ( nearRightInner && nearLowerInner )
563 QPointF scenePoint = mapToScene( itemCoordPos );
564 const QList<QGraphicsItem *> itemsAtCursorPos = sceneItemsAtPoint( scenePoint );
565 if ( itemsAtCursorPos.isEmpty() )
570 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
572 if ( graphicsItem && graphicsItem->isSelected() )
586 QPointF itemPos = mapFromScene( sceneCoordPos );
587 return mouseActionForPosition( itemPos );
590bool QgsGraphicsViewMouseHandles::shouldBlockEvent( QInputEvent * )
const
592 return mIsDragging || mIsResizing || mIsRotating;
595void QgsGraphicsViewMouseHandles::startMove( QPointF sceneCoordPos )
598 mMouseMoveStartPos = sceneCoordPos;
600 mBeginMouseEventPos = sceneCoordPos;
601 mBeginHandlePos = scenePos();
602 mBeginHandleWidth = rect().width();
603 mBeginHandleHeight = rect().height();
609 if ( mView->scene()->mouseGrabberItem() !=
this )
615void QgsGraphicsViewMouseHandles::selectedItemSizeChanged()
617 if ( !isDragging() && !isResizing() )
624void QgsGraphicsViewMouseHandles::selectedItemRotationChanged()
626 if ( !isDragging() && !isResizing() )
633void QgsGraphicsViewMouseHandles::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
635 setViewportCursor( cursorForPosition( event->pos() ) );
638void QgsGraphicsViewMouseHandles::hoverLeaveEvent( QGraphicsSceneHoverEvent *event )
641 setViewportCursor( Qt::ArrowCursor );
644void QgsGraphicsViewMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *event )
646 if ( event->button() != Qt::LeftButton )
652 if ( mCadMouseDigitizingMode && ( mIsDragging || mIsResizing || mIsRotating ) )
658 mMouseMoveStartPos =
event->lastScenePos();
660 mBeginMouseEventPos =
event->lastScenePos();
661 mBeginHandlePos = scenePos();
662 mBeginHandleWidth = rect().width();
663 mBeginHandleHeight = rect().height();
665 mCurrentMouseMoveAction = mouseActionForPosition( event->pos() );
669 switch ( mCurrentMouseMoveAction )
686 mResizeRect = QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
689 mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
697 mRotationCenter = sceneTransform().map( rect().center() );
698 mRotationBegin = std::atan2( mMouseMoveStartPos.y() - mRotationCenter.y(), mMouseMoveStartPos.x() - mRotationCenter.x() ) * 180 / M_PI;
699 mRotationCurrent = 0.0;
707 if ( mCadMouseDigitizingMode && mIsDragging )
709 mIsDragStarting =
true;
713void QgsGraphicsViewMouseHandles::resetStatusBar()
715 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
716 int selectedCount = selectedItems.size();
720 showStatusMessage( tr(
"%n item(s) selected",
nullptr, selectedCount ) );
725 showStatusMessage( QString() );
729void QgsGraphicsViewMouseHandles::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
736 dragMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );
738 else if ( isResizing() )
743 resizeMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::AltModifier );
745 else if ( isRotating() )
749 rotateMouseMove( event->lastScenePos(), event->modifiers() & Qt::ControlModifier );
753void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
755 if ( event->button() != Qt::LeftButton )
761 if ( mDoubleClickInProgress )
763 mDoubleClickInProgress =
false;
768 if ( mIsDragStarting )
770 mIsDragStarting =
false;
776 if ( mView->scene()->mouseGrabberItem() ==
this )
781 QPointF mouseMoveStopPoint =
event->lastScenePos();
782 double diffX = mouseMoveStopPoint.x() - mMouseMoveStartPos.x();
783 double diffY = mouseMoveStopPoint.y() - mMouseMoveStartPos.y();
785 const bool isClick = std::fabs( diffX ) < std::numeric_limits<double>::min() && std::fabs( diffY ) < std::numeric_limits<double>::min();
799 startMacroCommand( tr(
"Move Items" ) );
801 QPointF mEndHandleMovePos = scenePos();
803 double deltaX = mEndHandleMovePos.x() - mBeginHandlePos.x();
804 double deltaY = mEndHandleMovePos.y() - mBeginHandlePos.y();
807 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
808 for ( QGraphicsItem *item : selectedItems )
810 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
816 createItemCommand( item );
817 moveItem( item, deltaX, deltaY );
818 endItemCommand( item );
824 else if ( mIsResizing )
827 startMacroCommand( tr(
"Resize Items" ) );
830 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
831 for ( QGraphicsItem *item : selectedItems )
833 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 )
838 createItemCommand( item );
841 if ( selectedItems.size() == 1 )
844 thisItemRect = mResizeRect;
849 thisItemRect = mapRectFromItem( item, itemRect( item ) );
850 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
853 thisItemRect = thisItemRect.normalized();
854 QPointF newPos = mapToScene( thisItemRect.topLeft() );
855 thisItemRect.moveTopLeft( newPos );
856 setItemRect( item, thisItemRect );
858 endItemCommand( item );
864 else if ( mIsRotating )
866 const QPointF itemRotationCenter = sceneTransform().map( rect().center() );
869 startMacroCommand( tr(
"Rotate Items" ) );
872 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
873 for ( QGraphicsItem *item : selectedItems )
875 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
881 const QPointF itemCenter = item->mapToScene( itemRect( item ) ).boundingRect().center();
883 QTransform transform;
884 transform.translate( itemRotationCenter.x(), itemRotationCenter.y() );
885 transform.rotate( mRotationDelta );
886 transform.translate( -itemRotationCenter.x(), -itemRotationCenter.y() );
887 const QPointF rotatedItemCenter = transform.map( itemCenter );
889 createItemCommand( item );
890 rotateItem( item, mRotationDelta, rotatedItemCenter.x() - itemCenter.x(), rotatedItemCenter.y() - itemCenter.y() );
891 endItemCommand( item );
910bool QgsGraphicsViewMouseHandles::selectionRotation(
double &rotation )
const
913 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
914 auto itemIter = selectedItems.constBegin();
917 double firstItemRotation = ( *itemIter )->rotation();
920 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
922 if ( !
qgsDoubleNear( ( *itemIter )->rotation(), firstItemRotation ) )
930 rotation = firstItemRotation;
934void QgsGraphicsViewMouseHandles::updateHandles()
939 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
940 if ( !selectedItems.isEmpty() )
946 if ( selectionRotation( rotation ) )
949 setRotation( rotation );
958 QRectF newHandleBounds = selectionBounds();
961 setRect( 0, 0, newHandleBounds.width(), newHandleBounds.height() );
962 setPos( mapToScene( newHandleBounds.topLeft() ) );
976void QgsGraphicsViewMouseHandles::rotateMouseMove( QPointF currentPosition,
bool snapToCommonAngles )
983 mRotationCurrent = std::atan2( currentPosition.y() - mRotationCenter.y(), currentPosition.x() - mRotationCenter.x() ) * 180 / M_PI;
984 mRotationDelta = mRotationCurrent - mRotationBegin;
985 if ( snapToCommonAngles )
990 const double itemRotationRadian = rotation() * M_PI / 180;
991 const double deltaX = ( rect().width() / 2 ) * cos( itemRotationRadian ) - ( rect().height() / 2 ) * sin( itemRotationRadian );
992 const double deltaY = ( rect().width() / 2 ) * sin( itemRotationRadian ) + ( rect().height() / 2 ) * cos( itemRotationRadian );
994 QTransform rotateTransform;
995 rotateTransform.translate( deltaX, deltaY );
996 rotateTransform.rotate( mRotationDelta );
997 rotateTransform.translate( -deltaX, -deltaY );
998 setTransform( rotateTransform );
1001 showStatusMessage( tr(
"rotation: %1°" ).arg( QString::number( mRotationDelta,
'f', 2 ) ) );
1006void QgsGraphicsViewMouseHandles::dragMouseMove( QPointF currentPosition,
bool lockMovement,
bool preventSnap )
1014 double moveX = currentPosition.x() - mBeginMouseEventPos.x();
1015 double moveY = currentPosition.y() - mBeginMouseEventPos.y();
1018 QPointF upperLeftPoint( mBeginHandlePos.x() + moveX, mBeginHandlePos.y() + moveY );
1020 QPointF snappedLeftPoint;
1026 snappedLeftPoint = snapPoint( upperLeftPoint, Item );
1031 snappedLeftPoint = upperLeftPoint;
1036 double moveRectX = snappedLeftPoint.x() - mBeginHandlePos.x();
1037 double moveRectY = snappedLeftPoint.y() - mBeginHandlePos.y();
1043 if ( std::fabs( moveRectX ) <= std::fabs( moveRectY ) )
1054 QTransform moveTransform;
1055 moveTransform.translate( moveRectX, moveRectY );
1056 setTransform( moveTransform );
1058 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1059 for ( QGraphicsItem *item : selectedItems )
1061 previewItemMove( item, moveRectX, moveRectY );
1064 showStatusMessage( tr(
"dx: %1 mm dy: %2 mm" ).arg( moveRectX ).arg( moveRectY ) );
1067void QgsGraphicsViewMouseHandles::resizeMouseMove( QPointF currentPosition,
bool lockRatio,
bool fromCenter )
1074 double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
1076 QPointF beginMousePos;
1077 QPointF finalPosition;
1098 beginMousePos = mapFromScene( QPointF( mBeginMouseEventPos.x() - mCursorOffset.width(), mBeginMouseEventPos.y() - mCursorOffset.height() ) );
1099 QPointF snappedPosition = snapPoint( QPointF( currentPosition.x() - mCursorOffset.width(), currentPosition.y() - mCursorOffset.height() ), Point, snapHorizontal, snapVertical );
1100 finalPosition = mapFromScene( snappedPosition );
1105 beginMousePos = mapFromScene( mBeginMouseEventPos );
1106 finalPosition = mapFromScene( currentPosition );
1109 double diffX = finalPosition.x() - beginMousePos.x();
1110 double diffY = finalPosition.y() - beginMousePos.y();
1113 if ( lockRatio && !
qgsDoubleNear( mBeginHandleHeight, 0.0 ) )
1115 ratio = mBeginHandleWidth / mBeginHandleHeight;
1118 switch ( mCurrentMouseMoveAction )
1125 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1145 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1166 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1185 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1206 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1208 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight - diffY ) * ratio );
1212 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth - diffX ) / ratio );
1215 mx = diffX, my = diffY;
1226 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1228 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1232 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1237 rx = diffX, ry = diffY;
1246 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1248 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1252 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth + diffX ) / ratio );
1256 my = diffY, rx = diffX, ry = -diffY;
1265 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1267 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight + diffY ) * ratio );
1271 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1302 mResizeMoveX = mBeginHandleWidth + rx > 0 ? mx : mx + mBeginHandleWidth + rx;
1303 mResizeMoveY = mBeginHandleHeight + ry > 0 ? my : my + mBeginHandleHeight + ry;
1306 QLineF translateLine = QLineF( 0, 0, mResizeMoveX, mResizeMoveY );
1307 translateLine.setAngle( translateLine.angle() - rotation() );
1308 QPointF sceneTranslate = translateLine.p2();
1311 QTransform itemTransform;
1312 itemTransform.translate( sceneTranslate.x(), sceneTranslate.y() );
1313 setTransform( itemTransform );
1316 if ( mBeginHandleWidth + rx >= 0 && mBeginHandleHeight + ry >= 0 )
1318 mResizeRect = QRectF( 0, 0, mBeginHandleWidth + rx, mBeginHandleHeight + ry );
1320 else if ( mBeginHandleHeight + ry >= 0 )
1322 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), 0 ), QPointF( 0, mBeginHandleHeight + ry ) );
1324 else if ( mBeginHandleWidth + rx >= 0 )
1326 mResizeRect = QRectF( QPointF( 0, -( mBeginHandleHeight + ry ) ), QPointF( mBeginHandleWidth + rx, 0 ) );
1330 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), -( mBeginHandleHeight + ry ) ), QPointF( 0, 0 ) );
1333 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1334 QRectF newHandleBounds;
1335 for ( QGraphicsItem *item : selectedItems )
1338 QRectF thisItemRect = mapRectFromScene( storedItemRect( item ) );
1340 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
1342 thisItemRect = mapRectFromScene( previewSetItemRect( item, mapRectToScene( thisItemRect ) ) );
1343 newHandleBounds = newHandleBounds.isValid() ? newHandleBounds.united( thisItemRect ) : thisItemRect;
1346 setRect( newHandleBounds.isValid() ? newHandleBounds : QRectF( 0, 0, std::fabs( mBeginHandleWidth + rx ), std::fabs( mBeginHandleHeight + ry ) ) );
1349 showStatusMessage( tr(
"width: %1 mm height: %2 mm" ).arg( rect().width() ).arg( rect().height() ) );
1352void QgsGraphicsViewMouseHandles::setHandleSize(
double size )
1357void QgsGraphicsViewMouseHandles::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
1361 mDoubleClickInProgress =
true;
1364QSizeF QgsGraphicsViewMouseHandles::calcCursorEdgeOffset( QPointF cursorPos )
1367 QPointF sceneMousePos = mapFromScene( cursorPos );
1369 switch ( mCurrentMouseMoveAction )
1373 return QSizeF( 0, sceneMousePos.y() );
1376 return QSizeF( 0, sceneMousePos.y() - rect().height() );
1380 return QSizeF( sceneMousePos.x(), 0 );
1383 return QSizeF( sceneMousePos.x() - rect().width(), 0 );
1387 return QSizeF( sceneMousePos.x(), sceneMousePos.y() );
1390 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() - rect().height() );
1393 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() );
1396 return QSizeF( sceneMousePos.x(), sceneMousePos.y() - rect().height() );
1411QRectF QgsGraphicsViewMouseHandles::selectionBounds()
const
1414 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1415 auto itemIter = selectedItems.constBegin();
1418 QRectF bounds = mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect();
1421 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
1423 bounds = bounds.united( mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect() );
1429void QgsGraphicsViewMouseHandles::relativeResizeRect( QRectF &rectToResize,
const QRectF &boundsBefore,
const QRectF &boundsAfter )
1432 double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1433 double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1434 double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1435 double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1437 rectToResize.setRect( left, top, right - left, bottom - top );
1440double QgsGraphicsViewMouseHandles::relativePosition(
double position,
double beforeMin,
double beforeMax,
double afterMin,
double afterMax )
1443 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
1444 double c = afterMin - ( beforeMin * m );
1447 return m * position +
c;
MouseHandlesAction
Action to be performed by the mouse handles.
@ ResizeRightDown
Resize right down (Bottom right handle).
@ ResizeLeftUp
Resize left up (Top left handle).
@ ResizeLeftDown
Resize left down (Bottom left handle).
@ ResizeRight
Resize right (Right handle).
@ ResizeDown
Resize down (Bottom handle).
@ RotateTopRight
Rotate from top right handle.
@ RotateTopLeft
Rotate from top left handle.
@ RotateBottomRight
Rotate right bottom right handle.
@ ResizeRightUp
Resize right up (Top right handle).
@ ResizeLeft
Resize left (Left handle).
@ RotateBottomLeft
Rotate from bottom left handle.
@ ResizeUp
Resize up (Top handle).
static double snappedAngle(double angle)
Snaps an angle (in degrees) to its closest 45 degree angle.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define QgsDebugError(str)