QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 }
void enabledChangedAngle(bool enabled)
Emitted whenever the angle field is enabled or disabled.
bool cadEnabled() const
determines if CAD tools are enabled or if map tools behaves "nomally"
QgsAdvancedDigitizingFloater(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
Create an advanced digitizing floater widget.
void setAngle(const QString &value, WidgetSetMode mode)
Set the angle value on the widget.
void focusOut()
Emitted when parent object loses focus.
A event filter for watching for focus events on a parent object.
void valueAngleChanged(const QString &value)
Emitted whenever the angle value changes (either the mouse moved, or the user changed the input)...
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
void relativeAngleChanged(bool relative)
Emitted whenever the angleX parameter is toggled between absolute and relative.
void focusOnYRequested()
Emitted whenever the Y field should get the focus using the shortcuts (Y).
void lockYChanged(bool locked)
Emitted whenever the Y parameter is locked.
void lockAngleChanged(bool locked)
Emitted whenever the angle parameter is locked.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:73
bool active()
Whether the floater is active or not.
void setX(const QString &value, WidgetSetMode mode)
Set the X value on the widget.
void enabledChangedDistance(bool enabled)
Emitted whenever the distance 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)...
void focusOnXRequested()
Emitted whenever the X field should get the focus using the shortcuts (X).
void setDistance(const QString &value, WidgetSetMode mode)
Set the distance value on the widget.
void enabledChangedX(bool enabled)
Emitted whenever the X field is enabled or disabled.
void valueDistanceChanged(const QString &value)
Emitted whenever the distance value changes (either the mouse moved, or the user changed the input)...
void cadEnabledChanged(bool enabled)
Signals for external widgets that need to update according to current values.
void lockDistanceChanged(bool locked)
Emitted whenever the distance parameter is locked.
void enabledChangedY(bool enabled)
Emitted whenever the Y field is enabled or disabled.
void setY(const QString &value, WidgetSetMode mode)
Set the Y value on the widget.
void setActive(bool active)
Set whether the floater should be active or not.
void focusOnDistanceRequested()
Emitted whenever the distance field should get the focus using the shortcuts (D). ...
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void focusOnAngleRequested()
Emitted whenever the angle field should get the focus using the shortcuts (A).
void relativeYChanged(bool relative)
Emitted whenever the Y parameter is toggled between absolute and relative.
void valueXChanged(const QString &value)
Emitted whenever the X value changes (either the mouse moved, or the user changed the input)...
void relativeXChanged(bool relative)
Emitted whenever the X parameter is toggled between absolute and relative.
void lockXChanged(bool locked)
Emitted whenever the X parameter is locked.
The QgsAdvancedDigitizingDockWidget class is a dockable widget used to handle the CAD tools on top of...