File indexing completed on 2024-05-05 04:38:47

0001 /*
0002     SPDX-FileCopyrightText: 2016 Igor Kushnir <igorkuo@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "zoomcontroller.h"
0008 
0009 #include <KConfigGroup>
0010 
0011 #include <QPoint>
0012 #include <QKeyEvent>
0013 #include <QWheelEvent>
0014 
0015 #include <cmath>
0016 
0017 namespace {
0018 
0019 constexpr const char* factorConfigEntryKey() { return "Zoom Factor"; }
0020 
0021 constexpr double defaultFactor{1};
0022 constexpr double defaultMultiplier{1.1};
0023 
0024 double multiplier(double scale)
0025 {
0026     // Allow finer-grained control over zoom factor compared to defaultMultiplier
0027     constexpr double smallMultiplier{1.05};
0028     return std::pow(smallMultiplier, scale);
0029 }
0030 
0031 } // namespace
0032 
0033 using KDevelop::ZoomControllerPrivate;
0034 using KDevelop::ZoomController;
0035 
0036 class KDevelop::ZoomControllerPrivate
0037 {
0038 public:
0039     explicit ZoomControllerPrivate(const KConfigGroup& configGroup);
0040     void writeConfig();
0041 
0042     KConfigGroup m_configGroup;
0043     double m_factor{defaultFactor};
0044 };
0045 
0046 ZoomControllerPrivate::ZoomControllerPrivate(const KConfigGroup& configGroup)
0047     : m_configGroup{configGroup}
0048 {
0049     m_factor = m_configGroup.readEntry(factorConfigEntryKey(), defaultFactor);
0050 }
0051 
0052 void ZoomControllerPrivate::writeConfig()
0053 {
0054     m_configGroup.writeEntry(factorConfigEntryKey(), m_factor);
0055     m_configGroup.sync();
0056 }
0057 
0058 ZoomController::ZoomController(const KConfigGroup& configGroup, QObject* parent)
0059     : QObject(parent)
0060     , d_ptr{new ZoomControllerPrivate(configGroup)}
0061 {
0062 }
0063 
0064 ZoomController::~ZoomController() = default;
0065 
0066 double ZoomController::factor() const
0067 {
0068     Q_D(const ZoomController);
0069 
0070     return d->m_factor;
0071 }
0072 
0073 void ZoomController::setFactor(double factor)
0074 {
0075     Q_D(ZoomController);
0076 
0077     factor = qBound(0.1, factor, 10.0);
0078     if (d->m_factor == factor) {
0079         return;
0080     }
0081     d->m_factor = factor;
0082     d->writeConfig();
0083     emit factorChanged(d->m_factor);
0084 }
0085 
0086 void ZoomController::zoomBy(double scale)
0087 {
0088     Q_D(ZoomController);
0089 
0090     setFactor(d->m_factor * multiplier(scale));
0091 }
0092 
0093 bool ZoomController::handleKeyPressEvent(QKeyEvent* event)
0094 {
0095     Q_ASSERT(event);
0096 
0097     const auto requiredModifiers = Qt::ControlModifier;
0098     if (!(event->modifiers() & requiredModifiers)) {
0099         return false;
0100     }
0101     // Qt::ShiftModifier is required for the 0 key in some keyboard layouts
0102     // (such as Programmer Dvorak). Allow Qt::KeypadModifier to support numpad keys.
0103     // Don't allow other modifiers, such as Alt and Meta, to minimize shortcut conflicts.
0104     const auto allowedModifiers = Qt::ControlModifier | Qt::ShiftModifier | Qt::KeypadModifier;
0105     if (event->modifiers() & ~allowedModifiers) {
0106         return false;
0107     }
0108 
0109     if (event->key() == Qt::Key_0) {
0110         resetZoom();
0111         event->accept();
0112         return true;
0113     }
0114 
0115     return false;
0116 }
0117 
0118 bool ZoomController::handleWheelEvent(QWheelEvent* event)
0119 {
0120     Q_ASSERT(event);
0121 
0122     if (!(event->modifiers() & Qt::ControlModifier)) {
0123         return false;
0124     }
0125 
0126     constexpr double minStandardDelta{120};
0127     const QPoint delta = event->angleDelta();
0128     const double scale{(delta.x() + delta.y()) / minStandardDelta};
0129 
0130     zoomBy(scale);
0131     event->accept();
0132     return true;
0133 }
0134 
0135 void ZoomController::zoomIn()
0136 {
0137     Q_D(ZoomController);
0138 
0139     setFactor(d->m_factor * defaultMultiplier);
0140 }
0141 
0142 void ZoomController::zoomOut()
0143 {
0144     Q_D(ZoomController);
0145 
0146     setFactor(d->m_factor / defaultMultiplier);
0147 }
0148 
0149 void ZoomController::resetZoom()
0150 {
0151     setFactor(defaultFactor);
0152 }
0153 
0154 #include "moc_zoomcontroller.cpp"