Marble

MarbleWidgetInputHandler.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
4// SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5// SPDX-FileCopyrightText: 2014 Adam Dabrowski <adamdbrw@gmail.com>
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
27namespace Marble
28{
29
30class 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
105void MarbleWidgetInputHandler::setCursor(const QCursor &cursor)
106{
107 d->setCursor(cursor);
108}
109
110bool 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:
155 MarbleDebug::setEnabled(!MarbleDebug::isEnabled());
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
178bool 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
225bool 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
238void MarbleWidgetInputHandler::handlePinchGesture(QPinchGesture *pinch)
239{
240 MarbleAbstractPresenter *marblePresenter = d->m_marblePresenter;
241
242 switch (pinch->state())
243 {
244 case Qt::NoGesture:
245 break;
247 marblePresenter->setViewContext(Animation);
248 break;
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 }
270 restoreViewContext();
271 break;
272 }
273}
274
275AbstractSelectionRubber *MarbleWidgetInputHandler::selectionRubber()
276{
277 return &d->m_selectionRubber;
278}
279
280bool MarbleWidgetInputHandler::layersEventFilter(QObject *o, QEvent *e)
281{
282 return d->layersEventFilter(o, e);
283}
284
285void MarbleWidgetInputHandler::installPluginEventFilter(RenderPlugin *renderPlugin)
286{
287 d->installPluginEventFilter(renderPlugin);
288}
289
290MarbleWidgetInputHandler::MarbleWidgetInputHandler(MarbleAbstractPresenter *marblePresenter, MarbleWidget *widget)
291 : MarbleDefaultInputHandler(marblePresenter)
292 ,d(new MarbleWidgetInputHandlerPrivate(this, widget, marblePresenter))
293{
294}
295
296void 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
302void 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
311void MarbleWidgetInputHandler::showRmbMenu(int x, int y)
312{
313 if (isMouseButtonPopupEnabled(Qt::RightButton))
314 {
315 d->m_marbleWidget->popupMenu()->showRmbMenu(x, y);
316 }
317}
318
319void 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"
This file contains the headers for MarbleMap.
This file contains the headers for MarbleWidget.
This file contains the headers for ViewportParams.
bool eventFilter(QObject *obj, QEvent *event) override
Overriding QWidget, used to make the layer interactive.
KIOCORE_EXPORT CopyJob * move(const QList< QUrl > &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
Binds a QML item to a specific geodetic location in screen coordinates.
@ Animation
animated view (e.g. while rotating the globe)
QGesture * gesture(Qt::GestureType type) const const
bool blockSignals(bool block)
virtual bool event(QEvent *e)
void installEventFilter(QObject *filterObj)
T qobject_cast(QObject *object)
void setGeometry(const QRect &rect)
NoGesture
PinchGesture
ControlModifier
LeftButton
QTextStream & center(QTextStream &stream)
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
void setCursor(const QCursor &)
void grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
void hide()
void show()
bool isVisible() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.