QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsadvanceddigitizingfloater.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsadvanceddigitizingfloater.cpp - floater for CAD tools
3  ----------------------
4  begin : May 2019
5  copyright : (C) Olivier Dalang
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 #include <QMouseEvent>
17 #include <QEnterEvent>
18 #include <QLocale>
19 
21 #include "qgsmessagelog.h"
22 #include "qgsmapcanvas.h"
23 #include "qgssettings.h"
24 #include "qgsfocuswatcher.h"
25 
27  : QWidget( canvas->viewport() ), mMapCanvas( canvas ), mCadDockWidget( cadDockWidget )
28 {
29  setupUi( this );
30 
31  setAttribute( Qt::WA_TransparentForMouseEvents );
32  adjustSize();
33 
34  setActive( QgsSettings().value( QStringLiteral( "/Cad/Floater" ), false ).toBool() );
35 
36  hideIfDisabled();
37 
38  // This is required to be able to track mouse move events
39  mMapCanvas->viewport()->installEventFilter( this );
40  mMapCanvas->viewport()->setMouseTracking( true );
41 
42  // We reuse cadDockWidget's eventFilter for the CAD specific shortcuts
43  mAngleLineEdit->installEventFilter( cadDockWidget );
44  mDistanceLineEdit->installEventFilter( cadDockWidget );
45  mXLineEdit->installEventFilter( cadDockWidget );
46  mYLineEdit->installEventFilter( cadDockWidget );
47 
48  // Connect all cadDockWidget's signals to update the widget's display
49  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::cadEnabledChanged, this, &QgsAdvancedDigitizingFloater::hideIfDisabled );
50 
51  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::valueXChanged, this, &QgsAdvancedDigitizingFloater::changeX );
52  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::valueYChanged, this, &QgsAdvancedDigitizingFloater::changeY );
53  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::valueAngleChanged, this, &QgsAdvancedDigitizingFloater::changeAngle );
54  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::valueDistanceChanged, this, &QgsAdvancedDigitizingFloater::changeDistance );
55 
56  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::lockXChanged, this, &QgsAdvancedDigitizingFloater::changeLockX );
57  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::lockYChanged, this, &QgsAdvancedDigitizingFloater::changeLockY );
58  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::lockAngleChanged, this, &QgsAdvancedDigitizingFloater::changeLockAngle );
59  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::lockDistanceChanged, this, &QgsAdvancedDigitizingFloater::changeLockDistance );
60 
61  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::relativeXChanged, this, &QgsAdvancedDigitizingFloater::changeRelativeX );
62  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::relativeYChanged, this, &QgsAdvancedDigitizingFloater::changeRelativeY );
63  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::relativeAngleChanged, this, &QgsAdvancedDigitizingFloater::changeRelativeAngle );
64  // distance is always relative
65 
66  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::focusOnXRequested, this, &QgsAdvancedDigitizingFloater::focusOnX );
67  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::focusOnYRequested, this, &QgsAdvancedDigitizingFloater::focusOnY );
68  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::focusOnAngleRequested, this, &QgsAdvancedDigitizingFloater::focusOnAngle );
69  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::focusOnDistanceRequested, this, &QgsAdvancedDigitizingFloater::focusOnDistance );
70 
71  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::enabledChangedX, this, &QgsAdvancedDigitizingFloater::enabledChangedX );
72  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::enabledChangedY, this, &QgsAdvancedDigitizingFloater::enabledChangedY );
73  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::enabledChangedAngle, this, &QgsAdvancedDigitizingFloater::enabledChangedAngle );
74  connect( cadDockWidget, &QgsAdvancedDigitizingDockWidget::enabledChangedDistance, this, &QgsAdvancedDigitizingFloater::enabledChangedDistance );
75 
76  // Connect our line edits signals to update cadDockWidget's state (implementation copied from QgsAdvancedDigitizingDockWidget)
77  connect( mXLineEdit, &QLineEdit::returnPressed, cadDockWidget, [ = ]() { cadDockWidget->setX( mXLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::ReturnPressed ); } );
78  connect( mYLineEdit, &QLineEdit::returnPressed, cadDockWidget, [ = ]() { cadDockWidget->setY( mYLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::ReturnPressed ); } );
79  connect( mAngleLineEdit, &QLineEdit::returnPressed, cadDockWidget, [ = ]() { cadDockWidget->setAngle( mAngleLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::ReturnPressed ); } );
80  connect( mDistanceLineEdit, &QLineEdit::returnPressed, cadDockWidget, [ = ]() { cadDockWidget->setDistance( mDistanceLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::ReturnPressed ); } );
81 
82  connect( mXLineEdit, &QLineEdit::textEdited, cadDockWidget, [ = ]() { cadDockWidget->setX( mXLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::TextEdited ); } );
83  connect( mYLineEdit, &QLineEdit::textEdited, cadDockWidget, [ = ]() { cadDockWidget->setY( mYLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::TextEdited ); } );
84  connect( mAngleLineEdit, &QLineEdit::textEdited, cadDockWidget, [ = ]() { cadDockWidget->setAngle( mAngleLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::TextEdited ); } );
85  connect( mDistanceLineEdit, &QLineEdit::textEdited, cadDockWidget, [ = ]() { cadDockWidget->setDistance( mDistanceLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::TextEdited ); } );
86 
87  QgsFocusWatcher *xWatcher = new QgsFocusWatcher( mXLineEdit );
88  connect( xWatcher, &QgsFocusWatcher::focusOut, cadDockWidget, [ = ]() { cadDockWidget->setX( mXLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::FocusOut ); } );
89  QgsFocusWatcher *yWatcher = new QgsFocusWatcher( mYLineEdit );
90  connect( yWatcher, &QgsFocusWatcher::focusOut, cadDockWidget, [ = ]() { cadDockWidget->setY( mYLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::FocusOut ); } );
91  QgsFocusWatcher *angleWatcher = new QgsFocusWatcher( mAngleLineEdit );
92  connect( angleWatcher, &QgsFocusWatcher::focusOut, cadDockWidget, [ = ]() { cadDockWidget->setAngle( mAngleLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::FocusOut ); } );
93  QgsFocusWatcher *distanceWatcher = new QgsFocusWatcher( mDistanceLineEdit );
94  connect( distanceWatcher, &QgsFocusWatcher::focusOut, cadDockWidget, [ = ]() { cadDockWidget->setDistance( mDistanceLineEdit->text(), QgsAdvancedDigitizingDockWidget::WidgetSetMode::FocusOut ); } );
95 
96 }
97 
98 bool QgsAdvancedDigitizingFloater::eventFilter( QObject *obj, QEvent *event )
99 {
100  if ( mCadDockWidget->cadEnabled() && mActive )
101  {
102  if ( event->type() == QEvent::MouseMove )
103  {
104  // We update the position when mouse moves
105  QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>( event );
106  updatePos( mouseEvent->pos() );
107  }
108  else if ( event->type() == QEvent::Enter )
109  {
110  // We show the widget when mouse enters
111  QEnterEvent *enterEvent = dynamic_cast<QEnterEvent *>( event );
112  updatePos( enterEvent->pos() );
113  setVisible( true );
114  }
115  else if ( event->type() == QEvent::Leave )
116  {
117  // We hide the widget when mouse leaves
118  setVisible( false );
119  }
120  }
121  return QWidget::eventFilter( obj, event );
122 }
123 
125 {
126  return mActive;
127 }
128 
130 {
131  QgsSettings().setValue( QStringLiteral( "/Cad/Floater" ), active );
132 
133  mActive = active;
134 
135  hideIfDisabled();
136 }
137 
138 void QgsAdvancedDigitizingFloater::updatePos( const QPoint &pos )
139 {
140  // We hardcode a small delta between the mouse position and the widget's position
141  move( pos + QPoint( 15, 5 ) );
142 }
143 
144 void QgsAdvancedDigitizingFloater::hideIfDisabled()
145 {
146  if ( ! mCadDockWidget->cadEnabled() || ! mActive )
147  {
148  setVisible( false );
149  }
150 }
151 
152 void QgsAdvancedDigitizingFloater::changeX( const QString &text )
153 {
154  mXLineEdit->setText( text );
155 }
156 
157 void QgsAdvancedDigitizingFloater::changeY( const QString &text )
158 {
159  mYLineEdit->setText( text );
160 }
161 
162 void QgsAdvancedDigitizingFloater::changeDistance( const QString &text )
163 {
164  mDistanceLineEdit->setText( text );
165 }
166 
167 void QgsAdvancedDigitizingFloater::changeAngle( const QString &text )
168 {
169  mAngleLineEdit->setText( text );
170 }
171 
172 void QgsAdvancedDigitizingFloater::changeLockX( bool locked )
173 {
174  if ( !locked )
175  {
176  mXLineEdit->setStyleSheet( QString() );
177  mXLabel->setStyleSheet( QString() );
178  }
179  else
180  {
181  mXLineEdit->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
182  mXLabel->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
183  }
184 }
185 
186 void QgsAdvancedDigitizingFloater::changeLockY( bool locked )
187 {
188  if ( !locked )
189  {
190  mYLineEdit->setStyleSheet( QString() );
191  mYLabel->setStyleSheet( QString() );
192  }
193  else
194  {
195  mYLineEdit->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
196  mYLabel->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
197  }
198 }
199 
200 void QgsAdvancedDigitizingFloater::changeLockDistance( bool locked )
201 {
202  if ( !locked )
203  {
204  mDistanceLineEdit->setStyleSheet( QString() );
205  mDistanceLabel->setStyleSheet( QString() );
206  }
207  else
208  {
209  mDistanceLineEdit->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
210  mDistanceLabel->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
211  }
212 }
213 
214 void QgsAdvancedDigitizingFloater::changeLockAngle( bool locked )
215 {
216  if ( !locked )
217  {
218  mAngleLineEdit->setStyleSheet( QString() );
219  mAngleLabel->setStyleSheet( QString() );
220  }
221  else
222  {
223  mAngleLineEdit->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
224  mAngleLabel->setStyleSheet( QStringLiteral( "font-weight: bold" ) );
225  }
226 }
227 
228 
229 void QgsAdvancedDigitizingFloater::changeRelativeX( bool relative )
230 {
231  if ( !relative )
232  {
233  mXLabel->setText( "x" );
234  }
235  else
236  {
237  mXLabel->setText( "Δx" );
238  }
239  adjustSize();
240 }
241 
242 void QgsAdvancedDigitizingFloater::changeRelativeY( bool relative )
243 {
244  if ( !relative )
245  {
246  mYLabel->setText( "y" );
247  }
248  else
249  {
250  mYLabel->setText( "Δy" );
251  }
252  adjustSize();
253 }
254 
255 // distance is always relative
256 
257 void QgsAdvancedDigitizingFloater::changeRelativeAngle( bool relative )
258 {
259  if ( !relative )
260  {
261  mAngleLabel->setText( "a" );
262  }
263  else
264  {
265  mAngleLabel->setText( "Δa" );
266  }
267  adjustSize();
268 }
269 
270 void QgsAdvancedDigitizingFloater::focusOnX()
271 {
272  if ( mActive )
273  {
274  mXLineEdit->setFocus();
275  mXLineEdit->selectAll();
276  }
277 }
278 
279 void QgsAdvancedDigitizingFloater::focusOnY()
280 {
281  if ( mActive )
282  {
283  mYLineEdit->setFocus();
284  mYLineEdit->selectAll();
285  }
286 }
287 
288 void QgsAdvancedDigitizingFloater::focusOnDistance()
289 {
290  if ( mActive )
291  {
292  mDistanceLineEdit->setFocus();
293  mDistanceLineEdit->selectAll();
294  }
295 }
296 
297 void QgsAdvancedDigitizingFloater::focusOnAngle()
298 {
299  if ( mActive )
300  {
301  mAngleLineEdit->setFocus();
302  mAngleLineEdit->selectAll();
303  }
304 }
305 
306 
307 void QgsAdvancedDigitizingFloater::enabledChangedX( bool enabled )
308 {
309  mXLineEdit->setVisible( enabled );
310  mXLabel->setVisible( enabled );
311  adjustSize();
312 }
313 
314 void QgsAdvancedDigitizingFloater::enabledChangedY( bool enabled )
315 {
316  mYLineEdit->setVisible( enabled );
317  mYLabel->setVisible( enabled );
318  adjustSize();
319 }
320 
321 void QgsAdvancedDigitizingFloater::enabledChangedDistance( bool enabled )
322 {
323  mDistanceLineEdit->setVisible( enabled );
324  mDistanceLabel->setVisible( enabled );
325  adjustSize();
326 }
327 
328 void QgsAdvancedDigitizingFloater::enabledChangedAngle( bool enabled )
329 {
330  mAngleLineEdit->setVisible( enabled );
331  mAngleLabel->setVisible( enabled );
332  adjustSize();
333 }
qgsmapcanvas.h
QgsAdvancedDigitizingDockWidget::enabledChangedY
void enabledChangedY(bool enabled)
Emitted whenever the Y field is enabled or disabled.
QgsAdvancedDigitizingDockWidget::setAngle
void setAngle(const QString &value, WidgetSetMode mode)
Set the angle value on the widget.
Definition: qgsadvanceddigitizingdockwidget.cpp:200
QgsAdvancedDigitizingDockWidget::lockXChanged
void lockXChanged(bool locked)
Emitted whenever the X parameter is locked.
QgsAdvancedDigitizingFloater::setActive
void setActive(bool active)
Set whether the floater should be active or not.
Definition: qgsadvanceddigitizingfloater.cpp:129
QgsAdvancedDigitizingDockWidget::setDistance
void setDistance(const QString &value, WidgetSetMode mode)
Set the distance value on the widget.
Definition: qgsadvanceddigitizingdockwidget.cpp:217
QgsMapCanvas
Definition: qgsmapcanvas.h:83
QgsSettings
Definition: qgssettings.h:61
QgsFocusWatcher
Definition: qgsfocuswatcher.h:33
QgsAdvancedDigitizingDockWidget::valueDistanceChanged
void valueDistanceChanged(const QString &value)
Emitted whenever the distance value changes (either the mouse moved, or the user changed the input).
QgsAdvancedDigitizingFloater::QgsAdvancedDigitizingFloater
QgsAdvancedDigitizingFloater(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
Create an advanced digitizing floater widget.
Definition: qgsadvanceddigitizingfloater.cpp:26
QgsAdvancedDigitizingDockWidget::focusOnAngleRequested
void focusOnAngleRequested()
Emitted whenever the angle field should get the focus using the shortcuts (A).
QgsAdvancedDigitizingDockWidget::lockDistanceChanged
void lockDistanceChanged(bool locked)
Emitted whenever the distance parameter is locked.
QgsAdvancedDigitizingDockWidget::relativeYChanged
void relativeYChanged(bool relative)
Emitted whenever the Y parameter is toggled between absolute and relative.
QgsAdvancedDigitizingDockWidget::valueXChanged
void valueXChanged(const QString &value)
Emitted whenever the X value changes (either the mouse moved, or the user changed the input).
QgsAdvancedDigitizingDockWidget::focusOnXRequested
void focusOnXRequested()
Emitted whenever the X field should get the focus using the shortcuts (X).
QgsAdvancedDigitizingDockWidget::setX
void setX(const QString &value, WidgetSetMode mode)
Set the X value on the widget.
Definition: qgsadvanceddigitizingdockwidget.cpp:166
QgsAdvancedDigitizingDockWidget::cadEnabledChanged
void cadEnabledChanged(bool enabled)
Signals for external widgets that need to update according to current values.
QgsAdvancedDigitizingDockWidget::enabledChangedDistance
void enabledChangedDistance(bool enabled)
Emitted whenever the distance field is enabled or disabled.
QgsAdvancedDigitizingDockWidget::enabledChangedAngle
void enabledChangedAngle(bool enabled)
Emitted whenever the angle field is enabled or disabled.
QgsAdvancedDigitizingDockWidget::lockAngleChanged
void lockAngleChanged(bool locked)
Emitted whenever the angle parameter is locked.
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:289
qgsfocuswatcher.h
qgsadvanceddigitizingfloater.h
QgsFocusWatcher::focusOut
void focusOut()
Emitted when parent object loses focus.
QgsAdvancedDigitizingDockWidget
The QgsAdvancedDigitizingDockWidget class is a dockable widget used to handle the CAD tools on top of...
Definition: qgsadvanceddigitizingdockwidget.h:48
QgsAdvancedDigitizingDockWidget::valueAngleChanged
void valueAngleChanged(const QString &value)
Emitted whenever the angle value changes (either the mouse moved, or the user changed the input).
QgsAdvancedDigitizingDockWidget::enabledChangedX
void enabledChangedX(bool enabled)
Emitted whenever the X field is enabled or disabled.
QgsAdvancedDigitizingDockWidget::valueYChanged
void valueYChanged(const QString &value)
Emitted whenever the Y value changes (either the mouse moved, or the user changed the input).
QgsAdvancedDigitizingDockWidget::relativeXChanged
void relativeXChanged(bool relative)
Emitted whenever the X parameter is toggled between absolute and relative.
qgssettings.h
QgsAdvancedDigitizingFloater::active
bool active()
Whether the floater is active or not.
Definition: qgsadvanceddigitizingfloater.cpp:124
QgsAdvancedDigitizingDockWidget::focusOnDistanceRequested
void focusOnDistanceRequested()
Emitted whenever the distance field should get the focus using the shortcuts (D).
QgsAdvancedDigitizingDockWidget::relativeAngleChanged
void relativeAngleChanged(bool relative)
Emitted whenever the angleX parameter is toggled between absolute and relative.
QgsAdvancedDigitizingDockWidget::focusOnYRequested
void focusOnYRequested()
Emitted whenever the Y field should get the focus using the shortcuts (Y).
QgsAdvancedDigitizingDockWidget::setY
void setY(const QString &value, WidgetSetMode mode)
Set the Y value on the widget.
Definition: qgsadvanceddigitizingdockwidget.cpp:183
QgsAdvancedDigitizingDockWidget::lockYChanged
void lockYChanged(bool locked)
Emitted whenever the Y parameter is locked.
QgsAdvancedDigitizingDockWidget::cadEnabled
bool cadEnabled() const
determines if CAD tools are enabled or if map tools behaves "nomally"
Definition: qgsadvanceddigitizingdockwidget.h:251
qgsmessagelog.h