Skip to content

Commit 051ed1e

Browse files
committedOct 6, 2017
Prevent snapping to selected items when resizing
1 parent d8ffab1 commit 051ed1e

File tree

7 files changed

+88
-14
lines changed

7 files changed

+88
-14
lines changed
 

‎python/core/layout/qgslayoutsnapper.sip

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ class QgsLayoutSnapper: QgsLayoutSerializableObject
8383
%End
8484

8585
QPointF snapPoint( QPointF point, double scaleFactor, bool &snapped /Out/, QGraphicsLineItem *horizontalSnapLine = 0,
86-
QGraphicsLineItem *verticalSnapLine = 0 ) const;
86+
QGraphicsLineItem *verticalSnapLine = 0,
87+
const QList< QgsLayoutItem * > *ignoreItems = 0 ) const;
8788
%Docstring
8889
Snaps a layout coordinate ``point``. If ``point`` was snapped, ``snapped`` will be set to true.
8990

@@ -95,6 +96,8 @@ class QgsLayoutSnapper: QgsLayoutSerializableObject
9596

9697
If the ``horizontalSnapLine`` and ``verticalSnapLine`` arguments are specified, then the snapper
9798
will automatically display and position these lines to indicate snapping positions to item bounds.
99+
100+
A list of items to ignore during the snapping can be specified via the ``ignoreItems`` list.
98101
:rtype: QPointF
99102
%End
100103

‎src/core/layout/qgslayoutsnapper.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ void QgsLayoutSnapper::setSnapToItems( bool enabled )
4949
mSnapToItems = enabled;
5050
}
5151

52-
QPointF QgsLayoutSnapper::snapPoint( QPointF point, double scaleFactor, bool &snapped, QGraphicsLineItem *horizontalSnapLine, QGraphicsLineItem *verticalSnapLine ) const
52+
QPointF QgsLayoutSnapper::snapPoint( QPointF point, double scaleFactor, bool &snapped, QGraphicsLineItem *horizontalSnapLine, QGraphicsLineItem *verticalSnapLine,
53+
const QList< QgsLayoutItem * > *ignoreItems ) const
5354
{
5455
snapped = false;
5556

@@ -77,7 +78,7 @@ QPointF QgsLayoutSnapper::snapPoint( QPointF point, double scaleFactor, bool &sn
7778
bool snappedYToItems = false;
7879
if ( !snappedXToGuides )
7980
{
80-
newX = snapPointToItems( point.x(), Qt::Horizontal, scaleFactor, QList< QgsLayoutItem * >(), snappedXToItems, verticalSnapLine );
81+
newX = snapPointToItems( point.x(), Qt::Horizontal, scaleFactor, ignoreItems ? *ignoreItems : QList< QgsLayoutItem * >(), snappedXToItems, verticalSnapLine );
8182
if ( snappedXToItems )
8283
{
8384
snapped = true;
@@ -86,7 +87,7 @@ QPointF QgsLayoutSnapper::snapPoint( QPointF point, double scaleFactor, bool &sn
8687
}
8788
if ( !snappedYToGuides )
8889
{
89-
newY = snapPointToItems( point.y(), Qt::Vertical, scaleFactor, QList< QgsLayoutItem * >(), snappedYToItems, horizontalSnapLine );
90+
newY = snapPointToItems( point.y(), Qt::Vertical, scaleFactor, ignoreItems ? *ignoreItems : QList< QgsLayoutItem * >(), snappedYToItems, horizontalSnapLine );
9091
if ( snappedYToItems )
9192
{
9293
snapped = true;

‎src/core/layout/qgslayoutsnapper.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,12 @@ class CORE_EXPORT QgsLayoutSnapper: public QgsLayoutSerializableObject
105105
*
106106
* If the \a horizontalSnapLine and \a verticalSnapLine arguments are specified, then the snapper
107107
* will automatically display and position these lines to indicate snapping positions to item bounds.
108+
*
109+
* A list of items to ignore during the snapping can be specified via the \a ignoreItems list.
108110
*/
109111
QPointF snapPoint( QPointF point, double scaleFactor, bool &snapped SIP_OUT, QGraphicsLineItem *horizontalSnapLine = nullptr,
110-
QGraphicsLineItem *verticalSnapLine = nullptr ) const;
112+
QGraphicsLineItem *verticalSnapLine = nullptr,
113+
const QList< QgsLayoutItem * > *ignoreItems = nullptr ) const;
111114

112115
/**
113116
* Snaps a layout coordinate \a point to the grid. If \a point

‎src/gui/layout/qgslayoutmousehandles.cpp

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgslayoututils.h"
2525
#include "qgslayoutview.h"
2626
#include "qgslayoutviewtoolselect.h"
27+
#include "qgslayoutsnapper.h"
2728
#include <QGraphicsView>
2829
#include <QGraphicsSceneHoverEvent>
2930
#include <QPainter>
@@ -41,6 +42,13 @@ QgsLayoutMouseHandles::QgsLayoutMouseHandles( QgsLayout *layout, QgsLayoutView *
4142

4243
//accept hover events, required for changing cursor to resize cursors
4344
setAcceptHoverEvents( true );
45+
46+
mHorizontalSnapLine.reset( mView->createSnapLine() );
47+
mHorizontalSnapLine->hide();
48+
layout->addItem( mHorizontalSnapLine.get() );
49+
mVerticalSnapLine.reset( mView->createSnapLine() );
50+
mVerticalSnapLine->hide();
51+
layout->addItem( mVerticalSnapLine.get() );
4452
}
4553

4654
void QgsLayoutMouseHandles::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
@@ -697,6 +705,58 @@ void QgsLayoutMouseHandles::resetStatusBar()
697705
}
698706
}
699707

708+
QPointF QgsLayoutMouseHandles::snapPoint( QPointF originalPoint, QgsLayoutMouseHandles::SnapGuideMode mode )
709+
{
710+
//align item
711+
double alignX = 0;
712+
double alignY = 0;
713+
714+
bool snapped = false;
715+
716+
const QList< QgsLayoutItem * > selectedItems = mLayout->selectedLayoutItems();
717+
718+
//depending on the mode, we either snap just the single point, or all the bounds of the selection
719+
QPointF snappedPoint;
720+
switch ( mode )
721+
{
722+
case Item:
723+
//snappedPoint = alignItem( alignX, alignY, point.x(), point.y() );
724+
break;
725+
case Point:
726+
snappedPoint = mLayout->snapper().snapPoint( originalPoint, mView->transform().m11(), snapped, mHorizontalSnapLine.get(), mVerticalSnapLine.get(), &selectedItems );
727+
break;
728+
}
729+
#if 0
730+
if ( !qgsDoubleNear( alignX, -1.0 ) )
731+
{
732+
QGraphicsLineItem *item = hAlignSnapItem();
733+
int numPages = mComposition->numPages();
734+
double yLineCoord = 300; //default in case there is no single page
735+
if ( numPages > 0 )
736+
{
737+
yLineCoord = mComposition->paperHeight() * numPages + mComposition->spaceBetweenPages() * ( numPages - 1 );
738+
}
739+
item->setLine( QLineF( alignX, 0, alignX, yLineCoord ) );
740+
item->show();
741+
}
742+
else
743+
{
744+
deleteHAlignSnapItem();
745+
}
746+
if ( !qgsDoubleNear( alignY, -1.0 ) )
747+
{
748+
QGraphicsLineItem *item = vAlignSnapItem();
749+
item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
750+
item->show();
751+
}
752+
else
753+
{
754+
deleteVAlignSnapItem();
755+
}
756+
#endif
757+
return snappedPoint;
758+
}
759+
700760
void QgsLayoutMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *event )
701761
{
702762
//save current cursor position
@@ -797,9 +857,6 @@ void QgsLayoutMouseHandles::dragMouseMove( QPointF currentPosition, bool lockMov
797857

798858
QPointF snappedLeftPoint;
799859

800-
//TODO
801-
snappedLeftPoint = upperLeftPoint;
802-
#if 0
803860
//no snapping for rotated items for now
804861
if ( !preventSnap && qgsDoubleNear( rotation(), 0.0 ) )
805862
{
@@ -810,9 +867,11 @@ void QgsLayoutMouseHandles::dragMouseMove( QPointF currentPosition, bool lockMov
810867
{
811868
//no snapping
812869
snappedLeftPoint = upperLeftPoint;
870+
#if 0
813871
deleteAlignItems();
814-
}
815872
#endif
873+
}
874+
816875
//calculate total shift for item from beginning of drag operation to current position
817876
double moveRectX = snappedLeftPoint.x() - mBeginHandlePos.x();
818877
double moveRectY = snappedLeftPoint.y() - mBeginHandlePos.y();
@@ -859,11 +918,8 @@ void QgsLayoutMouseHandles::resizeMouseMove( QPointF currentPosition, bool lockR
859918
//subtract cursor edge offset from begin mouse event and current cursor position, so that snapping occurs to edge of mouse handles
860919
//rather then cursor position
861920
beginMousePos = mapFromScene( QPointF( mBeginMouseEventPos.x() - mCursorOffset.width(), mBeginMouseEventPos.y() - mCursorOffset.height() ) );
862-
#if 0
863921
QPointF snappedPosition = snapPoint( QPointF( currentPosition.x() - mCursorOffset.width(), currentPosition.y() - mCursorOffset.height() ), QgsLayoutMouseHandles::Point );
864922
finalPosition = mapFromScene( snappedPosition );
865-
#endif
866-
finalPosition = mapFromScene( currentPosition );
867923
}
868924
else
869925
{

‎src/gui/layout/qgslayoutmousehandles.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <QGraphicsRectItem>
2323
#include <QObject>
2424
#include <QPointer>
25+
#include <memory>
2526

2627
#include "qgis_gui.h"
2728

@@ -157,8 +158,8 @@ class GUI_EXPORT QgsLayoutMouseHandles: public QObject, public QGraphicsRectItem
157158
bool mIsResizing = false;
158159

159160
//! Align snap lines
160-
QGraphicsLineItem *mHAlignSnapItem = nullptr;
161-
QGraphicsLineItem *mVAlignSnapItem = nullptr;
161+
std::unique_ptr< QGraphicsLineItem > mHorizontalSnapLine;
162+
std::unique_ptr< QGraphicsLineItem > mVerticalSnapLine;
162163

163164
QSizeF mCursorOffset;
164165

@@ -199,6 +200,10 @@ class GUI_EXPORT QgsLayoutMouseHandles: public QObject, public QGraphicsRectItem
199200

200201
//resets the composer window status bar to the default message
201202
void resetStatusBar();
203+
204+
//! Snaps an item or point (depending on mode) originating at originalPoint to the grid or align rulers
205+
QPointF snapPoint( QPointF originalPoint, SnapGuideMode mode );
206+
202207
};
203208

204209
///@endcond PRIVATE

‎src/gui/layout/qgslayoutview.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
306306
int mCurrentPage = 0;
307307

308308
friend class TestQgsLayoutView;
309+
friend class QgsLayoutMouseHandles;
309310

310311
QGraphicsLineItem *createSnapLine() const;
311312
};

‎tests/src/python/test_qgslayoutsnapper.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ def testSnapPoint(self):
314314
self.assertTrue(snapped)
315315
self.assertEqual(point, QPointF(0, 1.1))
316316

317+
# ... unless item is ignored!
318+
point, snapped = s.snapPoint(QPointF(1, 1), 1, None, None, [item1])
319+
self.assertTrue(snapped)
320+
self.assertEqual(point, QPointF(0, 0))
321+
317322
def testReadWriteXml(self):
318323
p = QgsProject()
319324
l = QgsLayout(p)

0 commit comments

Comments
 (0)
Please sign in to comment.