diff --git a/src/tools/pin/pinwidget.cpp b/src/tools/pin/pinwidget.cpp index 9f4c6c07..2ead15e9 100644 --- a/src/tools/pin/pinwidget.cpp +++ b/src/tools/pin/pinwidget.cpp @@ -1,17 +1,27 @@ // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors +#include +#include + #include "pinwidget.h" #include "qguiappcurrentscreen.h" #include "src/utils/confighandler.h" #include "src/utils/globalvalues.h" -#include + #include #include #include #include #include +namespace { +static constexpr int MARGIN = 7; +static constexpr int BLUR_RADIUS = 2 * MARGIN; +static constexpr qreal STEP = 0.03; +static constexpr qreal MIN_SIZE = 100.0; +} + PinWidget::PinWidget(const QPixmap& pixmap, const QRect& geometry, QWidget* parent) @@ -29,12 +39,11 @@ PinWidget::PinWidget(const QPixmap& pixmap, m_hoverColor = conf.contrastUiColor(); m_layout = new QVBoxLayout(this); - const int margin = this->margin(); - m_layout->setContentsMargins(margin, margin, margin, margin); + m_layout->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN); m_shadowEffect = new QGraphicsDropShadowEffect(this); m_shadowEffect->setColor(m_baseColor); - m_shadowEffect->setBlurRadius(2 * margin); + m_shadowEffect->setBlurRadius(BLUR_RADIUS); m_shadowEffect->setOffset(0, 0); setGraphicsEffect(m_shadowEffect); @@ -52,7 +61,7 @@ PinWidget::PinWidget(const QPixmap& pixmap, devicePixelRatio = currentScreen->devicePixelRatio(); } #endif - const int m = margin * devicePixelRatio; + const int m = MARGIN * devicePixelRatio; QRect adjusted_pos = geometry + QMargins(m, m, m, m); setGeometry(adjusted_pos); #if defined(Q_OS_MACOS) @@ -69,35 +78,39 @@ PinWidget::PinWidget(const QPixmap& pixmap, move(adjusted_pos.x(), adjusted_pos.y()); } #endif + grabGesture(Qt::PinchGesture); } -int PinWidget::margin() const +bool PinWidget::scrollEvent(QWheelEvent* event) { - return 7; -} - -void PinWidget::wheelEvent(QWheelEvent* event) -{ - // getting the mouse wheel rotation in degree - const QPoint degrees = event->angleDelta() / 8; - - // is the user zooming in or out ? - const int direction = degrees.y() > 0 ? 1 : -1; - - // step taken in pixels (including direction) - const int step = degrees.manhattanLength() * direction; - const int newWidth = qBound(50, m_label->width() + step, maximumWidth()); - const int newHeight = qBound(50, m_label->height() + step, maximumHeight()); - - // Actual scaling of the pixmap - const QSize newSize(newWidth, newHeight); - const qreal scale = qApp->devicePixelRatio(); - const bool isExpanding = direction > 0; - setScaledPixmapToLabel(newSize, scale, isExpanding); - - // Reflect scaling to the label - adjustSize(); - event->accept(); + const auto phase = event->phase(); + if (phase == Qt::ScrollPhase::ScrollUpdate +#if defined(Q_OS_LINUX) + // Linux is getting only NoScrollPhase events. + or phase == Qt::ScrollPhase::NoScrollPhase +#endif + ) { + const auto angle = event->angleDelta(); + if (angle.y() == 0) { + return true; + } + m_currentStepScaleFactor = angle.y() > 0 + ? m_currentStepScaleFactor + STEP + : m_currentStepScaleFactor - STEP; + m_expanding = m_currentStepScaleFactor >= 1.0; + } +#if defined(Q_OS_MACOS) + // ScrollEnd is currently supported only on Mac OSX + if (phase == Qt::ScrollPhase::ScrollEnd) { +#else + else { +#endif + m_scaleFactor *= m_currentStepScaleFactor; + m_currentStepScaleFactor = 1.0; + m_expanding = false; + } + update(); + return true; } void PinWidget::enterEvent(QEvent*) @@ -112,6 +125,7 @@ void PinWidget::leaveEvent(QEvent*) void PinWidget::mouseDoubleClickEvent(QMouseEvent*) { + update(); close(); } @@ -131,18 +145,55 @@ void PinWidget::mouseMoveEvent(QMouseEvent* e) m_dragStart.y() + delta.y() - offsetH); } -void PinWidget::setScaledPixmapToLabel(const QSize& newSize, - const qreal scale, - const bool expanding) +bool PinWidget::gestureEvent(QGestureEvent* event) +{ + if (QGesture* pinch = event->gesture(Qt::PinchGesture)) { + pinchTriggered(static_cast(pinch)); + } + return true; +} + +bool PinWidget::event(QEvent* event) +{ + if (event->type() == QEvent::Gesture) { + return gestureEvent(static_cast(event)); + } else if (event->type() == QEvent::Wheel) { + return scrollEvent(static_cast(event)); + } + return QWidget::event(event); +} + +void PinWidget::paintEvent(QPaintEvent* event) { - ConfigHandler config; - QPixmap scaledPixmap; const auto aspectRatio = - expanding ? Qt::KeepAspectRatioByExpanding : Qt::KeepAspectRatio; - const auto transformType = config.antialiasingPinZoom() + m_expanding ? Qt::KeepAspectRatioByExpanding : Qt::KeepAspectRatio; + const auto transformType = ConfigHandler().antialiasingPinZoom() ? Qt::SmoothTransformation : Qt::FastTransformation; - scaledPixmap = m_pixmap.scaled(newSize * scale, aspectRatio, transformType); - scaledPixmap.setDevicePixelRatio(scale); - m_label->setPixmap(scaledPixmap); + const qreal iw = m_pixmap.width(); + const qreal ih = m_pixmap.height(); + const qreal nw = qBound(MIN_SIZE, + iw * m_currentStepScaleFactor * m_scaleFactor, + static_cast(maximumWidth())); + const qreal nh = qBound(MIN_SIZE, + ih * m_currentStepScaleFactor * m_scaleFactor, + static_cast(maximumHeight())); + const QPixmap pix = m_pixmap.scaled(nw, nh, aspectRatio, transformType); + m_label->setPixmap(pix); + adjustSize(); +} + +void PinWidget::pinchTriggered(QPinchGesture* gesture) +{ + const QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags(); + if (changeFlags & QPinchGesture::ScaleFactorChanged) { + m_currentStepScaleFactor = gesture->totalScaleFactor(); + m_expanding = m_currentStepScaleFactor > gesture->lastScaleFactor(); + } + if (gesture->state() == Qt::GestureFinished) { + m_scaleFactor *= m_currentStepScaleFactor; + m_currentStepScaleFactor = 1; + m_expanding = false; + } + update(); } diff --git a/src/tools/pin/pinwidget.h b/src/tools/pin/pinwidget.h index e9f04e86..be626237 100644 --- a/src/tools/pin/pinwidget.h +++ b/src/tools/pin/pinwidget.h @@ -3,11 +3,13 @@ #pragma once -#include #include -class QVBoxLayout; class QLabel; +class QVBoxLayout; +class QGestureEvent; +class QPinchGesture; +class QGraphicsDropShadowEffect; class PinWidget : public QWidget { @@ -17,20 +19,20 @@ public: const QRect& geometry, QWidget* parent = nullptr); - int margin() const; - protected: - void wheelEvent(QWheelEvent* e); - void mouseDoubleClickEvent(QMouseEvent*); - void mousePressEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - void enterEvent(QEvent*); - void leaveEvent(QEvent*); + void mouseDoubleClickEvent(QMouseEvent*) override; + void mousePressEvent(QMouseEvent*) override; + void mouseMoveEvent(QMouseEvent*) override; + void enterEvent(QEvent*) override; + void leaveEvent(QEvent*) override; + + bool event(QEvent* event) override; + void paintEvent(QPaintEvent* event) override; private: - void setScaledPixmapToLabel(const QSize& newSize, - const qreal scale, - const bool expanding); + bool gestureEvent(QGestureEvent* event); + bool scrollEvent(QWheelEvent* e); + void pinchTriggered(QPinchGesture*); QPixmap m_pixmap; QVBoxLayout* m_layout; @@ -39,4 +41,8 @@ private: qreal m_offsetX, m_offsetY; QGraphicsDropShadowEffect* m_shadowEffect; QColor m_baseColor, m_hoverColor; + + bool m_expanding{ false }; + qreal m_scaleFactor{ 1 }; + qreal m_currentStepScaleFactor{ 1 }; };