Skip to content

Commit

Permalink
[cad] update constraint when user changes values in widgets while
Browse files Browse the repository at this point in the history
constraint is locked

The previous behaviour was that the constraint had to be "relocked"
if the user manually altered the constraint value in the text
widgets. Now users can edit the constraint value after already
locking the constraint.
  • Loading branch information
nyalldawson committed May 2, 2016
1 parent 5654886 commit bd30588
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 21 deletions.
4 changes: 3 additions & 1 deletion python/gui/qgsadvanceddigitizingdockwidget.sip
Expand Up @@ -104,8 +104,10 @@ class QgsAdvancedDigitizingDockWidget : QDockWidget

/**
* Set the value of the constraint
* @param value new value for constraint
* @param updateWidget set to false to prevent automatically updating the associated widget's value
*/
void setValue( double value );
void setValue( double value, bool updateWidget = true );

/**
* Toggle lock mode
Expand Down
112 changes: 94 additions & 18 deletions src/gui/qgsadvanceddigitizingdockwidget.cpp
Expand Up @@ -29,6 +29,7 @@
#include "qgsmessagebaritem.h"
#include "qgspoint.h"
#include "qgslinestringv2.h"
#include "qgsfocuswatcher.h"

struct EdgesOnlyFilter : public QgsPointLocator::MatchFilter
{
Expand Down Expand Up @@ -138,6 +139,19 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas*
connect( mDistanceLineEdit, SIGNAL( returnPressed() ), this, SLOT( lockConstraint() ) );
connect( mXLineEdit, SIGNAL( returnPressed() ), this, SLOT( lockConstraint() ) );
connect( mYLineEdit, SIGNAL( returnPressed() ), this, SLOT( lockConstraint() ) );
connect( mAngleLineEdit, SIGNAL( textEdited( QString ) ), this, SLOT( constraintTextEdited( QString ) ) );
connect( mDistanceLineEdit, SIGNAL( textEdited( QString ) ), this, SLOT( constraintTextEdited( QString ) ) );
connect( mXLineEdit, SIGNAL( textEdited( QString ) ), this, SLOT( constraintTextEdited( QString ) ) );
connect( mYLineEdit, SIGNAL( textEdited( QString ) ), this, SLOT( constraintTextEdited( QString ) ) );
//also watch for focus out events on these widgets
QgsFocusWatcher* angleWatcher = new QgsFocusWatcher( mAngleLineEdit );
connect( angleWatcher, SIGNAL( focusOut() ), this, SLOT( constraintFocusOut() ) );
QgsFocusWatcher* distanceWatcher = new QgsFocusWatcher( mDistanceLineEdit );
connect( distanceWatcher, SIGNAL( focusOut() ), this, SLOT( constraintFocusOut() ) );
QgsFocusWatcher* xWatcher = new QgsFocusWatcher( mXLineEdit );
connect( xWatcher, SIGNAL( focusOut() ), this, SLOT( constraintFocusOut() ) );
QgsFocusWatcher* yWatcher = new QgsFocusWatcher( mYLineEdit );
connect( yWatcher, SIGNAL( focusOut() ), this, SLOT( constraintFocusOut() ) );

// config menu
QMenu *menu = new QMenu( this );
Expand Down Expand Up @@ -300,9 +314,8 @@ void QgsAdvancedDigitizingDockWidget::emit pointChanged()
}
#endif

void QgsAdvancedDigitizingDockWidget::lockConstraint( bool activate /* default true */ )
QgsAdvancedDigitizingDockWidget::CadConstraint* QgsAdvancedDigitizingDockWidget::objectToConstraint( const QObject* obj ) const
{
QObject* obj = sender();
CadConstraint* constraint = nullptr;
if ( obj == mAngleLineEdit || obj == mLockAngleButton )
{
Expand All @@ -320,6 +333,53 @@ void QgsAdvancedDigitizingDockWidget::lockConstraint( bool activate /* default t
{
constraint = mYConstraint;
}
return constraint;
}

double QgsAdvancedDigitizingDockWidget::parseUserInput( const QString& inputValue, bool& ok ) const
{
ok = false;
double value = inputValue.toDouble( &ok );
if ( ok )
{
return value;
}
else
{
// try to evalute expression
QgsExpression expr( inputValue );
QVariant result = expr.evaluate();
if ( expr.hasEvalError() )
ok = false;
else
value = result.toDouble( &ok );
return value;
}
}

void QgsAdvancedDigitizingDockWidget::updateConstraintValue( CadConstraint* constraint, const QString& textValue, bool convertExpression )
{
if ( !constraint || textValue.isEmpty() )
{
return;
}

if ( constraint->lockMode() == CadConstraint::NoLock )
return;

bool ok;
double value = parseUserInput( textValue, ok );
if ( !ok )
return;

constraint->setValue( value, convertExpression );
// run a fake map mouse event to update the paint item
emit pointChanged( mCadPointList.value( 0 ) );
}

void QgsAdvancedDigitizingDockWidget::lockConstraint( bool activate /* default true */ )
{
CadConstraint* constraint = objectToConstraint( sender() );
if ( !constraint )
{
return;
Expand All @@ -328,28 +388,17 @@ void QgsAdvancedDigitizingDockWidget::lockConstraint( bool activate /* default t
if ( activate )
{
QString textValue = constraint->lineEdit()->text();
bool ok;
double value = textValue.toDouble( &ok );
if ( !textValue.isEmpty() )
{
bool ok;
double value = parseUserInput( textValue, ok );
if ( ok )
{
constraint->setValue( value );
}
else
{
// try to evalute expression
QgsExpression expr( textValue );
QVariant result = expr.evaluate();
value = result.toDouble( &ok );
if ( expr.hasEvalError() || !ok )
{
activate = false;
}
else
{
constraint->setValue( value );
}
activate = false;
}
}
else
Expand All @@ -372,6 +421,32 @@ void QgsAdvancedDigitizingDockWidget::lockConstraint( bool activate /* default t
}
}

void QgsAdvancedDigitizingDockWidget::constraintTextEdited( const QString& textValue )
{
CadConstraint* constraint = objectToConstraint( sender() );
if ( !constraint )
{
return;
}

updateConstraintValue( constraint, textValue, false );
}

void QgsAdvancedDigitizingDockWidget::constraintFocusOut()
{
QLineEdit* lineEdit = qobject_cast< QLineEdit* >( sender()->parent() );
if ( !lineEdit )
return;

CadConstraint* constraint = objectToConstraint( lineEdit );
if ( !constraint )
{
return;
}

updateConstraintValue( constraint, lineEdit->text(), true );
}

void QgsAdvancedDigitizingDockWidget::lockAdditionalConstraint( AdditionalConstraint constraint )
{
mAdditionalConstraint = constraint;
Expand Down Expand Up @@ -1169,10 +1244,11 @@ void QgsAdvancedDigitizingDockWidget::CadConstraint::setRelative( bool relative
}
}

void QgsAdvancedDigitizingDockWidget::CadConstraint::setValue( double value )
void QgsAdvancedDigitizingDockWidget::CadConstraint::setValue( double value, bool updateWidget )
{
mValue = value;
mLineEdit->setText( QString::number( value, 'f' ) );
if ( updateWidget )
mLineEdit->setText( QString::number( value, 'f' ) );
}

void QgsAdvancedDigitizingDockWidget::CadConstraint::toggleLocked()
Expand Down
25 changes: 23 additions & 2 deletions src/gui/qgsadvanceddigitizingdockwidget.h
Expand Up @@ -133,8 +133,10 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QDockWidget, private U

/**
* Set the value of the constraint
* @param value new value for constraint
* @param updateWidget set to false to prevent automatically updating the associated widget's value
*/
void setValue( double value );
void setValue( double value, bool updateWidget = true );

/**
* Toggle lock mode
Expand Down Expand Up @@ -312,12 +314,20 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QDockWidget, private U
void pointChanged( const QgsPoint& point );

private slots:
//! set the additiona constraint by clicking on the perpendicular/parallel buttons
//! set the additional constraint by clicking on the perpendicular/parallel buttons
void addtionalConstraintClicked( bool activated );

//! lock/unlock a constraint and set its value
void lockConstraint( bool activate = true );

//! Called when user has manually altered a constraint value. Any entered expressions will
//! be left intact
void constraintTextEdited( const QString& textValue );

//! Called when a constraint input widget has lost focus. Any entered expressions
//! will be converted to their calculated value
void constraintFocusOut();

//! unlock all constraints
void releaseLocks();

Expand Down Expand Up @@ -372,7 +382,17 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QDockWidget, private U
//! trigger fake mouse move event to update map tool rubber band and/or show new constraints
void triggerMouseMoveEvent();

//! Returns the constraint associated with an object
CadConstraint* objectToConstraint( const QObject* obj ) const;

//! Attempts to convert a user input value to double, either directly or via expression
double parseUserInput( const QString& inputValue, bool& ok ) const;

/** Updates a constraint value based on a text input.
* @param textValue user entered text value, may be an expression
* @param convertExpression set to true to update widget contents to calculated expression value
*/
void updateConstraintValue( CadConstraint* constraint, const QString& textValue, bool convertExpression = false );

QgsMapCanvas* mMapCanvas;
QgsAdvancedDigitizingCanvasItem* mCadPaintItem;
Expand Down Expand Up @@ -409,6 +429,7 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QDockWidget, private U
QAction* mEnableAction;
QMap< QAction*, int > mCommonAngleActions; // map the common angle actions with their angle values
QMap< QAction*, QgsMapMouseEvent::SnappingMode > mSnappingActions; // map the snapping mode actions with their values

};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAdvancedDigitizingDockWidget::CadCapacities )
Expand Down

0 comments on commit bd30588

Please sign in to comment.