1818
1919#include " graphicsworkspace.h"
2020#include " logger.h"
21+ #include < cmath>
2122#include < QElapsedTimer>
2223#include < QRubberBand>
24+ #include < QGesture>
25+ #include < QGestureEvent>
26+ #include < QPanGesture>
27+ #include < QPinchGesture>
28+ #ifdef __APPLE__
29+ #include < QNativeGestureEvent>
30+ #endif
2331
2432#include < editing/_scenes/level/lvl_scene.h>
2533#include < editing/_scenes/world/wld_scene.h>
@@ -88,6 +96,13 @@ GraphicsWorkspace::GraphicsWorkspace(QWidget *parent) :
8896 rubberBandSelectionMode = Qt::IntersectsItemShape;
8997 this ->setMouseTracking (true );
9098 this ->setRubberBandSelectionMode (Qt::IntersectsItemShape);
99+ #ifdef __APPLE__
100+ this ->setAttribute (Qt::WA_AcceptTouchEvents, true );
101+ #endif
102+ this ->grabGesture (Qt::PanGesture);
103+ #ifndef __APPLE__
104+ this ->grabGesture (Qt::PinchGesture);
105+ #endif
91106
92107 movement = MOVE_IDLE;
93108
@@ -102,11 +117,17 @@ GraphicsWorkspace::GraphicsWorkspace(QWidget *parent) :
102117 scaleMin = 0.01 ;
103118 scaleMax = 20.0 ;
104119
120+ scaleGestureFactor = 1.0 ;
121+
105122 connect (&Mover, SIGNAL (timeout ()), this , SLOT (doMove ()));
106123 connect (horizontalScrollBar (), SIGNAL (valueChanged (int )), this , SLOT (replayLastMouseEvent (int )));
107124 connect (verticalScrollBar (), SIGNAL (valueChanged (int )), this , SLOT (replayLastMouseEvent (int )));
108125
109126 setTransformationAnchor (QGraphicsView::AnchorViewCenter);
127+
128+ #ifdef __APPLE__
129+ installEventFilter (this );
130+ #endif
110131}
111132
112133GraphicsWorkspace::~GraphicsWorkspace ()
@@ -183,10 +204,13 @@ void GraphicsWorkspace::doMove()
183204{
184205 if ((movement & MOVE_LEFT) != 0 )
185206 moveLeft ();
207+
186208 if ((movement & MOVE_RIGHT) != 0 )
187209 moveRight ();
210+
188211 if ((movement & MOVE_UP) != 0 )
189212 moveUp ();
213+
190214 if ((movement & MOVE_DOWN) != 0 )
191215 moveDown ();
192216}
@@ -291,6 +315,7 @@ void GraphicsWorkspace::focusOutEvent(QFocusEvent *event)
291315void GraphicsWorkspace::wheelEvent (QWheelEvent *event)
292316{
293317 int modS = 128 ;
318+ float modX, modY;
294319 // int modS_h = modS;
295320 // bool rtl = (qApp->layoutDirection() == Qt::RightToLeft);
296321
@@ -307,54 +332,34 @@ void GraphicsWorkspace::wheelEvent(QWheelEvent *event)
307332 int deltaX = delta.x ();
308333 int deltaY = delta.y ();
309334
335+ modX = std::abs (modS * ((deltaX / 8 .0f ) / 15 .0f ));
336+ modY = std::abs (modS * ((deltaY / 8 .0f ) / 15 .0f ));
337+
310338 if ((event->modifiers () & Qt::ControlModifier) != 0 )
311339 {
312- // Scale the view / do the zoom
313- if (deltaY > 0 )
314- {
315- if (zoomValue * scaleFactor >= scaleMax) return ;
316- // Zoom in
317- zoomValue *= scaleFactor;
318- scale (scaleFactor, scaleFactor);
319- emit zoomValueChanged (qRound (zoomValue * 100 ));
320- emit zoomValueChanged (QString::number (qRound (zoomValue * 100 )));
321- }
322- else if (deltaY < 0 )
323- {
324- if (zoomValue * scaleFactor <= scaleMin) return ;
325- // Zooming out
326- zoomValue *= 1.0 / scaleFactor;
327- scale (1.0 / scaleFactor, 1.0 / scaleFactor);
328- emit zoomValueChanged (qRound (zoomValue * 100 ));
329- emit zoomValueChanged (QString::number (qRound (zoomValue * 100 )));
330- }
340+ modY = 1.0 + std::abs (0.15 * ((deltaY / 8 .0f ) / 15 .0f ));
341+ // qDebug() << "Zoom factor: " << modY << scaleFactor << deltaY;
342+ eventZoom (deltaY, modY);
331343
332344 replayLastMouseEvent ();
333345 return ;
334346 }
335347
336- auto *hBar = horizontalScrollBar ();
337- auto *vBar = verticalScrollBar ();
338-
339348 if ((event->modifiers () & Qt::AltModifier) != 0 )
340349 {
341350 // Ensure values aren't already swapped
342351 if (delta.x () == 0 && delta.y () != 0 )
343352 {
344353 deltaY = delta.x ();
345354 deltaX = delta.y ();
355+ modY = std::abs (modS * ((deltaX / 8 .0f ) / 15 .0f ));
356+ modX = std::abs (modS * ((deltaY / 8 .0f ) / 15 .0f ));
346357 }
347358 }
348359
349- if (deltaX > 0 )
350- hBar->setValue (hBar->value () - modS);
351- else if (deltaX < 0 )
352- hBar->setValue (hBar->value () + modS);
360+ // qDebug() << "Wheel Delta: " << deltaX << deltaY;
353361
354- if (deltaY > 0 )
355- vBar->setValue (vBar->value () - modS);
356- else if (deltaY < 0 )
357- vBar->setValue (vBar->value () + modS);
362+ eventScroll (deltaX, modX, deltaY, modY);
358363
359364 // event->accept();
360365 replayLastMouseEvent ();
@@ -363,6 +368,112 @@ void GraphicsWorkspace::wheelEvent(QWheelEvent *event)
363368 scene ()->update ();
364369}
365370
371+ bool GraphicsWorkspace::event (QEvent *event)
372+ {
373+ if (event->type () == QEvent::Gesture)
374+ return gestureEvent (static_cast <QGestureEvent*>(event));
375+
376+ return QGraphicsView::event (event);
377+ }
378+
379+ #ifdef __APPLE__
380+ bool GraphicsWorkspace::eventFilter (QObject *obj, QEvent *event)
381+ {
382+ if (event->type () == QEvent::NativeGesture)
383+ {
384+ // Handle double-tap on Magic Mouse on macOS when "smart zoom" option is activated
385+ QNativeGestureEvent *gesture = static_cast <QNativeGestureEvent*>(event);
386+ Q_ASSERT (gesture);
387+
388+ if (gesture->gestureType () == Qt::NativeGestureType::SmartZoomNativeGesture)
389+ {
390+ if (qRound (zoomValue * 100 ) == 100 )
391+ setZoom (2.5 );
392+ else
393+ setZoom (1.0 );
394+ return true ;
395+ }
396+ }
397+
398+ return QGraphicsView::eventFilter (obj, event);
399+ }
400+ #endif
401+
402+ bool GraphicsWorkspace::gestureEvent (QGestureEvent *event)
403+ {
404+ if (QGesture *pan = event->gesture (Qt::PanGesture))
405+ gesturePan (static_cast <QPanGesture *>(pan));
406+ else if (QGesture *pinch = event->gesture (Qt::PinchGesture))
407+ gesturePinch (static_cast <QPinchGesture *>(pinch));
408+
409+ return true ;
410+ }
411+
412+ void GraphicsWorkspace::gesturePan (QPanGesture *gesture)
413+ {
414+ QPointF delta = gesture->delta ();
415+ eventScroll (delta.x (), std::abs (delta.x ()), delta.y (), std::abs (delta.y ()));
416+ }
417+
418+ void GraphicsWorkspace::gesturePinch (QPinchGesture *gesture)
419+ {
420+ QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags ();
421+
422+ if (changeFlags & QPinchGesture::ScaleFactorChanged)
423+ {
424+ scaleGestureFactor = gesture->totalScaleFactor ();
425+ qDebug () << " gesturePinch(): zoom by" << gesture->scaleFactor () << " ->" << scaleGestureFactor;
426+ }
427+
428+ if (gesture->state () == Qt::GestureFinished)
429+ {
430+ zoomValue *= gesture->scaleFactor ();
431+ scale (scaleGestureFactor, scaleGestureFactor);
432+ emit zoomValueChanged (qRound (zoomValue * 100 ));
433+ emit zoomValueChanged (QString::number (qRound (zoomValue * 100 )));
434+ scaleGestureFactor = 1.0 ;
435+ }
436+ }
437+
438+ void GraphicsWorkspace::eventScroll (int dirx, int x, int diry, int y)
439+ {
440+ auto *hBar = horizontalScrollBar ();
441+ auto *vBar = verticalScrollBar ();
442+
443+ if (dirx > 0 )
444+ hBar->setValue (hBar->value () - x);
445+ else if (dirx < 0 )
446+ hBar->setValue (hBar->value () + x);
447+
448+ if (diry > 0 )
449+ vBar->setValue (vBar->value () - y);
450+ else if (diry < 0 )
451+ vBar->setValue (vBar->value () + y);
452+ }
453+
454+ void GraphicsWorkspace::eventZoom (int dir, float delta)
455+ {
456+ // Scale the view / do the zoom
457+ if (dir > 0 )
458+ {
459+ if (zoomValue * delta >= scaleMax) return ;
460+ // Zoom in
461+ zoomValue *= delta;
462+ scale (delta, delta);
463+ emit zoomValueChanged (qRound (zoomValue * 100 ));
464+ emit zoomValueChanged (QString::number (qRound (zoomValue * 100 )));
465+ }
466+ else if (dir < 0 )
467+ {
468+ if (zoomValue * delta <= scaleMin) return ;
469+ // Zooming out
470+ zoomValue *= 1.0 / delta;
471+ scale (1.0 / delta, 1.0 / delta);
472+ emit zoomValueChanged (qRound (zoomValue * 100 ));
473+ emit zoomValueChanged (QString::number (qRound (zoomValue * 100 )));
474+ }
475+ }
476+
366477
367478
368479void GraphicsWorkspace::mousePressEvent (QMouseEvent *event)
0 commit comments