Skip to content

Commit

Permalink
Hook up snapping for QgsLayoutViewTools
Browse files Browse the repository at this point in the history
Tools can now indicate (via setFlags()) if they desire snapping
to be active for the tool. When a tool has the flag set,
any QgsLayoutViewMouseEvents it receives will have a snappedPoint()
available which returns the mouse event point snapped using
the layout's snapping settings.
  • Loading branch information
nyalldawson committed Aug 7, 2017
1 parent 5be237f commit f57212e
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 16 deletions.
20 changes: 18 additions & 2 deletions python/gui/layout/qgslayoutviewmouseevent.sip
Expand Up @@ -32,12 +32,12 @@ class QgsLayoutViewMouseEvent : QMouseEvent
%End
public:

QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event );
QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event, bool snap = false );
%Docstring
Constructor for QgsLayoutViewMouseEvent. Should only be required to be called from the QgsLayoutView.

\param view The view in which the event occurred.
\param event The original mouse event
\param snap set to true to snap the point using the layout's snapping settings
%End

QPointF layoutPoint() const;
Expand All @@ -47,6 +47,22 @@ class QgsLayoutViewMouseEvent : QMouseEvent
:rtype: QPointF
%End

QPointF snappedPoint() const;
%Docstring
Returns the snapped event point location in layout coordinates. The snapped point will consider
all possible snapping methods, such as snapping to grid or guide lines.
.. seealso:: isSnapped()
.. seealso:: pos()
:rtype: QPointF
%End

bool isSnapped() const;
%Docstring
Returns true if point was snapped, e.g. to grid or guide lines.
.. seealso:: snappedPoint()
:rtype: bool
%End

};

/************************************************************************
Expand Down
20 changes: 20 additions & 0 deletions python/gui/layout/qgslayoutviewtool.sip
Expand Up @@ -34,8 +34,22 @@ class QgsLayoutViewTool : QObject
%End
public:

enum Flag
{
FlagSnaps,
};
typedef QFlags<QgsLayoutViewTool::Flag> Flags;


virtual ~QgsLayoutViewTool();

QgsLayoutViewTool::Flags flags() const;
%Docstring
Returns the current combination of flags set for the tool.
.. seealso:: setFlags()
:rtype: QgsLayoutViewTool.Flags
%End

virtual void layoutMoveEvent( QgsLayoutViewMouseEvent *event );
%Docstring
Mouse move event for overriding. Default implementation does nothing.
Expand Down Expand Up @@ -147,6 +161,12 @@ class QgsLayoutViewTool : QObject

protected:

void setFlags( const QgsLayoutViewTool::Flags flags );
%Docstring
Sets the combination of ``flags`` that will be used for the tool.
.. seealso:: flags()
%End

QgsLayoutViewTool( QgsLayoutView *view /TransferThis/, const QString &name );
%Docstring
Constructor for QgsLayoutViewTool, taking a layout ``view`` and
Expand Down
13 changes: 9 additions & 4 deletions src/gui/layout/qgslayoutview.cpp
Expand Up @@ -209,7 +209,7 @@ void QgsLayoutView::mousePressEvent( QMouseEvent *event )
{
if ( mTool )
{
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event ) );
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
mTool->layoutPressEvent( me.get() );
event->setAccepted( me->isAccepted() );
}
Expand Down Expand Up @@ -246,7 +246,7 @@ void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
{
if ( mTool )
{
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event ) );
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
mTool->layoutReleaseEvent( me.get() );
event->setAccepted( me->isAccepted() );
}
Expand All @@ -264,7 +264,12 @@ void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )

if ( mTool )
{
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event ) );
if ( !event->buttons() && mTool->flags() & QgsLayoutViewTool::FlagSnaps )
{
//draw snapping point indicator

}
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
mTool->layoutMoveEvent( me.get() );
event->setAccepted( me->isAccepted() );
}
Expand All @@ -277,7 +282,7 @@ void QgsLayoutView::mouseDoubleClickEvent( QMouseEvent *event )
{
if ( mTool )
{
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event ) );
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
mTool->layoutDoubleClickEvent( me.get() );
event->setAccepted( me->isAccepted() );
}
Expand Down
16 changes: 12 additions & 4 deletions src/gui/layout/qgslayoutviewmouseevent.cpp
Expand Up @@ -16,16 +16,24 @@

#include "qgslayoutviewmouseevent.h"
#include "qgslayoutview.h"
#include "qgslayout.h"


QgsLayoutViewMouseEvent::QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event )
QgsLayoutViewMouseEvent::QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event, bool snap )
: QMouseEvent( event->type(), event->pos(), event->button(), event->buttons(), event->modifiers() )
, mView( view )
{

mLayoutPoint = mView->mapToScene( x(), y() );
if ( snap && mView->currentLayout() )
{
mSnappedPoint = mView->currentLayout()->snapper().snapPoint( mLayoutPoint, mView->transform().m11(), mSnapped );
}
else
{
mSnappedPoint = mLayoutPoint;
}
}

QPointF QgsLayoutViewMouseEvent::layoutPoint() const
{
return mView->mapToScene( x(), y() );
return mLayoutPoint;
}
22 changes: 20 additions & 2 deletions src/gui/layout/qgslayoutviewmouseevent.h
Expand Up @@ -46,23 +46,41 @@ class GUI_EXPORT QgsLayoutViewMouseEvent : public QMouseEvent

/**
* Constructor for QgsLayoutViewMouseEvent. Should only be required to be called from the QgsLayoutView.
*
* \param view The view in which the event occurred.
* \param event The original mouse event
* \param snap set to true to snap the point using the layout's snapping settings
*/
QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event );
QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event, bool snap = false );

/**
* Returns the event point location in layout coordinates.
* \see pos()
*/
QPointF layoutPoint() const;

/**
* Returns the snapped event point location in layout coordinates. The snapped point will consider
* all possible snapping methods, such as snapping to grid or guide lines.
* \see isSnapped()
* \see pos()
*/
QPointF snappedPoint() const { return mSnappedPoint; }

/**
* Returns true if point was snapped, e.g. to grid or guide lines.
* \see snappedPoint()
*/
bool isSnapped() const { return mSnapped; }

private:

//! The view in which the event was triggered.
QgsLayoutView *mView = nullptr;

bool mSnapped = false;
QPointF mLayoutPoint;
QPointF mSnappedPoint;

};

#endif // QGSLAYOUTVIEWMOUSEEVENT_H
11 changes: 11 additions & 0 deletions src/gui/layout/qgslayoutviewtool.cpp
Expand Up @@ -20,6 +20,7 @@
QgsLayoutViewTool::QgsLayoutViewTool( QgsLayoutView *view, const QString &name )
: QObject( view )
, mView( view )
, mFlags( 0 )
, mCursor( Qt::ArrowCursor )
, mToolName( name )
{
Expand Down Expand Up @@ -52,6 +53,16 @@ QgsLayoutViewTool::~QgsLayoutViewTool()
mView->unsetTool( this );
}

QgsLayoutViewTool::Flags QgsLayoutViewTool::flags() const
{
return mFlags;
}

void QgsLayoutViewTool::setFlags( QgsLayoutViewTool::Flags flags )
{
mFlags = flags;
}

void QgsLayoutViewTool::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
{
event->ignore();
Expand Down
21 changes: 21 additions & 0 deletions src/gui/layout/qgslayoutviewtool.h
Expand Up @@ -58,8 +58,21 @@ class GUI_EXPORT QgsLayoutViewTool : public QObject

public:

//! Flags for controlling how a tool behaves
enum Flag
{
FlagSnaps = 1 << 1, //!< Tool utilizes snapped coordinates.
};
Q_DECLARE_FLAGS( Flags, Flag )

virtual ~QgsLayoutViewTool();

/**
* Returns the current combination of flags set for the tool.
* \see setFlags()
*/
QgsLayoutViewTool::Flags flags() const;

/**
* Mouse move event for overriding. Default implementation does nothing.
*/
Expand Down Expand Up @@ -167,6 +180,12 @@ class GUI_EXPORT QgsLayoutViewTool : public QObject

protected:

/**
* Sets the combination of \a flags that will be used for the tool.
* \see flags()
*/
void setFlags( const QgsLayoutViewTool::Flags flags );

/**
* Constructor for QgsLayoutViewTool, taking a layout \a view and
* tool \a name as parameters.
Expand All @@ -186,6 +205,8 @@ class GUI_EXPORT QgsLayoutViewTool : public QObject
//! Pointer to layout view.
QgsLayoutView *mView = nullptr;

QgsLayoutViewTool::Flags mFlags;

//! Cursor used by tool
QCursor mCursor;

Expand Down
9 changes: 5 additions & 4 deletions src/gui/layout/qgslayoutviewtooladditem.cpp
Expand Up @@ -34,6 +34,7 @@
QgsLayoutViewToolAddItem::QgsLayoutViewToolAddItem( QgsLayoutView *view )
: QgsLayoutViewTool( view, tr( "Add item" ) )
{
setFlags( QgsLayoutViewTool::FlagSnaps );
QPixmap crosshairQPixmap = QPixmap( ( const char ** )( cross_hair_cursor ) );
setCursor( QCursor( crosshairQPixmap, 8, 8 ) );
}
Expand All @@ -56,15 +57,15 @@ void QgsLayoutViewToolAddItem::layoutPressEvent( QgsLayoutViewMouseEvent *event
mRubberBand.reset( QgsGui::layoutItemGuiRegistry()->createItemRubberBand( mItemType, view() ) );
if ( mRubberBand )
{
mRubberBand->start( event->layoutPoint(), event->modifiers() );
mRubberBand->start( event->snappedPoint(), event->modifiers() );
}
}

void QgsLayoutViewToolAddItem::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
{
if ( mDrawing && mRubberBand )
{
mRubberBand->update( event->layoutPoint(), event->modifiers() );
mRubberBand->update( event->snappedPoint(), event->modifiers() );
}
else
{
Expand All @@ -81,7 +82,7 @@ void QgsLayoutViewToolAddItem::layoutReleaseEvent( QgsLayoutViewMouseEvent *even
}
mDrawing = false;

QRectF rect = mRubberBand->finish( event->layoutPoint(), event->modifiers() );
QRectF rect = mRubberBand->finish( event->snappedPoint(), event->modifiers() );

QgsLayoutItem *item = QgsApplication::layoutItemRegistry()->createItem( mItemType, layout() );

Expand All @@ -91,7 +92,7 @@ void QgsLayoutViewToolAddItem::layoutReleaseEvent( QgsLayoutViewMouseEvent *even
{
QgsLayoutItemPropertiesDialog dlg( view() );
dlg.setLayout( layout() );
dlg.setItemPosition( QgsLayoutPoint( event->layoutPoint(), layout()->units() ) );
dlg.setItemPosition( QgsLayoutPoint( event->snappedPoint(), layout()->units() ) );
if ( dlg.exec() )
{
item->setReferencePoint( dlg.referencePoint() );
Expand Down

0 comments on commit f57212e

Please sign in to comment.