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"