Skip to content

Commit

Permalink
[composer] Use pixels for snapping rather than mm, allowing for finer…
Browse files Browse the repository at this point in the history
… work when zoomed in. Merge grid and guide snapping settings to a single snap tolerance setting.
  • Loading branch information
nyalldawson committed Jun 29, 2014
1 parent b43d131 commit a2a26c2
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 179 deletions.
52 changes: 47 additions & 5 deletions python/core/composer/qgscomposition.sip
Expand Up @@ -112,9 +112,6 @@ class QgsComposition : QGraphicsScene
void setSnapGridResolution( double r );
double snapGridResolution() const;

void setSnapGridTolerance( double tolerance );
double snapGridTolerance() const;

void setSnapGridOffsetX( double offset );
double snapGridOffsetX() const;

Expand All @@ -127,8 +124,53 @@ class QgsComposition : QGraphicsScene
void setGridStyle( GridStyle s );
GridStyle gridStyle() const;

void setAlignmentSnapTolerance( double t );
double alignmentSnapTolerance() const;
/**Sets the snap tolerance to use when automatically snapping items during movement and resizing to the
* composition grid.
* @param tolerance snap tolerance in pixels
* @see snapGridTolerance
* @deprecated Use setSnapTolerance instead
*/
void setSnapGridTolerance( double tolerance ) /Deprecated/;

/**Returns the snap tolerance to use when automatically snapping items during movement and resizing to the
* composition grid.
* @returns snap tolerance in pixels
* @see setSnapGridTolerance
* @deprecated Use snapTolerance instead
*/
double snapGridTolerance() const /Deprecated/;

/**Sets the snap tolerance to use when automatically snapping items during movement and resizing to guides
* and the edges and centers of other items.
* @param t snap tolerance in pixels
* @see alignmentSnapTolerance
* @deprecated Use setSnapTolerance instead
*/
void setAlignmentSnapTolerance( double t ) /Deprecated/;

/**Returns the snap tolerance to use when automatically snapping items during movement and resizing to guides
* and the edges and centers of other items.
* @returns snap tolerance in pixels
* @see setAlignmentSnapTolerance
* @deprecated Use snapTolerance instead
*/
double alignmentSnapTolerance() const /Deprecated/;

/**Sets the snap tolerance to use when automatically snapping items during movement and resizing to guides
* and the edges and centers of other items.
* @param t snap tolerance in pixels
* @see alignmentSnapTolerance
* @note Added in QGIS 2.5
*/
void setSnapTolerance( int snapTolerance );

/**Returns the snap tolerance to use when automatically snapping items during movement and resizing to guides
* and the edges and centers of other items.
* @returns snap tolerance in pixels
* @see setAlignmentSnapTolerance
* @note Added in QGIS 2.5
*/
int snapTolerance() const;

/**Returns pointer to undo/redo command storage*/
QUndoStack* undoStack();
Expand Down
19 changes: 4 additions & 15 deletions src/app/composer/qgscompositionwidget.cpp
Expand Up @@ -79,14 +79,12 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c )
connect( mComposition, SIGNAL( composerMapAdded( QgsComposerMap* ) ), this, SLOT( onComposerMapAdded( QgsComposerMap* ) ) );
connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( onItemRemoved( QgsComposerItem* ) ) );

mAlignmentToleranceSpinBox->setValue( mComposition->alignmentSnapTolerance() );
mSnapToleranceSpinBox->setValue( mComposition->snapTolerance() );

//snap grid
mGridResolutionSpinBox->setValue( mComposition->snapGridResolution() );
mOffsetXSpinBox->setValue( mComposition->snapGridOffsetX() );
mOffsetYSpinBox->setValue( mComposition->snapGridOffsetY() );

mGridToleranceSpinBox->setValue( mComposition->snapGridTolerance() );
}
blockSignals( false );
}
Expand Down Expand Up @@ -559,19 +557,11 @@ void QgsCompositionWidget::on_mOffsetYSpinBox_valueChanged( double d )
}
}

void QgsCompositionWidget::on_mGridToleranceSpinBox_valueChanged( double d )
{
if ( mComposition )
{
mComposition->setSnapGridTolerance( d );
}
}

void QgsCompositionWidget::on_mAlignmentToleranceSpinBox_valueChanged( double d )
void QgsCompositionWidget::on_mSnapToleranceSpinBox_valueChanged( int tolerance )
{
if ( mComposition )
{
mComposition->setAlignmentSnapTolerance( d );
mComposition->setSnapTolerance( tolerance );
}
}

Expand All @@ -589,7 +579,6 @@ void QgsCompositionWidget::blockSignals( bool block )
mGridResolutionSpinBox->blockSignals( block );
mOffsetXSpinBox->blockSignals( block );
mOffsetYSpinBox->blockSignals( block );
mGridToleranceSpinBox->blockSignals( block );
mAlignmentToleranceSpinBox->blockSignals( block );
mSnapToleranceSpinBox->blockSignals( block );
}

3 changes: 1 addition & 2 deletions src/app/composer/qgscompositionwidget.h
Expand Up @@ -57,8 +57,7 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
void on_mGridResolutionSpinBox_valueChanged( double d );
void on_mOffsetXSpinBox_valueChanged( double d );
void on_mOffsetYSpinBox_valueChanged( double d );
void on_mGridToleranceSpinBox_valueChanged( double d );
void on_mAlignmentToleranceSpinBox_valueChanged( double d );
void on_mSnapToleranceSpinBox_valueChanged( int tolerance );

/**Sets GUI elements to width/height from composition*/
void displayCompositionWidthHeight();
Expand Down
14 changes: 4 additions & 10 deletions src/app/qgsoptions.cpp
Expand Up @@ -723,15 +723,12 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl ) :
mGridStyleComboBox->setCurrentIndex( 1 );
}

//grid defaults
//grid and guide defaults
mGridResolutionSpinBox->setValue( settings.value( "/Composer/defaultSnapGridResolution", 10.0 ).toDouble() );
mGridToleranceSpinBox->setValue( settings.value( "/Composer/defaultSnapGridTolerance", 2 ).toDouble() );
mSnapToleranceSpinBox->setValue( settings.value( "/Composer/defaultSnapTolerancePixels", 10 ).toInt() );
mOffsetXSpinBox->setValue( settings.value( "/Composer/defaultSnapGridOffsetX", 0 ).toDouble() );
mOffsetYSpinBox->setValue( settings.value( "/Composer/defaultSnapGridOffsetY", 0 ).toDouble() );

//guide defaults
mGuideToleranceSpinBox->setValue( settings.value( "/Composer/defaultSnapGuideTolerance", 2 ).toDouble() );

//
// Locale settings
//
Expand Down Expand Up @@ -1311,15 +1308,12 @@ void QgsOptions::saveOptions()
settings.setValue( "/Composer/gridStyle", "Crosses" );
}

//grid defaults
//grid and guide defaults
settings.setValue( "/Composer/defaultSnapGridResolution", mGridResolutionSpinBox->value() );
settings.setValue( "/Composer/defaultSnapGridTolerance", mGridToleranceSpinBox->value() );
settings.setValue( "/Composer/defaultSnapTolerancePixels", mSnapToleranceSpinBox->value() );
settings.setValue( "/Composer/defaultSnapGridOffsetX", mOffsetXSpinBox->value() );
settings.setValue( "/Composer/defaultSnapGridOffsetY", mOffsetYSpinBox->value() );

//guide defaults
settings.setValue( "/Composer/defaultSnapGuideTolerance", mGuideToleranceSpinBox->value() );

//
// Locale settings
//
Expand Down
18 changes: 13 additions & 5 deletions src/core/composer/qgscomposermousehandles.cpp
Expand Up @@ -1229,8 +1229,12 @@ QPointF QgsComposerMouseHandles::alignPos( const QPointF& pos, double& alignX, d
return pos;
}

//convert snap tolerance from pixels to mm
double viewScaleFactor = graphicsView()->transform().m11();
double alignThreshold = mComposition->snapTolerance() / viewScaleFactor;

QPointF result( pos.x(), pos.y() );
if ( abs( nearestX - pos.x() ) < mComposition->alignmentSnapTolerance() )
if ( fabs( nearestX - pos.x() ) < alignThreshold )
{
result.setX( nearestX );
alignX = nearestX;
Expand All @@ -1240,7 +1244,7 @@ QPointF QgsComposerMouseHandles::alignPos( const QPointF& pos, double& alignX, d
alignX = -1;
}

if ( abs( nearestY - pos.y() ) < mComposition->alignmentSnapTolerance() )
if ( fabs( nearestY - pos.y() ) < alignThreshold )
{
result.setY( nearestY );
alignY = nearestY;
Expand Down Expand Up @@ -1309,16 +1313,20 @@ void QgsComposerMouseHandles::collectAlignCoordinates( QMap< double, const QgsCo
}
}

void QgsComposerMouseHandles::checkNearestItem( double checkCoord, const QMap< double, const QgsComposerItem* >& alignCoords, double& smallestDiff, double itemCoordOffset, double& itemCoord, double& alignCoord ) const
void QgsComposerMouseHandles::checkNearestItem( double checkCoord, const QMap< double, const QgsComposerItem* >& alignCoords, double& smallestDiff, double itemCoordOffset, double& itemCoord, double& alignCoord )
{
double currentCoord = 0;
if ( !nearestItem( alignCoords, checkCoord, currentCoord ) )
{
return;
}

double currentDiff = abs( checkCoord - currentCoord );
if ( currentDiff < mComposition->alignmentSnapTolerance() && currentDiff < smallestDiff )
double currentDiff = fabs( checkCoord - currentCoord );
//convert snap tolerance from pixels to mm
double viewScaleFactor = graphicsView()->transform().m11();
double alignThreshold = mComposition->snapTolerance() / viewScaleFactor;

if ( currentDiff < alignThreshold && currentDiff < smallestDiff )
{
itemCoord = currentCoord + itemCoordOffset;
alignCoord = currentCoord;
Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgscomposermousehandles.h
Expand Up @@ -188,7 +188,7 @@ class CORE_EXPORT QgsComposerMouseHandles: public QObject, public QGraphicsRectI
//helper functions for item align
void collectAlignCoordinates( QMap< double, const QgsComposerItem* >& alignCoordsX, QMap< double, const QgsComposerItem* >& alignCoordsY );
bool nearestItem( const QMap< double, const QgsComposerItem* >& coords, double value, double& nearestValue ) const;
void checkNearestItem( double checkCoord, const QMap< double, const QgsComposerItem* >& alignCoords, double& smallestDiff, double itemCoordOffset, double& itemCoord, double& alignCoord ) const;
void checkNearestItem( double checkCoord, const QMap< double, const QgsComposerItem* >& alignCoords, double& smallestDiff, double itemCoordOffset, double& itemCoord, double& alignCoord );

//tries to return the current QGraphicsView attached to the composition
QGraphicsView* graphicsView();
Expand Down
41 changes: 25 additions & 16 deletions src/core/composer/qgscomposition.cpp
Expand Up @@ -43,6 +43,7 @@
#include <QDomDocument>
#include <QDomElement>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QPainter>
#include <QPrinter>
#include <QSettings>
Expand Down Expand Up @@ -83,13 +84,12 @@ void QgsComposition::init()
mSnapToGrid = false;
mGridVisible = false;
mSnapGridResolution = 0;
mSnapGridTolerance = 0;
mSnapGridOffsetX = 0;
mSnapGridOffsetY = 0;
mAlignmentSnap = true;
mGuidesVisible = true;
mSmartGuides = true;
mAlignmentSnapTolerance = 0;
mSnapTolerance = 0;
mSelectionHandles = 0;
mActiveItemCommand = 0;
mActiveMultiFrameCommand = 0;
Expand Down Expand Up @@ -170,10 +170,9 @@ void QgsComposition::loadDefaults()
{
QSettings settings;
mSnapGridResolution = settings.value( "/Composer/defaultSnapGridResolution", 10.0 ).toDouble();
mSnapGridTolerance = settings.value( "/Composer/defaultSnapGridTolerance", 2 ).toDouble();
mSnapGridOffsetX = settings.value( "/Composer/defaultSnapGridOffsetX", 0 ).toDouble();
mSnapGridOffsetY = settings.value( "/Composer/defaultSnapGridOffsetY", 0 ).toDouble();
mAlignmentSnapTolerance = settings.value( "/Composer/defaultSnapGuideTolerance", 2 ).toDouble();
mSnapTolerance = settings.value( "/Composer/defaultSnapTolerancePixels", 10 ).toInt();
}

void QgsComposition::updateBounds()
Expand Down Expand Up @@ -640,7 +639,6 @@ bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
compositionElem.setAttribute( "gridVisible", "0" );
}
compositionElem.setAttribute( "snapGridResolution", QString::number( mSnapGridResolution ) );
compositionElem.setAttribute( "snapGridTolerance", QString::number( mSnapGridTolerance ) );
compositionElem.setAttribute( "snapGridOffsetX", QString::number( mSnapGridOffsetX ) );
compositionElem.setAttribute( "snapGridOffsetY", QString::number( mSnapGridOffsetY ) );

Expand Down Expand Up @@ -669,7 +667,7 @@ bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
compositionElem.setAttribute( "alignmentSnap", mAlignmentSnap ? 1 : 0 );
compositionElem.setAttribute( "guidesVisible", mGuidesVisible ? 1 : 0 );
compositionElem.setAttribute( "smartGuides", mSmartGuides ? 1 : 0 );
compositionElem.setAttribute( "alignmentSnapTolerance", mAlignmentSnapTolerance );
compositionElem.setAttribute( "snapTolerancePixels", mSnapTolerance );

//save items except paper items and frame items (they are saved with the corresponding multiframe)
QList<QGraphicsItem*> itemList = items();
Expand Down Expand Up @@ -733,14 +731,13 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
mGridVisible = compositionElem.attribute( "gridVisible", "0" ).toInt() == 0 ? false : true;

mSnapGridResolution = compositionElem.attribute( "snapGridResolution" ).toDouble();
mSnapGridTolerance = compositionElem.attribute( "snapGridTolerance", "2.0" ).toDouble();
mSnapGridOffsetX = compositionElem.attribute( "snapGridOffsetX" ).toDouble();
mSnapGridOffsetY = compositionElem.attribute( "snapGridOffsetY" ).toDouble();

mAlignmentSnap = compositionElem.attribute( "alignmentSnap", "1" ).toInt() == 0 ? false : true;
mGuidesVisible = compositionElem.attribute( "guidesVisible", "1" ).toInt() == 0 ? false : true;
mSmartGuides = compositionElem.attribute( "smartGuides", "1" ).toInt() == 0 ? false : true;
mAlignmentSnapTolerance = compositionElem.attribute( "alignmentSnapTolerance", "2.0" ).toDouble();
mSnapTolerance = compositionElem.attribute( "snapTolerancePixels", "10" ).toInt();

//custom snap lines
QDomNodeList snapLineNodes = compositionElem.elementsByTagName( "SnapLine" );
Expand Down Expand Up @@ -1733,7 +1730,7 @@ void QgsComposition::refreshZList()

QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const
{
if ( !mSnapToGrid || mSnapGridResolution <= 0 )
if ( !mSnapToGrid || mSnapGridResolution <= 0 || !graphicsView() )
{
return scenePoint;
}
Expand All @@ -1750,12 +1747,16 @@ QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const
double xSnapped = xRatio * mSnapGridResolution + mSnapGridOffsetX;
double ySnapped = yRatio * mSnapGridResolution + mSnapGridOffsetY + yOffset;

if ( abs( xSnapped - scenePoint.x() ) > mSnapGridTolerance )
//convert snap tolerance from pixels to mm
double viewScaleFactor = graphicsView()->transform().m11();
double alignThreshold = mSnapTolerance / viewScaleFactor;

if ( fabs( xSnapped - scenePoint.x() ) > alignThreshold )
{
//snap distance is outside of tolerance
xSnapped = scenePoint.x();
}
if ( abs( ySnapped - scenePoint.y() ) > mSnapGridTolerance )
if ( fabs( ySnapped - scenePoint.y() ) > alignThreshold )
{
//snap distance is outside of tolerance
ySnapped = scenePoint.y();
Expand Down Expand Up @@ -1961,11 +1962,6 @@ void QgsComposition::setSnapGridResolution( double r )
updatePaperItems();
}

void QgsComposition::setSnapGridTolerance( double tolerance )
{
mSnapGridTolerance = tolerance;
}

void QgsComposition::setSnapGridOffsetX( double offset )
{
mSnapGridOffsetX = offset;
Expand Down Expand Up @@ -2578,6 +2574,19 @@ QString QgsComposition::encodeStringForXML( const QString& str )
return modifiedStr;
}

QGraphicsView *QgsComposition::graphicsView() const
{
//try to find current view attached to composition
QList<QGraphicsView*> viewList = views();
if ( viewList.size() > 0 )
{
return viewList.at( 0 );
}

//no view attached to composition
return 0;
}

void QgsComposition::computeWorldFileParameters( double& a, double& b, double& c, double& d, double& e, double& f ) const
{
//
Expand Down

0 comments on commit a2a26c2

Please sign in to comment.