27#include <QGraphicsSceneHoverEvent>
28#include <QGraphicsView>
33#include "moc_qgsgraphicsviewmousehandles.cpp"
35using namespace Qt::StringLiterals;
39QgsGraphicsViewMouseHandles::QgsGraphicsViewMouseHandles( QGraphicsView *view )
41 , QGraphicsRectItem( nullptr )
45 setAcceptHoverEvents(
true );
48 mRotationHandlePath.moveTo( 0, 14 );
49 mRotationHandlePath.lineTo( 6, 20 );
50 mRotationHandlePath.lineTo( 12, 14 );
51 mRotationHandlePath.arcTo( 8, 8, 12, 12, 180, -90 );
52 mRotationHandlePath.lineTo( 14, 12 );
53 mRotationHandlePath.lineTo( 20, 6 );
54 mRotationHandlePath.lineTo( 14, 0 );
55 mRotationHandlePath.arcTo( 4, 4, 20, 20, 90, 90 );
56 mRotationHandlePath.lineTo( 0, 14 );
59void QgsGraphicsViewMouseHandles::setRotationEnabled(
bool enable )
61 if ( mRotationEnabled == enable )
66 mRotationEnabled = enable;
70void QgsGraphicsViewMouseHandles::setCadMouseDigitizingModeEnabled(
bool enable )
72 if ( mCadMouseDigitizingMode == enable )
77 mCadMouseDigitizingMode = enable;
80void QgsGraphicsViewMouseHandles::setResizeEnabled(
bool enable )
82 if ( mResizeEnabled == enable )
87 mResizeEnabled = enable;
91void QgsGraphicsViewMouseHandles::paintInternal( QPainter *painter,
bool showHandles,
bool showStaticBoundingBoxes,
bool showTemporaryBoundingBoxes,
const QStyleOptionGraphicsItem *, QWidget * )
98 if ( showStaticBoundingBoxes )
101 double rectHandlerSize = rectHandlerBorderTolerance();
102 drawHandles( painter, rectHandlerSize );
105 if ( showTemporaryBoundingBoxes && ( mIsResizing || mIsDragging || showStaticBoundingBoxes ) )
108 drawSelectedItemBounds( painter );
112QRectF QgsGraphicsViewMouseHandles::storedItemRect( QGraphicsItem *item )
const
114 return itemRect( item );
117void QgsGraphicsViewMouseHandles::rotateItem( QGraphicsItem *,
double,
double,
double )
119 QgsDebugError( u
"Rotation is not implemented for this class"_s );
122void QgsGraphicsViewMouseHandles::previewItemMove( QGraphicsItem *,
double,
double )
125void QgsGraphicsViewMouseHandles::setItemRect( QGraphicsItem *, QRectF )
127 QgsDebugError( u
"Resize is not implemented for this class"_s );
130QRectF QgsGraphicsViewMouseHandles::previewSetItemRect( QGraphicsItem *, QRectF )
135void QgsGraphicsViewMouseHandles::startMacroCommand(
const QString & )
138void QgsGraphicsViewMouseHandles::endMacroCommand()
141void QgsGraphicsViewMouseHandles::endItemCommand( QGraphicsItem * )
144void QgsGraphicsViewMouseHandles::createItemCommand( QGraphicsItem * )
147QPointF QgsGraphicsViewMouseHandles::snapPoint( QPointF originalPoint, QgsGraphicsViewMouseHandles::SnapGuideMode,
bool,
bool )
149 return originalPoint;
152void QgsGraphicsViewMouseHandles::expandItemList(
const QList<QGraphicsItem *> &items, QList<QGraphicsItem *> &collected )
const
157void QgsGraphicsViewMouseHandles::drawHandles( QPainter *painter,
double rectHandlerSize )
160 QPen handlePen = QPen( QColor( 55, 140, 195, 255 ) );
161 handlePen.setWidth( 0 );
162 painter->setPen( handlePen );
165 painter->setBrush( Qt::NoBrush );
166 painter->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
168 if ( isResizeEnabled() )
171 painter->setBrush( QColor( 255, 255, 255, 255 ) );
173 painter->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
175 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, 0, rectHandlerSize, rectHandlerSize ) );
177 painter->drawRect( QRectF( rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
179 painter->drawRect( QRectF( 0, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
181 painter->drawRect( QRectF( rect().width() - rectHandlerSize, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
183 painter->drawRect( QRectF( 0, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
185 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
187 painter->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
190 if ( isRotationEnabled() )
193 const double scale = rectHandlerSize / mHandleSize;
194 const bool drawBottomRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().height();
195 const bool drawRightRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().width();
196 QTransform transform;
200 transform.translate( rectHandlerSize, rectHandlerSize );
201 transform.scale( scale, scale );
203 QgsScopedQPainterState painterState( painter );
204 painter->setTransform( transform,
true );
205 painter->drawPath( mRotationHandlePath );
206 painterState.restore();
209 if ( drawRightRotationHandles )
212 transform.translate( rect().width() - rectHandlerSize, rectHandlerSize );
213 transform.rotate( 90 );
214 transform.scale( scale, scale );
216 painter->setTransform( transform,
true );
217 painter->drawPath( mRotationHandlePath );
218 painterState.restore();
221 if ( drawBottomRotationHandles )
225 transform.translate( rectHandlerSize, rect().height() - rectHandlerSize );
226 transform.rotate( 270 );
227 transform.scale( scale, scale );
229 painter->setTransform( transform,
true );
230 painter->drawPath( mRotationHandlePath );
231 painterState.restore();
234 if ( drawBottomRotationHandles && drawRightRotationHandles )
238 transform.translate( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize );
239 transform.rotate( 180 );
240 transform.scale( scale, scale );
242 painter->setTransform( transform,
true );
243 painter->drawPath( mRotationHandlePath );
244 painterState.restore();
249void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
252 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
253 if ( selectedItems.isEmpty() )
258 QList<QGraphicsItem *> itemsToDraw;
259 expandItemList( selectedItems, itemsToDraw );
261 if ( itemsToDraw.size() <= 1 )
268 QgsScopedQPainterState painterState( painter );
269 painter->setCompositionMode( QPainter::CompositionMode_Difference );
272 QPen selectedItemPen = QPen( QColor( 144, 144, 144, 255 ) );
273 selectedItemPen.setStyle( Qt::DashLine );
274 selectedItemPen.setWidth( 0 );
275 painter->setPen( selectedItemPen );
276 painter->setBrush( Qt::NoBrush );
278 for ( QGraphicsItem *item : std::as_const( itemsToDraw ) )
281 QPolygonF itemBounds;
282 if ( isDragging() && !itemIsLocked( item ) )
286 QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
289 itemSceneBounds.translate( transform().dx(), transform().dy() );
291 itemBounds = mapFromScene( itemSceneBounds );
293 else if ( isResizing() && !itemIsLocked( item ) )
297 QRectF thisItemRect = mapRectFromItem( item, itemRect( item ) );
299 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
300 itemBounds = QPolygonF( thisItemRect );
302 else if ( isRotating() && !itemIsLocked( item ) )
304 const QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
305 const QPointF rotationCenter = sceneTransform().map( rect().center() );
307 QTransform transform;
308 transform.translate( rotationCenter.x(), rotationCenter.y() );
309 transform.rotate( mRotationDelta );
310 transform.translate( -rotationCenter.x(), -rotationCenter.y() );
311 itemBounds = mapFromScene( transform.map( itemSceneBounds ) );
316 itemBounds = item->mapToItem(
this, itemRect( item ) );
322 path.addPolygon( itemBounds );
323 painter->drawPath( path );
327double QgsGraphicsViewMouseHandles::rectHandlerBorderTolerance()
const
334 double viewScaleFactor = mView->transform().m11();
337 double rectHandlerSize = mHandleSize / viewScaleFactor;
340 if ( rectHandlerSize > ( rect().width() / 3 ) )
342 rectHandlerSize = rect().width() / 3;
344 if ( rectHandlerSize > ( rect().height() / 3 ) )
346 rectHandlerSize = rect().height() / 3;
348 return rectHandlerSize;
351Qt::CursorShape QgsGraphicsViewMouseHandles::cursorForPosition( QPointF itemCoordPos )
354 double normalizedRotation = std::fmod( rotation(), 360 );
355 if ( normalizedRotation < 0 )
357 normalizedRotation += 360;
359 switch ( mouseAction )
362 return Qt::ForbiddenCursor;
364 return Qt::SizeAllCursor;
368 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
370 return Qt::SizeVerCursor;
372 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
374 return Qt::SizeBDiagCursor;
376 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
378 return Qt::SizeHorCursor;
382 return Qt::SizeFDiagCursor;
387 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
389 return Qt::SizeHorCursor;
391 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
393 return Qt::SizeFDiagCursor;
395 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
397 return Qt::SizeVerCursor;
401 return Qt::SizeBDiagCursor;
407 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
409 return Qt::SizeFDiagCursor;
411 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
413 return Qt::SizeVerCursor;
415 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
417 return Qt::SizeBDiagCursor;
421 return Qt::SizeHorCursor;
426 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
428 return Qt::SizeBDiagCursor;
430 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
432 return Qt::SizeHorCursor;
434 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
436 return Qt::SizeFDiagCursor;
440 return Qt::SizeVerCursor;
443 return Qt::ArrowCursor;
449 return Qt::PointingHandCursor;
452 return Qt::ArrowCursor;
457 bool nearLeftBorder =
false;
458 bool nearRightBorder =
false;
459 bool nearLowerBorder =
false;
460 bool nearUpperBorder =
false;
462 bool nearLeftInner =
false;
463 bool nearRightInner =
false;
464 bool nearLowerInner =
false;
465 bool nearUpperInner =
false;
467 bool withinWidth =
false;
468 bool withinHeight =
false;
470 if ( itemCoordPos.x() >= 0 && itemCoordPos.x() <= rect().width() )
474 if ( itemCoordPos.y() >= 0 && itemCoordPos.y() <= rect().height() )
479 double borderTolerance = rectHandlerBorderTolerance();
480 double innerTolerance = mRotationHandleSize * borderTolerance / mHandleSize;
482 if ( isResizeEnabled() && itemCoordPos.x() >= 0 && itemCoordPos.x() < borderTolerance )
484 nearLeftBorder =
true;
486 else if ( isRotationEnabled() && itemCoordPos.x() >= borderTolerance && itemCoordPos.x() < ( borderTolerance + innerTolerance ) )
488 nearLeftInner =
true;
490 if ( isResizeEnabled() && itemCoordPos.y() >= 0 && itemCoordPos.y() < borderTolerance )
492 nearUpperBorder =
true;
494 else if ( isRotationEnabled() && itemCoordPos.y() >= borderTolerance && itemCoordPos.y() < ( borderTolerance + innerTolerance ) )
496 nearUpperInner =
true;
498 if ( isResizeEnabled() && itemCoordPos.x() <= rect().width() && itemCoordPos.x() > ( rect().width() - borderTolerance ) )
500 nearRightBorder =
true;
502 else if ( isRotationEnabled() && itemCoordPos.x() <= ( rect().width() - borderTolerance ) && itemCoordPos.x() > ( rect().width() - borderTolerance - innerTolerance ) )
504 nearRightInner =
true;
506 if ( isResizeEnabled() && itemCoordPos.y() <= rect().height() && itemCoordPos.y() > ( rect().height() - borderTolerance ) )
508 nearLowerBorder =
true;
510 else if ( isRotationEnabled() && itemCoordPos.y() <= ( rect().height() - borderTolerance ) && itemCoordPos.y() > ( rect().height() - borderTolerance - innerTolerance ) )
512 nearLowerInner =
true;
515 if ( nearLeftBorder && nearUpperBorder )
519 else if ( nearLeftBorder && nearLowerBorder )
523 else if ( nearRightBorder && nearUpperBorder )
527 else if ( nearRightBorder && nearLowerBorder )
531 else if ( nearLeftBorder && withinHeight )
535 else if ( nearRightBorder && withinHeight )
539 else if ( nearUpperBorder && withinWidth )
543 else if ( nearLowerBorder && withinWidth )
547 else if ( nearLeftInner && nearUpperInner )
551 else if ( nearRightInner && nearUpperInner )
555 else if ( nearLeftInner && nearLowerInner )
559 else if ( nearRightInner && nearLowerInner )
565 QPointF scenePoint = mapToScene( itemCoordPos );
566 const QList<QGraphicsItem *> itemsAtCursorPos = sceneItemsAtPoint( scenePoint );
567 if ( itemsAtCursorPos.isEmpty() )
572 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
574 if ( graphicsItem && graphicsItem->isSelected() )
588 QPointF itemPos = mapFromScene( sceneCoordPos );
589 return mouseActionForPosition( itemPos );
592bool QgsGraphicsViewMouseHandles::shouldBlockEvent( QInputEvent * )
const
594 return mIsDragging || mIsResizing || mIsRotating;
597void QgsGraphicsViewMouseHandles::startMove( QPointF sceneCoordPos )
600 mMouseMoveStartPos = sceneCoordPos;
602 mBeginMouseEventPos = sceneCoordPos;
603 mBeginHandlePos = scenePos();
604 mBeginHandleWidth = rect().width();
605 mBeginHandleHeight = rect().height();
611 if ( mView->scene()->mouseGrabberItem() !=
this )
617void QgsGraphicsViewMouseHandles::selectedItemSizeChanged()
619 if ( !isDragging() && !isResizing() )
626void QgsGraphicsViewMouseHandles::selectedItemRotationChanged()
628 if ( !isDragging() && !isResizing() )
635void QgsGraphicsViewMouseHandles::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
637 setViewportCursor( cursorForPosition( event->pos() ) );
640void QgsGraphicsViewMouseHandles::hoverLeaveEvent( QGraphicsSceneHoverEvent *event )
643 setViewportCursor( Qt::ArrowCursor );
646void QgsGraphicsViewMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *event )
648 if ( event->button() != Qt::LeftButton )
654 if ( mCadMouseDigitizingMode && ( mIsDragging || mIsResizing || mIsRotating ) )
660 mMouseMoveStartPos =
event->lastScenePos();
662 mBeginMouseEventPos =
event->lastScenePos();
663 mBeginHandlePos = scenePos();
664 mBeginHandleWidth = rect().width();
665 mBeginHandleHeight = rect().height();
667 mCurrentMouseMoveAction = mouseActionForPosition( event->pos() );
671 switch ( mCurrentMouseMoveAction )
688 mResizeRect = QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
691 mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
699 mRotationCenter = sceneTransform().map( rect().center() );
700 mRotationBegin = std::atan2( mMouseMoveStartPos.y() - mRotationCenter.y(), mMouseMoveStartPos.x() - mRotationCenter.x() ) * 180 / M_PI;
701 mRotationCurrent = 0.0;
709 if ( mCadMouseDigitizingMode && mIsDragging )
711 mIsDragStarting =
true;
715void QgsGraphicsViewMouseHandles::resetStatusBar()
717 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
718 int selectedCount = selectedItems.size();
722 showStatusMessage( tr(
"%n item(s) selected",
nullptr, selectedCount ) );
727 showStatusMessage( QString() );
731void QgsGraphicsViewMouseHandles::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
738 dragMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );
740 else if ( isResizing() )
745 resizeMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::AltModifier );
747 else if ( isRotating() )
751 rotateMouseMove( event->lastScenePos(), event->modifiers() & Qt::ControlModifier );
755void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
757 if ( event->button() != Qt::LeftButton )
763 if ( mDoubleClickInProgress )
765 mDoubleClickInProgress =
false;
770 if ( mIsDragStarting )
772 mIsDragStarting =
false;
778 if ( mView->scene()->mouseGrabberItem() ==
this )
783 QPointF mouseMoveStopPoint =
event->lastScenePos();
784 double diffX = mouseMoveStopPoint.x() - mMouseMoveStartPos.x();
785 double diffY = mouseMoveStopPoint.y() - mMouseMoveStartPos.y();
787 const bool isClick = std::fabs( diffX ) < std::numeric_limits<double>::min() && std::fabs( diffY ) < std::numeric_limits<double>::min();
801 startMacroCommand( tr(
"Move Items" ) );
803 QPointF mEndHandleMovePos = scenePos();
805 double deltaX = mEndHandleMovePos.x() - mBeginHandlePos.x();
806 double deltaY = mEndHandleMovePos.y() - mBeginHandlePos.y();
809 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
810 for ( QGraphicsItem *item : selectedItems )
812 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
818 createItemCommand( item );
819 moveItem( item, deltaX, deltaY );
820 endItemCommand( item );
826 else if ( mIsResizing )
829 startMacroCommand( tr(
"Resize Items" ) );
832 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
833 for ( QGraphicsItem *item : selectedItems )
835 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 )
840 createItemCommand( item );
843 if ( selectedItems.size() == 1 )
846 thisItemRect = mResizeRect;
851 thisItemRect = mapRectFromItem( item, itemRect( item ) );
852 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
855 thisItemRect = thisItemRect.normalized();
856 QPointF newPos = mapToScene( thisItemRect.topLeft() );
857 thisItemRect.moveTopLeft( newPos );
858 setItemRect( item, thisItemRect );
860 endItemCommand( item );
866 else if ( mIsRotating )
868 const QPointF itemRotationCenter = sceneTransform().map( rect().center() );
871 startMacroCommand( tr(
"Rotate Items" ) );
874 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
875 for ( QGraphicsItem *item : selectedItems )
877 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
883 const QPointF itemCenter = item->mapToScene( itemRect( item ) ).boundingRect().center();
885 QTransform transform;
886 transform.translate( itemRotationCenter.x(), itemRotationCenter.y() );
887 transform.rotate( mRotationDelta );
888 transform.translate( -itemRotationCenter.x(), -itemRotationCenter.y() );
889 const QPointF rotatedItemCenter = transform.map( itemCenter );
891 createItemCommand( item );
892 rotateItem( item, mRotationDelta, rotatedItemCenter.x() - itemCenter.x(), rotatedItemCenter.y() - itemCenter.y() );
893 endItemCommand( item );
912bool QgsGraphicsViewMouseHandles::selectionRotation(
double &rotation )
const
915 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
916 auto itemIter = selectedItems.constBegin();
919 double firstItemRotation = ( *itemIter )->rotation();
922 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
924 if ( !
qgsDoubleNear( ( *itemIter )->rotation(), firstItemRotation ) )
932 rotation = firstItemRotation;
936void QgsGraphicsViewMouseHandles::updateHandles()
941 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
942 if ( !selectedItems.isEmpty() )
948 if ( selectionRotation( rotation ) )
951 setRotation( rotation );
960 QRectF newHandleBounds = selectionBounds();
963 setRect( 0, 0, newHandleBounds.width(), newHandleBounds.height() );
964 setPos( mapToScene( newHandleBounds.topLeft() ) );
978void QgsGraphicsViewMouseHandles::rotateMouseMove( QPointF currentPosition,
bool snapToCommonAngles )
985 mRotationCurrent = std::atan2( currentPosition.y() - mRotationCenter.y(), currentPosition.x() - mRotationCenter.x() ) * 180 / M_PI;
986 mRotationDelta = mRotationCurrent - mRotationBegin;
987 if ( snapToCommonAngles )
992 const double itemRotationRadian = rotation() * M_PI / 180;
993 const double deltaX = ( rect().width() / 2 ) * cos( itemRotationRadian ) - ( rect().height() / 2 ) * sin( itemRotationRadian );
994 const double deltaY = ( rect().width() / 2 ) * sin( itemRotationRadian ) + ( rect().height() / 2 ) * cos( itemRotationRadian );
996 QTransform rotateTransform;
997 rotateTransform.translate( deltaX, deltaY );
998 rotateTransform.rotate( mRotationDelta );
999 rotateTransform.translate( -deltaX, -deltaY );
1000 setTransform( rotateTransform );
1003 showStatusMessage( tr(
"rotation: %1°" ).arg( QString::number( mRotationDelta,
'f', 2 ) ) );
1008void QgsGraphicsViewMouseHandles::dragMouseMove( QPointF currentPosition,
bool lockMovement,
bool preventSnap )
1016 double moveX = currentPosition.x() - mBeginMouseEventPos.x();
1017 double moveY = currentPosition.y() - mBeginMouseEventPos.y();
1020 QPointF upperLeftPoint( mBeginHandlePos.x() + moveX, mBeginHandlePos.y() + moveY );
1022 QPointF snappedLeftPoint;
1028 snappedLeftPoint = snapPoint( upperLeftPoint, Item );
1033 snappedLeftPoint = upperLeftPoint;
1038 double moveRectX = snappedLeftPoint.x() - mBeginHandlePos.x();
1039 double moveRectY = snappedLeftPoint.y() - mBeginHandlePos.y();
1045 if ( std::fabs( moveRectX ) <= std::fabs( moveRectY ) )
1056 QTransform moveTransform;
1057 moveTransform.translate( moveRectX, moveRectY );
1058 setTransform( moveTransform );
1060 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1061 for ( QGraphicsItem *item : selectedItems )
1063 previewItemMove( item, moveRectX, moveRectY );
1066 showStatusMessage( tr(
"dx: %1 mm dy: %2 mm" ).arg( moveRectX ).arg( moveRectY ) );
1069void QgsGraphicsViewMouseHandles::resizeMouseMove( QPointF currentPosition,
bool lockRatio,
bool fromCenter )
1076 double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
1078 QPointF beginMousePos;
1079 QPointF finalPosition;
1100 beginMousePos = mapFromScene( QPointF( mBeginMouseEventPos.x() - mCursorOffset.width(), mBeginMouseEventPos.y() - mCursorOffset.height() ) );
1101 QPointF snappedPosition = snapPoint( QPointF( currentPosition.x() - mCursorOffset.width(), currentPosition.y() - mCursorOffset.height() ), Point, snapHorizontal, snapVertical );
1102 finalPosition = mapFromScene( snappedPosition );
1107 beginMousePos = mapFromScene( mBeginMouseEventPos );
1108 finalPosition = mapFromScene( currentPosition );
1111 double diffX = finalPosition.x() - beginMousePos.x();
1112 double diffY = finalPosition.y() - beginMousePos.y();
1115 if ( lockRatio && !
qgsDoubleNear( mBeginHandleHeight, 0.0 ) )
1117 ratio = mBeginHandleWidth / mBeginHandleHeight;
1120 switch ( mCurrentMouseMoveAction )
1127 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1147 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1168 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1187 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1208 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1210 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight - diffY ) * ratio );
1214 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth - diffX ) / ratio );
1217 mx = diffX, my = diffY;
1228 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1230 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1234 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1239 rx = diffX, ry = diffY;
1248 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1250 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1254 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth + diffX ) / ratio );
1258 my = diffY, rx = diffX, ry = -diffY;
1267 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1269 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight + diffY ) * ratio );
1273 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1304 mResizeMoveX = mBeginHandleWidth + rx > 0 ? mx : mx + mBeginHandleWidth + rx;
1305 mResizeMoveY = mBeginHandleHeight + ry > 0 ? my : my + mBeginHandleHeight + ry;
1308 QLineF translateLine = QLineF( 0, 0, mResizeMoveX, mResizeMoveY );
1309 translateLine.setAngle( translateLine.angle() - rotation() );
1310 QPointF sceneTranslate = translateLine.p2();
1313 QTransform itemTransform;
1314 itemTransform.translate( sceneTranslate.x(), sceneTranslate.y() );
1315 setTransform( itemTransform );
1318 if ( mBeginHandleWidth + rx >= 0 && mBeginHandleHeight + ry >= 0 )
1320 mResizeRect = QRectF( 0, 0, mBeginHandleWidth + rx, mBeginHandleHeight + ry );
1322 else if ( mBeginHandleHeight + ry >= 0 )
1324 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), 0 ), QPointF( 0, mBeginHandleHeight + ry ) );
1326 else if ( mBeginHandleWidth + rx >= 0 )
1328 mResizeRect = QRectF( QPointF( 0, -( mBeginHandleHeight + ry ) ), QPointF( mBeginHandleWidth + rx, 0 ) );
1332 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), -( mBeginHandleHeight + ry ) ), QPointF( 0, 0 ) );
1335 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1336 QRectF newHandleBounds;
1337 for ( QGraphicsItem *item : selectedItems )
1340 QRectF thisItemRect = mapRectFromScene( storedItemRect( item ) );
1342 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
1344 thisItemRect = mapRectFromScene( previewSetItemRect( item, mapRectToScene( thisItemRect ) ) );
1345 newHandleBounds = newHandleBounds.isValid() ? newHandleBounds.united( thisItemRect ) : thisItemRect;
1348 setRect( newHandleBounds.isValid() ? newHandleBounds : QRectF( 0, 0, std::fabs( mBeginHandleWidth + rx ), std::fabs( mBeginHandleHeight + ry ) ) );
1351 showStatusMessage( tr(
"width: %1 mm height: %2 mm" ).arg( rect().width() ).arg( rect().height() ) );
1354void QgsGraphicsViewMouseHandles::setHandleSize(
double size )
1359void QgsGraphicsViewMouseHandles::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
1363 mDoubleClickInProgress =
true;
1366QSizeF QgsGraphicsViewMouseHandles::calcCursorEdgeOffset( QPointF cursorPos )
1369 QPointF sceneMousePos = mapFromScene( cursorPos );
1371 switch ( mCurrentMouseMoveAction )
1375 return QSizeF( 0, sceneMousePos.y() );
1378 return QSizeF( 0, sceneMousePos.y() - rect().height() );
1382 return QSizeF( sceneMousePos.x(), 0 );
1385 return QSizeF( sceneMousePos.x() - rect().width(), 0 );
1389 return QSizeF( sceneMousePos.x(), sceneMousePos.y() );
1392 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() - rect().height() );
1395 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() );
1398 return QSizeF( sceneMousePos.x(), sceneMousePos.y() - rect().height() );
1413QRectF QgsGraphicsViewMouseHandles::selectionBounds()
const
1416 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1417 auto itemIter = selectedItems.constBegin();
1420 QRectF bounds = mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect();
1423 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
1425 bounds = bounds.united( mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect() );
1431void QgsGraphicsViewMouseHandles::relativeResizeRect( QRectF &rectToResize,
const QRectF &boundsBefore,
const QRectF &boundsAfter )
1434 double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1435 double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1436 double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1437 double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1439 rectToResize.setRect( left, top, right - left, bottom - top );
1442double QgsGraphicsViewMouseHandles::relativePosition(
double position,
double beforeMin,
double beforeMax,
double afterMin,
double afterMax )
1445 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
1446 double c = afterMin - ( beforeMin * m );
1449 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)