41   Q_ASSERT( segment.
count() == 2 );
    45   const double x1 = segment[0].x() - center.
x();
    46   const double y1 = segment[0].y() - center.
y();
    47   const double x2 = segment[1].x() - center.
x();
    48   const double y2 = segment[1].y() - center.
y();
    49   const double dx = x2 - x1;
    50   const double dy = y2 - y1;
    52   const double dr = sqrt( pow( dx, 2 ) + pow( dy, 2 ) );
    53   const double d = x1 * y2 - x2 * y1;
    55   const double disc = pow( radius, 2 ) * pow( dr, 2 ) - pow( d, 2 );
    65     const int sgnDy = dy < 0 ? -1 : 1;
    67     const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrt( pow( radius, 2 ) * pow( dr, 2 ) - pow( d, 2 ) ) ) / ( pow( dr, 2 ) );
    68     const double ay = center.
y() + ( -d * dx + qAbs( dy ) * sqrt( pow( radius, 2 ) * pow( dr, 2 ) - pow( d, 2 ) ) ) / ( pow( dr, 2 ) );
    71     const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrt( pow( radius, 2 ) * pow( dr, 2 ) - pow( d, 2 ) ) ) / ( pow( dr, 2 ) );
    72     const double by = center.
y() + ( -d * dx - qAbs( dy ) * sqrt( pow( radius, 2 ) * pow( dr, 2 ) - pow( d, 2 ) ) ) / ( pow( dr, 2 ) );
    79       intersection.
set( p1.
x(), p1.
y() );
    83       intersection.
set( p2.
x(), p2.
y() );
    92     , mMapCanvas( canvas )
    93     , mCurrentMapToolSupportsCad( false )
    94     , mCadEnabled( false )
    95     , mConstructionMode( false )
    97     , mCommonAngleConstraint( 
QSettings().value( 
"/Cad/CommonAngle", 90 ).toInt() )
    98     , mSnappedToVertex( false )
    99     , mSessionActive( false )
   100     , mErrorMessage( nullptr )
   106   mAngleConstraint.reset( 
new CadConstraint( mAngleLineEdit, mLockAngleButton, mRelativeAngleButton, mRepeatingLockAngleButton ) );
   107   mDistanceConstraint.reset( 
new CadConstraint( mDistanceLineEdit, mLockDistanceButton, 
nullptr, mRepeatingLockDistanceButton ) );
   108   mXConstraint.reset( 
new CadConstraint( mXLineEdit, mLockXButton, mRelativeXButton, mRepeatingLockXButton ) );
   109   mYConstraint.reset( 
new CadConstraint( mYLineEdit, mLockYButton, mRelativeYButton, mRepeatingLockYButton ) );
   113   mAngleLineEdit->installEventFilter( 
this );
   114   mDistanceLineEdit->installEventFilter( 
this );
   115   mXLineEdit->installEventFilter( 
this );
   116   mYLineEdit->installEventFilter( 
this );
   119   mEnableAction = 
new QAction( 
this );
   120   mEnableAction->
setText( 
tr( 
"Enable advanced digitizing tools" ) );
   123   mEnabledButton->addAction( mEnableAction );
   124   mEnabledButton->setDefaultAction( mEnableAction );
   127   connect( mEnableAction, SIGNAL( triggered( 
bool ) ), 
this, SLOT( activateCad( 
bool ) ) );
   128   connect( mConstructionModeButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstructionMode( 
bool ) ) );
   129   connect( mParallelButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( addtionalConstraintClicked( 
bool ) ) );
   130   connect( mPerpendicularButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( addtionalConstraintClicked( 
bool ) ) );
   131   connect( mLockAngleButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( lockConstraint( 
bool ) ) );
   132   connect( mLockDistanceButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( lockConstraint( 
bool ) ) );
   133   connect( mLockXButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( lockConstraint( 
bool ) ) );
   134   connect( mLockYButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( lockConstraint( 
bool ) ) );
   135   connect( mRelativeAngleButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRelative( 
bool ) ) );
   136   connect( mRelativeXButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRelative( 
bool ) ) );
   137   connect( mRelativeYButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRelative( 
bool ) ) );
   138   connect( mRepeatingLockDistanceButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRepeatingLock( 
bool ) ) );
   139   connect( mRepeatingLockAngleButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRepeatingLock( 
bool ) ) );
   140   connect( mRepeatingLockXButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRepeatingLock( 
bool ) ) );
   141   connect( mRepeatingLockYButton, SIGNAL( clicked( 
bool ) ), 
this, SLOT( setConstraintRepeatingLock( 
bool ) ) );
   142   connect( mAngleLineEdit, SIGNAL( returnPressed() ), 
this, SLOT( lockConstraint() ) );
   143   connect( mDistanceLineEdit, SIGNAL( returnPressed() ), 
this, SLOT( lockConstraint() ) );
   144   connect( mXLineEdit, SIGNAL( returnPressed() ), 
this, SLOT( lockConstraint() ) );
   145   connect( mYLineEdit, SIGNAL( returnPressed() ), 
this, SLOT( lockConstraint() ) );
   146   connect( mAngleLineEdit, SIGNAL( textEdited( 
QString ) ), 
this, SLOT( constraintTextEdited( 
QString ) ) );
   147   connect( mDistanceLineEdit, SIGNAL( textEdited( 
QString ) ), 
this, SLOT( constraintTextEdited( 
QString ) ) );
   148   connect( mXLineEdit, SIGNAL( textEdited( 
QString ) ), 
this, SLOT( constraintTextEdited( 
QString ) ) );
   149   connect( mYLineEdit, SIGNAL( textEdited( 
QString ) ), 
this, SLOT( constraintTextEdited( 
QString ) ) );
   152   connect( angleWatcher, SIGNAL( focusOut() ), 
this, SLOT( constraintFocusOut() ) );
   154   connect( distanceWatcher, SIGNAL( focusOut() ), 
this, SLOT( constraintFocusOut() ) );
   156   connect( xWatcher, SIGNAL( focusOut() ), 
this, SLOT( constraintFocusOut() ) );
   158   connect( yWatcher, SIGNAL( focusOut() ), 
this, SLOT( constraintFocusOut() ) );
   166   commonAngles << QPair<int, QString>( 0, 
tr( 
"Do not snap to common angles" ) );
   174     action->
setChecked( it->first == mCommonAngleConstraint );
   177     mCommonAngleActions.
insert( action, it->first );
   191     action->
setChecked( it->first == mSnappingMode );
   194     mSnappingActions.
insert( action, it->first );
   197   mSettingsButton->setMenu( menu );
   198   connect( mSettingsButton, SIGNAL( triggered( 
QAction* ) ), 
this, SLOT( settingsButtonTriggered( 
QAction* ) ) );
   200   updateCapacity( 
true );
   208   setCadEnabled( 
false );
   211 void QgsAdvancedDigitizingDockWidget::setCadEnabled( 
bool enabled )
   215   mCadButtons->setEnabled( enabled );
   216   mInputWidgets->setEnabled( enabled );
   220   setConstructionMode( 
false );
   223 void QgsAdvancedDigitizingDockWidget::activateCad( 
bool enabled )
   225   enabled &= mCurrentMapToolSupportsCad;
   234   setCadEnabled( enabled );
   237 void QgsAdvancedDigitizingDockWidget::addtionalConstraintClicked( 
bool activated )
   243   if ( 
sender() == mParallelButton )
   245     lockAdditionalConstraint( 
Parallel );
   247   else if ( 
sender() == mPerpendicularButton )
   254 void QgsAdvancedDigitizingDockWidget::setConstraintRelative( 
bool activate )
   256   if ( 
sender() == mRelativeAngleButton )
   258     mAngleConstraint->setRelative( activate );
   260   else if ( 
sender() == mRelativeXButton )
   262     mXConstraint->setRelative( activate );
   264   else if ( 
sender() == mRelativeYButton )
   266     mYConstraint->setRelative( activate );
   270 void QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock( 
bool activate )
   272   if ( 
sender() == mRepeatingLockDistanceButton )
   274     mDistanceConstraint->setRepeatingLock( activate );
   276   else if ( 
sender() == mRepeatingLockAngleButton )
   278     mAngleConstraint->setRepeatingLock( activate );
   280   else if ( 
sender() == mRepeatingLockXButton )
   282     mXConstraint->setRepeatingLock( activate );
   284   else if ( 
sender() == mRepeatingLockYButton )
   286     mYConstraint->setRepeatingLock( activate );
   290 void QgsAdvancedDigitizingDockWidget::setConstructionMode( 
bool enabled )
   293   mConstructionModeButton->setChecked( enabled );
   296 void QgsAdvancedDigitizingDockWidget::settingsButtonTriggered( 
QAction* action )
   300   if ( isn != mSnappingActions.
constEnd() )
   302     isn.
key()->setChecked( 
true );
   303     mSnappingMode = isn.
value();
   310   if ( ica != mCommonAngleActions.
constEnd() )
   312     ica.
key()->setChecked( 
true );
   313     mCommonAngleConstraint = ica.
value();
   319 void QgsAdvancedDigitizingDockWidget::releaseLocks( 
bool releaseRepeatingLocks )
   325   if ( releaseRepeatingLocks || !mAngleConstraint->isRepeatingLock() )
   327   if ( releaseRepeatingLocks || !mDistanceConstraint->isRepeatingLock() )
   329   if ( releaseRepeatingLocks || !mXConstraint->isRepeatingLock() )
   331   if ( releaseRepeatingLocks || !mYConstraint->isRepeatingLock() )
   336 void QgsAdvancedDigitizingDockWidget::emit 
pointChanged()
   341   QMouseEvent* e = 
new QMouseEvent( QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier );
   342   mCurrentMapTool->canvasMoveEvent( e );
   349   if ( obj == mAngleLineEdit || obj == mLockAngleButton )
   351     constraint = mAngleConstraint.data();
   353   else if ( obj == mDistanceLineEdit || obj == mLockDistanceButton )
   355     constraint = mDistanceConstraint.data();
   357   else if ( obj == mXLineEdit  || obj == mLockXButton )
   359     constraint = mXConstraint.data();
   361   else if ( obj == mYLineEdit  || obj == mLockYButton )
   363     constraint = mYConstraint.data();
   368 double QgsAdvancedDigitizingDockWidget::parseUserInput( 
const QString& inputValue, 
bool& ok )
 const   371   double value = inputValue.
toDouble( &ok );
   389 void QgsAdvancedDigitizingDockWidget::updateConstraintValue( 
CadConstraint* constraint, 
const QString& textValue, 
bool convertExpression )
   391   if ( !constraint || textValue.
isEmpty() )
   400   double value = parseUserInput( textValue, ok );
   404   constraint->
setValue( value, convertExpression );
   409 void QgsAdvancedDigitizingDockWidget::lockConstraint( 
bool activate  )
   423       double value = parseUserInput( textValue, ok );
   443     if ( constraint == mAngleConstraint.data() )
   453 void QgsAdvancedDigitizingDockWidget::constraintTextEdited( 
const QString& textValue )
   461   updateConstraintValue( constraint, textValue, 
false );
   464 void QgsAdvancedDigitizingDockWidget::constraintFocusOut()
   476   updateConstraintValue( constraint, lineEdit->
text(), true );
   479 void QgsAdvancedDigitizingDockWidget::lockAdditionalConstraint( 
AdditionalConstraint constraint )
   481   mAdditionalConstraint = constraint;
   482   mPerpendicularButton->setChecked( constraint == 
Perpendicular );
   483   mParallelButton->setChecked( constraint == 
Parallel );
   486 void QgsAdvancedDigitizingDockWidget::updateCapacity( 
bool updateUIwithoutChange )
   488   CadCapacities newCapacities = 
nullptr;
   490   if ( mCadPointList.
count() > 1 )
   494   if ( mCadPointList.
count() > 2 )
   498   if ( !updateUIwithoutChange && newCapacities == mCapacities )
   506   bool relativeAngle = mCadEnabled && newCapacities.testFlag( 
RelativeAngle );
   507   bool absoluteAngle = mCadEnabled && newCapacities.testFlag( 
AbsoluteAngle );
   510   mPerpendicularButton->setEnabled( absoluteAngle );
   511   mParallelButton->setEnabled( absoluteAngle );
   512   if ( !absoluteAngle )
   518   mLockAngleButton->setEnabled( absoluteAngle );
   519   mRelativeAngleButton->setEnabled( relativeAngle );
   520   mAngleLineEdit->setEnabled( absoluteAngle );
   521   if ( !absoluteAngle )
   525   if ( !relativeAngle )
   527     mAngleConstraint->setRelative( 
false );
   529   else if ( relativeAngle && !mCapacities.testFlag( 
RelativeAngle ) )
   532     mAngleConstraint->setRelative( 
true );
   536   mLockDistanceButton->setEnabled( relativeCoordinates );
   537   mDistanceLineEdit->setEnabled( relativeCoordinates );
   538   if ( !relativeCoordinates )
   543   mRelativeXButton->setEnabled( relativeCoordinates );
   544   mRelativeYButton->setEnabled( relativeCoordinates );
   547   mCapacities = newCapacities;
   555   QgsDebugMsg( 
"Constraints (locked / relative / value" );
   556   QgsDebugMsg( 
QString( 
"Angle:    %1 %2 %3" ).arg( mAngleConstraint->isLocked() ).arg( mAngleConstraint->relative() ).arg( mAngleConstraint->value() ) );
   557   QgsDebugMsg( 
QString( 
"Distance: %1 %2 %3" ).arg( mDistanceConstraint->isLocked() ).arg( mDistanceConstraint->relative() ).arg( mDistanceConstraint->value() ) );
   558   QgsDebugMsg( 
QString( 
"X:        %1 %2 %3" ).arg( mXConstraint->isLocked() ).arg( mXConstraint->relative() ).arg( mXConstraint->value() ) );
   559   QgsDebugMsg( 
QString( 
"Y:        %1 %2 %3" ).arg( mYConstraint->isLocked() ).arg( mYConstraint->relative() ).arg( mYConstraint->value() ) );
   565   bool previousPointExist, penulPointExist;
   571   if ( mXConstraint->isLocked() )
   573     if ( !mXConstraint->relative() )
   575       point.
setX( mXConstraint->value() );
   579       point.
setX( previousPt.
x() + mXConstraint->value() );
   581     if ( !mSnappedSegment.
isEmpty() && !mYConstraint->isLocked() )
   584       const double dx = mSnappedSegment.
at( 1 ).x() - mSnappedSegment.
at( 0 ).x();
   587         point.
setY( mSnappedSegment.
at( 0 ).y() );
   591         const double dy = mSnappedSegment.
at( 1 ).y() - mSnappedSegment.
at( 0 ).y();
   592         point.
setY( mSnappedSegment.
at( 0 ).y() + ( dy * ( point.
x() - mSnappedSegment.
at( 0 ).x() ) ) / dx );
   598   if ( mYConstraint->isLocked() )
   600     if ( !mYConstraint->relative() )
   602       point.
setY( mYConstraint->value() );
   606       point.
setY( previousPt.
y() + mYConstraint->value() );
   608     if ( !mSnappedSegment.
isEmpty() && !mXConstraint->isLocked() )
   611       const double dy = mSnappedSegment.
at( 1 ).y() - mSnappedSegment.
at( 0 ).y();
   614         point.
setX( mSnappedSegment.
at( 0 ).x() );
   618         const double dx = mSnappedSegment.
at( 1 ).x() - mSnappedSegment.
at( 0 ).x();
   619         point.
setX( mSnappedSegment.
at( 0 ).x() + ( dx * ( point.
y() - mSnappedSegment.
at( 0 ).y() ) ) / dy );
   631   if ( !mAngleConstraint->isLocked() && mCapacities.testFlag( 
AbsoluteAngle ) && mCommonAngleConstraint != 0 )
   633     double commonAngle = mCommonAngleConstraint * 
M_PI / 180;
   636     double softAngle = qAtan2( point.
y() - previousPt.
y(),
   637                                point.
x() - previousPt.
x() );
   638     double deltaAngle = 0;
   639     if ( mAngleConstraint->relative() && mCapacities.testFlag( 
RelativeAngle ) )
   642       deltaAngle = qAtan2( previousPt.
y() - penultimatePt.
y(),
   643                            previousPt.
x() - penultimatePt.
x() );
   644       softAngle -= deltaAngle;
   646     int quo = qRound( softAngle / commonAngle );
   650       softAngle = quo * commonAngle ;
   653       const double dist = qAbs( qCos( softAngle + deltaAngle ) * ( previousPt.
y() - point.
y() )
   654                                 - qSin( softAngle + deltaAngle ) * ( previousPt.
x() - point.
x() ) );
   658         mAngleConstraint->setValue( 180.0 / 
M_PI * softAngle );
   662   if ( mAngleConstraint->isLocked() )
   664     double angleValue = mAngleConstraint->value() * 
M_PI / 180;
   665     if ( mAngleConstraint->relative() && mCapacities.testFlag( 
RelativeAngle ) )
   668       angleValue += qAtan2( previousPt.
y() - penultimatePt.
y(),
   669                             previousPt.
x() - penultimatePt.
x() );
   672     double cosa = qCos( angleValue );
   673     double sina = qSin( angleValue );
   674     double v = ( point.
x() - previousPt.
x() ) * cosa + ( point.
y() - previousPt.
y() ) * sina ;
   675     if ( mXConstraint->isLocked() && mYConstraint->isLocked() )
   679     else if ( mXConstraint->isLocked() )
   687         double x = mXConstraint->value();
   688         if ( !mXConstraint->relative() )
   692         point.
setY( previousPt.
y() + x * sina / cosa );
   695     else if ( mYConstraint->isLocked() )
   703         double y = mYConstraint->value();
   704         if ( !mYConstraint->relative() )
   708         point.
setX( previousPt.
x() + y * cosa / sina );
   713       point.
setX( previousPt.
x() + cosa * v );
   714       point.
setY( previousPt.
y() + sina * v );
   717     if ( !mSnappedSegment.
isEmpty() && !mDistanceConstraint->isLocked() )
   722       const double x1 = previousPt.
x();
   723       const double y1 = previousPt.
y();
   724       const double x2 = previousPt.
x() + cosa;
   725       const double y2 = previousPt.
y() + sina;
   727       const double x3 = mSnappedSegment.
at( 0 ).x();
   728       const double y3 = mSnappedSegment.
at( 0 ).y();
   729       const double x4 = mSnappedSegment.
at( 1 ).x();
   730       const double y4 = mSnappedSegment.
at( 1 ).y();
   732       const double d = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 );
   736       if ( qAbs( d ) > 0.01 )
   738         point.
setX((( x3 - x4 )*( x1*y2 - y1*x2 ) - ( x1 - x2 )*( x3*y4 - y3*x4 ) ) / d );
   739         point.
setY((( y3 - y4 )*( x1*y2 - y1*x2 ) - ( y1 - y2 )*( x3*y4 - y3*x4 ) ) / d );
   745   if ( mDistanceConstraint->isLocked() && previousPointExist )
   747     if ( mXConstraint->isLocked() || mYConstraint->isLocked() )
   750       if ( mXConstraint->isLocked() )
   753                                                 << 
QgsPoint( mXConstraint->value(), point.
y() )
   754                                                 << 
QgsPoint( mXConstraint->value(), point.
y() + 1 );
   757       if ( mYConstraint->isLocked() )
   760             << 
QgsPoint( point.
x(), mYConstraint->value() )
   761             << 
QgsPoint( point.
x() + 1, mYConstraint->value() );
   767       const double dist = sqrt( point.
sqrDist( previousPt ) );
   772         point.
set( previousPt.
x() + mDistanceConstraint->value(), previousPt.
y() );
   776         const double vP = mDistanceConstraint->value() / dist;
   777         point.
set( previousPt.
x() + ( point.
x() - previousPt.
x() ) * vP,
   778                    previousPt.
y() + ( point.
y() - previousPt.
y() ) * vP );
   781       if ( !mSnappedSegment.
isEmpty() && !mAngleConstraint->isLocked() )
   793   QgsDebugMsg( 
QString( 
"penultimate point: %1 %2" ).arg( penultimatePt.
x() ).arg( penultimatePt.
y() ) );
   801   updateCurrentPoint( point );
   806   if ( !mAngleConstraint->isLocked() && previousPointExist )
   809     if ( penulPointExist && mAngleConstraint->relative() )
   812       angle = qAtan2( previousPt.
y() - penultimatePt.
y(),
   813                       previousPt.
x() - penultimatePt.
x() );
   815     angle = ( qAtan2( point.
y() - previousPt.
y(),
   816                       point.
x() - previousPt.
x()
   817                     ) - angle ) * 180 / 
M_PI;
   819     angle = fmod( angle, 360.0 );
   820     mAngleConstraint->setValue( angle );
   823   if ( !mDistanceConstraint->isLocked() && previousPointExist )
   825     mDistanceConstraint->setValue( sqrt( previousPt.
sqrDist( point ) ) );
   828   if ( !mXConstraint->isLocked() )
   830     if ( previousPointExist && mXConstraint->relative() )
   832       mXConstraint->setValue( point.
x() - previousPt.
x() );
   836       mXConstraint->setValue( point.
x() );
   840   if ( !mYConstraint->isLocked() )
   842     if ( previousPointExist && mYConstraint->relative() )
   844       mYConstraint->setValue( point.
y() - previousPt.
y() );
   848       mYConstraint->setValue( point.
y() );
   863   bool previousPointExist, penulPointExist, mSnappedSegmentExist;
   868   if ( !previousPointExist || !mSnappedSegmentExist )
   873   double angle = qAtan2( mSnappedSegment[0].
y() - mSnappedSegment[1].
y(), mSnappedSegment[0].
x() - mSnappedSegment[1].
x() );
   875   if ( mAngleConstraint->relative() && penulPointExist )
   877     angle -= qAtan2( previousPt.
y() - penultimatePt.
y(), previousPt.
x() - penultimatePt.
x() );
   887   mAngleConstraint->setValue( angle );
   888   mAngleConstraint->setLockMode( lockMode );
   900   return mCadEnabled && mConstructionMode;
   910   if ( e->
button() == Qt::RightButton )
   919   if ( alignToSegment( e ) )
   931   releaseLocks( 
false );
   933   if ( e->
button() == Qt::LeftButton )
   936     if ( !mConstructionMode && !captureSegment )
   941   return mConstructionMode;
   951     emit 
pushWarning( 
tr( 
"Some constraints are incompatible. Resulting point might be incorrect." ) );
   975     case Qt::Key_Backspace:
   978       removePreviousPoint();
   979       releaseLocks( 
false );
  1012     case Qt::Key_Backspace:
  1013     case Qt::Key_Delete:
  1015       removePreviousPoint();
  1016       releaseLocks( 
false );
  1019     case Qt::Key_Escape:
  1026       filterKeyPress( e );
  1036   if ( event->
type() != QEvent::KeyPress )
  1045   return filterKeyPress( keyEvent ) ;
  1048 bool QgsAdvancedDigitizingDockWidget::filterKeyPress( 
QKeyEvent* e )
  1056         mXConstraint->toggleLocked();
  1059       else if ( e->
modifiers() == Qt::ShiftModifier )
  1063           mXConstraint->toggleRelative();
  1069         mXLineEdit->setFocus();
  1070         mXLineEdit->selectAll();
  1078         mYConstraint->toggleLocked();
  1081       else if ( e->
modifiers() == Qt::ShiftModifier )
  1085           mYConstraint->toggleRelative();
  1091         mYLineEdit->setFocus();
  1092         mYLineEdit->selectAll();
  1102           mAngleConstraint->toggleLocked();
  1106       else if ( e->
modifiers() == Qt::ShiftModifier )
  1110           mAngleConstraint->toggleRelative();
  1116         mAngleLineEdit->setFocus();
  1117         mAngleLineEdit->selectAll();
  1127           mDistanceConstraint->toggleLocked();
  1133         mDistanceLineEdit->setFocus();
  1134         mDistanceLineEdit->selectAll();
  1140       setConstructionMode( !mConstructionMode );
  1145       bool parallel = mParallelButton->isChecked();
  1146       bool perpendicular = mPerpendicularButton->isChecked();
  1148       if ( !parallel && !perpendicular )
  1152       else if ( perpendicular )
  1154         lockAdditionalConstraint( 
Parallel );
  1174     mErrorLabel->setText( 
tr( 
"CAD tools can not be used on geographic coordinates. Change the coordinates system in the project properties." ) );
  1175     mErrorLabel->show();
  1177     setCadEnabled( 
false );
  1182     mErrorLabel->hide();
  1186     mCurrentMapToolSupportsCad = 
true;
  1192     setCadEnabled( mSessionActive );
  1199   mErrorLabel->setText( 
tr( 
"CAD tools are not enabled for the current map tool" ) );
  1200   mErrorLabel->show();
  1204   mCurrentMapToolSupportsCad = 
false;
  1206   setCadEnabled( 
false );
  1209 void QgsAdvancedDigitizingDockWidget::addPoint( 
const QgsPoint& point )
  1213     mCadPointList << point;
  1217     mCadPointList.
insert( 0, point );
  1223 void QgsAdvancedDigitizingDockWidget::removePreviousPoint()
  1233 void QgsAdvancedDigitizingDockWidget::clearPoints()
  1235   mCadPointList.
clear();
  1236   mSnappedSegment.
clear();
  1237   mSnappedToVertex = 
false;
  1242 void QgsAdvancedDigitizingDockWidget::updateCurrentPoint( 
const QgsPoint& point )
  1246     mCadPointList << point;
  1251     mCadPointList[0] = point ;
  1259   mLockerButton->setChecked( mode == HardLock );
  1260   if ( mRepeatingLockButton )
  1262     if ( mode == HardLock )
  1264       mRepeatingLockButton->setEnabled( 
true );
  1268       mRepeatingLockButton->setChecked( 
false );
  1269       mRepeatingLockButton->setEnabled( 
false );
  1273   if ( mode == NoLock )
  1281   mRepeatingLock = repeating;
  1282   if ( mRepeatingLockButton )
  1283     mRepeatingLockButton->setChecked( repeating );
  1288   mRelative = relative;
  1289   if ( mRelativeButton )
  1291     mRelativeButton->setChecked( relative );
  1304   setLockMode( mLockMode == HardLock ? NoLock : HardLock );
  1309   setRelative( mRelative ? 
false : 
true );
  1317     return mCadPointList.
value( 0 );
  1327     return mCadPointList.
value( 1 );
  1337     return mCadPointList.
value( 2 );
 
void setText(const QString &text)
 
Class for parsing and evaluation of expressions (formerly called "search strings"). 
 
Qt::KeyboardModifiers modifiers() const
 
A event filter for watching for focus events on a parent object. 
 
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result. 
 
snap to all rendered layers (tolerance and type from defaultSettings()) 
 
QgsPoint mapPoint() const
mapPoint returns the point in coordinates 
 
bool acceptMatch(const QgsPointLocator::Match &m) override
 
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon. 
 
void setIcon(const QIcon &icon)
 
const T & at(int i) const
 
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas. 
 
QAction * addAction(QAction *action)
 
const_iterator constFind(const Key &key) const
 
Interface that allows rejection of some matches in intersection queries (e.g. 
 
double toDouble(bool *ok) const
 
QString tr(const char *sourceText, const char *disambiguation, int n)
 
Map canvas is a class for displaying all GIS data types on a canvas. 
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference) 
 
void update(const QRectF &rect)
 
double y() const
Get the y value of the point. 
 
void setValue(const QString &key, const QVariant &value)
 
QString number(int n, int base)
 
int count(const T &value) const
 
snap according to the configuration set in the snapping settings 
 
QString fromUtf8(const char *str, int size)
 
void installEventFilter(QObject *filterObj)
 
QList< QgsPoint > snapSegment(SnappingMode snappingMode, bool *snapped=nullptr, bool allLayers=false) const
Returns the first snapped segment. 
 
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map. 
 
const_iterator constEnd() const
 
void set(double x, double y)
Sets the x and y value of the point. 
 
A class to represent a point. 
 
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored) 
 
void setX(double x)
Sets the x value of the point. 
 
void setMapPoint(const QgsPoint &point)
Set the (snapped) point this event points to in map coordinates. 
 
void setY(double y)
Sets the y value of the point. 
 
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering. 
 
const Key key(const T &value) const
 
void insert(int i, const T &value)
 
double toDouble(bool *ok) const
 
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate. 
 
iterator insert(const Key &key, const T &value)
 
QgsPoint snapPoint(SnappingMode snappingMode)
snapPoint will snap the points using the map canvas snapping utils configuration 
 
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
 
bool hasEvalError() const
Returns true if an error occurred when evaluating last input. 
 
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
 
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system 
 
The QgsAdvancedDigitizingCanvasItem class draws the graphical elements of the CAD tools (...
 
double x() const
Get the x value of the point. 
 
bool geographicFlag() const
Returns whether the CRS is a geographic CRS. 
 
const T value(const Key &key) const