Marble

MarbleWidgetInputHandler.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <[email protected]>
4 // SPDX-FileCopyrightText: 2007 Inge Wallin <[email protected]>
5 // SPDX-FileCopyrightText: 2014 Adam Dabrowski <[email protected]>
6 //
7 
8 #include "MarbleWidgetInputHandler.h"
9 
10 #include <QRubberBand>
11 #include <QToolTip>
12 #include <QTimer>
13 #include <QKeyEvent>
14 
15 #include "MarbleGlobal.h"
16 #include "MarbleDebug.h"
17 #include "MarbleWidget.h"
18 #include "MarbleMap.h"
19 #include "ViewportParams.h"
20 #include "AbstractDataPluginItem.h"
21 #include "MarbleAbstractPresenter.h"
22 #include "MarbleWidgetPopupMenu.h"
23 #include "PopupLayer.h"
24 #include "RenderPlugin.h"
25 #include "RoutingLayer.h"
26 
27 namespace Marble
28 {
29 
30 class MarbleWidgetInputHandlerPrivate
31 {
32  class MarbleWidgetSelectionRubber : public AbstractSelectionRubber
33  {
34  public:
35  explicit MarbleWidgetSelectionRubber(MarbleWidget *widget)
36  : m_rubberBand(QRubberBand::Rectangle, widget)
37  {
38  m_rubberBand.hide();
39  }
40 
41  void show() override { m_rubberBand.show(); }
42  void hide() override { m_rubberBand.hide(); }
43  bool isVisible() const override { return m_rubberBand.isVisible(); }
44  const QRect &geometry() const override { return m_rubberBand.geometry(); }
45  void setGeometry(const QRect &geometry) override { m_rubberBand.setGeometry(geometry); }
46 
47  private:
48  QRubberBand m_rubberBand;
49  };
50 
51  public:
52  MarbleWidgetInputHandlerPrivate(MarbleWidgetInputHandler *handler, MarbleWidget *widget,
53  MarbleAbstractPresenter *presenter)
54  : m_inputHandler(handler)
55  ,m_marbleWidget(widget)
56  ,m_marblePresenter(presenter)
57  ,m_selectionRubber(widget)
58  ,m_debugModeEnabled(false)
59  {
60  for(RenderPlugin *renderPlugin: widget->renderPlugins())
61  {
62  if(renderPlugin->isInitialized())
63  {
64  installPluginEventFilter(renderPlugin);
65  }
66  }
67  m_marbleWidget->grabGesture(Qt::PinchGesture);
68  }
69 
70  void setCursor(const QCursor &cursor)
71  {
72  m_marbleWidget->setCursor(cursor);
73  }
74 
75  bool layersEventFilter(QObject *o, QEvent *e)
76  { //FIXME - this should go up in hierarchy to MarbleInputHandler
77  if (m_marbleWidget->popupLayer()->eventFilter(o, e))
78  {
79  return true;
80  }
81 
82  if (m_marbleWidget->routingLayer()->eventFilter(o, e))
83  {
84  return true;
85  }
86 
87  return false;
88  }
89 
90  void installPluginEventFilter(RenderPlugin *renderPlugin)
91  {
92  m_marbleWidget->installEventFilter(renderPlugin);
93  }
94 
95  MarbleWidgetInputHandler *m_inputHandler;
96  MarbleWidget *m_marbleWidget;
97  MarbleAbstractPresenter *m_marblePresenter;
98  MarbleWidgetSelectionRubber m_selectionRubber;
99  bool m_debugModeEnabled;
100  bool m_pinchDetected = false;
101  bool m_panDetected = false;
102 };
103 
104 
105 void MarbleWidgetInputHandler::setCursor(const QCursor &cursor)
106 {
107  d->setCursor(cursor);
108 }
109 
110 bool MarbleWidgetInputHandler::handleKeyPress(QKeyEvent *event)
111 {
112  if (d->m_debugModeEnabled) {
113  if (event->modifiers() == Qt::ControlModifier && d->m_marbleWidget->debugLevelTags()) {
114  switch(event->key()) {
115  case Qt::Key_0:
116  d->m_marbleWidget->setLevelToDebug(0);
117  break;
118  case Qt::Key_1:
119  d->m_marbleWidget->setLevelToDebug(1);
120  break;
121  case Qt::Key_2:
122  d->m_marbleWidget->setLevelToDebug(2);
123  break;
124  case Qt::Key_3:
125  d->m_marbleWidget->setLevelToDebug(3);
126  break;
127  case Qt::Key_4:
128  d->m_marbleWidget->setLevelToDebug(4);
129  break;
130  case Qt::Key_5:
131  d->m_marbleWidget->setLevelToDebug(5);
132  break;
133  case Qt::Key_6:
134  d->m_marbleWidget->setLevelToDebug(6);
135  break;
136  case Qt::Key_7:
137  d->m_marbleWidget->setLevelToDebug(7);
138  break;
139  case Qt::Key_8:
140  d->m_marbleWidget->setLevelToDebug(8);
141  break;
142  case Qt::Key_9:
143  d->m_marbleWidget->setLevelToDebug(9);
144  break;
145  case Qt::Key_Plus:
146  d->m_marbleWidget->setLevelToDebug(d->m_marbleWidget->levelToDebug() + 1);
147  break;
148  case Qt::Key_Minus:
149  d->m_marbleWidget->setLevelToDebug(d->m_marbleWidget->levelToDebug() - 1);
150  break;
151  }
152  } else {
153  switch(event->key()) {
154  case Qt::Key_I:
156  break;
157  case Qt::Key_R:
158  d->m_marbleWidget->setShowRuntimeTrace(!d->m_marbleWidget->showRuntimeTrace());
159  break;
160  case Qt::Key_O:
161  d->m_marbleWidget->setShowDebugPlacemarks(!d->m_marbleWidget->showDebugPlacemarks());
162  break;
163  case Qt::Key_P:
164  d->m_marbleWidget->setShowDebugPolygons(!d->m_marbleWidget->showDebugPolygons());
165  break;
166  case Qt::Key_B:
167  d->m_marbleWidget->setShowDebugBatchRender(!d->m_marbleWidget->showDebugBatchRender());
168  break;
169  case Qt::Key_L:
170  d->m_marbleWidget->setDebugLevelTags(!d->m_marbleWidget->debugLevelTags());
171  break;
172  }
173  }
174  }
175  return MarbleDefaultInputHandler::handleKeyPress(event);
176 }
177 
178 bool MarbleWidgetInputHandler::handleTouch(QTouchEvent *event)
179 {
180  event->accept();
181 
182  if (event->touchPoints().count() == 1)
183  {
184  QTouchEvent::TouchPoint p = event->touchPoints().at(0);
185  if (event->type() == QEvent::TouchBegin)
186  {
187  d->m_pinchDetected = false;
188  d->m_panDetected = false;
191  handleMouseEvent(&press);
192  }
193  else if (event->type() == QEvent::TouchUpdate)
194  {
195  if (!d->m_pinchDetected)
196  {
197  d->m_panDetected = true;
200  handleMouseEvent(&move);
201  }
202  }
203  else if (event->type() == QEvent::TouchEnd)
204  {
205  // avoid triggering mouse clicked signal when we just changed the viewport
206  if (d->m_pinchDetected || d->m_panDetected)
207  blockSignals(true);
208 
211  handleMouseEvent(&release);
212 
213  if (d->m_pinchDetected || d->m_panDetected)
214  {
215  if (d->m_pinchDetected)
216  stopInertialEarthRotation(); // ensures we keep the viewport
217 
218  blockSignals(false);
219  }
220  }
221  }
222  return true;
223 }
224 
225 bool MarbleWidgetInputHandler::handleGesture(QGestureEvent *e)
226 {
227  QPinchGesture *pinch = static_cast<QPinchGesture*>(e->gesture(Qt::PinchGesture));
228  if (pinch && !d->m_panDetected)
229  {
230  d->m_pinchDetected = true;
231  handlePinchGesture(pinch);
232  return true;
233  }
234 
235  return false;
236 }
237 
238 void MarbleWidgetInputHandler::handlePinchGesture(QPinchGesture *pinch)
239 {
240  MarbleAbstractPresenter *marblePresenter = d->m_marblePresenter;
241 
242  switch (pinch->state())
243  {
244  case Qt::NoGesture:
245  break;
246  case Qt::GestureStarted:
247  marblePresenter->setViewContext(Animation);
248  break;
249  case Qt::GestureUpdated:
250  {
251  qreal scaleFactor = pinch->scaleFactor();
252  QPoint center = d->m_marbleWidget->mapFromGlobal(pinch->centerPoint().toPoint());
253 
254  if (scaleFactor > 1.0)
255  scaleFactor = 0.2;
256  else if (scaleFactor < 1.0)
257  scaleFactor = -0.2;
258  else return; // 1 .. no change
259 
260  qreal zoom = marblePresenter->zoom();
261  bool oldAnim = marblePresenter->animationsEnabled();
262  qreal newDistance = marblePresenter->distanceFromZoom(zoom + 20 * scaleFactor);
263  marblePresenter->setAnimationsEnabled(false);
264  marblePresenter->zoomAt(center, newDistance);
265  marblePresenter->setAnimationsEnabled(oldAnim);
266  break;
267  }
268  case Qt::GestureFinished:
269  case Qt::GestureCanceled:
270  restoreViewContext();
271  break;
272  }
273 }
274 
275 AbstractSelectionRubber *MarbleWidgetInputHandler::selectionRubber()
276 {
277  return &d->m_selectionRubber;
278 }
279 
280 bool MarbleWidgetInputHandler::layersEventFilter(QObject *o, QEvent *e)
281 {
282  return d->layersEventFilter(o, e);
283 }
284 
285 void MarbleWidgetInputHandler::installPluginEventFilter(RenderPlugin *renderPlugin)
286 {
287  d->installPluginEventFilter(renderPlugin);
288 }
289 
290 MarbleWidgetInputHandler::MarbleWidgetInputHandler(MarbleAbstractPresenter *marblePresenter, MarbleWidget *widget)
291  : MarbleDefaultInputHandler(marblePresenter)
292  ,d(new MarbleWidgetInputHandlerPrivate(this, widget, marblePresenter))
293 {
294 }
295 
296 void MarbleWidgetInputHandler::setDebugModeEnabled(bool enabled)
297 {
298  d->m_debugModeEnabled = enabled;
299 }
300 
301 //FIXME - these should be moved to superclass and popupMenu should be abstracted in MarbleAbstractPresenter
302 void MarbleWidgetInputHandler::showLmbMenu(int x, int y)
303 {
304  if (isMouseButtonPopupEnabled(Qt::LeftButton) && !d->m_pinchDetected && !d->m_panDetected)
305  {
306  d->m_marbleWidget->popupMenu()->showLmbMenu(x, y);
307  toolTipTimer()->stop();
308  }
309 }
310 
311 void MarbleWidgetInputHandler::showRmbMenu(int x, int y)
312 {
313  if (isMouseButtonPopupEnabled(Qt::RightButton))
314  {
315  d->m_marbleWidget->popupMenu()->showRmbMenu(x, y);
316  }
317 }
318 
319 void MarbleWidgetInputHandler::openItemToolTip()
320 {
321  if (lastToolTipItem())
322  {
323  QToolTip::showText(d->m_marbleWidget->mapToGlobal(toolTipPosition()),
324  lastToolTipItem()->toolTip(),
325  d->m_marbleWidget,
326  lastToolTipItem()->containsRect(toolTipPosition()).toRect());
327  }
328 }
329 
330 }
331 
332 #include "moc_MarbleWidgetInputHandler.cpp"
void showText(const QPoint &pos, const QString &text, QWidget *w)
NoGesture
virtual void release(quint64 objid)
@ Animation
animated view (e.g. while rotating the globe)
Definition: MarbleGlobal.h:68
LeftButton
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
Binds a QML item to a specific geodetic location in screen coordinates.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
PinchGesture
static bool isEnabled()
isEnabled returns whether debug information output is generated
Definition: MarbleDebug.cpp:42
KIOCORE_EXPORT CopyJob * move(const QList< QUrl > &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QPointF pos() const const
QTextStream & center(QTextStream &stream)
ControlModifier
QGesture * gesture(Qt::GestureType type) const const
static void setEnabled(bool enabled)
setEnabled Toggle debug information output generation
Definition: MarbleDebug.cpp:47
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu May 26 2022 04:07:50 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.