18#include <QCoreApplication>
42#include <QActionGroup>
50 , mMapCanvas( canvas )
52 , mCommonAngleConstraint(
QgsSettings().value( QStringLiteral(
"/Cad/CommonAngle" ), 0.0 ).toDouble() )
58 mAngleConstraint.reset(
new CadConstraint( mAngleLineEdit, mLockAngleButton, mRelativeAngleButton, mRepeatingLockAngleButton ) );
60 mAngleConstraint->setMapCanvas( mMapCanvas );
61 mDistanceConstraint.reset(
new CadConstraint( mDistanceLineEdit, mLockDistanceButton,
nullptr, mRepeatingLockDistanceButton ) );
63 mDistanceConstraint->setMapCanvas( mMapCanvas );
64 mXConstraint.reset(
new CadConstraint( mXLineEdit, mLockXButton, mRelativeXButton, mRepeatingLockXButton ) );
66 mXConstraint->setMapCanvas( mMapCanvas );
67 mYConstraint.reset(
new CadConstraint( mYLineEdit, mLockYButton, mRelativeYButton, mRepeatingLockYButton ) );
69 mYConstraint->setMapCanvas( mMapCanvas );
70 mZConstraint.reset(
new CadConstraint( mZLineEdit, mLockZButton, mRelativeZButton, mRepeatingLockZButton ) );
72 mZConstraint->setMapCanvas( mMapCanvas );
73 mMConstraint.reset(
new CadConstraint( mMLineEdit, mLockMButton, mRelativeMButton, mRepeatingLockMButton ) );
75 mMConstraint->setMapCanvas( mMapCanvas );
77 mLineExtensionConstraint.reset(
new CadConstraint(
new QLineEdit(),
new QToolButton() ) );
78 mXyVertexConstraint.reset(
new CadConstraint(
new QLineEdit(),
new QToolButton() ) );
79 mXyVertexConstraint->setMapCanvas( mMapCanvas );
83 mMapCanvas->installEventFilter(
this );
84 mAngleLineEdit->installEventFilter(
this );
85 mDistanceLineEdit->installEventFilter(
this );
86 mXLineEdit->installEventFilter(
this );
87 mYLineEdit->installEventFilter(
this );
88 mZLineEdit->installEventFilter(
this );
89 mMLineEdit->installEventFilter(
this );
92 connect( mEnableAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::activateCad );
93 connect( mConstructionModeAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::setConstructionMode );
94 connect( mParallelAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::betweenLineConstraintClicked );
95 connect( mPerpendicularAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::betweenLineConstraintClicked );
96 connect( mLockAngleButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
97 connect( mLockDistanceButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
98 connect( mLockXButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
99 connect( mLockYButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
100 connect( mLockZButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
101 connect( mLockMButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::lockConstraint );
102 connect( mRelativeAngleButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
103 connect( mRelativeXButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
104 connect( mRelativeYButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
105 connect( mRelativeZButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
106 connect( mRelativeMButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRelative );
107 connect( mRepeatingLockDistanceButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
108 connect( mRepeatingLockAngleButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
109 connect( mRepeatingLockXButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
110 connect( mRepeatingLockYButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
111 connect( mRepeatingLockZButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
112 connect( mRepeatingLockMButton, &QAbstractButton::clicked,
this, &QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock );
113 connect( mAngleLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
114 connect( mDistanceLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
115 connect( mXLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
116 connect( mYLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
117 connect( mZLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
118 connect( mMLineEdit, &QLineEdit::returnPressed,
this, [ = ]() { lockConstraint(); } );
119 connect( mAngleLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
120 connect( mDistanceLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
121 connect( mXLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
122 connect( mYLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
123 connect( mZLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
124 connect( mMLineEdit, &QLineEdit::textEdited,
this, &QgsAdvancedDigitizingDockWidget::constraintTextEdited );
131 whileBlocking( mAngleLineEdit )->setText( cleanedInputValue );
138 whileBlocking( mDistanceLineEdit )->setText( cleanedInputValue );
150 mCommonAngleActionsMenu =
new QMenu(
this );
152#ifndef __clang_analyzer__
153 QActionGroup *angleButtonGroup =
new QActionGroup( mCommonAngleActionsMenu );
155 QList< QPair< double, QString > > commonAngles;
156 const QList<double> anglesDouble( { 0.0, 0.1, 0.5, 1.0, 5.0, 10.0, 15.0, 18.0, 22.5, 30.0, 45.0, 90.0} );
157 for ( QList<double>::const_iterator it = anglesDouble.constBegin(); it != anglesDouble.constEnd(); ++it )
163 QMenu *snappingPriorityMenu =
new QMenu( tr(
"Snapping Priority" ), mCommonAngleActionsMenu );
164 QActionGroup *snappingPriorityActionGroup =
new QActionGroup( snappingPriorityMenu );
165 QAction *featuresAction =
new QAction( tr(
"Prioritize Snapping to Features" ), snappingPriorityActionGroup );
166 featuresAction->setCheckable(
true );
167 QAction *anglesAction =
new QAction( tr(
"Prioritize Snapping to Common Angles" ), snappingPriorityActionGroup );
168 anglesAction->setCheckable(
true );
169 snappingPriorityActionGroup->addAction( featuresAction );
170 snappingPriorityActionGroup->addAction( anglesAction );
171 snappingPriorityMenu->addAction( anglesAction );
172 snappingPriorityMenu->addAction( featuresAction );
173 connect( anglesAction, &QAction::changed,
this, [ = ]
175 mSnappingPrioritizeFeatures = featuresAction->isChecked();
176 settingsCadSnappingPriorityPrioritizeFeature->
setValue( featuresAction->isChecked() );
178 featuresAction->setChecked( settingsCadSnappingPriorityPrioritizeFeature->
value( ) );
179 anglesAction->setChecked( ! featuresAction->isChecked() );
180 mCommonAngleActionsMenu->addMenu( snappingPriorityMenu );
184 for ( QList< QPair<double, QString > >::const_iterator it = commonAngles.constBegin(); it != commonAngles.constEnd(); ++it )
186 QAction *action =
new QAction( it->second, mCommonAngleActionsMenu );
187 action->setCheckable(
true );
188 action->setChecked( it->first == mCommonAngleConstraint );
189 mCommonAngleActionsMenu->addAction( action );
191#ifndef __clang_analyzer__
192 angleButtonGroup->addAction( action );
194 mCommonAngleActions.insert( it->first, action );
197 qobject_cast< QToolButton *>( mToolbar->widgetForAction( mSettingsAction ) )->setPopupMode( QToolButton::InstantPopup );
198 mSettingsAction->setMenu( mCommonAngleActionsMenu );
199 mSettingsAction->setCheckable(
true );
200 mSettingsAction->setToolTip(
"<b>" + tr(
"Snap to common angles" ) +
"</b><br>(" + tr(
"press n to cycle through the options" ) +
")" );
201 mSettingsAction->setChecked( mCommonAngleConstraint != 0 );
202 connect( mCommonAngleActionsMenu, &QMenu::triggered,
this, &QgsAdvancedDigitizingDockWidget::settingsButtonTriggered );
205 QMenu *constructionMenu =
new QMenu(
this );
207 mLineExtensionAction =
new QAction( tr(
"Line Extension" ), constructionMenu );
208 mLineExtensionAction->setCheckable(
true );
209 constructionMenu->addAction( mLineExtensionAction );
210 connect( mLineExtensionAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::lockParameterlessConstraint );
212 mXyVertexAction =
new QAction( tr(
"X/Y Point" ), constructionMenu );
213 mXyVertexAction->setCheckable(
true );
214 constructionMenu->addAction( mXyVertexAction );
215 connect( mXyVertexAction, &QAction::triggered,
this, &QgsAdvancedDigitizingDockWidget::lockParameterlessConstraint );
217 auto constructionToolBar = qobject_cast< QToolButton *>( mToolbar->widgetForAction( mConstructionAction ) );
218 constructionToolBar->setPopupMode( QToolButton::InstantPopup );
219 constructionToolBar->setMenu( constructionMenu );
220 constructionToolBar->setObjectName( QStringLiteral(
"ConstructionButton" ) );
222 mConstructionAction->setMenu( mCommonAngleActionsMenu );
223 mConstructionAction->setCheckable(
true );
224 mConstructionAction->setToolTip( tr(
"Construction Tools" ) );
228 mConstructionModeAction->setToolTip(
"<b>" + tr(
"Construction mode" ) +
"</b><br>(" + tr(
"press c to toggle on/off" ) +
")" );
229 mDistanceLineEdit->setToolTip(
"<b>" + tr(
"Distance" ) +
"</b><br>(" + tr(
"press d for quick access" ) +
")" );
230 mLockDistanceButton->setToolTip(
"<b>" + tr(
"Lock distance" ) +
"</b><br>(" + tr(
"press Ctrl + d for quick access" ) +
")" );
231 mRepeatingLockDistanceButton->setToolTip(
"<b>" + tr(
"Continuously lock distance" ) +
"</b>" );
233 mRelativeAngleButton->setToolTip(
"<b>" + tr(
"Toggles relative angle to previous segment" ) +
"</b><br>(" + tr(
"press Shift + a for quick access" ) +
")" );
234 mAngleLineEdit->setToolTip(
"<b>" + tr(
"Angle" ) +
"</b><br>(" + tr(
"press a for quick access" ) +
")" );
235 mLockAngleButton->setToolTip(
"<b>" + tr(
"Lock angle" ) +
"</b><br>(" + tr(
"press Ctrl + a for quick access" ) +
")" );
236 mRepeatingLockAngleButton->setToolTip(
"<b>" + tr(
"Continuously lock angle" ) +
"</b>" );
238 mRelativeXButton->setToolTip(
"<b>" + tr(
"Toggles relative x to previous node" ) +
"</b><br>(" + tr(
"press Shift + x for quick access" ) +
")" );
239 mXLineEdit->setToolTip(
"<b>" + tr(
"X coordinate" ) +
"</b><br>(" + tr(
"press x for quick access" ) +
")" );
240 mLockXButton->setToolTip(
"<b>" + tr(
"Lock x coordinate" ) +
"</b><br>(" + tr(
"press Ctrl + x for quick access" ) +
")" );
241 mRepeatingLockXButton->setToolTip(
"<b>" + tr(
"Continuously lock x coordinate" ) +
"</b>" );
243 mRelativeYButton->setToolTip(
"<b>" + tr(
"Toggles relative y to previous node" ) +
"</b><br>(" + tr(
"press Shift + y for quick access" ) +
")" );
244 mYLineEdit->setToolTip(
"<b>" + tr(
"Y coordinate" ) +
"</b><br>(" + tr(
"press y for quick access" ) +
")" );
245 mLockYButton->setToolTip(
"<b>" + tr(
"Lock y coordinate" ) +
"</b><br>(" + tr(
"press Ctrl + y for quick access" ) +
")" );
246 mRepeatingLockYButton->setToolTip(
"<b>" + tr(
"Continuously lock y coordinate" ) +
"</b>" );
248 mRelativeZButton->setToolTip(
"<b>" + tr(
"Toggles relative z to previous node" ) +
"</b><br>(" + tr(
"press Shift + z for quick access" ) +
")" );
249 mZLineEdit->setToolTip(
"<b>" + tr(
"Z coordinate" ) +
"</b><br>(" + tr(
"press z for quick access" ) +
")" );
250 mLockZButton->setToolTip(
"<b>" + tr(
"Lock z coordinate" ) +
"</b><br>(" + tr(
"press Ctrl + z for quick access" ) +
")" );
251 mRepeatingLockZButton->setToolTip(
"<b>" + tr(
"Continuously lock z coordinate" ) +
"</b>" );
253 mRelativeMButton->setToolTip(
"<b>" + tr(
"Toggles relative m to previous node" ) +
"</b><br>(" + tr(
"press Shift + m for quick access" ) +
")" );
254 mMLineEdit->setToolTip(
"<b>" + tr(
"M coordinate" ) +
"</b><br>(" + tr(
"press m for quick access" ) +
")" );
255 mLockMButton->setToolTip(
"<b>" + tr(
"Lock m coordinate" ) +
"</b><br>(" + tr(
"press Ctrl + m for quick access" ) +
")" );
256 mRepeatingLockMButton->setToolTip(
"<b>" + tr(
"Continuously lock m coordinate" ) +
"</b>" );
267 mFloaterActionsMenu =
new QMenu(
this );
268 qobject_cast< QToolButton *>( mToolbar->widgetForAction( mFloaterAction ) )->setPopupMode( QToolButton::InstantPopup );
269 mFloaterAction->setMenu( mFloaterActionsMenu );
270 mFloaterAction->setCheckable(
true );
272 mFloaterAction->setChecked( mFloater->
active() );
276 QAction *action =
new QAction( tr(
"Show floater" ), mFloaterActionsMenu );
277 action->setCheckable(
true );
278 action->setChecked( mFloater->
active() );
279 mFloaterActionsMenu->addAction( action );
280 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
283 mFloaterAction->setChecked( checked );
287 mFloaterActionsMenu->addSeparator();
290 QAction *action =
new QAction( tr(
"Show distance" ), mFloaterActionsMenu );
291 action->setCheckable(
true );
292 mFloaterActionsMenu->addAction( action );
293 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
297 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/DistanceShowInFloater" ),
true ).toBool() );
301 QAction *action =
new QAction( tr(
"Show angle" ), mFloaterActionsMenu );
302 action->setCheckable(
true );
303 mFloaterActionsMenu->addAction( action );
304 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
308 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/AngleShowInFloater" ),
true ).toBool() );
312 QAction *action =
new QAction( tr(
"Show XY coordinates" ), mFloaterActionsMenu );
313 action->setCheckable(
true );
314 mFloaterActionsMenu->addAction( action );
315 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
321 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/XCoordinateShowInFloater" ),
true ).toBool() );
325 QAction *action =
new QAction( tr(
"Show Z value" ), mFloaterActionsMenu );
326 action->setCheckable(
true );
327 mFloaterActionsMenu->addAction( action );
328 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
332 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/ZCoordinateShowInFloater" ),
true ).toBool() );
336 QAction *action =
new QAction( tr(
"Show M value" ), mFloaterActionsMenu );
337 action->setCheckable(
true );
338 mFloaterActionsMenu->addAction( action );
339 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
343 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/MCoordinateShowInFloater" ),
true ).toBool() );
347 QAction *action =
new QAction( tr(
"Show bearing/azimuth" ), mFloaterActionsMenu );
348 action->setCheckable(
true );
349 mFloaterActionsMenu->addAction( action );
350 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
354 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/BearingShowInFloater" ),
false ).toBool() );
358 QAction *action =
new QAction( tr(
"Show common snapping angle" ), mFloaterActionsMenu );
359 action->setCheckable(
true );
360 mFloaterActionsMenu->addAction( action );
361 connect( action, &QAction::toggled,
this, [ = ](
bool checked )
365 action->setChecked(
QgsSettings().value( QStringLiteral(
"/Cad/CommonAngleSnappingShowInFloater" ),
false ).toBool() );
368 updateCapacity(
true );
377 return tr(
"Do Not Snap to Common Angles" );
379 return QString( tr(
"%1, %2, %3, %4°…" ) ).arg( angle, 0,
'f', 1 ).arg( angle * 2, 0,
'f', 1 ).arg( angle * 3, 0,
'f', 1 ).arg( angle * 4, 0,
'f', 1 );
384 mXLineEdit->setText( value );
387 emit mXLineEdit->returnPressed();
391 QEvent *e =
new QEvent( QEvent::FocusOut );
392 QCoreApplication::postEvent( mXLineEdit, e );
396 emit mXLineEdit->textEdited( value );
401 mYLineEdit->setText( value );
404 emit mYLineEdit->returnPressed();
408 QEvent *e =
new QEvent( QEvent::FocusOut );
409 QCoreApplication::postEvent( mYLineEdit, e );
413 emit mYLineEdit->textEdited( value );
418 mZLineEdit->setText( value );
421 emit mZLineEdit->returnPressed();
425 QEvent *e =
new QEvent( QEvent::FocusOut );
426 QCoreApplication::postEvent( mZLineEdit, e );
430 emit mZLineEdit->textEdited( value );
435 mMLineEdit->setText( value );
438 emit mMLineEdit->returnPressed();
442 QEvent *e =
new QEvent( QEvent::FocusOut );
443 QCoreApplication::postEvent( mMLineEdit, e );
447 emit mMLineEdit->textEdited( value );
452 mAngleLineEdit->setText( value );
455 emit mAngleLineEdit->returnPressed();
459 emit mAngleLineEdit->textEdited( value );
464 mDistanceLineEdit->setText( value );
467 emit mDistanceLineEdit->returnPressed();
471 QEvent *e =
new QEvent( QEvent::FocusOut );
472 QCoreApplication::postEvent( mDistanceLineEdit, e );
476 emit mDistanceLineEdit->textEdited( value );
481void QgsAdvancedDigitizingDockWidget::setCadEnabled(
bool enabled )
483 mCadEnabled = enabled;
484 mEnableAction->setChecked( enabled );
485 mConstructionModeAction->setEnabled( enabled );
486 mSettingsAction->setEnabled( enabled );
487 mInputWidgets->setEnabled( enabled );
488 mFloaterAction->setEnabled( enabled );
489 mConstructionAction->setEnabled( enabled );
494 mLineExtensionAction->setChecked(
false );
495 mXyVertexAction->setChecked(
false );
497 mParallelAction->setEnabled(
false );
498 mPerpendicularAction->setEnabled(
false );
504 setConstructionMode(
false );
520 bool enableZ =
false;
521 bool enableM =
false;
525 switch ( layer->type() )
538 QgsMeshLayer *mlayer = qobject_cast<QgsMeshLayer *>( layer );
560 mRelativeZButton->setEnabled(
enable );
561 mZLabel->setEnabled(
enable );
562 mZLineEdit->setEnabled(
enable );
563 if ( mZLineEdit->isEnabled() )
567 mLockZButton->setEnabled(
enable );
573 mRelativeMButton->setEnabled(
enable );
574 mMLabel->setEnabled(
enable );
575 mMLineEdit->setEnabled(
enable );
576 if ( mMLineEdit->isEnabled() )
580 mLockMButton->setEnabled(
enable );
584void QgsAdvancedDigitizingDockWidget::activateCad(
bool enabled )
586 enabled &= mCurrentMapToolSupportsCad;
588 mSessionActive = enabled;
590 if ( enabled && !isVisible() )
595 setCadEnabled( enabled );
598void QgsAdvancedDigitizingDockWidget::betweenLineConstraintClicked(
bool activated )
604 else if ( sender() == mParallelAction )
608 else if ( sender() == mPerpendicularAction )
614void QgsAdvancedDigitizingDockWidget::setConstraintRelative(
bool activate )
616 if ( sender() == mRelativeAngleButton )
618 mAngleConstraint->setRelative( activate );
621 else if ( sender() == mRelativeXButton )
623 mXConstraint->setRelative( activate );
626 else if ( sender() == mRelativeYButton )
628 mYConstraint->setRelative( activate );
631 else if ( sender() == mRelativeZButton )
633 mZConstraint->setRelative( activate );
636 else if ( sender() == mRelativeMButton )
638 mMConstraint->setRelative( activate );
643void QgsAdvancedDigitizingDockWidget::setConstraintRepeatingLock(
bool activate )
645 if ( sender() == mRepeatingLockDistanceButton )
647 mDistanceConstraint->setRepeatingLock( activate );
649 else if ( sender() == mRepeatingLockAngleButton )
651 mAngleConstraint->setRepeatingLock( activate );
653 else if ( sender() == mRepeatingLockXButton )
655 mXConstraint->setRepeatingLock( activate );
657 else if ( sender() == mRepeatingLockYButton )
659 mYConstraint->setRepeatingLock( activate );
661 else if ( sender() == mRepeatingLockZButton )
663 mZConstraint->setRepeatingLock( activate );
665 else if ( sender() == mRepeatingLockMButton )
667 mMConstraint->setRepeatingLock( activate );
671void QgsAdvancedDigitizingDockWidget::setConstructionMode(
bool enabled )
673 mConstructionMode = enabled;
674 mConstructionModeAction->setChecked( enabled );
677void QgsAdvancedDigitizingDockWidget::settingsButtonTriggered( QAction *action )
680 for (
auto it = mCommonAngleActions.cbegin(); it != mCommonAngleActions.cend(); ++it )
682 if ( it.value() == action )
684 it.value()->setChecked(
true );
685 mCommonAngleConstraint = it.key();
687 mSettingsAction->setChecked( mCommonAngleConstraint != 0 );
694QgsMapLayer *QgsAdvancedDigitizingDockWidget::targetLayer()
const
698 return advancedTool->layer();
712 if ( releaseRepeatingLocks )
714 mXyVertexAction->setChecked(
false );
718 mLineExtensionAction->setChecked(
false );
725 if ( releaseRepeatingLocks || !mAngleConstraint->isRepeatingLock() )
730 if ( releaseRepeatingLocks || !mDistanceConstraint->isRepeatingLock() )
735 if ( releaseRepeatingLocks || !mXConstraint->isRepeatingLock() )
740 if ( releaseRepeatingLocks || !mYConstraint->isRepeatingLock() )
745 if ( releaseRepeatingLocks || !mZConstraint->isRepeatingLock() )
750 if ( releaseRepeatingLocks || !mMConstraint->isRepeatingLock() )
756 if ( !mCadPointList.empty() )
758 if ( !mXConstraint->isLocked() && !mXConstraint->relative() )
760 mXConstraint->setValue( mCadPointList.constLast().x(),
true );
762 if ( !mYConstraint->isLocked() && !mYConstraint->relative() )
764 mYConstraint->setValue( mCadPointList.constLast().y(),
true );
766 if ( !mZConstraint->isLocked() && !mZConstraint->relative() )
768 mZConstraint->setValue( mCadPointList.constLast().z(),
true );
770 if ( !mMConstraint->isLocked() && !mMConstraint->relative() )
772 mMConstraint->setValue( mCadPointList.constLast().m(),
true );
779void QgsAdvancedDigitizingDockWidget::emit pointChanged()
782 QPoint globalPos = mMapCanvas->cursor().pos();
783 QPoint pos = mMapCanvas->mapFromGlobal( globalPos );
784 QMouseEvent *e =
new QMouseEvent( QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier );
785 mCurrentMapTool->canvasMoveEvent( e );
791 CadConstraint *constraint =
nullptr;
792 if ( obj == mAngleLineEdit || obj == mLockAngleButton )
794 constraint = mAngleConstraint.get();
796 else if ( obj == mDistanceLineEdit || obj == mLockDistanceButton )
798 constraint = mDistanceConstraint.get();
800 else if ( obj == mXLineEdit || obj == mLockXButton )
802 constraint = mXConstraint.get();
804 else if ( obj == mYLineEdit || obj == mLockYButton )
806 constraint = mYConstraint.get();
808 else if ( obj == mZLineEdit || obj == mLockZButton )
810 constraint = mZConstraint.get();
812 else if ( obj == mMLineEdit || obj == mLockMButton )
814 constraint = mMConstraint.get();
816 else if ( obj == mLineExtensionAction )
818 constraint = mLineExtensionConstraint.get();
820 else if ( obj == mXyVertexAction )
822 constraint = mXyVertexConstraint.get();
827double QgsAdvancedDigitizingDockWidget::parseUserInput(
const QString &inputValue,
const Qgis::CadConstraintType type,
bool &ok )
const
838 const QVariant result = expr.evaluate();
839 if ( expr.hasEvalError() )
842 QString inputValueC { inputValue };
845 if ( inputValue.contains( QLocale().groupSeparator() ) )
847 inputValueC.remove( QLocale().groupSeparator() );
849 const QVariant resultC = exprC.evaluate();
850 if ( ! exprC.hasEvalError() )
852 value = resultC.toDouble( &ok );
857 if ( !ok && QLocale().decimalPoint() != QChar(
'.' ) && inputValueC.contains( QLocale().decimalPoint() ) )
859 QgsExpression exprC( inputValueC .replace( QLocale().decimalPoint(), QChar(
'.' ) ) );
860 const QVariant resultC = exprC.evaluate();
861 if ( ! exprC.hasEvalError() )
863 value = resultC.toDouble( &ok );
869 value = result.toDouble( &ok );
875void QgsAdvancedDigitizingDockWidget::updateConstraintValue( CadConstraint *constraint,
const QString &textValue,
bool convertExpression )
877 if ( !constraint || textValue.isEmpty() )
886 const double value = parseUserInput( textValue, constraint->cadConstraintType(), ok );
890 constraint->setValue( value, convertExpression );
895void QgsAdvancedDigitizingDockWidget::lockConstraint(
bool activate )
897 CadConstraint *constraint = objectToConstraint( sender() );
905 const QString textValue = constraint->lineEdit()->text();
906 if ( !textValue.isEmpty() )
909 const double value = parseUserInput( textValue, constraint->cadConstraintType(), ok );
912 constraint->setValue( value );
926 if ( constraint == mXConstraint.get() )
930 else if ( constraint == mYConstraint.get() )
934 else if ( constraint == mZConstraint.get() )
938 else if ( constraint == mMConstraint.get() )
942 else if ( constraint == mDistanceConstraint.get() )
946 else if ( constraint == mAngleConstraint.get() )
954 if ( constraint == mAngleConstraint.get() )
964void QgsAdvancedDigitizingDockWidget::constraintTextEdited(
const QString &textValue )
966 CadConstraint *constraint = objectToConstraint( sender() );
972 updateConstraintValue( constraint, textValue,
false );
975void QgsAdvancedDigitizingDockWidget::constraintFocusOut()
977 QLineEdit *lineEdit = qobject_cast< QLineEdit * >( sender()->parent() );
981 CadConstraint *constraint = objectToConstraint( lineEdit );
987 updateConstraintValue( constraint, lineEdit->text(),
true );
992 mBetweenLineConstraint = constraint;
997void QgsAdvancedDigitizingDockWidget::lockParameterlessConstraint(
bool activate )
999 CadConstraint *constraint = objectToConstraint( sender() );
1007 if ( constraint == mXyVertexConstraint.get() )
1011 else if ( constraint == mLineExtensionConstraint.get() )
1025void QgsAdvancedDigitizingDockWidget::updateCapacity(
bool updateUIwithoutChange )
1027 CadCapacities newCapacities = CadCapacities();
1031 if ( mCadPointList.count() > 1 )
1034 if ( !isGeographic )
1040 if ( mCadPointList.count() > 2 )
1042 if ( !isGeographic )
1045 if ( !updateUIwithoutChange && newCapacities == mCapacities )
1055 const bool distance = mCadEnabled && newCapacities.testFlag(
Distance );
1056 const bool relativeAngle = mCadEnabled && newCapacities.testFlag(
RelativeAngle );
1057 const bool absoluteAngle = mCadEnabled && newCapacities.testFlag(
AbsoluteAngle );
1058 const bool relativeCoordinates = mCadEnabled && newCapacities.testFlag(
RelativeCoordinates );
1060 mPerpendicularAction->setEnabled( distance && snappingEnabled );
1061 mParallelAction->setEnabled( distance && snappingEnabled );
1063 mLineExtensionAction->setEnabled( snappingEnabled );
1064 mXyVertexAction->setEnabled( snappingEnabled );
1068 if ( !snappingEnabled )
1070 mPerpendicularAction->setToolTip( tr(
"Snapping must be enabled to utilize perpendicular mode." ) );
1071 mParallelAction->setToolTip( tr(
"Snapping must be enabled to utilize parallel mode." ) );
1072 mLineExtensionAction->setToolTip( tr(
"Snapping must be enabled to utilize line extension mode." ) );
1073 mXyVertexAction->setToolTip( tr(
"Snapping must be enabled to utilize xy point mode." ) );
1075 else if ( mCadPointList.count() <= 1 )
1077 mPerpendicularAction->setToolTip( tr(
"A first vertex should be drawn to utilize perpendicular mode." ) );
1078 mParallelAction->setToolTip( tr(
"A first vertex should be drawn to utilize parallel mode." ) );
1080 else if ( isGeographic )
1082 mPerpendicularAction->setToolTip( tr(
"Perpendicular mode cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1083 mParallelAction->setToolTip( tr(
"Parallel mode cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1087 mPerpendicularAction->setToolTip(
"<b>" + tr(
"Perpendicular" ) +
"</b><br>(" + tr(
"press p to switch between perpendicular, parallel and normal mode" ) +
")" );
1088 mParallelAction->setToolTip(
"<b>" + tr(
"Parallel" ) +
"</b><br>(" + tr(
"press p to switch between perpendicular, parallel and normal mode" ) +
")" );
1092 if ( !absoluteAngle )
1098 mLockAngleButton->setEnabled( absoluteAngle );
1099 mRelativeAngleButton->setEnabled( relativeAngle );
1100 mAngleLineEdit->setEnabled( absoluteAngle );
1102 if ( !absoluteAngle )
1106 if ( !relativeAngle )
1108 mAngleConstraint->setRelative(
false );
1111 else if ( relativeAngle && !mCapacities.testFlag(
RelativeAngle ) )
1114 mAngleConstraint->setRelative(
true );
1119 mLockDistanceButton->setEnabled( distance && relativeCoordinates );
1120 mDistanceLineEdit->setEnabled( distance && relativeCoordinates );
1122 if ( !( distance && relativeCoordinates ) )
1127 mRelativeXButton->setEnabled( relativeCoordinates );
1128 mRelativeYButton->setEnabled( relativeCoordinates );
1129 mRelativeZButton->setEnabled( relativeCoordinates );
1130 mRelativeMButton->setEnabled( relativeCoordinates );
1133 mCapacities = newCapacities;
1141 constr.
locked =
c->isLocked();
1143 constr.
value =
c->value();
1150 if ( !mLineExtensionConstraint->isLocked() && !mXyVertexConstraint->isLocked() )
1156 const int lastIndex = mLockedSnapVertices.length() - 1;
1157 for (
int i = lastIndex ; i >= 0; --i )
1159 if ( mLockedSnapVertices[i].point() == snapMatch.
point() )
1161 if ( snapMatch.
point() != previouslySnap.
point() )
1163 mLockedSnapVertices.removeAt( i );
1169 if ( snapMatch.
point() != previouslySnap.
point() )
1171 mLockedSnapVertices.enqueue( snapMatch );
1174 if ( mLockedSnapVertices.count() > 3 )
1176 mLockedSnapVertices.dequeue();
1185 context.
xConstraint = _constraint( mXConstraint.get() );
1186 context.
yConstraint = _constraint( mYConstraint.get() );
1187 context.
zConstraint = _constraint( mZConstraint.get() );
1188 context.
mConstraint = _constraint( mMConstraint.get() );
1205 const bool res = output.
valid;
1207 mSnappedSegment.clear();
1212 mSnappedSegment << edgePt0 << edgePt1;
1233 mSnapIndicator->setMatch( output.
snapMatch );
1234 mSnapIndicator->setVisible(
true );
1238 mSnapIndicator->setVisible(
false );
1259 if ( mSnapMatch.
layer() )
1271 toggleLockedSnapVertex( mSnapMatch, mLastSnapMatch );
1272 mLastSnapMatch = mSnapMatch;
1282 if ( mLockZButton->isChecked() )
1284 point.
setZ( QLocale().toDouble( mZLineEdit->text() ) );
1286 if ( mLockMButton->isChecked() )
1288 point.
setM( QLocale().toDouble( mMLineEdit->text() ) );
1294 updateUnlockedConstraintValues( point );
1302 emit
pushWarning( tr(
"Some constraints are incompatible. Resulting point might be incorrect." ) );
1309void QgsAdvancedDigitizingDockWidget::updateUnlockedConstraintValues(
const QgsPoint &point )
1311 bool previousPointExist, penulPointExist;
1316 if ( !mAngleConstraint->isLocked() && previousPointExist )
1318 double prevAngle = 0.0;
1320 if ( penulPointExist && mAngleConstraint->relative() )
1323 prevAngle = std::atan2( previousPt.
y() - penultimatePt.
y(),
1324 previousPt.
x() - penultimatePt.
x() ) * 180 / M_PI;
1327 const double xAngle { std::atan2( point.
y() - previousPt.
y(),
1328 point.
x() - previousPt.
x() ) * 180 / M_PI };
1331 const double angle = std::fmod( xAngle - prevAngle, 360.0 );
1332 mAngleConstraint->setValue( angle );
1335 double bearing { std::fmod( xAngle, 360.0 ) };
1336 bearing = bearing <= 90.0 ? 90.0 - bearing : ( bearing > 90 ? 270.0 + 180.0 - bearing : 270.0 - bearing );
1343 if ( !mDistanceConstraint->isLocked() && previousPointExist )
1345 mDistanceConstraint->setValue( std::sqrt( previousPt.
distanceSquared( point ) ) );
1348 if ( !mXConstraint->isLocked() )
1350 if ( previousPointExist && mXConstraint->relative() )
1352 mXConstraint->setValue( point.
x() - previousPt.
x() );
1356 mXConstraint->setValue( point.
x() );
1360 if ( !mYConstraint->isLocked() )
1362 if ( previousPointExist && mYConstraint->relative() )
1364 mYConstraint->setValue( point.
y() - previousPt.
y() );
1368 mYConstraint->setValue( point.
y() );
1372 if ( !mZConstraint->isLocked() )
1374 if ( previousPointExist && mZConstraint->relative() )
1376 mZConstraint->setValue( point.
z() - previousPt.
z() );
1380 mZConstraint->setValue( point.
z() );
1384 if ( !mMConstraint->isLocked() )
1386 if ( previousPointExist && mMConstraint->relative() )
1388 mMConstraint->setValue( point.
m() - previousPt.
m() );
1392 mMConstraint->setValue( point.
m() );
1398QList<QgsPointXY> QgsAdvancedDigitizingDockWidget::snapSegmentToAllLayers(
const QgsPointXY &originalMapPoint,
bool *snapped )
const
1411 snappingUtils->
setConfig( localConfig );
1413 match = snappingUtils->
snapToMap( originalMapPoint,
nullptr,
true );
1415 snappingUtils->
setConfig( canvasConfig );
1425 *snapped =
segment.count() == 2;
1438 bool previousPointExist, penulPointExist, snappedSegmentExist;
1441 mSnappedSegment = snapSegmentToAllLayers( e->
originalMapPoint(), &snappedSegmentExist );
1443 if ( !previousPointExist || !snappedSegmentExist )
1448 double angle = std::atan2( mSnappedSegment[0].y() - mSnappedSegment[1].y(), mSnappedSegment[0].x() - mSnappedSegment[1].x() );
1450 if ( mAngleConstraint->relative() && penulPointExist )
1452 angle -= std::atan2( previousPt.
y() - penultimatePt.
y(), previousPt.
x() - penultimatePt.
x() );
1460 angle *= 180 / M_PI;
1462 mAngleConstraint->setValue( angle );
1463 mAngleConstraint->setLockMode( lockMode );
1481 case Qt::Key_Backspace:
1482 case Qt::Key_Delete:
1488 case Qt::Key_Escape:
1518 case Qt::Key_Backspace:
1519 case Qt::Key_Delete:
1525 case Qt::Key_Escape:
1532 filterKeyPress( e );
1541 const auto constPoints = points;
1548bool QgsAdvancedDigitizingDockWidget::eventFilter( QObject *obj, QEvent *event )
1552 return QgsDockWidget::eventFilter( obj, event );
1560 if ( event->type() == QEvent::ShortcutOverride || event->type() == QEvent::KeyPress )
1562 if ( QKeyEvent *keyEvent =
dynamic_cast<QKeyEvent *
>( event ) )
1564 return filterKeyPress( keyEvent );
1567 return QgsDockWidget::eventFilter( obj, event );
1570bool QgsAdvancedDigitizingDockWidget::filterKeyPress( QKeyEvent *e )
1576 const QEvent::Type type = e->type();
1582 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1584 mXConstraint->toggleLocked();
1589 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1593 mXConstraint->toggleRelative();
1600 else if ( type == QEvent::KeyPress )
1602 mXLineEdit->setFocus();
1603 mXLineEdit->selectAll();
1612 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1614 mYConstraint->toggleLocked();
1619 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1623 mYConstraint->toggleRelative();
1630 else if ( type == QEvent::KeyPress )
1632 mYLineEdit->setFocus();
1633 mYLineEdit->selectAll();
1642 if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::AltModifier )
1644 mZConstraint->toggleLocked();
1649 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1653 mZConstraint->toggleRelative();
1660 else if ( type == QEvent::KeyPress )
1662 mZLineEdit->setFocus();
1663 mZLineEdit->selectAll();
1672 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1674 mMConstraint->toggleLocked();
1679 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1683 mMConstraint->toggleRelative();
1690 else if ( type == QEvent::KeyPress )
1692 mMLineEdit->setFocus();
1693 mMLineEdit->selectAll();
1702 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1706 mAngleConstraint->toggleLocked();
1712 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1716 mAngleConstraint->toggleRelative();
1723 else if ( type == QEvent::KeyPress )
1725 mAngleLineEdit->setFocus();
1726 mAngleLineEdit->selectAll();
1735 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1739 mDistanceConstraint->toggleLocked();
1746 else if ( type == QEvent::KeyPress )
1748 mDistanceLineEdit->setFocus();
1749 mDistanceLineEdit->selectAll();
1757 if ( type == QEvent::KeyPress )
1759 setConstructionMode( !mConstructionMode );
1766 if ( type == QEvent::KeyPress )
1768 const bool parallel = mParallelAction->isChecked();
1769 const bool perpendicular = mPerpendicularAction->isChecked();
1771 if ( !parallel && !perpendicular )
1775 else if ( perpendicular )
1792 if ( type == QEvent::ShortcutOverride )
1794 const QList<double> constActionKeys { mCommonAngleActions.keys() };
1795 const int currentAngleActionIndex {
static_cast<int>( constActionKeys .indexOf( mCommonAngleConstraint ) ) };
1796 const QList<QAction *> constActions { mCommonAngleActions.values( ) };
1797 QAction *nextAngleAction;
1798 if ( e->modifiers() == Qt::ShiftModifier )
1800 nextAngleAction = currentAngleActionIndex == 0 ? constActions.last() : constActions.at( currentAngleActionIndex - 1 );
1804 nextAngleAction = currentAngleActionIndex == constActions.count() - 1 ? constActions.first() : constActions.at( currentAngleActionIndex + 1 );
1806 nextAngleAction->trigger();
1816 return e->isAccepted();
1825 mAngleLineEdit->setToolTip( tr(
"Angle constraint cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1826 mDistanceLineEdit->setToolTip( tr(
"Distance constraint cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1828 mLabelX->setText( tr(
"Long" ) );
1829 mLabelY->setText( tr(
"Lat" ) );
1831 mXConstraint->setPrecision( 8 );
1832 mYConstraint->setPrecision( 8 );
1836 mAngleLineEdit->setToolTip(
"<b>" + tr(
"Angle" ) +
"</b><br>(" + tr(
"press a for quick access" ) +
")" );
1837 mAngleLineEdit->setToolTip( QString() );
1839 mDistanceLineEdit->setToolTip(
"<b>" + tr(
"Distance" ) +
"</b><br>(" + tr(
"press d for quick access" ) +
")" );
1841 mLabelX->setText( tr(
"x" ) );
1842 mLabelY->setText( tr(
"y" ) );
1844 mXConstraint->setPrecision( 6 );
1845 mYConstraint->setPrecision( 6 );
1850 mEnableAction->setEnabled(
true );
1851 mErrorLabel->hide();
1854 mCurrentMapToolSupportsCad =
true;
1856 if ( mSessionActive && !isVisible() )
1860 setCadEnabled( mSessionActive );
1867 mEnableAction->setEnabled(
false );
1868 mErrorLabel->setText( tr(
"Advanced digitizing tools are not enabled for the current map tool" ) );
1869 mErrorLabel->show();
1872 mCurrentMapToolSupportsCad =
false;
1874 mSnapIndicator->setVisible(
false );
1876 setCadEnabled(
false );
1881 mCadPaintItem->update();
1886 if ( !force && ( mLineExtensionConstraint->isLocked() || mXyVertexConstraint->isLocked() ) )
1891 mLockedSnapVertices.clear();
1897 QgsPoint pt = pointXYToPoint( point );
1900 mCadPointList << pt;
1904 mCadPointList.insert( 0, pt );
1917 mCadPointList.removeAt( i );
1924 mCadPointList.clear();
1925 mSnappedSegment.clear();
1935 mCadPointList << point;
1940 mCadPointList[0] = point;
1947 if ( mode == mLockMode )
1952 mLockerButton->setChecked( mode ==
HardLock );
1953 if ( mRepeatingLockButton )
1957 mRepeatingLockButton->setEnabled(
true );
1961 mRepeatingLockButton->setChecked(
false );
1962 mRepeatingLockButton->setEnabled(
false );
1975 mRepeatingLock = repeating;
1976 if ( mRepeatingLockButton )
1977 mRepeatingLockButton->setChecked( repeating );
1982 mRelative = relative;
1983 if ( mRelativeButton )
1985 mRelativeButton->setChecked( relative );
1992 if ( updateWidget && mLineEdit->isEnabled() )
1993 mLineEdit->setText( displayValue() );
1998 switch ( mCadConstraintType )
2002 return QLocale().toString( mValue,
'f', mPrecision ).append( tr(
" °" ) );
2009 return QLocale().toString( mValue,
'f', mPrecision ).append( tr(
" °" ) );
2013 return QLocale().toString( mValue,
'f', mPrecision );
2027 return QLocale().toString( mValue,
'f', mPrecision );
2032 setLockMode( mLockMode == HardLock ? NoLock : HardLock );
2037 setRelative( !mRelative );
2043 if ( mLineEdit->isEnabled() )
2044 mLineEdit->setText( displayValue() );
2049 return mCadConstraintType;
2054 mCadConstraintType = constraintType;
2059 mMapCanvas = mapCanvas;
2064 QString value { text.trimmed() };
2065 switch ( constraintType )
2071 if ( value.endsWith( distanceUnit ) )
2073 value.chop( distanceUnit.length() );
2080 const QString angleUnit { tr(
"°" ) };
2081 if ( value.endsWith( angleUnit ) )
2083 value.chop( angleUnit.length() );
2090 return value.trimmed();
2098 return mCadPointList.value( 0 );
2107 QgsPoint res = mCadPointList.value( 0 );
2109 res.
setX( layerCoordinates.
x() );
2110 res.
setY( layerCoordinates.
y() );
2121 return mCadPointList.value( 1 );
2131 return mCadPointList.value( 2 );
2136QgsPoint QgsAdvancedDigitizingDockWidget::pointXYToPoint(
const QgsPointXY &point )
const
2143 return mZLineEdit->isEnabled() ? QLocale().toDouble( mZLineEdit->text() ) : std::numeric_limits<double>::quiet_NaN();
2148 return mMLineEdit->isEnabled() ? QLocale().toDouble( mMLineEdit->text() ) : std::numeric_limits<double>::quiet_NaN();
DistanceUnit
Units of distance.
CadConstraintType
Advanced digitizing constraint type.
@ Distance
Distance value.
@ YCoordinate
Y Coordinate value.
@ XCoordinate
X Coordinate value.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
@ AllLayers
On all vector layers.
BetweenLineConstraint
Between line constraints which can be enabled.
@ NoConstraint
No additional constraint.
@ Perpendicular
Perpendicular.
WkbType
The WKB type describes the number of dimensions a geometry has.
The QgsAdvancedDigitizingCanvasItem class draws the graphical elements of the CAD tools (.
void updatePosition() override
called on changed extent or resize event to update position of the item
The QgsAdvancedDigitizingFloater class is widget that floats next to the mouse pointer,...
void setItemVisibility(const QgsAdvancedDigitizingFloater::FloaterItem &item, bool visible)
Set whether the floater item should be visible or not.
void setActive(bool active)
Set whether the floater should be active or not.
bool active()
Whether the floater is active or not.
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.
Defines constraints for the QgsCadUtils::alignMapPoint() method.
QgsCadUtils::AlignMapPointConstraint xyVertexConstraint
QgsCadUtils::AlignMapPointConstraint yConstraint
Constraint for Y coordinate.
QgsCadUtils::AlignMapPointConstraint xConstraint
Constraint for X coordinate.
double mapUnitsPerPixel
Map units/pixel ratio from map canvas.
void setCadPoints(const QList< QgsPoint > &points)
Sets the list of recent CAD points (in map coordinates).
void setLockedSnapVertices(const QQueue< QgsPointLocator::Match > &lockedSnapVertices)
Sets the queue of locked vertices.
QgsCadUtils::AlignMapPointConstraint mConstraint
Constraint for M coordinate.
QgsCadUtils::AlignMapPointConstraint distanceConstraint
Constraint for distance.
bool snappingToFeaturesOverridesCommonAngle
Flag to set snapping to features priority over common angle.
QgsCadUtils::AlignMapPointConstraint zConstraint
Constraint for Z coordinate.
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 lineExtensionConstraint
QgsCadUtils::AlignMapPointConstraint angleConstraint
Constraint for angle.
Structure returned from alignMapPoint() method.
Qgis::LineExtensionSide softLockLineExtension
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)
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.
static QString formatDistance(double distance, int decimals, Qgis::DistanceUnit unit, bool keepBaseUnit=false)
Returns an distance formatted as a friendly string.
Class for parsing and evaluation of expressions (formerly called "search strings").
A event filter for watching for focus events on a parent object.
void focusIn()
Emitted when parent object gains focus.
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.
QgsMapTool * mapTool()
Returns the currently active tool.
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.
QgsMapLayer * currentLayer()
returns current layer (set by legend widget)
Base class for all map layer types.
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
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
bool isEditable() const override
Returns true if the layer can be edited.
A context for numeric formats.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
void setY(double y)
Sets the point's y-coordinate.
void setX(double x)
Sets the point's x-coordinate.
void setM(double m)
Sets the point's m-value.
void setZ(double z)
Sets the point's z-coordinate.
double distanceSquared(double x, double y) const
Returns the Cartesian 2D squared distance between this point a specified x, y coordinate.
const QgsBearingNumericFormat * bearingFormat() const
Returns the project bearing's format, which controls how bearings associated with the project are dis...
Qgis::DistanceUnit distanceUnits
static QgsProject * instance()
Returns the QgsProject singleton instance.
void snappingConfigChanged(const QgsSnappingConfig &config)
Emitted whenever the configuration for snapping has changed.
QgsSnappingConfig snappingConfig
QgsProjectDisplaySettings * displaySettings
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
bool setValue(const T &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
A boolean settings entry.
static QgsSettingsTreeNode * sTreeDigitizing
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.
void setTypeFlag(Qgis::SnappingTypes type)
define the type of snapping
void setMode(Qgis::SnappingMode mode)
define the mode of snapping
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.
static Q_INVOKABLE QString toAbbreviatedString(Qgis::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
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...
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
QLineF segment(int index, QRectF rect, double radius)
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
QgsPoint interpolatedPoint(const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem()) const
Convenient method to return a point on an edge with linear interpolation of the Z value.
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 hasLineEndpoint() const
Returns true if the Match is a line endpoint (start or end vertex).
bool hasVertex() const
Returns true if the Match is a vertex.