Skip to content
Permalink
Browse files

Hook up snapping for QgsLayoutViewTools

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 Jul 24, 2017
1 parent 5be237f commit f57212eee528ed3af3f8e927e8cb77268bef9099
@@ -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;
@@ -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

};

/************************************************************************
@@ -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.
@@ -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
@@ -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() );
}
@@ -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() );
}
@@ -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() );
}
@@ -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() );
}
@@ -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;
}
@@ -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
@@ -20,6 +20,7 @@
QgsLayoutViewTool::QgsLayoutViewTool( QgsLayoutView *view, const QString &name )
: QObject( view )
, mView( view )
, mFlags( 0 )
, mCursor( Qt::ArrowCursor )
, mToolName( name )
{
@@ -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();
@@ -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.
*/
@@ -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.
@@ -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;

@@ -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 ) );
}
@@ -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
{
@@ -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() );

@@ -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() );

0 comments on commit f57212e

Please sign in to comment.
You can’t perform that action at this time.