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

KDE's Doxygen guidelines are available online.