18 #include <QCoreApplication>
44 , mMapCanvas( canvas )
46 , mCommonAngleConstraint(
QgsSettings().value( QStringLiteral(
"/Cad/CommonAngle" ), 0.0 ).toDouble() )
52 mAngleConstraint.reset(
new CadConstraint( mAngleLineEdit, mLockAngleButton, mRelativeAngleButton, mRepeatingLockAngleButton ) );
53 mDistanceConstraint.reset(
new CadConstraint( mDistanceLineEdit, mLockDistanceButton,
nullptr, mRepeatingLockDistanceButton ) );
54 mXConstraint.reset(
new CadConstraint( mXLineEdit, mLockXButton, mRelativeXButton, mRepeatingLockXButton ) );
55 mYConstraint.reset(
new CadConstraint( mYLineEdit, mLockYButton, mRelativeYButton, mRepeatingLockYButton ) );
58 mMapCanvas->installEventFilter(
this );
59 mAngleLineEdit->installEventFilter(
this );
60 mDistanceLineEdit->installEventFilter(
this );
61 mXLineEdit->installEventFilter(
this );
62 mYLineEdit->installEventFilter(
this );
65 connect( mEnableAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::activateCad );
66 connect( mConstructionModeAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::setConstructionMode );
67 connect( mParallelAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::additionalConstraintClicked );
68 connect( mPerpendicularAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::additionalConstraintClicked );
69 connect( mLockAngleButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
70 connect( mLockDistanceButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
71 connect( mLockXButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
72 connect( mLockYButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
73 connect( mRelativeAngleButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
74 connect( mRelativeXButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
75 connect( mRelativeYButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
76 connect( mRepeatingLockDistanceButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
77 connect( mRepeatingLockAngleButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
78 connect( mRepeatingLockXButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
79 connect( mRepeatingLockYButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
80 connect( mAngleLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
81 connect( mDistanceLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
82 connect( mXLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
83 connect( mYLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
84 connect( mAngleLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
85 connect( mDistanceLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
86 connect( mXLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
87 connect( mYLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
99 QMenu *menu =
new QMenu(
this );
101 QActionGroup *angleButtonGroup =
new QActionGroup( menu );
102 mCommonAngleActions = QMap<QAction *, double>();
103 QList< QPair< double, QString > > commonAngles;
105 QList<double> anglesDouble( { 0.0, 5.0, 10.0, 15.0, 18.0, 22.5, 30.0, 45.0, 90.0} );
106 for ( QList<double>::const_iterator it = anglesDouble.constBegin(); it != anglesDouble.constEnd(); ++it )
109 menuText = tr(
"Do Not Snap to Common Angles" );
111 menuText = QString( tr(
"%1, %2, %3, %4°…" ) ).arg( *it, 0,
'f', 1 ).arg( *it * 2, 0,
'f', 1 ).arg( *it * 3, 0,
'f', 1 ).arg( *it * 4, 0,
'f', 1 );
112 commonAngles << QPair<double, QString>( *it, menuText );
114 for ( QList< QPair<double, QString > >::const_iterator it = commonAngles.constBegin(); it != commonAngles.constEnd(); ++it )
116 QAction *action =
new QAction( it->second, menu );
117 action->setCheckable(
true );
118 action->setChecked( it->first == mCommonAngleConstraint );
119 menu->addAction( action );
120 angleButtonGroup->addAction( action );
121 mCommonAngleActions.insert( action, it->first );
124 qobject_cast< QToolButton *>( mToolbar->widgetForAction( mSettingsAction ) )->setPopupMode( QToolButton::InstantPopup );
125 mSettingsAction->setMenu( menu );
126 connect( menu, &QMenu::triggered,
this, &QgsAdvancedDigitizingDockWidget::settingsButtonTriggered );
129 mConstructionModeAction->setToolTip(
"<b>" + tr(
"Construction mode" ) +
"</b><br>(" + tr(
"press c to toggle on/off" ) +
")" );
130 mDistanceLineEdit->setToolTip(
"<b>" + tr(
"Distance" ) +
"</b><br>(" + tr(
"press d for quick access" ) +
")" );
131 mLockDistanceButton->setToolTip(
"<b>" + tr(
"Lock distance" ) +
"</b><br>(" + tr(
"press Ctrl + d for quick access" ) +
")" );
132 mRepeatingLockDistanceButton->setToolTip(
"<b>" + tr(
"Continuously lock distance" ) +
"</b>" );
134 mRelativeAngleButton->setToolTip(
"<b>" + tr(
"Toggles relative angle to previous segment" ) +
"</b><br>(" + tr(
"press Shift + a for quick access" ) +
")" );
135 mAngleLineEdit->setToolTip(
"<b>" + tr(
"Angle" ) +
"</b><br>(" + tr(
"press a for quick access" ) +
")" );
136 mLockAngleButton->setToolTip(
"<b>" + tr(
"Lock angle" ) +
"</b><br>(" + tr(
"press Ctrl + a for quick access" ) +
")" );
137 mRepeatingLockAngleButton->setToolTip(
"<b>" + tr(
"Continuously lock angle" ) +
"</b>" );
139 mRelativeXButton->setToolTip(
"<b>" + tr(
"Toggles relative x to previous node" ) +
"</b><br>(" + tr(
"press Shift + x for quick access" ) +
")" );
140 mXLineEdit->setToolTip(
"<b>" + tr(
"X coordinate" ) +
"</b><br>(" + tr(
"press x for quick access" ) +
")" );
141 mLockXButton->setToolTip(
"<b>" + tr(
"Lock x coordinate" ) +
"</b><br>(" + tr(
"press Ctrl + x for quick access" ) +
")" );
142 mRepeatingLockXButton->setToolTip(
"<b>" + tr(
"Continuously lock x coordinate" ) +
"</b>" );
144 mRelativeYButton->setToolTip(
"<b>" + tr(
"Toggles relative y to previous node" ) +
"</b><br>(" + tr(
"press Shift + y for quick access" ) +
")" );
145 mYLineEdit->setToolTip(
"<b>" + tr(
"Y coordinate" ) +
"</b><br>(" + tr(
"press y for quick access" ) +
")" );
146 mLockYButton->setToolTip(
"<b>" + tr(
"Lock y coordinate" ) +
"</b><br>(" + tr(
"press Ctrl + y for quick access" ) +
")" );
147 mRepeatingLockYButton->setToolTip(
"<b>" + tr(
"Continuously lock y coordinate" ) +
"</b>" );
158 mToggleFloaterAction->setChecked( mFloater->
active() );
160 updateCapacity(
true );
168 mXLineEdit->setText( value );
169 if ( mode == WidgetSetMode::ReturnPressed )
171 mXLineEdit->returnPressed();
173 else if ( mode == WidgetSetMode::FocusOut )
175 QEvent *e =
new QEvent( QEvent::FocusOut );
176 QCoreApplication::postEvent( mXLineEdit, e );
178 else if ( mode == WidgetSetMode::TextEdited )
180 mXLineEdit->textEdited( value );
185 mYLineEdit->setText( value );
186 if ( mode == WidgetSetMode::ReturnPressed )
188 mYLineEdit->returnPressed();
190 else if ( mode == WidgetSetMode::FocusOut )
192 QEvent *e =
new QEvent( QEvent::FocusOut );
193 QCoreApplication::postEvent( mYLineEdit, e );
195 else if ( mode == WidgetSetMode::TextEdited )
197 mYLineEdit->textEdited( value );
202 mAngleLineEdit->setText( value );
203 if ( mode == WidgetSetMode::ReturnPressed )
205 mAngleLineEdit->returnPressed();
207 else if ( mode == WidgetSetMode::FocusOut )
209 QEvent *e =
new QEvent( QEvent::FocusOut );
210 QCoreApplication::postEvent( mAngleLineEdit, e );
212 else if ( mode == WidgetSetMode::TextEdited )
214 mAngleLineEdit->textEdited( value );
219 mDistanceLineEdit->setText( value );
220 if ( mode == WidgetSetMode::ReturnPressed )
222 mDistanceLineEdit->returnPressed();
224 else if ( mode == WidgetSetMode::FocusOut )
226 QEvent *e =
new QEvent( QEvent::FocusOut );
227 QCoreApplication::postEvent( mDistanceLineEdit, e );
229 else if ( mode == WidgetSetMode::TextEdited )
231 mDistanceLineEdit->textEdited( value );
236 void QgsAdvancedDigitizingDockWidget::setCadEnabled(
bool enabled )
238 mCadEnabled = enabled;
239 mEnableAction->setChecked( enabled );
240 mConstructionModeAction->setEnabled( enabled );
241 mParallelAction->setEnabled( enabled );
242 mPerpendicularAction->setEnabled( enabled );
243 mSettingsAction->setEnabled( enabled );
244 mInputWidgets->setEnabled( enabled );
245 mToggleFloaterAction->setEnabled( enabled );
248 setConstructionMode(
false );
253 void QgsAdvancedDigitizingDockWidget::activateCad(
bool enabled )
255 enabled &= mCurrentMapToolSupportsCad;
257 mSessionActive = enabled;
259 if ( enabled && !isVisible() )
264 setCadEnabled( enabled );
267 void QgsAdvancedDigitizingDockWidget::additionalConstraintClicked(
bool activated )
273 if ( sender() == mParallelAction )
277 else if ( sender() == mPerpendicularAction )
283 void QgsAdvancedDigitizingDockWidget::setConstraintRelative(
bool activate )
285 if ( sender() == mRelativeAngleButton )
287 mAngleConstraint->setRelative( activate );
290 else if ( sender() == mRelativeXButton )
292 mXConstraint->setRelative( activate );
295 else if ( sender() == mRelativeYButton )
297 mYConstraint->setRelative( activate );
302 void QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock(
bool activate )
304 if ( sender() == mRepeatingLockDistanceButton )
306 mDistanceConstraint->setRepeatingLock( activate );
308 else if ( sender() == mRepeatingLockAngleButton )
310 mAngleConstraint->setRepeatingLock( activate );
312 else if ( sender() == mRepeatingLockXButton )
314 mXConstraint->setRepeatingLock( activate );
316 else if ( sender() == mRepeatingLockYButton )
318 mYConstraint->setRepeatingLock( activate );
322 void QgsAdvancedDigitizingDockWidget::setConstructionMode(
bool enabled )
324 mConstructionMode = enabled;
325 mConstructionModeAction->setChecked( enabled );
328 void QgsAdvancedDigitizingDockWidget::settingsButtonTriggered( QAction *action )
331 QMap<QAction *, double>::const_iterator ica = mCommonAngleActions.constFind( action );
332 if ( ica != mCommonAngleActions.constEnd() )
334 ica.key()->setChecked(
true );
335 mCommonAngleConstraint = ica.value();
347 if ( releaseRepeatingLocks || !mAngleConstraint->isRepeatingLock() )
352 if ( releaseRepeatingLocks || !mDistanceConstraint->isRepeatingLock() )
357 if ( releaseRepeatingLocks || !mXConstraint->isRepeatingLock() )
362 if ( releaseRepeatingLocks || !mYConstraint->isRepeatingLock() )
368 if ( !mCadPointList.empty() )
370 if ( !mXConstraint->isLocked() && !mXConstraint->relative() )
372 mXConstraint->setValue( mCadPointList.constLast().x(),
true );
374 if ( !mYConstraint->isLocked() && !mYConstraint->relative() )
376 mYConstraint->setValue( mCadPointList.constLast().y(),
true );
383 void QgsAdvancedDigitizingDockWidget::emit pointChanged()
386 QPoint globalPos = mMapCanvas->cursor().pos();
387 QPoint pos = mMapCanvas->mapFromGlobal( globalPos );
388 QMouseEvent *e =
new QMouseEvent( QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier );
389 mCurrentMapTool->canvasMoveEvent( e );
395 CadConstraint *constraint =
nullptr;
396 if ( obj == mAngleLineEdit || obj == mLockAngleButton )
398 constraint = mAngleConstraint.get();
400 else if ( obj == mDistanceLineEdit || obj == mLockDistanceButton )
402 constraint = mDistanceConstraint.get();
404 else if ( obj == mXLineEdit || obj == mLockXButton )
406 constraint = mXConstraint.get();
408 else if ( obj == mYLineEdit || obj == mLockYButton )
410 constraint = mYConstraint.get();
415 double QgsAdvancedDigitizingDockWidget::parseUserInput(
const QString &inputValue,
bool &ok )
const
427 QVariant result = expr.evaluate();
428 if ( expr.hasEvalError() )
431 value = result.toDouble( &ok );
436 void QgsAdvancedDigitizingDockWidget::updateConstraintValue( CadConstraint *constraint,
const QString &textValue,
bool convertExpression )
438 if ( !constraint || textValue.isEmpty() )
447 double value = parseUserInput( textValue, ok );
451 constraint->setValue( value, convertExpression );
456 void QgsAdvancedDigitizingDockWidget::lockConstraint(
bool activate )
458 CadConstraint *constraint = objectToConstraint( sender() );
466 QString textValue = constraint->lineEdit()->text();
467 if ( !textValue.isEmpty() )
470 double value = parseUserInput( textValue, ok );
473 constraint->setValue( value );
487 if ( constraint == mXConstraint.get() )
491 else if ( constraint == mYConstraint.get() )
495 else if ( constraint == mDistanceConstraint.get() )
499 else if ( constraint == mAngleConstraint.get() )
507 if ( constraint == mAngleConstraint.get() )
517 void QgsAdvancedDigitizingDockWidget::constraintTextEdited(
const QString &textValue )
519 CadConstraint *constraint = objectToConstraint( sender() );
525 updateConstraintValue( constraint, textValue,
false );
528 void QgsAdvancedDigitizingDockWidget::constraintFocusOut()
530 QLineEdit *lineEdit = qobject_cast< QLineEdit * >( sender()->parent() );
534 CadConstraint *constraint = objectToConstraint( lineEdit );
540 updateConstraintValue( constraint, lineEdit->text(),
true );
543 void QgsAdvancedDigitizingDockWidget::lockAdditionalConstraint( AdditionalConstraint constraint )
545 mAdditionalConstraint = constraint;
550 void QgsAdvancedDigitizingDockWidget::updateCapacity(
bool updateUIwithoutChange )
552 CadCapacities newCapacities = CadCapacities();
554 if ( mCadPointList.count() > 1 )
558 if ( mCadPointList.count() > 2 )
562 if ( !updateUIwithoutChange && newCapacities == mCapacities )
572 bool relativeAngle = mCadEnabled && newCapacities.testFlag(
RelativeAngle );
573 bool absoluteAngle = mCadEnabled && newCapacities.testFlag(
AbsoluteAngle );
576 mPerpendicularAction->setEnabled( absoluteAngle && snappingEnabled );
577 mParallelAction->setEnabled( absoluteAngle && snappingEnabled );
580 if ( !snappingEnabled )
582 mPerpendicularAction->setToolTip( tr(
"Snapping must be enabled to utilize perpendicular mode" ) );
583 mParallelAction->setToolTip( tr(
"Snapping must be enabled to utilize parallel mode" ) );
587 mPerpendicularAction->setToolTip(
"<b>" + tr(
"Perpendicular" ) +
"</b><br>(" + tr(
"press p to switch between perpendicular, parallel and normal mode" ) +
")" );
588 mParallelAction->setToolTip(
"<b>" + tr(
"Parallel" ) +
"</b><br>(" + tr(
"press p to switch between perpendicular, parallel and normal mode" ) +
")" );
592 if ( !absoluteAngle )
598 mLockAngleButton->setEnabled( absoluteAngle );
599 mRelativeAngleButton->setEnabled( relativeAngle );
600 mAngleLineEdit->setEnabled( absoluteAngle );
602 if ( !absoluteAngle )
606 if ( !relativeAngle )
608 mAngleConstraint->setRelative(
false );
611 else if ( relativeAngle && !mCapacities.testFlag(
RelativeAngle ) )
614 mAngleConstraint->setRelative(
true );
619 mLockDistanceButton->setEnabled( relativeCoordinates );
620 mDistanceLineEdit->setEnabled( relativeCoordinates );
622 if ( !relativeCoordinates )
627 mRelativeXButton->setEnabled( relativeCoordinates );
628 mRelativeYButton->setEnabled( relativeCoordinates );
631 mCapacities = newCapacities;
640 constr.
value =
c->value();
649 context.
xConstraint = _constraint( mXConstraint.get() );
650 context.
yConstraint = _constraint( mYConstraint.get() );
661 bool res = output.
valid;
663 mSnappedSegment.clear();
668 mSnappedSegment << edgePt0 << edgePt1;
685 mSnapIndicator->setMatch( output.
snapMatch );
686 mSnapIndicator->setVisible(
true );
690 mSnapIndicator->setVisible(
false );
708 updateCurrentPoint( point );
710 updateUnlockedConstraintValues( point );
718 emit
pushWarning( tr(
"Some constraints are incompatible. Resulting point might be incorrect." ) );
725 void QgsAdvancedDigitizingDockWidget::updateUnlockedConstraintValues(
const QgsPointXY &point )
727 bool previousPointExist, penulPointExist;
732 if ( !mAngleConstraint->isLocked() && previousPointExist )
735 if ( penulPointExist && mAngleConstraint->relative() )
738 angle = std::atan2( previousPt.
y() - penultimatePt.
y(),
739 previousPt.
x() - penultimatePt.
x() );
741 angle = ( std::atan2( point.
y() - previousPt.
y(),
742 point.
x() - previousPt.
x()
743 ) -
angle ) * 180 / M_PI;
746 mAngleConstraint->setValue(
angle );
749 if ( !mDistanceConstraint->isLocked() && previousPointExist )
751 mDistanceConstraint->setValue( std::sqrt( previousPt.
sqrDist( point ) ) );
754 if ( !mXConstraint->isLocked() )
756 if ( previousPointExist && mXConstraint->relative() )
758 mXConstraint->setValue( point.
x() - previousPt.
x() );
762 mXConstraint->setValue( point.
x() );
766 if ( !mYConstraint->isLocked() )
768 if ( previousPointExist && mYConstraint->relative() )
770 mYConstraint->setValue( point.
y() - previousPt.
y() );
774 mYConstraint->setValue( point.
y() );
780 QList<QgsPointXY> QgsAdvancedDigitizingDockWidget::snapSegmentToAllLayers(
const QgsPointXY &originalMapPoint,
bool *snapped )
const
782 QList<QgsPointXY> segment;
795 match = snappingUtils->
snapToMap( originalMapPoint,
nullptr,
true );
797 snappingUtils->
setConfig( canvasConfig );
802 segment << pt1 << pt2;
807 *snapped = segment.count() == 2;
820 bool previousPointExist, penulPointExist, snappedSegmentExist;
823 mSnappedSegment = snapSegmentToAllLayers( e->
originalMapPoint(), &snappedSegmentExist );
825 if ( !previousPointExist || !snappedSegmentExist )
830 double angle = std::atan2( mSnappedSegment[0].y() - mSnappedSegment[1].y(), mSnappedSegment[0].x() - mSnappedSegment[1].x() );
832 if ( mAngleConstraint->relative() && penulPointExist )
834 angle -= std::atan2( previousPt.
y() - penultimatePt.
y(), previousPt.
x() - penultimatePt.
x() );
844 mAngleConstraint->setValue(
angle );
845 mAngleConstraint->setLockMode( lockMode );
863 case Qt::Key_Backspace:
900 case Qt::Key_Backspace:
923 const auto constPoints = points;
930 bool QgsAdvancedDigitizingDockWidget::eventFilter( QObject *obj, QEvent *event )
934 return QgsDockWidget::eventFilter( obj, event );
942 if ( event->type() == QEvent::ShortcutOverride || event->type() == QEvent::KeyPress )
944 if ( QKeyEvent *keyEvent =
dynamic_cast<QKeyEvent *
>( event ) )
946 return filterKeyPress( keyEvent );
949 return QgsDockWidget::eventFilter( obj, event );
952 bool QgsAdvancedDigitizingDockWidget::filterKeyPress( QKeyEvent *e )
958 QEvent::Type type = e->type();
964 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
966 mXConstraint->toggleLocked();
971 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
975 mXConstraint->toggleRelative();
982 else if ( type == QEvent::KeyPress )
984 mXLineEdit->setFocus();
985 mXLineEdit->selectAll();
994 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
996 mYConstraint->toggleLocked();
1001 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1005 mYConstraint->toggleRelative();
1012 else if ( type == QEvent::KeyPress )
1014 mYLineEdit->setFocus();
1015 mYLineEdit->selectAll();
1024 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1028 mAngleConstraint->toggleLocked();
1034 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1038 mAngleConstraint->toggleRelative();
1045 else if ( type == QEvent::KeyPress )
1047 mAngleLineEdit->setFocus();
1048 mAngleLineEdit->selectAll();
1057 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1061 mDistanceConstraint->toggleLocked();
1068 else if ( type == QEvent::KeyPress )
1070 mDistanceLineEdit->setFocus();
1071 mDistanceLineEdit->selectAll();
1079 if ( type == QEvent::KeyPress )
1081 setConstructionMode( !mConstructionMode );
1088 if ( type == QEvent::KeyPress )
1090 bool parallel = mParallelAction->isChecked();
1091 bool perpendicular = mPerpendicularAction->isChecked();
1093 if ( !parallel && !perpendicular )
1097 else if ( perpendicular )
1114 return e->isAccepted();
1122 mErrorLabel->setText( tr(
"CAD tools can not be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1123 mErrorLabel->show();
1124 mEnableAction->setEnabled(
false );
1125 setCadEnabled(
false );
1129 mEnableAction->setEnabled(
true );
1130 mErrorLabel->hide();
1133 mCurrentMapToolSupportsCad =
true;
1135 if ( mSessionActive && !isVisible() )
1139 setCadEnabled( mSessionActive );
1147 mEnableAction->setEnabled(
false );
1148 mErrorLabel->setText( tr(
"CAD tools are not enabled for the current map tool" ) );
1149 mErrorLabel->show();
1152 mCurrentMapToolSupportsCad =
false;
1154 setCadEnabled(
false );
1159 mCadPaintItem->update();
1166 mCadPointList << point;
1170 mCadPointList.insert( 0, point );
1183 mCadPointList.removeAt( i );
1190 mCadPointList.clear();
1191 mSnappedSegment.clear();
1197 void QgsAdvancedDigitizingDockWidget::updateCurrentPoint(
const QgsPointXY &point )
1201 mCadPointList << point;
1206 mCadPointList[0] = point;
1215 mLockerButton->setChecked( mode ==
HardLock );
1216 if ( mRepeatingLockButton )
1220 mRepeatingLockButton->setEnabled(
true );
1224 mRepeatingLockButton->setChecked(
false );
1225 mRepeatingLockButton->setEnabled(
false );
1238 mRepeatingLock = repeating;
1239 if ( mRepeatingLockButton )
1240 mRepeatingLockButton->setChecked( repeating );
1245 mRelative = relative;
1246 if ( mRelativeButton )
1248 mRelativeButton->setChecked( relative );
1256 mLineEdit->setText( QLocale().toString( value,
'f', 6 ) );
1261 setLockMode( mLockMode == HardLock ? NoLock : HardLock );
1266 setRelative( !mRelative );
1274 return mCadPointList.value( 0 );
1284 return mCadPointList.value( 1 );
1294 return mCadPointList.value( 2 );
The QgsAdvancedDigitizingCanvasItem class draws the graphical elements of the CAD tools (.
The QgsAdvancedDigitizingFloater class is widget that floats next to the mouse pointer,...
void setActive(bool active)
Set whether the floater should be active or not.
bool active()
Whether the floater is active or not.
static QgsCadUtils::AlignMapPointOutput alignMapPoint(const QgsPointXY &originalMapPoint, const QgsCadUtils::AlignMapPointContext &ctx)
Applies X/Y/angle/distance constraints from the given context to a map point.
Class for parsing and evaluation of expressions (formerly called "search strings").
A event filter for watching for focus events on a parent object.
void focusOut()
Emitted when parent object loses focus.
Map canvas is a class for displaying all GIS data types on a canvas.
QgsSnappingUtils * snappingUtils() const
Returns snapping utility class that is associated with map canvas.
void destinationCrsChanged()
Emitted when map CRS has changed.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
QgsPointXY originalMapPoint() const
Returns the original, unmodified map point of the mouse cursor.
void setMapPoint(const QgsPointXY &point)
Set the (snapped) point this event points to in map coordinates.
QgsPointXY snapPoint()
snapPoint will snap the points using the map canvas snapping utils configuration
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
A class to represent a 2D point.
double sqrDist(double x, double y) const SIP_HOLDGIL
Returns the squared distance between this point a specified x, y coordinate.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void snappingConfigChanged(const QgsSnappingConfig &config)
Emitted whenever the configuration for snapping has changed.
QgsSnappingConfig snappingConfig
This class is a composition of two QSettings instances:
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Class that shows snapping marker on map canvas for the current snapping match.
This is a container for configuration of the snapping of the project.
@ AllLayers
On all vector layers.
@ SegmentFlag
On segments.
void setTypeFlag(QgsSnappingConfig::SnappingTypeFlag type)
define the type of snapping
void setMode(SnappingMode mode)
define the mode of snapping
bool enabled() const
Returns if snapping is enabled.
This class has all the configuration of snapping and can return answers to snapping queries.
QgsPointLocator::Match snapToMap(QPoint point, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Snap to map according to the current configuration.
void setConfig(const QgsSnappingConfig &snappingConfig)
The snapping configuration controls the behavior of this object.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
double qgsPermissiveToDouble(QString string, bool &ok)
Converts a string to a double in a permissive way, e.g., allowing for incorrect numbers of digits bet...
Structure with details of one constraint.
bool locked
Whether the constraint is active, i.e. should be considered.
double value
Numeric value of the constraint (coordinate/distance in map units or angle in degrees)
bool relative
Whether the value is relative to previous value.
Structure defining all constraints for alignMapPoint() method.
QgsCadUtils::AlignMapPointConstraint yConstraint
Constraint for Y coordinate.
QgsCadUtils::AlignMapPointConstraint xConstraint
Constraint for X coordinate.
double mapUnitsPerPixel
Map units/pixel ratio from map canvas. Needed for.
QgsCadUtils::AlignMapPointConstraint distanceConstraint
Constraint for distance.
QList< QgsPointXY > cadPointList
List of recent CAD points in map coordinates.
QgsSnappingUtils * snappingUtils
Snapping utils that will be used to snap point to map. Must not be nullptr.
QgsCadUtils::AlignMapPointConstraint commonAngleConstraint
Constraint for soft lock to a common angle.
QgsCadUtils::AlignMapPointConstraint angleConstraint
Constraint for angle.
Structure returned from alignMapPoint() method.
QgsPointXY finalMapPoint
map point aligned according to the constraints
bool valid
Whether the combination of constraints is actually valid.
QgsPointLocator::Match snapMatch
Snapped point - only valid if actually used for something.
double softLockCommonAngle
Angle (in degrees) to which we have soft-locked ourselves (if not set it is -1)
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
bool hasEdge() const
Returns true if the Match is an edge.
void edgePoints(QgsPointXY &pt1, QgsPointXY &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
bool hasVertex() const
Returns true if the Match is a vertex.