Skip to content

Commit

Permalink
[FEATURE][layouts] Snapping to item bounds when creating new items
Browse files Browse the repository at this point in the history
Previously snapping to item bounds would only occur when resizing
or moving items, now it also applies to item creation
  • Loading branch information
nyalldawson committed Oct 6, 2017
1 parent d950f17 commit d8ffab1
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 2 deletions.
8 changes: 8 additions & 0 deletions python/gui/layout/qgslayoutviewmouseevent.sip
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions src/app/layout/qgslayoutdesignerdialog.cpp
Expand Up @@ -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 );

Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions src/app/layout/qgslayoutdesignerdialog.h
Expand Up @@ -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:

/**
Expand Down
3 changes: 2 additions & 1 deletion src/gui/layout/qgslayoutmousehandles.cpp
Expand Up @@ -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 )
Expand Down
23 changes: 22 additions & 1 deletion src/gui/layout/qgslayoutview.cpp
Expand Up @@ -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(); } );
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/gui/layout/qgslayoutview.h
Expand Up @@ -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;
};


Expand Down
8 changes: 8 additions & 0 deletions src/gui/layout/qgslayoutviewmouseevent.cpp
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/gui/layout/qgslayoutviewmouseevent.h
Expand Up @@ -21,6 +21,7 @@
#include "qgis_gui.h"

class QgsLayoutView;
class QGraphicsLineItem;

/**
* \ingroup gui
Expand Down Expand Up @@ -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()
Expand Down
15 changes: 15 additions & 0 deletions src/ui/layout/qgslayoutdesignerbase.ui
Expand Up @@ -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"/>
Expand Down Expand Up @@ -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"/>
Expand Down

0 comments on commit d8ffab1

Please sign in to comment.