17 #include <QGraphicsView> 18 #include <QGraphicsSceneHoverEvent> 36 , mComposition( composition )
37 , mGraphicsView( nullptr )
38 , mCurrentMouseMoveAction( NoAction )
39 , mBeginHandleWidth( 0 )
40 , mBeginHandleHeight( 0 )
43 , mIsDragging( false )
44 , mIsResizing( false )
45 , mHAlignSnapItem( nullptr )
46 , mVAlignSnapItem( nullptr )
74 mGraphicsView = viewList.
at( 0 );
85 Q_UNUSED( itemStyle );
97 double rectHandlerSize = rectHandlerBorderTolerance();
98 drawHandles( painter, rectHandlerSize );
104 drawSelectedItemBounds( painter );
108 void QgsComposerMouseHandles::drawHandles(
QPainter* painter,
double rectHandlerSize )
113 painter->
setPen( handlePen );
122 painter->
drawRect(
QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
124 painter->
drawRect(
QRectF((
rect().width() - rectHandlerSize ) / 2, 0, rectHandlerSize, rectHandlerSize ) );
126 painter->
drawRect(
QRectF(
rect().width() - rectHandlerSize, 0, rectHandlerSize, rectHandlerSize ) );
128 painter->
drawRect(
QRectF( 0, (
rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
130 painter->
drawRect(
QRectF(
rect().width() - rectHandlerSize, (
rect().height() - rectHandlerSize ) / 2, rectHandlerSize, rectHandlerSize ) );
132 painter->
drawRect(
QRectF( 0,
rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
134 painter->
drawRect(
QRectF((
rect().width() - rectHandlerSize ) / 2,
rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
136 painter->
drawRect(
QRectF(
rect().width() - rectHandlerSize,
rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
139 void QgsComposerMouseHandles::drawSelectedItemBounds(
QPainter* painter )
154 selectedItemPen.
setStyle( Qt::DashLine );
156 painter->
setPen( selectedItemPen );
160 for ( ; itemIter != selectedItems.
end(); ++itemIter )
164 if ( mIsDragging && !( *itemIter )->positionLock() )
168 QPolygonF itemSceneBounds = ( *itemIter )->mapToScene(( *itemIter )->rectWithFrame() );
175 else if ( mIsResizing && !( *itemIter )->positionLock() )
178 if ( selectedItems.
size() > 1 )
195 itemBounds =
mapRectFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() );
207 for ( ; itemIt != itemList.
end(); ++itemIt )
235 if ( !mIsDragging && !mIsResizing )
244 if ( !mIsDragging && !mIsResizing )
251 void QgsComposerMouseHandles::updateHandles()
257 if ( !selectedItems.
isEmpty() )
263 if ( selectionRotation( rotation ) )
275 QRectF newHandleBounds = selectionBounds();
292 QRectF QgsComposerMouseHandles::selectionBounds()
const 302 for ( ++itemIter; itemIter != selectedItems.
end(); ++itemIter )
310 bool QgsComposerMouseHandles::selectionRotation(
double &
rotation )
const 317 double firstItemRotation = ( *itemIter )->itemRotation();
320 for ( ++itemIter; itemIter != selectedItems.
end(); ++itemIter )
322 if ( !
qgsDoubleNear(( *itemIter )->itemRotation(), firstItemRotation ) )
330 rotation = firstItemRotation;
334 double QgsComposerMouseHandles::rectHandlerBorderTolerance()
338 double viewScaleFactor = graphicsView()->
transform().
m11();
341 double rectHandlerSize = 10.0 / viewScaleFactor;
344 if ( rectHandlerSize > (
rect().width() / 3 ) )
348 if ( rectHandlerSize > (
rect().height() / 3 ) )
352 return rectHandlerSize;
355 Qt::CursorShape QgsComposerMouseHandles::cursorForPosition(
QPointF itemCoordPos )
358 switch ( mouseAction )
361 return Qt::ForbiddenCursor;
363 return Qt::SizeAllCursor;
369 return Qt::SizeVerCursor;
373 return Qt::SizeBDiagCursor;
377 return Qt::SizeHorCursor;
381 return Qt::SizeFDiagCursor;
388 return Qt::SizeHorCursor;
392 return Qt::SizeFDiagCursor;
396 return Qt::SizeVerCursor;
400 return Qt::SizeBDiagCursor;
408 return Qt::SizeFDiagCursor;
412 return Qt::SizeVerCursor;
416 return Qt::SizeBDiagCursor;
420 return Qt::SizeHorCursor;
427 return Qt::SizeBDiagCursor;
431 return Qt::SizeHorCursor;
435 return Qt::SizeFDiagCursor;
439 return Qt::SizeVerCursor;
443 return Qt::ArrowCursor;
449 bool nearLeftBorder =
false;
450 bool nearRightBorder =
false;
451 bool nearLowerBorder =
false;
452 bool nearUpperBorder =
false;
454 bool withinWidth =
false;
455 bool withinHeight =
false;
456 if ( itemCoordPos.
x() >= 0 && itemCoordPos.
x() <=
rect().
width() )
460 if ( itemCoordPos.
y() >= 0 && itemCoordPos.
y() <=
rect().
height() )
465 double borderTolerance = rectHandlerBorderTolerance();
467 if ( itemCoordPos.
x() >= 0 && itemCoordPos.
x() < borderTolerance )
469 nearLeftBorder =
true;
471 if ( itemCoordPos.
y() >= 0 && itemCoordPos.
y() < borderTolerance )
473 nearUpperBorder =
true;
475 if ( itemCoordPos.
x() <=
rect().
width() && itemCoordPos.
x() > (
rect().
width() - borderTolerance ) )
477 nearRightBorder =
true;
481 nearLowerBorder =
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 )
520 if ( itemsAtCursorPos.
isEmpty() )
526 for ( ; itemIter != itemsAtCursorPos.
end(); ++itemIter )
544 return mouseActionForPosition( itemPos );
549 setViewportCursor( cursorForPosition( event->
pos() ) );
555 setViewportCursor( Qt::ArrowCursor );
558 void QgsComposerMouseHandles::setViewportCursor( Qt::CursorShape
cursor )
576 dragMouseMove( event->
lastScenePos(),
event->modifiers() & Qt::ShiftModifier,
event->modifiers() & Qt::ControlModifier );
578 else if ( mIsResizing )
583 resizeMouseMove( event->
lastScenePos(),
event->modifiers() & Qt::ShiftModifier,
event->modifiers() & Qt::AltModifier );
586 mLastMouseEventPos =
event->lastScenePos();
591 QPointF mouseMoveStopPoint =
event->lastScenePos();
592 double diffX = mouseMoveStopPoint.
x() - mMouseMoveStartPos.
x();
593 double diffY = mouseMoveStopPoint.
y() - mMouseMoveStartPos.
y();
614 for ( ; itemIter != selectedItems.
end(); ++itemIter )
616 if (( *itemIter )->positionLock() || (( *itemIter )->flags() & QGraphicsItem::ItemIsSelectable ) == 0 )
623 ( *itemIter )->move( mEndHandleMovePos.
x() - mBeginHandlePos.
x(), mEndHandleMovePos.
y() - mBeginHandlePos.
y() );
637 for ( ; itemIter != selectedItems.
end(); ++itemIter )
639 if (( *itemIter )->positionLock() || (( *itemIter )->flags() & QGraphicsItem::ItemIsSelectable ) == 0 )
648 if ( selectedItems.
size() == 1 )
651 itemRect = mResizeRect;
656 itemRect =
mapRectFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() );
683 setViewportCursor( Qt::ArrowCursor );
691 void QgsComposerMouseHandles::resetStatusBar()
694 int selectedCount = selectedItems.
size();
695 if ( selectedCount > 1 )
700 else if ( selectedCount == 1 )
715 mMouseMoveStartPos =
event->lastScenePos();
716 mLastMouseEventPos =
event->lastScenePos();
718 mBeginMouseEventPos =
event->lastScenePos();
723 mCurrentMouseMoveAction = mouseActionForPosition( event->
pos() );
737 mResizeRect =
QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
740 mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
751 QSizeF QgsComposerMouseHandles::calcCursorEdgeOffset(
QPointF cursorPos )
756 switch ( mCurrentMouseMoveAction )
760 return QSizeF( 0, sceneMousePos.
y() );
767 return QSizeF( sceneMousePos.
x(), 0 );
774 return QSizeF( sceneMousePos.
x(), sceneMousePos.
y() );
791 void QgsComposerMouseHandles::dragMouseMove(
QPointF currentPosition,
bool lockMovement,
bool preventSnap )
799 double moveX = currentPosition.
x() - mBeginMouseEventPos.
x();
800 double moveY = currentPosition.
y() - mBeginMouseEventPos.
y();
803 QPointF upperLeftPoint( mBeginHandlePos.
x() + moveX, mBeginHandlePos.
y() + moveY );
815 snappedLeftPoint = upperLeftPoint;
820 double moveRectX = snappedLeftPoint.x() - mBeginHandlePos.
x();
821 double moveRectY = snappedLeftPoint.y() - mBeginHandlePos.
y();
827 if ( qAbs( moveRectX ) <= qAbs( moveRectY ) )
839 moveTransform.
translate( moveRectX, moveRectY );
845 void QgsComposerMouseHandles::resizeMouseMove(
QPointF currentPosition,
bool lockRatio,
bool fromCenter )
853 double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
874 double diffX = finalPosition.
x() - beginMousePos.
x();
875 double diffY = finalPosition.
y() - beginMousePos.
y();
878 if ( lockRatio && !
qgsDoubleNear( mBeginHandleHeight, 0.0 ) )
880 ratio = mBeginHandleWidth / mBeginHandleHeight;
883 switch ( mCurrentMouseMoveAction )
890 diffX = (( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
910 diffX = (( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
931 diffY = (( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
950 diffY = (( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
971 if (( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
973 diffX = mBeginHandleWidth - (( mBeginHandleHeight - diffY ) * ratio );
977 diffY = mBeginHandleHeight - (( mBeginHandleWidth - diffX ) / ratio );
980 mx = diffX, my = diffY;
991 if (( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
993 diffX = (( mBeginHandleHeight + diffY ) * ratio ) - mBeginHandleWidth;
997 diffY = (( mBeginHandleWidth + diffX ) / ratio ) - mBeginHandleHeight;
1002 rx = diffX, ry = diffY;
1011 if (( mBeginHandleWidth + diffX ) / ( mBeginHandleHeight - diffY ) > ratio )
1013 diffX = (( mBeginHandleHeight - diffY ) * ratio ) - mBeginHandleWidth;
1017 diffY = mBeginHandleHeight - (( mBeginHandleWidth + diffX ) / ratio );
1021 my = diffY, rx = diffX, ry = -diffY;
1030 if (( mBeginHandleWidth - diffX ) / ( mBeginHandleHeight + diffY ) > ratio )
1032 diffX = mBeginHandleWidth - (( mBeginHandleHeight + diffY ) * ratio );
1036 diffY = (( mBeginHandleWidth - diffX ) / ratio ) - mBeginHandleHeight;
1063 mResizeMoveX = mBeginHandleWidth + rx > 0 ? mx : mx + mBeginHandleWidth + rx;
1064 mResizeMoveY = mBeginHandleHeight + ry > 0 ? my : my + mBeginHandleHeight + ry;
1067 QLineF translateLine =
QLineF( 0, 0, mResizeMoveX, mResizeMoveY );
1069 QPointF sceneTranslate = translateLine.
p2();
1073 itemTransform.
translate( sceneTranslate.
x(), sceneTranslate.
y() );
1077 if ( mBeginHandleWidth + rx >= 0 && mBeginHandleHeight + ry >= 0 )
1079 mResizeRect =
QRectF( 0, 0, mBeginHandleWidth + rx, mBeginHandleHeight + ry );
1081 else if ( mBeginHandleHeight + ry >= 0 )
1083 mResizeRect =
QRectF(
QPointF( -( mBeginHandleWidth + rx ), 0 ),
QPointF( 0, mBeginHandleHeight + ry ) );
1085 else if ( mBeginHandleWidth + rx >= 0 )
1087 mResizeRect =
QRectF(
QPointF( 0, -( mBeginHandleHeight + ry ) ),
QPointF( mBeginHandleWidth + rx, 0 ) );
1091 mResizeRect =
QRectF(
QPointF( -( mBeginHandleWidth + rx ), -( mBeginHandleHeight + ry ) ),
QPointF( 0, 0 ) );
1094 setRect( 0, 0, fabs( mBeginHandleWidth + rx ), fabs( mBeginHandleHeight + ry ) );
1105 if ( snappedPoint != point )
1108 return snappedPoint;
1124 snappedPoint = alignItem( alignX, alignY, point.
x(), point.
y() );
1127 snappedPoint = alignPos( point, alignX, alignY );
1134 int numPages = mComposition->
numPages();
1135 double yLineCoord = 300;
1145 deleteHAlignSnapItem();
1155 deleteVAlignSnapItem();
1157 return snappedPoint;
1162 if ( !mHAlignSnapItem )
1169 return mHAlignSnapItem;
1174 if ( !mVAlignSnapItem )
1181 return mVAlignSnapItem;
1184 void QgsComposerMouseHandles::deleteHAlignSnapItem()
1186 if ( mHAlignSnapItem )
1189 delete mHAlignSnapItem;
1190 mHAlignSnapItem =
nullptr;
1194 void QgsComposerMouseHandles::deleteVAlignSnapItem()
1196 if ( mVAlignSnapItem )
1199 delete mVAlignSnapItem;
1200 mVAlignSnapItem =
nullptr;
1204 void QgsComposerMouseHandles::deleteAlignItems()
1206 deleteHAlignSnapItem();
1207 deleteVAlignSnapItem();
1210 QPointF QgsComposerMouseHandles::alignItem(
double& alignX,
double& alignY,
double unalignedX,
double unalignedY )
1212 double left = unalignedX;
1214 double midH = ( left + right ) / 2.0;
1215 double top = unalignedY;
1217 double midV = ( top + bottom ) / 2.0;
1221 collectAlignCoordinates( xAlignCoordinates, yAlignCoordinates );
1224 double xItemLeft = left;
1225 double xAlignCoord = 0;
1226 double smallestDiffX = DBL_MAX;
1228 checkNearestItem( left, xAlignCoordinates, smallestDiffX, 0, xItemLeft, xAlignCoord );
1229 checkNearestItem( midH, xAlignCoordinates, smallestDiffX, ( left - right ) / 2.0, xItemLeft, xAlignCoord );
1230 checkNearestItem( right, xAlignCoordinates, smallestDiffX, left - right, xItemLeft, xAlignCoord );
1233 double yItemTop = top;
1234 double yAlignCoord = 0;
1235 double smallestDiffY = DBL_MAX;
1237 checkNearestItem( top, yAlignCoordinates, smallestDiffY, 0, yItemTop, yAlignCoord );
1238 checkNearestItem( midV, yAlignCoordinates, smallestDiffY, ( top - bottom ) / 2.0, yItemTop, yAlignCoord );
1239 checkNearestItem( bottom, yAlignCoordinates, smallestDiffY, top - bottom, yItemTop, yAlignCoord );
1241 double xCoord = ( smallestDiffX < 5 ) ? xItemLeft : unalignedX;
1242 alignX = ( smallestDiffX < 5 ) ? xAlignCoord : -1;
1243 double yCoord = ( smallestDiffY < 5 ) ? yItemTop : unalignedY;
1244 alignY = ( smallestDiffY < 5 ) ? yAlignCoord : -1;
1245 return QPointF( xCoord, yCoord );
1248 QPointF QgsComposerMouseHandles::alignPos(
QPointF pos,
double& alignX,
double& alignY )
1252 collectAlignCoordinates( xAlignCoordinates, yAlignCoordinates );
1254 double nearestX = pos.
x();
1255 double nearestY = pos.
y();
1256 if ( !nearestItem( xAlignCoordinates, pos.
x(), nearestX )
1257 || !nearestItem( yAlignCoordinates, pos.
y(), nearestY ) )
1265 double viewScaleFactor = graphicsView()->
transform().
m11();
1266 double alignThreshold = mComposition->
snapTolerance() / viewScaleFactor;
1269 if ( fabs( nearestX - pos.
x() ) < alignThreshold )
1271 result.
setX( nearestX );
1279 if ( fabs( nearestY - pos.
y() ) < alignThreshold )
1281 result.setY( nearestY );
1293 alignCoordsX.
clear();
1294 alignCoordsY.
clear();
1300 for ( ; itemIt != itemList.
end(); ++itemIt )
1311 if ( dynamic_cast<const QgsPaperItem *>( *itemIt ) )
1321 alignCoordsX.
insert( itemRect.
left(), currentItem );
1322 alignCoordsX.
insert( itemRect.
right(), currentItem );
1324 alignCoordsY.
insert( itemRect.
top(), currentItem );
1336 double x = ( *sIt )->line().x1();
1337 double y = ( *sIt )->line().y1();
1340 alignCoordsX.
insert( x,
nullptr );
1344 alignCoordsY.
insert( y,
nullptr );
1350 void QgsComposerMouseHandles::checkNearestItem(
double checkCoord,
const QMap< double, const QgsComposerItem* >& alignCoords,
double& smallestDiff,
double itemCoordOffset,
double& itemCoord,
double& alignCoord )
1352 double currentCoord = 0;
1353 if ( !nearestItem( alignCoords, checkCoord, currentCoord ) )
1358 double currentDiff = fabs( checkCoord - currentCoord );
1360 double viewScaleFactor = graphicsView()->
transform().
m11();
1361 double alignThreshold = mComposition->
snapTolerance() / viewScaleFactor;
1363 if ( currentDiff < alignThreshold && currentDiff < smallestDiff )
1365 itemCoord = currentCoord + itemCoordOffset;
1366 alignCoord = currentCoord;
1367 smallestDiff = currentDiff;
1373 if ( coords.
size() < 1 )
1381 nearestValue = it.
key();
1384 else if ( it == coords.
constEnd() )
1387 nearestValue = it.
key();
1393 double upperVal = it.
key();
1395 double lowerVal = it.
key();
1397 double lowerDiff = value - lowerVal;
1398 double upperDiff = upperVal - value;
1399 if ( lowerDiff < upperDiff )
1401 nearestValue = lowerVal;
1406 nearestValue = upperVal;
QgsComposerMouseHandles::MouseAction mouseActionForScenePos(QPointF sceneCoordPos)
Finds out which mouse move action to choose depending on the scene cursor position.
QRectF mapRectFromItem(const QGraphicsItem *item, const QRectF &rect) const
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
QUndoStack * undoStack()
Returns pointer to undo/redo command storage.
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override
double paperWidth() const
Width of paper item.
void setStyle(Qt::PenStyle style)
bool boundingBoxesVisible() const
Returns whether selection bounding boxes should be shown in the composition.
void setCompositionMode(CompositionMode mode)
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
void selectedItemRotationChanged()
Redraws handles when selected item rotation changes.
QPointF snapPointToGrid(QPointF scenePoint) const
Snaps a scene coordinate point to grid.
virtual bool selected() const
Is selected.
QList< QGraphicsItem * > items() const
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
void setAcceptHoverEvents(bool enabled)
const_iterator constBegin() const
bool smartGuidesEnabled() const
const T & at(int i) const
A item that forms part of a map composition.
bool preventCursorChange() const
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
void savePreviousState()
Saves current item state as previous state.
MouseAction
Describes the action (move or resize in different directon) to be done during mouse move...
void selectedItemSizeChanged()
Redraws handles when selected item size changes.
QRectF mapRectToScene(const QRectF &rect) const
virtual ~QgsComposerMouseHandles()
QGraphicsScene * scene() const
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
double spaceBetweenPages() const
Returns the vertical space between pages in a composer view.
bool alignmentSnap() const
void setStatusMessage(const QString &message)
Sets the status bar message for the composer window.
QString tr(const char *sourceText, const char *disambiguation, int n)
int numPages() const
Returns the number of pages in the composition.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
void update(const QRectF &rect)
void setRect(const QRectF &rectangle)
virtual bool event(QEvent *e)
void drawRect(const QRectF &rectangle)
virtual QRectF boundingRect() const
void removeItem(QGraphicsItem *item)
void setPen(const QColor &color)
void setPos(const QPointF &pos)
QList< QGraphicsView * > views() const
QRectF normalized() const
void setAngle(qreal angle)
const_iterator constEnd() const
void setLine(const QLineF &line)
QPointF mapFromScene(const QPointF &point) const
void translate(qreal dx, qreal dy)
void setBrush(const QBrush &brush)
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
QRectF united(const QRectF &rectangle) const
iterator lowerBound(const Key &key)
void selectionChanged()
Sets up listeners to sizeChanged signal for all selected items.
Graphics scene for map printing.
void setPen(const QPen &pen)
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override
virtual QRectF rectWithFrame() const
Returns the item's rectangular bounds, including any bleed caused by the item's frame.
void saveAfterState()
Saves current item state as after state.
QPointF mapToScene(const QPointF &point) const
QgsComposition * composition()
QPointF mapFromItem(const QGraphicsItem *item, const QPointF &point) const
Undo command to undo/redo all composer item related changes.
int snapTolerance() const
Returns the snap tolerance to use when automatically snapping items during movement and resizing to g...
static QgsProject * instance()
access to canonical QgsProject instance
double paperHeight() const
Height of paper item.
void setRotation(qreal angle)
iterator insert(const Key &key, const T &value)
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
const_iterator constEnd() const
const_iterator constBegin() const
QgsComposerMouseHandles(QgsComposition *composition)
void addItem(QGraphicsItem *item)
QgsComposition::PlotStyle plotStyle() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
bool isGroupMember() const
Returns whether this item is part of a group.
void push(QUndoCommand *cmd)
QPointF lastScenePos() const
QList< QgsComposerItem * > selectedComposerItems(const bool includeLockedItems=true)
Returns list of selected composer items.
QList< QGraphicsLineItem * > * snapLines()
Returns pointer to snap lines collection.