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 );
778void QgsAdvancedDigitizingDockWidget::emit pointChanged()
781 QPoint globalPos = mMapCanvas->cursor().pos();
782 QPoint pos = mMapCanvas->mapFromGlobal( globalPos );
783 QMouseEvent *e =
new QMouseEvent( QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier );
784 mCurrentMapTool->canvasMoveEvent( e );
790 CadConstraint *constraint =
nullptr;
791 if ( obj == mAngleLineEdit || obj == mLockAngleButton )
793 constraint = mAngleConstraint.get();
795 else if ( obj == mDistanceLineEdit || obj == mLockDistanceButton )
797 constraint = mDistanceConstraint.get();
799 else if ( obj == mXLineEdit || obj == mLockXButton )
801 constraint = mXConstraint.get();
803 else if ( obj == mYLineEdit || obj == mLockYButton )
805 constraint = mYConstraint.get();
807 else if ( obj == mZLineEdit || obj == mLockZButton )
809 constraint = mZConstraint.get();
811 else if ( obj == mMLineEdit || obj == mLockMButton )
813 constraint = mMConstraint.get();
815 else if ( obj == mLineExtensionAction )
817 constraint = mLineExtensionConstraint.get();
819 else if ( obj == mXyVertexAction )
821 constraint = mXyVertexConstraint.get();
826double QgsAdvancedDigitizingDockWidget::parseUserInput(
const QString &inputValue,
const Qgis::CadConstraintType type,
bool &ok )
const
837 const QVariant result = expr.evaluate();
838 if ( expr.hasEvalError() )
841 QString inputValueC { inputValue };
844 if ( inputValue.contains( QLocale().groupSeparator() ) )
846 inputValueC.remove( QLocale().groupSeparator() );
848 const QVariant resultC = exprC.evaluate();
849 if ( ! exprC.hasEvalError() )
851 value = resultC.toDouble( &ok );
856 if ( !ok && QLocale().decimalPoint() != QChar(
'.' ) && inputValueC.contains( QLocale().decimalPoint() ) )
858 QgsExpression exprC( inputValueC .replace( QLocale().decimalPoint(), QChar(
'.' ) ) );
859 const QVariant resultC = exprC.evaluate();
860 if ( ! exprC.hasEvalError() )
862 value = resultC.toDouble( &ok );
868 value = result.toDouble( &ok );
874void QgsAdvancedDigitizingDockWidget::updateConstraintValue( CadConstraint *constraint,
const QString &textValue,
bool convertExpression )
876 if ( !constraint || textValue.isEmpty() )
885 const double value = parseUserInput( textValue, constraint->cadConstraintType(), ok );
889 constraint->setValue( value, convertExpression );
894void QgsAdvancedDigitizingDockWidget::lockConstraint(
bool activate )
896 CadConstraint *constraint = objectToConstraint( sender() );
904 const QString textValue = constraint->lineEdit()->text();
905 if ( !textValue.isEmpty() )
908 const double value = parseUserInput( textValue, constraint->cadConstraintType(), ok );
911 constraint->setValue( value );
925 if ( constraint == mXConstraint.get() )
929 else if ( constraint == mYConstraint.get() )
933 else if ( constraint == mZConstraint.get() )
937 else if ( constraint == mMConstraint.get() )
941 else if ( constraint == mDistanceConstraint.get() )
945 else if ( constraint == mAngleConstraint.get() )
953 if ( constraint == mAngleConstraint.get() )
963void QgsAdvancedDigitizingDockWidget::constraintTextEdited(
const QString &textValue )
965 CadConstraint *constraint = objectToConstraint( sender() );
971 updateConstraintValue( constraint, textValue,
false );
974void QgsAdvancedDigitizingDockWidget::constraintFocusOut()
976 QLineEdit *lineEdit = qobject_cast< QLineEdit * >( sender()->parent() );
980 CadConstraint *constraint = objectToConstraint( lineEdit );
986 updateConstraintValue( constraint, lineEdit->text(),
true );
991 mBetweenLineConstraint = constraint;
996void QgsAdvancedDigitizingDockWidget::lockParameterlessConstraint(
bool activate )
998 CadConstraint *constraint = objectToConstraint( sender() );
1006 if ( constraint == mXyVertexConstraint.get() )
1010 else if ( constraint == mLineExtensionConstraint.get() )
1024void QgsAdvancedDigitizingDockWidget::updateCapacity(
bool updateUIwithoutChange )
1030 if ( mCadPointList.count() > 1 )
1033 if ( !isGeographic )
1039 if ( mCadPointList.count() > 2 )
1041 if ( !isGeographic )
1044 if ( !updateUIwithoutChange && newCapacities == mCapacities )
1054 const bool distance = mCadEnabled && newCapacities.testFlag(
Distance );
1055 const bool relativeAngle = mCadEnabled && newCapacities.testFlag(
RelativeAngle );
1056 const bool absoluteAngle = mCadEnabled && newCapacities.testFlag(
AbsoluteAngle );
1057 const bool relativeCoordinates = mCadEnabled && newCapacities.testFlag(
RelativeCoordinates );
1059 mPerpendicularAction->setEnabled( distance && snappingEnabled );
1060 mParallelAction->setEnabled( distance && snappingEnabled );
1062 mLineExtensionAction->setEnabled( snappingEnabled );
1063 mXyVertexAction->setEnabled( snappingEnabled );
1067 if ( !snappingEnabled )
1069 mPerpendicularAction->setToolTip( tr(
"Snapping must be enabled to utilize perpendicular mode." ) );
1070 mParallelAction->setToolTip( tr(
"Snapping must be enabled to utilize parallel mode." ) );
1071 mLineExtensionAction->setToolTip( tr(
"Snapping must be enabled to utilize line extension mode." ) );
1072 mXyVertexAction->setToolTip( tr(
"Snapping must be enabled to utilize xy point mode." ) );
1074 else if ( mCadPointList.count() <= 1 )
1076 mPerpendicularAction->setToolTip( tr(
"A first vertex should be drawn to utilize perpendicular mode." ) );
1077 mParallelAction->setToolTip( tr(
"A first vertex should be drawn to utilize parallel mode." ) );
1079 else if ( isGeographic )
1081 mPerpendicularAction->setToolTip( tr(
"Perpendicular mode cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1082 mParallelAction->setToolTip( tr(
"Parallel mode cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1086 mPerpendicularAction->setToolTip(
"<b>" + tr(
"Perpendicular" ) +
"</b><br>(" + tr(
"press p to switch between perpendicular, parallel and normal mode" ) +
")" );
1087 mParallelAction->setToolTip(
"<b>" + tr(
"Parallel" ) +
"</b><br>(" + tr(
"press p to switch between perpendicular, parallel and normal mode" ) +
")" );
1091 if ( !absoluteAngle )
1097 mLockAngleButton->setEnabled( absoluteAngle );
1098 mRelativeAngleButton->setEnabled( relativeAngle );
1099 mAngleLineEdit->setEnabled( absoluteAngle );
1101 if ( !absoluteAngle )
1105 if ( !relativeAngle )
1107 mAngleConstraint->setRelative(
false );
1110 else if ( relativeAngle && !mCapacities.testFlag(
RelativeAngle ) )
1113 mAngleConstraint->setRelative(
true );
1118 mLockDistanceButton->setEnabled( distance && relativeCoordinates );
1119 mDistanceLineEdit->setEnabled( distance && relativeCoordinates );
1121 if ( !( distance && relativeCoordinates ) )
1126 mRelativeXButton->setEnabled( relativeCoordinates );
1127 mRelativeYButton->setEnabled( relativeCoordinates );
1128 mRelativeZButton->setEnabled( relativeCoordinates );
1129 mRelativeMButton->setEnabled( relativeCoordinates );
1132 mCapacities = newCapacities;
1140 constr.
locked =
c->isLocked();
1142 constr.
value =
c->value();
1149 if ( !mLineExtensionConstraint->isLocked() && !mXyVertexConstraint->isLocked() )
1155 const int lastIndex = mLockedSnapVertices.length() - 1;
1156 for (
int i = lastIndex ; i >= 0; --i )
1158 if ( mLockedSnapVertices[i].point() == snapMatch.
point() )
1160 if ( snapMatch.
point() != previouslySnap.
point() )
1162 mLockedSnapVertices.removeAt( i );
1168 if ( snapMatch.
point() != previouslySnap.
point() )
1170 mLockedSnapVertices.enqueue( snapMatch );
1173 if ( mLockedSnapVertices.count() > 3 )
1175 mLockedSnapVertices.dequeue();
1184 context.
xConstraint = _constraint( mXConstraint.get() );
1185 context.
yConstraint = _constraint( mYConstraint.get() );
1186 context.
zConstraint = _constraint( mZConstraint.get() );
1187 context.
mConstraint = _constraint( mMConstraint.get() );
1204 const bool res = output.
valid;
1206 mSnappedSegment.clear();
1211 mSnappedSegment << edgePt0 << edgePt1;
1232 mSnapIndicator->setMatch( output.
snapMatch );
1233 mSnapIndicator->setVisible(
true );
1237 mSnapIndicator->setVisible(
false );
1258 if ( mSnapMatch.
layer() )
1270 toggleLockedSnapVertex( mSnapMatch, mLastSnapMatch );
1271 mLastSnapMatch = mSnapMatch;
1281 if ( mLockZButton->isChecked() )
1283 point.
setZ( QLocale().toDouble( mZLineEdit->text() ) );
1285 if ( mLockMButton->isChecked() )
1287 point.
setM( QLocale().toDouble( mMLineEdit->text() ) );
1293 updateUnlockedConstraintValues( point );
1301 emit
pushWarning( tr(
"Some constraints are incompatible. Resulting point might be incorrect." ) );
1308void QgsAdvancedDigitizingDockWidget::updateUnlockedConstraintValues(
const QgsPoint &point )
1310 bool previousPointExist, penulPointExist;
1315 if ( !mAngleConstraint->isLocked() && previousPointExist )
1317 double prevAngle = 0.0;
1319 if ( penulPointExist && mAngleConstraint->relative() )
1322 prevAngle = std::atan2( previousPt.
y() - penultimatePt.
y(),
1323 previousPt.
x() - penultimatePt.
x() ) * 180 / M_PI;
1326 const double xAngle { std::atan2( point.
y() - previousPt.
y(),
1327 point.
x() - previousPt.
x() ) * 180 / M_PI };
1330 const double angle = std::fmod( xAngle - prevAngle, 360.0 );
1331 mAngleConstraint->setValue( angle );
1334 double bearing { std::fmod( xAngle, 360.0 ) };
1335 bearing = bearing <= 90.0 ? 90.0 - bearing : ( bearing > 90 ? 270.0 + 180.0 - bearing : 270.0 - bearing );
1342 if ( !mDistanceConstraint->isLocked() && previousPointExist )
1344 mDistanceConstraint->setValue( std::sqrt( previousPt.
distanceSquared( point ) ) );
1347 if ( !mXConstraint->isLocked() )
1349 if ( previousPointExist && mXConstraint->relative() )
1351 mXConstraint->setValue( point.
x() - previousPt.
x() );
1355 mXConstraint->setValue( point.
x() );
1359 if ( !mYConstraint->isLocked() )
1361 if ( previousPointExist && mYConstraint->relative() )
1363 mYConstraint->setValue( point.
y() - previousPt.
y() );
1367 mYConstraint->setValue( point.
y() );
1371 if ( !mZConstraint->isLocked() )
1373 if ( previousPointExist && mZConstraint->relative() )
1375 mZConstraint->setValue( point.
z() - previousPt.
z() );
1379 mZConstraint->setValue( point.
z() );
1383 if ( !mMConstraint->isLocked() )
1385 if ( previousPointExist && mMConstraint->relative() )
1387 mMConstraint->setValue( point.
m() - previousPt.
m() );
1391 mMConstraint->setValue( point.
m() );
1397QList<QgsPointXY> QgsAdvancedDigitizingDockWidget::snapSegmentToAllLayers(
const QgsPointXY &originalMapPoint,
bool *snapped )
const
1410 snappingUtils->
setConfig( localConfig );
1412 match = snappingUtils->
snapToMap( originalMapPoint,
nullptr,
true );
1414 snappingUtils->
setConfig( canvasConfig );
1424 *snapped =
segment.count() == 2;
1437 bool previousPointExist, penulPointExist, snappedSegmentExist;
1440 mSnappedSegment = snapSegmentToAllLayers( e->
originalMapPoint(), &snappedSegmentExist );
1442 if ( !previousPointExist || !snappedSegmentExist )
1447 double angle = std::atan2( mSnappedSegment[0].y() - mSnappedSegment[1].y(), mSnappedSegment[0].x() - mSnappedSegment[1].x() );
1449 if ( mAngleConstraint->relative() && penulPointExist )
1451 angle -= std::atan2( previousPt.
y() - penultimatePt.
y(), previousPt.
x() - penultimatePt.
x() );
1459 angle *= 180 / M_PI;
1461 mAngleConstraint->setValue( angle );
1462 mAngleConstraint->setLockMode( lockMode );
1480 case Qt::Key_Backspace:
1481 case Qt::Key_Delete:
1487 case Qt::Key_Escape:
1517 case Qt::Key_Backspace:
1518 case Qt::Key_Delete:
1524 case Qt::Key_Escape:
1531 filterKeyPress( e );
1540 const auto constPoints = points;
1547bool QgsAdvancedDigitizingDockWidget::eventFilter( QObject *obj, QEvent *event )
1551 return QgsDockWidget::eventFilter( obj, event );
1559 if ( event->type() == QEvent::ShortcutOverride || event->type() == QEvent::KeyPress )
1561 if ( QKeyEvent *keyEvent =
dynamic_cast<QKeyEvent *
>( event ) )
1563 return filterKeyPress( keyEvent );
1566 return QgsDockWidget::eventFilter( obj, event );
1569bool QgsAdvancedDigitizingDockWidget::filterKeyPress( QKeyEvent *e )
1575 const QEvent::Type type = e->type();
1581 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1583 mXConstraint->toggleLocked();
1588 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1592 mXConstraint->toggleRelative();
1599 else if ( type == QEvent::KeyPress )
1601 mXLineEdit->setFocus();
1602 mXLineEdit->selectAll();
1611 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1613 mYConstraint->toggleLocked();
1618 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1622 mYConstraint->toggleRelative();
1629 else if ( type == QEvent::KeyPress )
1631 mYLineEdit->setFocus();
1632 mYLineEdit->selectAll();
1641 if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::AltModifier )
1643 mZConstraint->toggleLocked();
1648 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1652 mZConstraint->toggleRelative();
1659 else if ( type == QEvent::KeyPress )
1661 mZLineEdit->setFocus();
1662 mZLineEdit->selectAll();
1671 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1673 mMConstraint->toggleLocked();
1678 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1682 mMConstraint->toggleRelative();
1689 else if ( type == QEvent::KeyPress )
1691 mMLineEdit->setFocus();
1692 mMLineEdit->selectAll();
1701 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1705 mAngleConstraint->toggleLocked();
1711 else if ( type == QEvent::ShortcutOverride && e->modifiers() == Qt::ShiftModifier )
1715 mAngleConstraint->toggleRelative();
1722 else if ( type == QEvent::KeyPress )
1724 mAngleLineEdit->setFocus();
1725 mAngleLineEdit->selectAll();
1734 if ( type == QEvent::ShortcutOverride && ( e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ControlModifier ) )
1738 mDistanceConstraint->toggleLocked();
1745 else if ( type == QEvent::KeyPress )
1747 mDistanceLineEdit->setFocus();
1748 mDistanceLineEdit->selectAll();
1756 if ( type == QEvent::KeyPress )
1758 setConstructionMode( !mConstructionMode );
1765 if ( type == QEvent::KeyPress )
1767 const bool parallel = mParallelAction->isChecked();
1768 const bool perpendicular = mPerpendicularAction->isChecked();
1770 if ( !parallel && !perpendicular )
1774 else if ( perpendicular )
1791 if ( type == QEvent::ShortcutOverride )
1793 const QList<double> constActionKeys { mCommonAngleActions.keys() };
1794 const int currentAngleActionIndex {
static_cast<int>( constActionKeys .indexOf( mCommonAngleConstraint ) ) };
1795 const QList<QAction *> constActions { mCommonAngleActions.values( ) };
1796 QAction *nextAngleAction;
1797 if ( e->modifiers() == Qt::ShiftModifier )
1799 nextAngleAction = currentAngleActionIndex == 0 ? constActions.last() : constActions.at( currentAngleActionIndex - 1 );
1803 nextAngleAction = currentAngleActionIndex == constActions.count() - 1 ? constActions.first() : constActions.at( currentAngleActionIndex + 1 );
1805 nextAngleAction->trigger();
1815 return e->isAccepted();
1824 mAngleLineEdit->setToolTip( tr(
"Angle constraint cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1825 mDistanceLineEdit->setToolTip( tr(
"Distance constraint cannot be used on geographic coordinates. Change the coordinates system in the project properties." ) );
1827 mLabelX->setText( tr(
"Long" ) );
1828 mLabelY->setText( tr(
"Lat" ) );
1830 mXConstraint->setPrecision( 8 );
1831 mYConstraint->setPrecision( 8 );
1835 mAngleLineEdit->setToolTip(
"<b>" + tr(
"Angle" ) +
"</b><br>(" + tr(
"press a for quick access" ) +
")" );
1836 mAngleLineEdit->setToolTip( QString() );
1838 mDistanceLineEdit->setToolTip(
"<b>" + tr(
"Distance" ) +
"</b><br>(" + tr(
"press d for quick access" ) +
")" );
1840 mLabelX->setText( tr(
"x" ) );
1841 mLabelY->setText( tr(
"y" ) );
1843 mXConstraint->setPrecision( 6 );
1844 mYConstraint->setPrecision( 6 );
1849 mEnableAction->setEnabled(
true );
1850 mErrorLabel->hide();
1853 mCurrentMapToolSupportsCad =
true;
1855 if ( mSessionActive && !isVisible() )
1859 setCadEnabled( mSessionActive );
1866 mEnableAction->setEnabled(
false );
1867 mErrorLabel->setText( tr(
"Advanced digitizing tools are not enabled for the current map tool" ) );
1868 mErrorLabel->show();
1871 mCurrentMapToolSupportsCad =
false;
1873 mSnapIndicator->setVisible(
false );
1875 setCadEnabled(
false );
1880 mCadPaintItem->update();
1885 if ( !force && ( mLineExtensionConstraint->isLocked() || mXyVertexConstraint->isLocked() ) )
1890 mLockedSnapVertices.clear();
1896 QgsPoint pt = pointXYToPoint( point );
1899 mCadPointList << pt;
1903 mCadPointList.insert( 0, pt );
1916 mCadPointList.removeAt( i );
1923 mCadPointList.clear();
1924 mSnappedSegment.clear();
1934 mCadPointList << point;
1939 mCadPointList[0] = point;
1946 if ( mode == mLockMode )
1951 mLockerButton->setChecked( mode ==
HardLock );
1952 if ( mRepeatingLockButton )
1956 mRepeatingLockButton->setEnabled(
true );
1960 mRepeatingLockButton->setChecked(
false );
1961 mRepeatingLockButton->setEnabled(
false );
1974 mRepeatingLock = repeating;
1975 if ( mRepeatingLockButton )
1976 mRepeatingLockButton->setChecked( repeating );
1981 mRelative = relative;
1982 if ( mRelativeButton )
1984 mRelativeButton->setChecked( relative );
1991 if ( updateWidget && mLineEdit->isEnabled() )
1992 mLineEdit->setText( displayValue() );
1997 switch ( mCadConstraintType )
2001 return QLocale().toString( mValue,
'f', mPrecision ).append( tr(
" °" ) );
2008 return QLocale().toString( mValue,
'f', mPrecision ).append( tr(
" °" ) );
2012 return QLocale().toString( mValue,
'f', mPrecision );
2026 return QLocale().toString( mValue,
'f', mPrecision );
2031 setLockMode( mLockMode == HardLock ? NoLock : HardLock );
2036 setRelative( !mRelative );
2042 if ( mLineEdit->isEnabled() )
2043 mLineEdit->setText( displayValue() );
2048 return mCadConstraintType;
2053 mCadConstraintType = constraintType;
2058 mMapCanvas = mapCanvas;
2063 QString value { text.trimmed() };
2064 switch ( constraintType )
2070 if ( value.endsWith( distanceUnit ) )
2072 value.chop( distanceUnit.length() );
2079 const QString angleUnit { tr(
"°" ) };
2080 if ( value.endsWith( angleUnit ) )
2082 value.chop( angleUnit.length() );
2089 return value.trimmed();
2097 return mCadPointList.value( 0 );
2106 QgsPoint res = mCadPointList.value( 0 );
2108 res.
setX( layerCoordinates.
x() );
2109 res.
setY( layerCoordinates.
y() );
2120 return mCadPointList.value( 1 );
2130 return mCadPointList.value( 2 );
2135QgsPoint QgsAdvancedDigitizingDockWidget::pointXYToPoint(
const QgsPointXY &point )
const
2142 return mZLineEdit->isEnabled() ? QLocale().toDouble( mZLineEdit->text() ) : std::numeric_limits<double>::quiet_NaN();
2147 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.