18#include "moc_qgsgraphicsviewmousehandles.cpp"
25#include <QGraphicsView>
26#include <QGraphicsSceneHoverEvent>
33QgsGraphicsViewMouseHandles::QgsGraphicsViewMouseHandles( QGraphicsView *view )
35 , QGraphicsRectItem( nullptr )
39 setAcceptHoverEvents(
true );
42 mRotationHandlePath.moveTo( 0, 14 );
43 mRotationHandlePath.lineTo( 6, 20 );
44 mRotationHandlePath.lineTo( 12, 14 );
45 mRotationHandlePath.arcTo( 8, 8, 12, 12, 180, -90 );
46 mRotationHandlePath.lineTo( 14, 12 );
47 mRotationHandlePath.lineTo( 20, 6 );
48 mRotationHandlePath.lineTo( 14, 0 );
49 mRotationHandlePath.arcTo( 4, 4, 20, 20, 90, 90 );
50 mRotationHandlePath.lineTo( 0, 14 );
53void QgsGraphicsViewMouseHandles::setRotationEnabled(
bool enable )
55 if ( mRotationEnabled == enable )
60 mRotationEnabled = enable;
64void QgsGraphicsViewMouseHandles::paintInternal( QPainter *painter,
bool showHandles,
bool showStaticBoundingBoxes,
bool showTemporaryBoundingBoxes,
const QStyleOptionGraphicsItem *, QWidget * )
71 if ( showStaticBoundingBoxes )
74 double rectHandlerSize = rectHandlerBorderTolerance();
75 drawHandles( painter, rectHandlerSize );
78 if ( showTemporaryBoundingBoxes && ( mIsResizing || mIsDragging || showStaticBoundingBoxes ) )
81 drawSelectedItemBounds( painter );
85QRectF QgsGraphicsViewMouseHandles::storedItemRect( QGraphicsItem *item )
const
87 return itemRect( item );
90void QgsGraphicsViewMouseHandles::rotateItem( QGraphicsItem *,
double,
double,
double )
92 QgsDebugError( QStringLiteral(
"Rotation is not implemented for this class" ) );
95void QgsGraphicsViewMouseHandles::previewItemMove( QGraphicsItem *,
double,
double )
99QRectF QgsGraphicsViewMouseHandles::previewSetItemRect( QGraphicsItem *, QRectF )
104void QgsGraphicsViewMouseHandles::startMacroCommand(
const QString & )
108void QgsGraphicsViewMouseHandles::endMacroCommand()
112void QgsGraphicsViewMouseHandles::endItemCommand( QGraphicsItem * )
116void QgsGraphicsViewMouseHandles::createItemCommand( QGraphicsItem * )
120QPointF QgsGraphicsViewMouseHandles::snapPoint( QPointF originalPoint, QgsGraphicsViewMouseHandles::SnapGuideMode,
bool,
bool )
122 return originalPoint;
125void QgsGraphicsViewMouseHandles::expandItemList(
const QList<QGraphicsItem *> &items, QList<QGraphicsItem *> &collected )
const
130void QgsGraphicsViewMouseHandles::drawHandles( QPainter *painter,
double rectHandlerSize )
133 QPen handlePen = QPen( QColor( 55, 140, 195, 255 ) );
134 handlePen.setWidth( 0 );
135 painter->setPen( handlePen );
138 painter->setBrush( Qt::NoBrush );
139 painter->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
142 painter->setBrush( QColor( 255, 255, 255, 255 ) );
144 painter->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
146 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, 0, rectHandlerSize, rectHandlerSize ) );
148 painter->drawRect( QRectF( rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
150 painter->drawRect( QRectF( 0, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
152 painter->drawRect( QRectF( rect().width() - rectHandlerSize, ( rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
154 painter->drawRect( QRectF( 0, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
156 painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
158 painter->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
160 if ( isRotationEnabled() )
163 const double scale = rectHandlerSize / mHandleSize;
164 const bool drawBottomRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().height();
165 const bool drawRightRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().width();
166 QTransform transform;
170 transform.translate( rectHandlerSize, rectHandlerSize );
171 transform.scale( scale, scale );
173 painter->setTransform( transform,
true );
174 painter->drawPath( mRotationHandlePath );
178 if ( drawRightRotationHandles )
181 transform.translate( rect().width() - rectHandlerSize, rectHandlerSize );
182 transform.rotate( 90 );
183 transform.scale( scale, scale );
185 painter->setTransform( transform,
true );
186 painter->drawPath( mRotationHandlePath );
190 if ( drawBottomRotationHandles )
194 transform.translate( rectHandlerSize, rect().height() - rectHandlerSize );
195 transform.rotate( 270 );
196 transform.scale( scale, scale );
198 painter->setTransform( transform,
true );
199 painter->drawPath( mRotationHandlePath );
203 if ( drawBottomRotationHandles && drawRightRotationHandles )
207 transform.translate( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize );
208 transform.rotate( 180 );
209 transform.scale( scale, scale );
211 painter->setTransform( transform,
true );
212 painter->drawPath( mRotationHandlePath );
218void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
221 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
222 if ( selectedItems.isEmpty() )
227 QList<QGraphicsItem *> itemsToDraw;
228 expandItemList( selectedItems, itemsToDraw );
230 if ( itemsToDraw.size() <= 1 )
238 painter->setCompositionMode( QPainter::CompositionMode_Difference );
241 QPen selectedItemPen = QPen( QColor( 144, 144, 144, 255 ) );
242 selectedItemPen.setStyle( Qt::DashLine );
243 selectedItemPen.setWidth( 0 );
244 painter->setPen( selectedItemPen );
245 painter->setBrush( Qt::NoBrush );
247 for ( QGraphicsItem *item : std::as_const( itemsToDraw ) )
250 QPolygonF itemBounds;
251 if ( isDragging() && !itemIsLocked( item ) )
255 QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
258 itemSceneBounds.translate( transform().dx(), transform().dy() );
260 itemBounds = mapFromScene( itemSceneBounds );
262 else if ( isResizing() && !itemIsLocked( item ) )
266 QRectF thisItemRect = mapRectFromItem( item, itemRect( item ) );
268 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
269 itemBounds = QPolygonF( thisItemRect );
271 else if ( isRotating() && !itemIsLocked( item ) )
273 const QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
274 const QPointF rotationCenter = sceneTransform().map( rect().center() );
276 QTransform transform;
277 transform.translate( rotationCenter.x(), rotationCenter.y() );
278 transform.rotate( mRotationDelta );
279 transform.translate( -rotationCenter.x(), -rotationCenter.y() );
280 itemBounds = mapFromScene( transform.map( itemSceneBounds ) );
285 itemBounds = item->mapToItem(
this, itemRect( item ) );
291 path.addPolygon( itemBounds );
292 painter->drawPath( path );
296double QgsGraphicsViewMouseHandles::rectHandlerBorderTolerance()
const
303 double viewScaleFactor = mView->transform().m11();
306 double rectHandlerSize = mHandleSize / viewScaleFactor;
309 if ( rectHandlerSize > ( rect().width() / 3 ) )
311 rectHandlerSize = rect().width() / 3;
313 if ( rectHandlerSize > ( rect().height() / 3 ) )
315 rectHandlerSize = rect().height() / 3;
317 return rectHandlerSize;
320Qt::CursorShape QgsGraphicsViewMouseHandles::cursorForPosition( QPointF itemCoordPos )
323 double normalizedRotation = std::fmod( rotation(), 360 );
324 if ( normalizedRotation < 0 )
326 normalizedRotation += 360;
328 switch ( mouseAction )
331 return Qt::ForbiddenCursor;
333 return Qt::SizeAllCursor;
337 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
339 return Qt::SizeVerCursor;
341 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
343 return Qt::SizeBDiagCursor;
345 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
347 return Qt::SizeHorCursor;
351 return Qt::SizeFDiagCursor;
356 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
358 return Qt::SizeHorCursor;
360 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
362 return Qt::SizeFDiagCursor;
364 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
366 return Qt::SizeVerCursor;
370 return Qt::SizeBDiagCursor;
376 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
378 return Qt::SizeFDiagCursor;
380 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
382 return Qt::SizeVerCursor;
384 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
386 return Qt::SizeBDiagCursor;
390 return Qt::SizeHorCursor;
395 if ( ( normalizedRotation <= 22.5 || normalizedRotation >= 337.5 ) || ( normalizedRotation >= 157.5 && normalizedRotation <= 202.5 ) )
397 return Qt::SizeBDiagCursor;
399 else if ( ( normalizedRotation >= 22.5 && normalizedRotation <= 67.5 ) || ( normalizedRotation >= 202.5 && normalizedRotation <= 247.5 ) )
401 return Qt::SizeHorCursor;
403 else if ( ( normalizedRotation >= 67.5 && normalizedRotation <= 112.5 ) || ( normalizedRotation >= 247.5 && normalizedRotation <= 292.5 ) )
405 return Qt::SizeFDiagCursor;
409 return Qt::SizeVerCursor;
412 return Qt::ArrowCursor;
418 return Qt::PointingHandCursor;
421 return Qt::ArrowCursor;
426 bool nearLeftBorder =
false;
427 bool nearRightBorder =
false;
428 bool nearLowerBorder =
false;
429 bool nearUpperBorder =
false;
431 bool nearLeftInner =
false;
432 bool nearRightInner =
false;
433 bool nearLowerInner =
false;
434 bool nearUpperInner =
false;
436 bool withinWidth =
false;
437 bool withinHeight =
false;
439 if ( itemCoordPos.x() >= 0 && itemCoordPos.x() <= rect().width() )
443 if ( itemCoordPos.y() >= 0 && itemCoordPos.y() <= rect().height() )
448 double borderTolerance = rectHandlerBorderTolerance();
449 double innerTolerance = mRotationHandleSize * borderTolerance / mHandleSize;
451 if ( itemCoordPos.x() >= 0 && itemCoordPos.x() < borderTolerance )
453 nearLeftBorder =
true;
455 else if ( isRotationEnabled() && itemCoordPos.x() >= borderTolerance && itemCoordPos.x() < ( borderTolerance + innerTolerance ) )
457 nearLeftInner =
true;
459 if ( itemCoordPos.y() >= 0 && itemCoordPos.y() < borderTolerance )
461 nearUpperBorder =
true;
463 else if ( isRotationEnabled() && itemCoordPos.y() >= borderTolerance && itemCoordPos.y() < ( borderTolerance + innerTolerance ) )
465 nearUpperInner =
true;
467 if ( itemCoordPos.x() <= rect().width() && itemCoordPos.x() > ( rect().width() - borderTolerance ) )
469 nearRightBorder =
true;
471 else if ( isRotationEnabled() && itemCoordPos.x() <= ( rect().width() - borderTolerance ) && itemCoordPos.x() > ( rect().width() - borderTolerance - innerTolerance ) )
473 nearRightInner =
true;
475 if ( itemCoordPos.y() <= rect().height() && itemCoordPos.y() > ( rect().height() - borderTolerance ) )
477 nearLowerBorder =
true;
479 else if ( isRotationEnabled() && itemCoordPos.y() <= ( rect().height() - borderTolerance ) && itemCoordPos.y() > ( rect().height() - borderTolerance - innerTolerance ) )
481 nearLowerInner =
true;
484 if ( nearLeftBorder && nearUpperBorder )
488 else if ( nearLeftBorder && nearLowerBorder )
492 else if ( nearRightBorder && nearUpperBorder )
496 else if ( nearRightBorder && nearLowerBorder )
500 else if ( nearLeftBorder && withinHeight )
504 else if ( nearRightBorder && withinHeight )
508 else if ( nearUpperBorder && withinWidth )
512 else if ( nearLowerBorder && withinWidth )
516 else if ( nearLeftInner && nearUpperInner )
520 else if ( nearRightInner && nearUpperInner )
524 else if ( nearLeftInner && nearLowerInner )
528 else if ( nearRightInner && nearLowerInner )
534 QPointF scenePoint = mapToScene( itemCoordPos );
535 const QList<QGraphicsItem *> itemsAtCursorPos = sceneItemsAtPoint( scenePoint );
536 if ( itemsAtCursorPos.isEmpty() )
541 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
543 if ( graphicsItem && graphicsItem->isSelected() )
557 QPointF itemPos = mapFromScene( sceneCoordPos );
558 return mouseActionForPosition( itemPos );
561bool QgsGraphicsViewMouseHandles::shouldBlockEvent( QInputEvent * )
const
563 return mIsDragging || mIsResizing;
566void QgsGraphicsViewMouseHandles::startMove( QPointF sceneCoordPos )
569 mMouseMoveStartPos = sceneCoordPos;
571 mBeginMouseEventPos = sceneCoordPos;
572 mBeginHandlePos = scenePos();
573 mBeginHandleWidth = rect().width();
574 mBeginHandleHeight = rect().height();
580 if ( mView->scene()->mouseGrabberItem() !=
this )
586void QgsGraphicsViewMouseHandles::selectedItemSizeChanged()
588 if ( !isDragging() && !isResizing() )
595void QgsGraphicsViewMouseHandles::selectedItemRotationChanged()
597 if ( !isDragging() && !isResizing() )
604void QgsGraphicsViewMouseHandles::hoverMoveEvent( QGraphicsSceneHoverEvent *event )
606 setViewportCursor( cursorForPosition( event->pos() ) );
609void QgsGraphicsViewMouseHandles::hoverLeaveEvent( QGraphicsSceneHoverEvent *event )
612 setViewportCursor( Qt::ArrowCursor );
615void QgsGraphicsViewMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *event )
617 if ( event->button() != Qt::LeftButton )
624 mMouseMoveStartPos =
event->lastScenePos();
626 mBeginMouseEventPos =
event->lastScenePos();
627 mBeginHandlePos = scenePos();
628 mBeginHandleWidth = rect().width();
629 mBeginHandleHeight = rect().height();
631 mCurrentMouseMoveAction = mouseActionForPosition( event->pos() );
635 switch ( mCurrentMouseMoveAction )
652 mResizeRect = QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
655 mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
663 mRotationCenter = sceneTransform().map( rect().center() );
664 mRotationBegin = std::atan2( mMouseMoveStartPos.y() - mRotationCenter.y(), mMouseMoveStartPos.x() - mRotationCenter.x() ) * 180 / M_PI;
665 mRotationCurrent = 0.0;
674void QgsGraphicsViewMouseHandles::resetStatusBar()
676 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
677 int selectedCount = selectedItems.size();
681 showStatusMessage( tr(
"%n item(s) selected",
nullptr, selectedCount ) );
686 showStatusMessage( QString() );
690void QgsGraphicsViewMouseHandles::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
697 dragMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );
699 else if ( isResizing() )
704 resizeMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::AltModifier );
706 else if ( isRotating() )
710 rotateMouseMove( event->lastScenePos(), event->modifiers() & Qt::ControlModifier );
714void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
716 if ( event->button() != Qt::LeftButton )
722 if ( mDoubleClickInProgress )
724 mDoubleClickInProgress =
false;
733 QPointF mouseMoveStopPoint =
event->lastScenePos();
734 double diffX = mouseMoveStopPoint.x() - mMouseMoveStartPos.x();
735 double diffY = mouseMoveStopPoint.y() - mMouseMoveStartPos.y();
738 if ( std::fabs( diffX ) < std::numeric_limits<double>::min() && std::fabs( diffY ) < std::numeric_limits<double>::min() )
751 startMacroCommand( tr(
"Move Items" ) );
753 QPointF mEndHandleMovePos = scenePos();
755 double deltaX = mEndHandleMovePos.x() - mBeginHandlePos.x();
756 double deltaY = mEndHandleMovePos.y() - mBeginHandlePos.y();
759 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
760 for ( QGraphicsItem *item : selectedItems )
762 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
768 createItemCommand( item );
769 moveItem( item, deltaX, deltaY );
770 endItemCommand( item );
776 else if ( mIsResizing )
779 startMacroCommand( tr(
"Resize Items" ) );
782 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
783 for ( QGraphicsItem *item : selectedItems )
785 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 )
790 createItemCommand( item );
793 if ( selectedItems.size() == 1 )
796 thisItemRect = mResizeRect;
801 thisItemRect = mapRectFromItem( item, itemRect( item ) );
802 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
805 thisItemRect = thisItemRect.normalized();
806 QPointF newPos = mapToScene( thisItemRect.topLeft() );
807 thisItemRect.moveTopLeft( newPos );
808 setItemRect( item, thisItemRect );
810 endItemCommand( item );
816 else if ( mIsRotating )
818 const QPointF itemRotationCenter = sceneTransform().map( rect().center() );
821 startMacroCommand( tr(
"Rotate Items" ) );
824 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
825 for ( QGraphicsItem *item : selectedItems )
827 if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
833 const QPointF itemCenter = item->mapToScene( itemRect( item ) ).boundingRect().center();
835 QTransform transform;
836 transform.translate( itemRotationCenter.x(), itemRotationCenter.y() );
837 transform.rotate( mRotationDelta );
838 transform.translate( -itemRotationCenter.x(), -itemRotationCenter.y() );
839 const QPointF rotatedItemCenter = transform.map( itemCenter );
841 createItemCommand( item );
842 rotateItem( item, mRotationDelta, rotatedItemCenter.x() - itemCenter.x(), rotatedItemCenter.y() - itemCenter.y() );
843 endItemCommand( item );
861bool QgsGraphicsViewMouseHandles::selectionRotation(
double &rotation )
const
864 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
865 auto itemIter = selectedItems.constBegin();
868 double firstItemRotation = ( *itemIter )->rotation();
871 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
873 if ( !
qgsDoubleNear( ( *itemIter )->rotation(), firstItemRotation ) )
881 rotation = firstItemRotation;
885void QgsGraphicsViewMouseHandles::updateHandles()
890 QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
891 if ( !selectedItems.isEmpty() )
897 if ( selectionRotation( rotation ) )
900 setRotation( rotation );
909 QRectF newHandleBounds = selectionBounds();
912 setRect( 0, 0, newHandleBounds.width(), newHandleBounds.height() );
913 setPos( mapToScene( newHandleBounds.topLeft() ) );
926void QgsGraphicsViewMouseHandles::rotateMouseMove( QPointF currentPosition,
bool snapToCommonAngles )
933 mRotationCurrent = std::atan2( currentPosition.y() - mRotationCenter.y(), currentPosition.x() - mRotationCenter.x() ) * 180 / M_PI;
934 mRotationDelta = mRotationCurrent - mRotationBegin;
935 if ( snapToCommonAngles )
940 const double itemRotationRadian = rotation() * M_PI / 180;
941 const double deltaX = ( rect().width() / 2 ) * cos( itemRotationRadian ) - ( rect().height() / 2 ) * sin( itemRotationRadian );
942 const double deltaY = ( rect().width() / 2 ) * sin( itemRotationRadian ) + ( rect().height() / 2 ) * cos( itemRotationRadian );
944 QTransform rotateTransform;
945 rotateTransform.translate( deltaX, deltaY );
946 rotateTransform.rotate( mRotationDelta );
947 rotateTransform.translate( -deltaX, -deltaY );
948 setTransform( rotateTransform );
951 showStatusMessage( tr(
"rotation: %1°" ).arg( QString::number( mRotationDelta,
'f', 2 ) ) );
956void QgsGraphicsViewMouseHandles::dragMouseMove( QPointF currentPosition,
bool lockMovement,
bool preventSnap )
964 double moveX = currentPosition.x() - mBeginMouseEventPos.x();
965 double moveY = currentPosition.y() - mBeginMouseEventPos.y();
968 QPointF upperLeftPoint( mBeginHandlePos.x() + moveX, mBeginHandlePos.y() + moveY );
970 QPointF snappedLeftPoint;
976 snappedLeftPoint = snapPoint( upperLeftPoint, Item );
981 snappedLeftPoint = upperLeftPoint;
986 double moveRectX = snappedLeftPoint.x() - mBeginHandlePos.x();
987 double moveRectY = snappedLeftPoint.y() - mBeginHandlePos.y();
993 if ( std::fabs( moveRectX ) <= std::fabs( moveRectY ) )
1004 QTransform moveTransform;
1005 moveTransform.translate( moveRectX, moveRectY );
1006 setTransform( moveTransform );
1008 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1009 for ( QGraphicsItem *item : selectedItems )
1011 previewItemMove( item, moveRectX, moveRectY );
1014 showStatusMessage( tr(
"dx: %1 mm dy: %2 mm" ).arg( moveRectX ).arg( moveRectY ) );
1017void QgsGraphicsViewMouseHandles::resizeMouseMove( QPointF currentPosition,
bool lockRatio,
bool fromCenter )
1024 double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
1026 QPointF beginMousePos;
1027 QPointF finalPosition;
1038 beginMousePos = mapFromScene( QPointF( mBeginMouseEventPos.x() - mCursorOffset.width(), mBeginMouseEventPos.y() - mCursorOffset.height() ) );
1039 QPointF snappedPosition = snapPoint( QPointF( currentPosition.x() - mCursorOffset.width(), currentPosition.y() - mCursorOffset.height() ), Point, snapHorizontal, snapVertical );
1040 finalPosition = mapFromScene( snappedPosition );
1045 beginMousePos = mapFromScene( mBeginMouseEventPos );
1046 finalPosition = mapFromScene( currentPosition );
1049 double diffX = finalPosition.x() - beginMousePos.x();
1050 double diffY = finalPosition.y() - beginMousePos.y();
1053 if ( lockRatio && !
qgsDoubleNear( mBeginHandleHeight, 0.0 ) )
1055 ratio = mBeginHandleWidth / mBeginHandleHeight;
1058 switch ( mCurrentMouseMoveAction )
1065 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1085 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1106 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1125 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1146 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1148 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight - diffY ) * ratio );
1152 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth - diffX ) / ratio );
1155 mx = diffX, my = diffY;
1166 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1168 diffX = ( ( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
1172 diffY = ( ( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1177 rx = diffX, ry = diffY;
1186 if ( ( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1188 diffX = ( ( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1192 diffY = mBeginHandleHeight - ( ( mBeginHandleWidth + diffX ) / ratio );
1196 my = diffY, rx = diffX, ry = -diffY;
1205 if ( ( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1207 diffX = mBeginHandleWidth - ( ( mBeginHandleHeight + diffY ) * ratio );
1211 diffY = ( ( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1242 mResizeMoveX = mBeginHandleWidth + rx > 0 ? mx : mx + mBeginHandleWidth + rx;
1243 mResizeMoveY = mBeginHandleHeight + ry > 0 ? my : my + mBeginHandleHeight + ry;
1246 QLineF translateLine = QLineF( 0, 0, mResizeMoveX, mResizeMoveY );
1247 translateLine.setAngle( translateLine.angle() - rotation() );
1248 QPointF sceneTranslate = translateLine.p2();
1251 QTransform itemTransform;
1252 itemTransform.translate( sceneTranslate.x(), sceneTranslate.y() );
1253 setTransform( itemTransform );
1256 if ( mBeginHandleWidth + rx >= 0 && mBeginHandleHeight + ry >= 0 )
1258 mResizeRect = QRectF( 0, 0, mBeginHandleWidth + rx, mBeginHandleHeight + ry );
1260 else if ( mBeginHandleHeight + ry >= 0 )
1262 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), 0 ), QPointF( 0, mBeginHandleHeight + ry ) );
1264 else if ( mBeginHandleWidth + rx >= 0 )
1266 mResizeRect = QRectF( QPointF( 0, -( mBeginHandleHeight + ry ) ), QPointF( mBeginHandleWidth + rx, 0 ) );
1270 mResizeRect = QRectF( QPointF( -( mBeginHandleWidth + rx ), -( mBeginHandleHeight + ry ) ), QPointF( 0, 0 ) );
1273 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1274 QRectF newHandleBounds;
1275 for ( QGraphicsItem *item : selectedItems )
1278 QRectF thisItemRect = mapRectFromScene( storedItemRect( item ) );
1280 relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
1282 thisItemRect = mapRectFromScene( previewSetItemRect( item, mapRectToScene( thisItemRect ) ) );
1283 newHandleBounds = newHandleBounds.isValid() ? newHandleBounds.united( thisItemRect ) : thisItemRect;
1286 setRect( newHandleBounds.isValid() ? newHandleBounds : QRectF( 0, 0, std::fabs( mBeginHandleWidth + rx ), std::fabs( mBeginHandleHeight + ry ) ) );
1289 showStatusMessage( tr(
"width: %1 mm height: %2 mm" ).arg( rect().width() ).arg( rect().height() ) );
1292void QgsGraphicsViewMouseHandles::setHandleSize(
double size )
1297void QgsGraphicsViewMouseHandles::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
1301 mDoubleClickInProgress =
true;
1304QSizeF QgsGraphicsViewMouseHandles::calcCursorEdgeOffset( QPointF cursorPos )
1307 QPointF sceneMousePos = mapFromScene( cursorPos );
1309 switch ( mCurrentMouseMoveAction )
1313 return QSizeF( 0, sceneMousePos.y() );
1316 return QSizeF( 0, sceneMousePos.y() - rect().height() );
1320 return QSizeF( sceneMousePos.x(), 0 );
1323 return QSizeF( sceneMousePos.x() - rect().width(), 0 );
1327 return QSizeF( sceneMousePos.x(), sceneMousePos.y() );
1330 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() - rect().height() );
1333 return QSizeF( sceneMousePos.x() - rect().width(), sceneMousePos.y() );
1336 return QSizeF( sceneMousePos.x(), sceneMousePos.y() - rect().height() );
1351QRectF QgsGraphicsViewMouseHandles::selectionBounds()
const
1354 const QList<QGraphicsItem *> selectedItems = selectedSceneItems(
false );
1355 auto itemIter = selectedItems.constBegin();
1358 QRectF bounds = mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect();
1361 for ( ++itemIter; itemIter != selectedItems.constEnd(); ++itemIter )
1363 bounds = bounds.united( mapFromItem( ( *itemIter ), itemRect( *itemIter ) ).boundingRect() );
1369void QgsGraphicsViewMouseHandles::relativeResizeRect( QRectF &rectToResize,
const QRectF &boundsBefore,
const QRectF &boundsAfter )
1372 double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1373 double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
1374 double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1375 double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
1377 rectToResize.setRect( left, top, right - left, bottom - top );
1380double QgsGraphicsViewMouseHandles::relativePosition(
double position,
double beforeMin,
double beforeMax,
double afterMin,
double afterMax )
1383 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
1384 double c = afterMin - ( beforeMin * m );
1387 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)