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::paintInternal( QPainter *painter,
bool showHandles,
bool showStaticBoundingBoxes,
bool showTemporaryBoundingBoxes,
const QStyleOptionGraphicsItem *, QWidget * )
86 if ( showStaticBoundingBoxes )
89 double rectHandlerSize = rectHandlerBorderTolerance();
90 drawHandles( painter, rectHandlerSize );
93 if ( showTemporaryBoundingBoxes && ( mIsResizing || mIsDragging || showStaticBoundingBoxes ) )
96 drawSelectedItemBounds( painter );
100QRectF QgsGraphicsViewMouseHandles::storedItemRect( QGraphicsItem *item )
const
102 return itemRect( item );
105void QgsGraphicsViewMouseHandles::rotateItem( QGraphicsItem *,
double,
double,
double )
107 QgsDebugError( u
"Rotation is not implemented for this class"_s );
110void QgsGraphicsViewMouseHandles::previewItemMove( QGraphicsItem *,
double,
double )
114QRectF QgsGraphicsViewMouseHandles::previewSetItemRect( QGraphicsItem *, QRectF )
119void QgsGraphicsViewMouseHandles::startMacroCommand(
const QString & )
123void QgsGraphicsViewMouseHandles::endMacroCommand()
127void QgsGraphicsViewMouseHandles::endItemCommand( QGraphicsItem * )
131void QgsGraphicsViewMouseHandles::createItemCommand( QGraphicsItem * )
135QPointF QgsGraphicsViewMouseHandles::snapPoint( QPointF originalPoint, QgsGraphicsViewMouseHandles::SnapGuideMode,
bool,
bool )
137 return originalPoint;
140void QgsGraphicsViewMouseHandles::expandItemList(
const QList<QGraphicsItem *> &items, QList<QGraphicsItem *> &collected )
const
145void QgsGraphicsViewMouseHandles::drawHandles( QPainter *painter,
double rectHandlerSize )
148 QPen handlePen = QPen( QColor( 55, 140, 195, 255 ) );
149 handlePen.setWidth( 0 );
150 painter->setPen( handlePen );
153 painter->setBrush( Qt::NoBrush );
154 painter->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
157 painter->setBrush( QColor( 255, 255, 255, 255 ) );
159 painter->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
161 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, 0, rectHandlerSize, rectHandlerSize ) );
163 painter->drawRect( QRectF( rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
165 painter->drawRect( QRectF( 0, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
167 painter->drawRect( QRectF( rect().width() - rectHandlerSize, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
169 painter->drawRect( QRectF( 0, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
171 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
173 painter->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
175 if ( isRotationEnabled() )
178 const double scale = rectHandlerSize / mHandleSize;
179 const bool drawBottomRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().height();
180 const bool drawRightRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().width();
181 QTransform transform;
185 transform.translate( rectHandlerSize, rectHandlerSize );
186 transform.scale( scale, scale );
188 painter->setTransform( transform,
true );
189 painter->drawPath( mRotationHandlePath );
193 if ( drawRightRotationHandles )
196 transform.translate( rect().width() - rectHandlerSize, rectHandlerSize );
197 transform.rotate( 90 );
198 transform.scale( scale, scale );
200 painter->setTransform( transform,
true );
201 painter->drawPath( mRotationHandlePath );
205 if ( drawBottomRotationHandles )
209 transform.translate( rectHandlerSize, rect().height() - rectHandlerSize );
210 transform.rotate( 270 );
211 transform.scale( scale, scale );
213 painter->setTransform( transform,
true );
214 painter->drawPath( mRotationHandlePath );
218 if ( drawBottomRotationHandles && drawRightRotationHandles )
222 transform.translate( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize );
223 transform.rotate( 180 );
224 transform.scale( scale, scale );
226 painter->setTransform( transform,
true );
227 painter->drawPath( mRotationHandlePath );
233void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
236 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
237 if ( selectedItems.isEmpty() )
242 QList<QGraphicsItem *> itemsToDraw;
243 expandItemList( selectedItems, itemsToDraw );
245 if ( itemsToDraw.size() <= 1 )
253 painter->setCompositionMode( QPainter::CompositionMode_Difference );
256 QPen selectedItemPen = QPen( QColor( 144, 144, 144, 255 ) );
257 selectedItemPen.setStyle( Qt::DashLine );
258 selectedItemPen.setWidth( 0 );
259 painter->setPen( selectedItemPen );
260 painter->setBrush( Qt::NoBrush );
262 for ( QGraphicsItem *item : std::as_const( itemsToDraw ) )
265 QPolygonF itemBounds;
266 if ( isDragging() && !itemIsLocked( item ) )
270 QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
273 itemSceneBounds.translate( transform().dx(), transform().dy() );
275 itemBounds = mapFromScene( itemSceneBounds );
277 else if ( isResizing() && !itemIsLocked( item ) )
281 QRectF thisItemRect = mapRectFromItem( item, itemRect( item ) );
283 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
284 itemBounds = QPolygonF( thisItemRect );
286 else if ( isRotating() && !itemIsLocked( item ) )
288 const QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
289 const QPointF rotationCenter = sceneTransform().map( rect().center() );
291 QTransform transform;
292 transform.translate( rotationCenter.x(), rotationCenter.y() );
293 transform.rotate( mRotationDelta );
294 transform.translate( -rotationCenter.x(), -rotationCenter.y() );
295 itemBounds = mapFromScene( transform.map( itemSceneBounds ) );
300 itemBounds = item->mapToItem(
this, itemRect( item ) );
306 path.addPolygon( itemBounds );
307 painter->drawPath( path );
311double QgsGraphicsViewMouseHandles::rectHandlerBorderTolerance()
const
318 double viewScaleFactor = mView->transform().m11();
321 double rectHandlerSize = mHandleSize / viewScaleFactor;
324 if ( rectHandlerSize > ( rect().width() / 3 ) )
326 rectHandlerSize = rect().width() / 3;
328 if ( rectHandlerSize > ( rect().height() / 3 ) )
330 rectHandlerSize = rect().height() / 3;
332 return rectHandlerSize;
335Qt::CursorShape QgsGraphicsViewMouseHandles::cursorForPosition( QPointF itemCoordPos )
338 double normalizedRotation = std::fmod( rotation(), 360 );
339 if ( normalizedRotation < 0 )
341 normalizedRotation += 360;
343 switch ( mouseAction )
346 return Qt::ForbiddenCursor;
348 return Qt::SizeAllCursor;
352 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
354 return Qt::SizeVerCursor;
356 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
358 return Qt::SizeBDiagCursor;
360 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
362 return Qt::SizeHorCursor;
366 return Qt::SizeFDiagCursor;
371 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
373 return Qt::SizeHorCursor;
375 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
377 return Qt::SizeFDiagCursor;
379 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
381 return Qt::SizeVerCursor;
385 return Qt::SizeBDiagCursor;
391 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
393 return Qt::SizeFDiagCursor;
395 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
397 return Qt::SizeVerCursor;
399 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
401 return Qt::SizeBDiagCursor;
405 return Qt::SizeHorCursor;
410 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
412 return Qt::SizeBDiagCursor;
414 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
416 return Qt::SizeHorCursor;
418 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
420 return Qt::SizeFDiagCursor;
424 return Qt::SizeVerCursor;
427 return Qt::ArrowCursor;
433 return Qt::PointingHandCursor;
436 return Qt::ArrowCursor;
441 bool nearLeftBorder =
false;
442 bool nearRightBorder =
false;
443 bool nearLowerBorder =
false;
444 bool nearUpperBorder =
false;
446 bool nearLeftInner =
false;
447 bool nearRightInner =
false;
448 bool nearLowerInner =
false;
449 bool nearUpperInner =
false;
451 bool withinWidth =
false;
452 bool withinHeight =
false;
454 if ( itemCoordPos.x() >= 0 && itemCoordPos.x() <= rect().width() )
458 if ( itemCoordPos.y() >= 0 && itemCoordPos.y() <= rect().height() )
463 double borderTolerance = rectHandlerBorderTolerance();
464 double innerTolerance = mRotationHandleSize * borderTolerance / mHandleSize;
466 if ( itemCoordPos.x() >= 0 && itemCoordPos.x() < borderTolerance )
468 nearLeftBorder =
true;
470 else if ( isRotationEnabled() && itemCoordPos.x() >= borderTolerance && itemCoordPos.x() < ( borderTolerance + innerTolerance ) )
472 nearLeftInner =
true;
474 if ( itemCoordPos.y() >= 0 && itemCoordPos.y() < borderTolerance )
476 nearUpperBorder =
true;
478 else if ( isRotationEnabled() && itemCoordPos.y() >= borderTolerance && itemCoordPos.y() < ( borderTolerance + innerTolerance ) )
480 nearUpperInner =
true;
482 if ( itemCoordPos.x() <= rect().width() && itemCoordPos.x() > ( rect().width() - borderTolerance ) )
484 nearRightBorder =
true;
486 else if ( isRotationEnabled() && itemCoordPos.x() <= ( rect().width() - borderTolerance ) && itemCoordPos.x() > ( rect().width() - borderTolerance - innerTolerance ) )
488 nearRightInner =
true;
490 if ( itemCoordPos.y() <= rect().height() && itemCoordPos.y() > ( rect().height() - borderTolerance ) )
492 nearLowerBorder =
true;
494 else if ( isRotationEnabled() && itemCoordPos.y() <= ( rect().height() - borderTolerance ) && itemCoordPos.y() > ( rect().height() - borderTolerance - innerTolerance ) )
496 nearLowerInner =
true;
499 if ( nearLeftBorder && nearUpperBorder )
503 else if ( nearLeftBorder && nearLowerBorder )
507 else if ( nearRightBorder && nearUpperBorder )
511 else if ( nearRightBorder && nearLowerBorder )
515 else if ( nearLeftBorder && withinHeight )
519 else if ( nearRightBorder && withinHeight )
523 else if ( nearUpperBorder && withinWidth )
527 else if ( nearLowerBorder && withinWidth )
531 else if ( nearLeftInner && nearUpperInner )
535 else if ( nearRightInner && nearUpperInner )
539 else if ( nearLeftInner && nearLowerInner )
543 else if ( nearRightInner && nearLowerInner )
549 QPointF scenePoint = mapToScene( itemCoordPos );
550 const QList<QGraphicsItem *> itemsAtCursorPos = sceneItemsAtPoint( scenePoint );
551 if ( itemsAtCursorPos.isEmpty() )
556 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
558 if ( graphicsItem && graphicsItem->isSelected() )
572 QPointF itemPos = mapFromScene( sceneCoordPos );
573 return mouseActionForPosition( itemPos );
576bool QgsGraphicsViewMouseHandles::shouldBlockEvent( QInputEvent * )
const
578 return mIsDragging || mIsResizing || mIsRotating;
581void QgsGraphicsViewMouseHandles::startMove( QPointF sceneCoordPos )
584 mMouseMoveStartPos = sceneCoordPos;
586 mBeginMouseEventPos = sceneCoordPos;
587 mBeginHandlePos = scenePos();
588 mBeginHandleWidth = rect().width();
589 mBeginHandleHeight = rect().height();
595 if ( mView->scene()->mouseGrabberItem() !=
this )
601void QgsGraphicsViewMouseHandles::selectedItemSizeChanged()
603 if ( !isDragging() && !isResizing() )
610void QgsGraphicsViewMouseHandles::selectedItemRotationChanged()
612 if ( !isDragging() && !isResizing() )
619void QgsGraphicsViewMouseHandles::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
621 setViewportCursor( cursorForPosition( event->pos() ) );
624void QgsGraphicsViewMouseHandles::hoverLeaveEvent( QGraphicsSceneHoverEvent *event )
627 setViewportCursor( Qt::ArrowCursor );
630void QgsGraphicsViewMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *event )
632 if ( event->button() != Qt::LeftButton )
638 if ( mCadMouseDigitizingMode && ( mIsDragging || mIsResizing || mIsRotating ) )
644 mMouseMoveStartPos =
event->lastScenePos();
646 mBeginMouseEventPos =
event->lastScenePos();
647 mBeginHandlePos = scenePos();
648 mBeginHandleWidth = rect().width();
649 mBeginHandleHeight = rect().height();
651 mCurrentMouseMoveAction = mouseActionForPosition( event->pos() );
655 switch ( mCurrentMouseMoveAction )
672 mResizeRect = QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
675 mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
683 mRotationCenter = sceneTransform().map( rect().center() );
684 mRotationBegin = std::atan2( mMouseMoveStartPos.y() - mRotationCenter.y(), mMouseMoveStartPos.x() - mRotationCenter.x() ) * 180 / M_PI;
685 mRotationCurrent = 0.0;
693 if ( mCadMouseDigitizingMode && mIsDragging )
695 mIsDragStarting =
true;
699void QgsGraphicsViewMouseHandles::resetStatusBar()
701 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
702 int selectedCount = selectedItems.size();
706 showStatusMessage( tr(
"%n item(s) selected",
nullptr, selectedCount ) );
711 showStatusMessage( QString() );
715void QgsGraphicsViewMouseHandles::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
722 dragMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );
724 else if ( isResizing() )
729 resizeMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::AltModifier );
731 else if ( isRotating() )
735 rotateMouseMove( event->lastScenePos(), event->modifiers() & Qt::ControlModifier );
739void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
741 if ( event->button() != Qt::LeftButton )
747 if ( mDoubleClickInProgress )
749 mDoubleClickInProgress =
false;
754 if ( mIsDragStarting )
756 mIsDragStarting =
false;
762 if ( mView->scene()->mouseGrabberItem() ==
this )
767 QPointF mouseMoveStopPoint =
event->lastScenePos();
768 double diffX = mouseMoveStopPoint.x() - mMouseMoveStartPos.x();
769 double diffY = mouseMoveStopPoint.y() - mMouseMoveStartPos.y();
771 const bool isClick = std::fabs( diffX ) < std::numeric_limits<double>::min() && std::fabs( diffY ) < std::numeric_limits<double>::min();
785 startMacroCommand( tr(
"Move Items" ) );
787 QPointF mEndHandleMovePos = scenePos();
789 double deltaX = mEndHandleMovePos.x() - mBeginHandlePos.x();
790 double deltaY = mEndHandleMovePos.y() - mBeginHandlePos.y();
793 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
794 for ( QGraphicsItem *item : selectedItems )
796 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
802 createItemCommand( item );
803 moveItem( item, deltaX, deltaY );
804 endItemCommand( item );
810 else if ( mIsResizing )
813 startMacroCommand( tr(
"Resize Items" ) );
816 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
817 for ( QGraphicsItem *item : selectedItems )
819 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 )
824 createItemCommand( item );
827 if ( selectedItems.size() == 1 )
830 thisItemRect = mResizeRect;
835 thisItemRect = mapRectFromItem( item, itemRect( item ) );
836 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
839 thisItemRect = thisItemRect.normalized();
840 QPointF newPos = mapToScene( thisItemRect.topLeft() );
841 thisItemRect.moveTopLeft( newPos );
842 setItemRect( item, thisItemRect );
844 endItemCommand( item );
850 else if ( mIsRotating )
852 const QPointF itemRotationCenter = sceneTransform().map( rect().center() );
855 startMacroCommand( tr(
"Rotate Items" ) );
858 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
859 for ( QGraphicsItem *item : selectedItems )
861 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
867 const QPointF itemCenter = item->mapToScene( itemRect( item ) ).boundingRect().center();
869 QTransform transform;
870 transform.translate( itemRotationCenter.x(), itemRotationCenter.y() );
871 transform.rotate( mRotationDelta );
872 transform.translate( -itemRotationCenter.x(), -itemRotationCenter.y() );
873 const QPointF rotatedItemCenter = transform.map( itemCenter );
875 createItemCommand( item );
876 rotateItem( item, mRotationDelta, rotatedItemCenter.x() - itemCenter.x(), rotatedItemCenter.y() - itemCenter.y() );
877 endItemCommand( item );
896bool QgsGraphicsViewMouseHandles::selectionRotation(
double &rotation )
const
899 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
900 auto itemIter = selectedItems.constBegin();
903 double firstItemRotation = ( *itemIter )->rotation();
906 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
908 if ( !
qgsDoubleNear( ( *itemIter )->rotation(), firstItemRotation ) )
916 rotation = firstItemRotation;
920void QgsGraphicsViewMouseHandles::updateHandles()
925 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
926 if ( !selectedItems.isEmpty() )
932 if ( selectionRotation( rotation ) )
935 setRotation( rotation );
944 QRectF newHandleBounds = selectionBounds();
947 setRect( 0, 0, newHandleBounds.width(), newHandleBounds.height() );
948 setPos( mapToScene( newHandleBounds.topLeft() ) );
962void QgsGraphicsViewMouseHandles::rotateMouseMove( QPointF currentPosition,
bool snapToCommonAngles )
969 mRotationCurrent = std::atan2( currentPosition.y() - mRotationCenter.y(), currentPosition.x() - mRotationCenter.x() ) * 180 / M_PI;
970 mRotationDelta = mRotationCurrent - mRotationBegin;
971 if ( snapToCommonAngles )
976 const double itemRotationRadian = rotation() * M_PI / 180;
977 const double deltaX = ( rect().width() / 2 ) * cos( itemRotationRadian ) - ( rect().height() / 2 ) * sin( itemRotationRadian );
978 const double deltaY = ( rect().width() / 2 ) * sin( itemRotationRadian ) + ( rect().height() / 2 ) * cos( itemRotationRadian );
980 QTransform rotateTransform;
981 rotateTransform.translate( deltaX, deltaY );
982 rotateTransform.rotate( mRotationDelta );
983 rotateTransform.translate( -deltaX, -deltaY );
984 setTransform( rotateTransform );
987 showStatusMessage( tr(
"rotation: %1°" ).arg( QString::number( mRotationDelta,
'f', 2 ) ) );
992void QgsGraphicsViewMouseHandles::dragMouseMove( QPointF currentPosition,
bool lockMovement,
bool preventSnap )
1000 double moveX = currentPosition.x() - mBeginMouseEventPos.x();
1001 double moveY = currentPosition.y() - mBeginMouseEventPos.y();
1004 QPointF upperLeftPoint( mBeginHandlePos.x() + moveX, mBeginHandlePos.y() + moveY );
1006 QPointF snappedLeftPoint;
1012 snappedLeftPoint = snapPoint( upperLeftPoint, Item );
1017 snappedLeftPoint = upperLeftPoint;
1022 double moveRectX = snappedLeftPoint.x() - mBeginHandlePos.x();
1023 double moveRectY = snappedLeftPoint.y() - mBeginHandlePos.y();
1029 if ( std::fabs( moveRectX ) <= std::fabs( moveRectY ) )
1040 QTransform moveTransform;
1041 moveTransform.translate( moveRectX, moveRectY );
1042 setTransform( moveTransform );
1044 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1045 for ( QGraphicsItem *item : selectedItems )
1047 previewItemMove( item, moveRectX, moveRectY );
1050 showStatusMessage( tr(
"dx: %1 mm dy: %2 mm" ).arg( moveRectX ).arg( moveRectY ) );
1053void QgsGraphicsViewMouseHandles::resizeMouseMove( QPointF currentPosition,
bool lockRatio,
bool fromCenter )
1060 double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
1062 QPointF beginMousePos;
1063 QPointF finalPosition;
1074 beginMousePos = mapFromScene( QPointF( mBeginMouseEventPos.x() - mCursorOffset.width(), mBeginMouseEventPos.y() - mCursorOffset.height() ) );
1075 QPointF snappedPosition = snapPoint( QPointF( currentPosition.x() - mCursorOffset.width(), currentPosition.y() - mCursorOffset.height() ), Point, snapHorizontal, snapVertical );
1076 finalPosition = mapFromScene( snappedPosition );
1081 beginMousePos = mapFromScene( mBeginMouseEventPos );
1082 finalPosition = mapFromScene( currentPosition );
1085 double diffX = finalPosition.x() - beginMousePos.x();
1086 double diffY = finalPosition.y() - beginMousePos.y();
1089 if ( lockRatio && !
qgsDoubleNear( mBeginHandleHeight, 0.0 ) )
1091 ratio = mBeginHandleWidth / mBeginHandleHeight;
1094 switch ( mCurrentMouseMoveAction )
1101 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1121 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1142 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1161 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1182 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1184 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight - diffY ) * ratio );
1188 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth - diffX ) / ratio );
1191 mx = diffX, my = diffY;
1202 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1204 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1208 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1213 rx = diffX, ry = diffY;
1222 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1224 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1228 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth + diffX ) / ratio );
1232 my = diffY, rx = diffX, ry = -diffY;
1241 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1243 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight + diffY ) * ratio );
1247 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1278 mResizeMoveX = mBeginHandleWidth + rx > 0 ? mx : mx + mBeginHandleWidth + rx;
1279 mResizeMoveY = mBeginHandleHeight + ry > 0 ? my : my + mBeginHandleHeight + ry;
1282 QLineF translateLine = QLineF( 0, 0, mResizeMoveX, mResizeMoveY );
1283 translateLine.setAngle( translateLine.angle() - rotation() );
1284 QPointF sceneTranslate = translateLine.p2();
1287 QTransform itemTransform;
1288 itemTransform.translate( sceneTranslate.x(), sceneTranslate.y() );
1289 setTransform( itemTransform );
1292 if ( mBeginHandleWidth + rx >= 0 && mBeginHandleHeight + ry >= 0 )
1294 mResizeRect = QRectF( 0, 0, mBeginHandleWidth + rx, mBeginHandleHeight + ry );
1296 else if ( mBeginHandleHeight + ry >= 0 )
1298 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), 0 ), QPointF( 0, mBeginHandleHeight + ry ) );
1300 else if ( mBeginHandleWidth + rx >= 0 )
1302 mResizeRect = QRectF( QPointF( 0, -( mBeginHandleHeight + ry ) ), QPointF( mBeginHandleWidth + rx, 0 ) );
1306 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), -( mBeginHandleHeight + ry ) ), QPointF( 0, 0 ) );
1309 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1310 QRectF newHandleBounds;
1311 for ( QGraphicsItem *item : selectedItems )
1314 QRectF thisItemRect = mapRectFromScene( storedItemRect( item ) );
1316 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
1318 thisItemRect = mapRectFromScene( previewSetItemRect( item, mapRectToScene( thisItemRect ) ) );
1319 newHandleBounds = newHandleBounds.isValid() ? newHandleBounds.united( thisItemRect ) : thisItemRect;
1322 setRect( newHandleBounds.isValid() ? newHandleBounds : QRectF( 0, 0, std::fabs( mBeginHandleWidth + rx ), std::fabs( mBeginHandleHeight + ry ) ) );
1325 showStatusMessage( tr(
"width: %1 mm height: %2 mm" ).arg( rect().width() ).arg( rect().height() ) );
1328void QgsGraphicsViewMouseHandles::setHandleSize(
double size )
1333void QgsGraphicsViewMouseHandles::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
1337 mDoubleClickInProgress =
true;
1340QSizeF QgsGraphicsViewMouseHandles::calcCursorEdgeOffset( QPointF cursorPos )
1343 QPointF sceneMousePos = mapFromScene( cursorPos );
1345 switch ( mCurrentMouseMoveAction )
1349 return QSizeF( 0, sceneMousePos.y() );
1352 return QSizeF( 0, sceneMousePos.y() - rect().height() );
1356 return QSizeF( sceneMousePos.x(), 0 );
1359 return QSizeF( sceneMousePos.x() - rect().width(), 0 );
1363 return QSizeF( sceneMousePos.x(), sceneMousePos.y() );
1366 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() - rect().height() );
1369 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() );
1372 return QSizeF( sceneMousePos.x(), sceneMousePos.y() - rect().height() );
1387QRectF QgsGraphicsViewMouseHandles::selectionBounds()
const
1390 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1391 auto itemIter = selectedItems.constBegin();
1394 QRectF bounds = mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect();
1397 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
1399 bounds = bounds.united( mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect() );
1405void QgsGraphicsViewMouseHandles::relativeResizeRect( QRectF &rectToResize,
const QRectF &boundsBefore,
const QRectF &boundsAfter )
1408 double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1409 double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1410 double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1411 double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1413 rectToResize.setRect( left, top, right - left, bottom - top );
1416double QgsGraphicsViewMouseHandles::relativePosition(
double position,
double beforeMin,
double beforeMax,
double afterMin,
double afterMax )
1419 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
1420 double c = afterMin - ( beforeMin * m );
1423 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.
Scoped object for saving and restoring a QPainter object's state.
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)