Skip to content

Commit

Permalink
[FEATURE][processing] Add option to enable automatic snapping to grid
Browse files Browse the repository at this point in the history
while designer models

If enabled, model component moving or resizing will be automatically
snapped to a grid
  • Loading branch information
nyalldawson committed Mar 23, 2020
1 parent 78d445e commit 4bad254
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 11 deletions.
11 changes: 10 additions & 1 deletion src/gui/processing/models/qgsmodeldesignerdialog.cpp
Expand Up @@ -118,6 +118,7 @@ QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags
mainLayout->insertWidget( 0, mMessageBar );

mView->setAcceptDrops( true );
QgsSettings settings;

connect( mActionClose, &QAction::triggered, this, &QWidget::close );
connect( mActionZoomIn, &QAction::triggered, this, &QgsModelDesignerDialog::zoomIn );
Expand All @@ -132,6 +133,14 @@ QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags
connect( mActionSaveAs, &QAction::triggered, this, [ = ] { saveModel( true ); } );
connect( mActionDeleteComponents, &QAction::triggered, this, &QgsModelDesignerDialog::deleteSelected );

mActionSnappingEnabled->setChecked( settings.value( QStringLiteral( "/Processing/modelDesignerEnableSnap" ), true ).toBool() );
connect( mActionSnappingEnabled, &QAction::toggled, this, [ = ]( bool enabled )
{
mView->snapper()->setSnapToGrid( enabled );
QgsSettings().setValue( QStringLiteral( "/Processing/modelDesignerEnableSnap" ), enabled );
} );
mView->snapper()->setSnapToGrid( mActionSnappingEnabled->isChecked() );

mUndoAction = mUndoStack->createUndoAction( this );
mUndoAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ) );
mUndoAction->setShortcuts( QKeySequence::Undo );
Expand All @@ -146,7 +155,7 @@ QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags
mToolbar->insertAction( mActionZoomIn, mRedoAction );
mToolbar->insertSeparator( mActionZoomIn );

QgsSettings settings;

QgsProcessingToolboxProxyModel::Filters filters = QgsProcessingToolboxProxyModel::FilterModeler;
if ( settings.value( QStringLiteral( "Processing/Configuration/SHOW_ALGORITHMS_KNOWN_ISSUES" ), false ).toBool() )
{
Expand Down
16 changes: 8 additions & 8 deletions src/gui/processing/models/qgsmodelsnapper.cpp
Expand Up @@ -21,7 +21,7 @@
QgsModelSnapper::QgsModelSnapper()
{
QgsSettings s;
mTolerance = s.value( QStringLiteral( "LayoutDesigner/defaultSnapTolerancePixels" ), 5, QgsSettings::Gui ).toInt();
mTolerance = s.value( QStringLiteral( "/Processing/modelDesignerSnapTolerancePixels" ), 20 ).toInt();
}

void QgsModelSnapper::setSnapTolerance( const int snapTolerance )
Expand All @@ -34,19 +34,19 @@ void QgsModelSnapper::setSnapToGrid( bool enabled )
mSnapToGrid = enabled;
}

QPointF QgsModelSnapper::snapPoint( QPointF point, double scaleFactor, bool &snapped ) const
QPointF QgsModelSnapper::snapPoint( QPointF point, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
{
snapped = false;

bool snappedXToGrid = false;
bool snappedYToGrid = false;
QPointF res = snapPointToGrid( point, scaleFactor, snappedXToGrid, snappedYToGrid );
if ( snappedXToGrid )
if ( snappedXToGrid && snapVertical )
{
snapped = true;
point.setX( res.x() );
}
if ( snappedYToGrid )
if ( snappedYToGrid && snapHorizontal )
{
snapped = true;
point.setY( res.y() );
Expand All @@ -55,7 +55,7 @@ QPointF QgsModelSnapper::snapPoint( QPointF point, double scaleFactor, bool &sna
return point;
}

QRectF QgsModelSnapper::snapRect( const QRectF &rect, double scaleFactor, bool &snapped ) const
QRectF QgsModelSnapper::snapRect( const QRectF &rect, double scaleFactor, bool &snapped, bool snapHorizontal, bool snapVertical ) const
{
snapped = false;
QRectF snappedRect = rect;
Expand All @@ -70,12 +70,12 @@ QRectF QgsModelSnapper::snapRect( const QRectF &rect, double scaleFactor, bool &
QList< QPointF > points;
points << rect.topLeft() << rect.topRight() << rect.bottomLeft() << rect.bottomRight();
QPointF res = snapPointsToGrid( points, scaleFactor, snappedXToGrid, snappedYToGrid );
if ( snappedXToGrid )
if ( snappedXToGrid && snapVertical )
{
snapped = true;
snappedRect.translate( res.x(), 0 );
}
if ( snappedYToGrid )
if ( snappedYToGrid && snapHorizontal )
{
snapped = true;
snappedRect.translate( 0, res.y() );
Expand Down Expand Up @@ -111,7 +111,7 @@ QPointF QgsModelSnapper::snapPointsToGrid( const QList<QPointF> &points, double
for ( QPointF point : points )
{
//snap x coordinate
double gridRes = 10; //mLayout->convertToLayoutUnits( grid.resolution() );
double gridRes = 30; //mLayout->convertToLayoutUnits( grid.resolution() );
int xRatio = static_cast< int >( ( point.x() ) / gridRes + 0.5 ); //NOLINT
int yRatio = static_cast< int >( ( point.y() ) / gridRes + 0.5 ); //NOLINT

Expand Down
4 changes: 2 additions & 2 deletions src/gui/processing/models/qgsmodelsnapper.h
Expand Up @@ -80,7 +80,7 @@ class GUI_EXPORT QgsModelSnapper
* \see snapRect()
*/
QPointF snapPoint( QPointF point, double scaleFactor, bool &snapped SIP_OUT ) const;
QPointF snapPoint( QPointF point, double scaleFactor, bool &snapped SIP_OUT, bool snapHorizontal = true, bool snapVertical = true ) const;

/**
* Snaps a layout coordinate \a rect. If \a rect was snapped, \a snapped will be set to TRUE.
Expand All @@ -101,7 +101,7 @@ class GUI_EXPORT QgsModelSnapper
*
* \see snapPoint()
*/
QRectF snapRect( const QRectF &rect, double scaleFactor, bool &snapped SIP_OUT ) const;
QRectF snapRect( const QRectF &rect, double scaleFactor, bool &snapped SIP_OUT, bool snapHorizontal = true, bool snapVertical = true ) const;

/**
* Snaps a layout coordinate \a point to the grid. If \a point
Expand Down
19 changes: 19 additions & 0 deletions src/gui/processing/models/qgsmodelviewmousehandles.cpp
Expand Up @@ -160,5 +160,24 @@ void QgsModelViewMouseHandles::endMacroCommand()
mView->endMacroCommand();
}

QPointF QgsModelViewMouseHandles::snapPoint( QPointF originalPoint, QgsGraphicsViewMouseHandles::SnapGuideMode mode, bool snapHorizontal, bool snapVertical )
{
bool snapped = false;

//depending on the mode, we either snap just the single point, or all the bounds of the selection
QPointF snappedPoint;
switch ( mode )
{
case Item:
snappedPoint = mView->snapper()->snapRect( rect().translated( originalPoint ), mView->transform().m11(), snapped, snapHorizontal, snapVertical ).topLeft();
break;
case Point:
snappedPoint = mView->snapper()->snapPoint( originalPoint, mView->transform().m11(), snapped, snapHorizontal, snapVertical );
break;
}

return snapped ? snappedPoint : originalPoint;
}


///@endcond PRIVATE
1 change: 1 addition & 0 deletions src/gui/processing/models/qgsmodelviewmousehandles.h
Expand Up @@ -65,6 +65,7 @@ class GUI_EXPORT QgsModelViewMouseHandles: public QgsGraphicsViewMouseHandles
QRectF previewSetItemRect( QGraphicsItem *item, QRectF rect ) override;
void startMacroCommand( const QString &text ) override;
void endMacroCommand() override;
QPointF snapPoint( QPointF originalPoint, SnapGuideMode mode, bool snapHorizontal = true, bool snapVertical = true ) override;

public slots:

Expand Down
10 changes: 10 additions & 0 deletions src/ui/processing/qgsmodeldesignerdialogbase.ui
Expand Up @@ -80,6 +80,8 @@
<addaction name="mActionZoomToItems"/>
<addaction name="separator"/>
<addaction name="mActionShowComments"/>
<addaction name="separator"/>
<addaction name="mActionSnappingEnabled"/>
</widget>
<widget class="QMenu" name="mMenuEdit">
<property name="title">
Expand Down Expand Up @@ -610,6 +612,14 @@
<string>Del</string>
</property>
</action>
<action name="mActionSnappingEnabled">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Enable Snapping</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
Expand Down

0 comments on commit 4bad254

Please sign in to comment.