QGIS API Documentation  3.27.0-Master (597e8eebd4)
qgsadvanceddigitizingdockwidget.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsadvanceddigitizingdockwidget.h - dock for CAD tools
3  ----------------------
4  begin : October 2014
5  copyright : (C) Denis Rouzaud
6  email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #ifndef QGSADVANCEDDIGITIZINGDOCK
17 #define QGSADVANCEDDIGITIZINGDOCK
18 
19 #include <QList>
20 #include <QQueue>
21 
22 #include <memory>
23 
24 #include "ui_qgsadvanceddigitizingdockwidgetbase.h"
26 #include "qgis_gui.h"
27 #include "qgis_sip.h"
28 #include "qgsdockwidget.h"
29 #include "qgsmessagebaritem.h"
30 #include "qgspointxy.h"
31 #include "qgspointlocator.h"
32 #include "qgssnapindicator.h"
33 #include "qgscadutils.h"
34 
35 
38 class QgsMapCanvas;
39 class QgsMapTool;
41 class QgsMapMouseEvent;
42 
50 class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private Ui::QgsAdvancedDigitizingDockWidgetBase
51 {
52  Q_OBJECT
53 
54  public:
55 
62  {
63  AbsoluteAngle = 1,
64  RelativeAngle = 2,
65  RelativeCoordinates = 4,
66  Distance = 8,
67  };
68  Q_DECLARE_FLAGS( CadCapacities, CadCapacity )
69  Q_FLAG( CadCapacities )
70 
71 
77  {
78  ReturnPressed, FocusOut, TextEdited
79  };
80 
81 
88  class GUI_EXPORT CadConstraint
89  {
90  public:
91 
95  enum LockMode
96  {
99  HardLock
100  };
101 
109  CadConstraint( QLineEdit *lineEdit, QToolButton *lockerButton, QToolButton *relativeButton = nullptr, QToolButton *repeatingLockButton = nullptr )
110  : mLineEdit( lineEdit )
111  , mLockerButton( lockerButton )
112  , mRelativeButton( relativeButton )
113  , mRepeatingLockButton( repeatingLockButton )
114  , mLockMode( NoLock )
115  , mRepeatingLock( false )
116  , mRelative( false )
117  , mValue( 0.0 )
118  {}
119 
124  LockMode lockMode() const { return mLockMode; }
125 
129  bool isLocked() const { return mLockMode != NoLock; }
130 
137  bool isRepeatingLock() const { return mRepeatingLock; }
138 
142  bool relative() const { return mRelative; }
143 
147  double value() const { return mValue; }
148 
152  QLineEdit *lineEdit() const { return mLineEdit; }
153 
157  void setLockMode( LockMode mode );
158 
166  void setRepeatingLock( bool repeating );
167 
171  void setRelative( bool relative );
172 
178  void setValue( double value, bool updateWidget = true );
179 
183  void toggleLocked();
184 
188  void toggleRelative();
189 
196  int precision() const { return mPrecision; }
197 
204  void setPrecision( int precision );
205 
206  private:
207  QLineEdit *mLineEdit = nullptr;
208  QToolButton *mLockerButton = nullptr;
209  QToolButton *mRelativeButton = nullptr;
210  QToolButton *mRepeatingLockButton = nullptr;
211  LockMode mLockMode;
212  bool mRepeatingLock;
213  bool mRelative;
214  double mValue;
215  int mPrecision = 6;
216  };
217 
223  explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = nullptr );
224 
231  bool canvasKeyPressEventFilter( QKeyEvent *e );
232 
237  bool applyConstraints( QgsMapMouseEvent *e );
238 
245 
251  void releaseLocks( bool releaseRepeatingLocks = true );
252 
256  void clear();
257 
258  void keyPressEvent( QKeyEvent *e ) override;
259 
261  bool cadEnabled() const { return mCadEnabled; }
262 
267  void switchZM( );
268 
273  void setEnabledZ( bool enable );
274 
279  void setEnabledM( bool enable );
280 
282  bool constructionMode() const { return mConstructionMode; }
283 
288  Qgis::BetweenLineConstraint betweenLineConstraint() const { return mBetweenLineConstraint; }
290  const CadConstraint *constraintAngle() const { return mAngleConstraint.get(); }
292  const CadConstraint *constraintDistance() const { return mDistanceConstraint.get(); }
294  const CadConstraint *constraintX() const { return mXConstraint.get(); }
296  const CadConstraint *constraintY() const { return mYConstraint.get(); }
297 
302  const CadConstraint *constraintZ() const { return mZConstraint.get(); }
303 
308  const CadConstraint *constraintM() const { return mMConstraint.get(); }
310  bool commonAngleConstraint() const { return !qgsDoubleNear( mCommonAngleConstraint, 0.0 ); }
311 
313  const CadConstraint *constraintLineExtension() const { return mLineExtensionConstraint.get(); }
314 
316  Qgis::LineExtensionSide lineExtensionSide() const { return mSoftLockLineExtension; }
317 
319  const CadConstraint *constraintXyVertex() const { return mXyVertexConstraint.get(); }
320 
322  double softLockX() const { return mSoftLockX; }
323 
325  double softLockY() const { return mSoftLockY; }
326 
331  QgsPointLocator::Match mapPointMatch() const { return mSnapMatch; }
332 
337  QList< QgsPointLocator::Match > lockedSnapVertices() const { return mLockedSnapVertices; }
338 
344  void clearLockedSnapVertices( bool force = true );
345 
350  void clearPoints();
351 
356  void addPoint( const QgsPointXY &point );
357 
362  void removePreviousPoint();
363 
371  void setPoints( const QList<QgsPointXY> &points );
372 
380  QgsPoint currentPointV2( bool *exists = nullptr ) const;
381 
387  QgsPoint currentPointLayerCoordinates( QgsMapLayer *layer ) const;
388 
395  Q_DECL_DEPRECATED QgsPointXY currentPoint( bool *exists = nullptr ) const SIP_DEPRECATED { return currentPointV2( exists ); };
396 
402  QgsPoint previousPointV2( bool *exists = nullptr ) const;
403 
410  Q_DECL_DEPRECATED QgsPointXY previousPoint( bool *exists = nullptr ) const SIP_DEPRECATED { return previousPointV2( exists ); };
411 
417  QgsPoint penultimatePointV2( bool *exists = nullptr ) const;
418 
425  Q_DECL_DEPRECATED QgsPointXY penultimatePoint( bool *exists = nullptr ) const SIP_DEPRECATED { return penultimatePointV2( exists ); };
426 
430  inline int pointsCount() const { return mCadPointList.count(); }
431 
435  inline bool snappedToVertex() const { return ( mSnapMatch.isValid() && ( mSnapMatch.hasVertex() || mSnapMatch.hasLineEndpoint() ) ); }
436 
440  QList<QgsPointXY> snappedSegment() const { return mSnappedSegment; }
441 
443  QAction *enableAction() { return mEnableAction; }
444 
451  void enable();
452 
456  void disable();
457 
462  void updateCadPaintItem();
463 
472  void setX( const QString &value, WidgetSetMode mode );
473 
482  void setY( const QString &value, WidgetSetMode mode );
483 
492  void setZ( const QString &value, WidgetSetMode mode );
493 
502  void setM( const QString &value, WidgetSetMode mode );
503 
512  void setAngle( const QString &value, WidgetSetMode mode );
513 
522  void setDistance( const QString &value, WidgetSetMode mode );
523 
528  double getLineZ( ) const;
529 
534  double getLineM( ) const;
535 
540  CadCapacities capacities() const { return mCapacities; };
541 
542  signals:
543 
549  void pushWarning( const QString &message );
550 
554  void popWarning();
555 
563  void pointChangedV2( const QgsPoint &point );
564 
572  Q_DECL_DEPRECATED void pointChanged( const QgsPointXY &point ) SIP_DEPRECATED;
573 
575 
583  void cadEnabledChanged( bool enabled );
584 
591  void valueXChanged( const QString &value );
592 
599  void valueYChanged( const QString &value );
600 
607  void valueZChanged( const QString &value );
608 
615  void valueMChanged( const QString &value );
616 
623  void valueAngleChanged( const QString &value );
624 
631  void valueDistanceChanged( const QString &value );
632 
639  void lockXChanged( bool locked );
640 
647  void lockYChanged( bool locked );
648 
655  void lockZChanged( bool locked );
656 
663  void lockMChanged( bool locked );
664 
671  void lockAngleChanged( bool locked );
672 
679  void lockDistanceChanged( bool locked );
680 
689  void relativeXChanged( bool relative );
690 
699  void relativeYChanged( bool relative );
700 
709  void relativeZChanged( bool relative );
710 
719  void relativeMChanged( bool relative );
720 
729  void relativeAngleChanged( bool relative );
730 
737  void softLockLineExtensionChanged( bool locked );
738 
745  void softLockXyChanged( bool locked );
746 
747  // relativeDistanceChanged doesn't exist as distance is always relative
748 
758  void enabledChangedX( bool enabled );
759 
769  void enabledChangedY( bool enabled );
770 
780  void enabledChangedZ( bool enabled );
781 
791  void enabledChangedM( bool enabled );
792 
802  void enabledChangedAngle( bool enabled );
803 
813  void enabledChangedDistance( bool enabled );
814 
822 
830 
838 
846 
854 
862 
863 
864  private slots:
866  void betweenLineConstraintClicked( bool activated );
867 
869  void lockConstraint( bool activate = true );
870 
872  void lockParameterlessConstraint( bool activate = true );
873 
878  void constraintTextEdited( const QString &textValue );
879 
884  void constraintFocusOut();
885 
887  void setConstraintRelative( bool activate );
888 
890  void setConstraintRepeatingLock( bool activate );
891 
896  void activateCad( bool enabled );
897 
899  void setConstructionMode( bool enabled );
900 
902  void settingsButtonTriggered( QAction *action );
903 
904  private:
905 
909  QgsMapLayer *targetLayer() const;
910 
912  void setCadEnabled( bool enabled );
913 
918  void updateCapacity( bool updateUIwithoutChange = false );
919 
921  void lockBetweenLineConstraint( Qgis::BetweenLineConstraint constraint );
922 
928  QList<QgsPointXY> snapSegmentToAllLayers( const QgsPointXY &originalMapPoint, bool *snapped = nullptr ) const;
929 
931  void updateCurrentPoint( const QgsPoint &point );
932 
933 
938  bool filterKeyPress( QKeyEvent *e );
939 
944  bool eventFilter( QObject *obj, QEvent *event ) override SIP_SKIP;
945 
947  void triggerMouseMoveEvent();
948 
950  CadConstraint *objectToConstraint( const QObject *obj ) const;
951 
953  double parseUserInput( const QString &inputValue, bool &ok ) const;
954 
961  void updateConstraintValue( CadConstraint *constraint, const QString &textValue, bool convertExpression = false );
962 
964  void updateUnlockedConstraintValues( const QgsPoint &point );
965 
966 
972  void toggleLockedSnapVertex( const QgsPointLocator::Match &snapMatch, QgsPointLocator::Match previouslySnap );
973 
974  QgsMapCanvas *mMapCanvas = nullptr;
975  QgsAdvancedDigitizingCanvasItem *mCadPaintItem = nullptr;
977  std::unique_ptr<QgsSnapIndicator> mSnapIndicator;
978 
979  CadCapacities mCapacities = CadCapacities();
980 
981  bool mCurrentMapToolSupportsCad = false;
982 
983  // Pointer to the floater
984  QgsAdvancedDigitizingFloater *mFloater = nullptr;
985 
986  // CAD properties
988  bool mCadEnabled = false;
989  bool mConstructionMode = false;
990 
991  // constraints
992  std::unique_ptr< CadConstraint > mAngleConstraint;
993  std::unique_ptr< CadConstraint > mDistanceConstraint;
994  std::unique_ptr< CadConstraint > mXConstraint;
995  std::unique_ptr< CadConstraint > mYConstraint;
996  std::unique_ptr< CadConstraint > mZConstraint;
997  std::unique_ptr< CadConstraint > mMConstraint;
998  std::unique_ptr< CadConstraint > mLineExtensionConstraint;
999  std::unique_ptr< CadConstraint > mXyVertexConstraint;
1000  Qgis::BetweenLineConstraint mBetweenLineConstraint;
1001  double mCommonAngleConstraint; // if 0: do not snap to common angles
1002 
1003  // point list and current snap point / segment
1004  QList<QgsPoint> mCadPointList;
1005  QList<QgsPointXY> mSnappedSegment;
1006 
1007  bool mSessionActive = false;
1008 
1009  // error message
1010  std::unique_ptr<QgsMessageBarItem> mErrorMessage;
1011 
1012  // UI
1013  QMap< QAction *, double > mCommonAngleActions; // map the common angle actions with their angle values
1014  QAction *mLineExtensionAction;
1015  QAction *mXyVertexAction;
1016 
1017  // Snap indicator
1018  QgsPointLocator::Match mSnapMatch;
1019  QgsPointLocator::Match mLastSnapMatch;
1020 
1021  // Extra constraint context
1022  Qgis::LineExtensionSide mSoftLockLineExtension;
1023  double mSoftLockX;
1024  double mSoftLockY;
1025  QQueue< QgsPointLocator::Match > mLockedSnapVertices;
1026 
1027 #ifdef SIP_RUN
1029  bool eventFilter( QObject *obj, QEvent *event );
1030 #endif
1032  QgsPoint pointXYToPoint( const QgsPointXY &point ) const;
1033 
1034  friend class TestQgsAdvancedDigitizing;
1035  friend class TestQgsAdvancedDigitizingDockWidget;
1036 };
1037 
1038 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAdvancedDigitizingDockWidget::CadCapacities )
1039 
1040 #endif // QGSADVANCEDDIGITIZINGDOCK_H
BetweenLineConstraint
Between line constraints which can be enabled.
Definition: qgis.h:1801
LineExtensionSide
Designates whether the line extension constraint is currently soft locked with the previous or next v...
Definition: qgis.h:1814
The QgsAdvancedDigitizingCanvasItem class draws the graphical elements of the CAD tools (.
The CadConstraint is an abstract class for all basic constraints (angle/distance/x/y).
CadConstraint(QLineEdit *lineEdit, QToolButton *lockerButton, QToolButton *relativeButton=nullptr, QToolButton *repeatingLockButton=nullptr)
Constructor for CadConstraint.
QLineEdit * lineEdit() const
The line edit that manages the value of the constraint.
bool isLocked() const
Is any kind of lock mode enabled.
double value() const
The value of the constraint.
bool isRepeatingLock() const
Returns true if a repeating lock is set for the constraint.
LockMode lockMode() const
The current lock mode of this constraint.
int precision() const
Returns the numeric precision (decimal places) to show in the associated widget.
bool relative() const
Is the constraint in relative mode.
The QgsAdvancedDigitizingDockWidget class is a dockable widget used to handle the CAD tools on top of...
void valueDistanceChanged(const QString &value)
Emitted whenever the distance value changes (either the mouse moved, or the user changed the input).
bool commonAngleConstraint() const
Returns true if a constraint on a common angle is active.
Q_DECL_DEPRECATED QgsPointXY currentPoint(bool *exists=nullptr) const
The last point.
void lockZChanged(bool locked)
Emitted whenever the Z parameter is locked.
const CadConstraint * constraintDistance() const
Returns the CadConstraint on the distance.
double softLockY() const
Returns the Y value of the Y soft lock. The value is NaN is the constraint isn't magnetized to a line...
void enabledChangedY(bool enabled)
Emitted whenever the Y field is enabled or disabled.
bool cadEnabled() const
determines if CAD tools are enabled or if map tools behaves "nomally"
int pointsCount() const
The number of points in the CAD point helper list.
void relativeMChanged(bool relative)
Emitted whenever the M parameter is toggled between absolute and relative.
void lockXChanged(bool locked)
Emitted whenever the X parameter is locked.
void softLockLineExtensionChanged(bool locked)
Emitted whenever the soft line extension parameter is locked.
void focusOnXRequested()
Emitted whenever the X field should get the focus using the shortcuts (X).
bool constructionMode() const
construction mode is used to draw intermediate points. These points won't be given any further (i....
const CadConstraint * constraintZ() const
Returns the CadConstraint on the Z coordinate.
void enabledChangedX(bool enabled)
Emitted whenever the X field is enabled or disabled.
void valueYChanged(const QString &value)
Emitted whenever the Y value changes (either the mouse moved, or the user changed the input).
Q_DECL_DEPRECATED QgsPointXY penultimatePoint(bool *exists=nullptr) const
The penultimate point.
const CadConstraint * constraintM() const
Returns the CadConstraint on the M coordinate.
void focusOnYRequested()
Emitted whenever the Y field should get the focus using the shortcuts (Y).
void enabledChangedDistance(bool enabled)
Emitted whenever the distance field is enabled or disabled.
bool snappedToVertex() const
Is it snapped to a vertex.
void valueZChanged(const QString &value)
Emitted whenever the Z value changes (either the mouse moved, or the user changed the input).
QList< QgsPointLocator::Match > lockedSnapVertices() const
Returns the snap matches whose vertices have been locked.
void lockAngleChanged(bool locked)
Emitted whenever the angle parameter is locked.
const CadConstraint * constraintX() const
Returns the CadConstraint on the X coordinate.
void pointChangedV2(const QgsPoint &point)
Sometimes a constraint may change the current point out of a mouse event.
void relativeXChanged(bool relative)
Emitted whenever the X parameter is toggled between absolute and relative.
void focusOnAngleRequested()
Emitted whenever the angle field should get the focus using the shortcuts (A).
WidgetSetMode
Type of interaction to simulate when editing values from external widget.
void focusOnZRequested()
Emitted whenever the Z field should get the focus using the shortcuts (Z).
void focusOnMRequested()
Emitted whenever the M field should get the focus using the shortcuts (M).
void popWarning()
Remove any previously emitted warnings (if any)
void valueXChanged(const QString &value)
Emitted whenever the X value changes (either the mouse moved, or the user changed the input).
void lockMChanged(bool locked)
Emitted whenever the M parameter is locked.
void cadEnabledChanged(bool enabled)
Signals for external widgets that need to update according to current values.
void lockYChanged(bool locked)
Emitted whenever the Y parameter is locked.
void valueAngleChanged(const QString &value)
Emitted whenever the angle value changes (either the mouse moved, or the user changed the input).
void valueMChanged(const QString &value)
Emitted whenever the M value changes (either the mouse moved, or the user changed the input).
void relativeZChanged(bool relative)
Emitted whenever the Z parameter is toggled between absolute and relative.
double softLockX() const
Returns the X value of the X soft lock. The value is NaN is the constraint isn't magnetized to a line...
Q_DECL_DEPRECATED void pointChanged(const QgsPointXY &point)
Sometimes a constraint may change the current point out of a mouse event.
CadCapacity
The CadCapacity enum defines the possible constraints to be set depending on the number of points in ...
Qgis::BetweenLineConstraint betweenLineConstraint() const
Returns the between line constraints which are used to place perpendicular/parallel segments to snapp...
void enabledChangedAngle(bool enabled)
Emitted whenever the angle field is enabled or disabled.
const CadConstraint * constraintXyVertex() const
Returns the CadConstraint.
Q_DECL_DEPRECATED QgsPointXY previousPoint(bool *exists=nullptr) const
The previous point.
const CadConstraint * constraintAngle() const
Returns the CadConstraint on the angle.
void enabledChangedZ(bool enabled)
Emitted whenever the Z field is enabled or disabled.
void lockDistanceChanged(bool locked)
Emitted whenever the distance parameter is locked.
void relativeAngleChanged(bool relative)
Emitted whenever the angleX parameter is toggled between absolute and relative.
CadCapacities capacities() const
Returns the capacities.
void softLockXyChanged(bool locked)
Emitted whenever the soft x/y extension parameter is locked.
void enabledChangedM(bool enabled)
Emitted whenever the M field is enabled or disabled.
QgsPointLocator::Match mapPointMatch() const
Returns the point locator match.
QAction * enableAction()
Returns the action used to enable/disable the tools.
const CadConstraint * constraintY() const
Returns the CadConstraint on the Y coordinate.
void focusOnDistanceRequested()
Emitted whenever the distance field should get the focus using the shortcuts (D).
const CadConstraint * constraintLineExtension() const
Returns the CadConstraint.
void pushWarning(const QString &message)
Push a warning.
Qgis::LineExtensionSide lineExtensionSide() const
Returns on which side of the constraint line extension point, the line was created.
void relativeYChanged(bool relative)
Emitted whenever the Y parameter is toggled between absolute and relative.
QList< QgsPointXY > snappedSegment() const
Snapped to a segment.
The QgsAdvancedDigitizingFloater class is widget that floats next to the mouse pointer,...
QgsDockWidget subclass with more fine-grained control over how the widget is closed or opened.
Definition: qgsdockwidget.h:32
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:90
Base class for all map layer types.
Definition: qgsmaplayer.h:73
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
The QgsMapToolAdvancedDigitizing class is a QgsMapTool which gives event directly in map coordinates ...
Abstract base class for all map tools.
Definition: qgsmaptool.h:71
A class to represent a 2D point.
Definition: qgspointxy.h:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2260
#define SIP_DEPRECATED
Definition: qgis_sip.h:106
#define SIP_SKIP
Definition: qgis_sip.h:126
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsField::ConfigurationFlags) CORE_EXPORT QDataStream &operator<<(QDataStream &out
Writes the field to stream out. QGIS version compatibility is not guaranteed.
int precision