Pinch gesture on pinned screenshot (#2447)
* Minor refactoring * Pinch gesture works fine * Consolidated Zooming in/out * Minor refactoring * Minor refactoring * clang-format * Fixed scroll phases on Linux * clang-format * Re-added size constraint * clang-format
This commit is contained in:
@@ -1,17 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QPinchGesture>
|
||||
|
||||
#include "pinwidget.h"
|
||||
#include "qguiappcurrentscreen.h"
|
||||
#include "src/utils/confighandler.h"
|
||||
#include "src/utils/globalvalues.h"
|
||||
#include <QApplication>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QScreen>
|
||||
#include <QShortcut>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWheelEvent>
|
||||
|
||||
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<QPinchGesture*>(pinch));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinWidget::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Gesture) {
|
||||
return gestureEvent(static_cast<QGestureEvent*>(event));
|
||||
} else if (event->type() == QEvent::Wheel) {
|
||||
return scrollEvent(static_cast<QWheelEvent*>(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<qreal>(maximumWidth()));
|
||||
const qreal nh = qBound(MIN_SIZE,
|
||||
ih * m_currentStepScaleFactor * m_scaleFactor,
|
||||
static_cast<qreal>(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();
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QWidget>
|
||||
|
||||
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 };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user