[FEATURE][layouts] Snapping to item bounds when creating new items

Previously snapping to item bounds would only occur when resizing
or moving items, now it also applies to item creation
This commit is contained in:
Nyall Dawson 2017-10-02 16:55:28 +10:00
parent d950f17e75
commit d8ffab1523
9 changed files with 80 additions and 2 deletions

View File

@ -40,6 +40,14 @@ class QgsLayoutViewMouseEvent : QMouseEvent
\param snap set to true to snap the point using the layout's snapping settings
%End
void snapPoint( QGraphicsLineItem *horizontalSnapLine = 0, QGraphicsLineItem *verticalSnapLine = 0 );
%Docstring
Manually triggers a snap for the mouse event position using the layout's snapper.
If the ``horizontalSnapLine`` and ``verticalSnapLine`` arguments are specified, then the snapper
will automatically display and position these lines to indicate snapping positions to item bounds.
%End
QPointF layoutPoint() const;
%Docstring
Returns the event point location in layout coordinates.

View File

@ -141,6 +141,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
connect( mActionShowGuides, &QAction::triggered, this, &QgsLayoutDesignerDialog::showGuides );
connect( mActionSnapGuides, &QAction::triggered, this, &QgsLayoutDesignerDialog::snapToGuides );
connect( mActionSmartGuides, &QAction::triggered, this, &QgsLayoutDesignerDialog::snapToItems );
connect( mActionShowBoxes, &QAction::triggered, this, &QgsLayoutDesignerDialog::showBoxes );
@ -344,6 +345,7 @@ void QgsLayoutDesignerDialog::setCurrentLayout( QgsLayout *layout )
mActionSnapGrid->setChecked( mLayout->snapper().snapToGrid() );
mActionShowGuides->setChecked( mLayout->guides().visible() );
mActionSnapGuides->setChecked( mLayout->snapper().snapToGuides() );
mActionSmartGuides->setChecked( mLayout->snapper().snapToItems() );
mActionShowBoxes->setChecked( mLayout->context().boundingBoxesVisible() );
connect( mLayout->undoStack()->stack(), &QUndoStack::canUndoChanged, mActionUndo, &QAction::setEnabled );
@ -460,6 +462,11 @@ void QgsLayoutDesignerDialog::snapToGuides( bool enabled )
mLayout->snapper().setSnapToGuides( enabled );
}
void QgsLayoutDesignerDialog::snapToItems( bool enabled )
{
mLayout->snapper().setSnapToItems( enabled );
}
void QgsLayoutDesignerDialog::closeEvent( QCloseEvent * )
{
emit aboutToClose();

View File

@ -141,6 +141,11 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
*/
void snapToGuides( bool enabled );
/**
* Toggles whether snapping to the item guides ("smart" guides) is \a enabled.
*/
void snapToItems( bool enabled );
signals:
/**

View File

@ -408,9 +408,10 @@ Qt::CursorShape QgsLayoutMouseHandles::cursorForPosition( QPointF itemCoordPos )
return Qt::SizeVerCursor;
}
case SelectItem:
// default:
return Qt::ArrowCursor;
}
return Qt::ArrowCursor;
}
QgsLayoutMouseHandles::MouseAction QgsLayoutMouseHandles::mouseActionForPosition( QPointF itemCoordPos )

View File

@ -74,6 +74,13 @@ void QgsLayoutView::setCurrentLayout( QgsLayout *layout )
mSnapMarker->hide();
layout->addItem( mSnapMarker.get() );
mHorizontalSnapLine.reset( createSnapLine() );
mHorizontalSnapLine->hide();
layout->addItem( mHorizontalSnapLine.get() );
mVerticalSnapLine.reset( createSnapLine() );
mVerticalSnapLine->hide();
layout->addItem( mVerticalSnapLine.get() );
if ( mHorizontalRuler )
{
connect( &layout->guides(), &QAbstractItemModel::dataChanged, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
@ -318,7 +325,11 @@ void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )
QPointF cursorPos = mapToScene( mMouseCurrentXY );
if ( mTool )
{
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, false ) );
if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
{
me->snapPoint( mHorizontalSnapLine.get(), mVerticalSnapLine.get() );
}
if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
{
//draw snapping point indicator
@ -494,6 +505,16 @@ void QgsLayoutView::wheelZoom( QWheelEvent *event )
}
}
QGraphicsLineItem *QgsLayoutView::createSnapLine() const
{
std::unique_ptr< QGraphicsLineItem> item( new QGraphicsLineItem( nullptr ) );
QPen pen = QPen( QColor( Qt::blue ) );
pen.setStyle( Qt::DotLine );
pen.setWidthF( 0.0 );
item->setPen( pen );
item->setZValue( QgsLayout::ZSmartGuide );
return item.release();
}
//
// QgsLayoutViewSnapMarker

View File

@ -300,10 +300,14 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
std::unique_ptr< QgsLayoutViewSnapMarker > mSnapMarker;
std::unique_ptr< QGraphicsLineItem > mHorizontalSnapLine;
std::unique_ptr< QGraphicsLineItem > mVerticalSnapLine;
int mCurrentPage = 0;
friend class TestQgsLayoutView;
QGraphicsLineItem *createSnapLine() const;
};

View File

@ -33,6 +33,14 @@ QgsLayoutViewMouseEvent::QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEve
}
}
void QgsLayoutViewMouseEvent::snapPoint( QGraphicsLineItem *horizontalSnapLine, QGraphicsLineItem *verticalSnapLine )
{
if ( mView->currentLayout() )
{
mSnappedPoint = mView->currentLayout()->snapper().snapPoint( mLayoutPoint, mView->transform().m11(), mSnapped, horizontalSnapLine, verticalSnapLine );
}
}
QPointF QgsLayoutViewMouseEvent::layoutPoint() const
{
return mLayoutPoint;

View File

@ -21,6 +21,7 @@
#include "qgis_gui.h"
class QgsLayoutView;
class QGraphicsLineItem;
/**
* \ingroup gui
@ -52,6 +53,14 @@ class GUI_EXPORT QgsLayoutViewMouseEvent : public QMouseEvent
*/
QgsLayoutViewMouseEvent( QgsLayoutView *view, QMouseEvent *event, bool snap = false );
/**
* Manually triggers a snap for the mouse event position using the layout's snapper.
*
* If the \a horizontalSnapLine and \a verticalSnapLine arguments are specified, then the snapper
* will automatically display and position these lines to indicate snapping positions to item bounds.
*/
void snapPoint( QGraphicsLineItem *horizontalSnapLine = nullptr, QGraphicsLineItem *verticalSnapLine = nullptr );
/**
* Returns the event point location in layout coordinates.
* \see pos()

View File

@ -127,6 +127,7 @@
<addaction name="separator"/>
<addaction name="mActionShowGuides"/>
<addaction name="mActionSnapGuides"/>
<addaction name="mActionSmartGuides"/>
<addaction name="mActionManageGuides"/>
<addaction name="mActionClearGuides"/>
<addaction name="separator"/>
@ -451,6 +452,20 @@
<string>Ctrl+Shift+B</string>
</property>
</action>
<action name="mActionSmartGuides">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>S&amp;mart Guides</string>
</property>
<property name="toolTip">
<string>Smart guides</string>
</property>
<property name="shortcut">
<string>Ctrl+Alt+;</string>
</property>
</action>
</widget>
<resources>
<include location="../../../images/images.qrc"/>