Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_zoom_action.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_zoom_action.h"
8
9#include <QApplication>
10#include <QNativeGestureEvent>
11
12#include <klocalizedstring.h>
13
15
16#include <kis_canvas2.h>
19#include "kis_cursor.h"
20#include "KisViewManager.h"
21#include "kis_input_manager.h"
22#include "kis_config.h"
23
26
27
29{
30public:
31 Private(KisZoomAction *qq) : q(qq) {}
32
33 KisZoomAction *q {nullptr};
34 // Coverity requires sane defaults for all variables (CID 36380)
36
38
39 qreal startZoom {1.0};
41
42 std::unique_ptr<KisCanvasNavigationActionStrategy> actionStrategy;
43};
44
46 : KisAbstractInputAction("Zoom Canvas")
47 , d(new Private(this))
48{
49 setName(i18n("Zoom Canvas"));
50 setDescription(i18n("The <i>Zoom Canvas</i> action zooms the canvas."));
51
52 QHash< QString, int > shortcuts;
53 shortcuts.insert(i18n("Zoom Mode"), ZoomModeShortcut);
54 shortcuts.insert(i18n("Discrete Zoom Mode"), DiscreteZoomModeShortcut);
55 shortcuts.insert(i18n("Relative Zoom Mode"), RelativeZoomModeShortcut);
56 shortcuts.insert(i18n("Relative Discrete Zoom Mode"), RelativeDiscreteZoomModeShortcut);
57 shortcuts.insert(i18n("Zoom In"), ZoomInShortcut);
58 shortcuts.insert(i18n("Zoom Out"), ZoomOutShortcut);
59 shortcuts.insert(i18n("Zoom In To Cursor"), ZoomInToCursorShortcut);
60 shortcuts.insert(i18n("Zoom Out From Cursor"), ZoomOutFromCursorShortcut);
61 shortcuts.insert(i18n("Zoom to 100%"), Zoom100PctShortcut);
62 shortcuts.insert(i18n("Fit to View"), FitToViewShortcut);
63 shortcuts.insert(i18n("Fit to View Width"), FitToWidthShortcut);
64 shortcuts.insert(i18n("Fit to View Height"), FitToHeightShortcut);
65 setShortcutIndexes(shortcuts);
66}
67
69{
70 delete d;
71}
72
74{
75 return 4;
76}
77
78void KisZoomAction::activate(int shortcut)
79{
80 if (shortcut == DiscreteZoomModeShortcut ||
82 QApplication::setOverrideCursor(KisCursor::zoomDiscreteCursor());
83 } else /* if (shortcut == SmoothZoomModeShortcut) */ {
84 QApplication::setOverrideCursor(KisCursor::zoomSmoothCursor());
85 }
86}
87
88void KisZoomAction::deactivate(int shortcut)
89{
90 Q_UNUSED(shortcut);
91 QApplication::restoreOverrideCursor();
92}
93
94void KisZoomAction::begin(int shortcut, QEvent *event)
95{
96 KisAbstractInputAction::begin(shortcut, event);
97
101 if (event
102 && (event->type() == QEvent::NativeGesture || event->type() == QEvent::TouchBegin
103 || event->type() == QEvent::TouchUpdate)
104 && (shortcut == ZoomModeShortcut || shortcut == RelativeZoomModeShortcut || shortcut == DiscreteZoomModeShortcut
105 || shortcut == RelativeDiscreteZoomModeShortcut)) {
107 using Flags = KisCanvasNavigationActionStrategyNativeGesture::Flags;
108
109 Flags flags;
110 flags.setFlag(Flag::PanEnabled);
111 flags.setFlag(Flag::ZoomEnabled);
112 flags.setFlag(Flag::ZoomDescrete,
114
115 if (event->type() == QEvent::NativeGesture) {
117 } else {
118 const QTouchEvent *tevent = static_cast<const QTouchEvent*>(event);
120 }
121
122 // native gestures don't have cursor tracking by the OS, so they shouldn't show any cursor
123 QApplication::restoreOverrideCursor();
124 return;
125 }
126
127 switch(shortcut) {
128 case ZoomModeShortcut:
131 d->mode = (Shortcuts)shortcut;
133 break;
134 }
139 d->mode = (Shortcuts)shortcut;
141 break;
142 case ZoomInShortcut:
143 case ZoomOutShortcut:
146 KoCanvasControllerWidget *controller =
149
150 QPoint pt;
151 if (shortcut == ZoomInToCursorShortcut || shortcut == ZoomOutFromCursorShortcut) {
152 pt = eventPos(event);
153 if (pt.isNull()) {
154 pt = controller->mapFromGlobal(QCursor::pos());
155 }
156 }
157
158 if (shortcut == ZoomInToCursorShortcut || shortcut == ZoomInShortcut) {
159 if (pt.isNull()) {
160 controller->zoomIn();
161 } else {
162 controller->zoomIn(inputManager()->canvas()->coordinatesConverter()->makeWidgetStillPoint(pt));
163 }
164 } else {
165 if (pt.isNull()) {
166 controller->zoomOut();
167 } else {
168 controller->zoomOut(inputManager()->canvas()->coordinatesConverter()->makeWidgetStillPoint(pt));
169 }
170 }
171 break;
172 }
173 case Zoom100PctShortcut: {
174 KoCanvasControllerWidget *controller =
176 controller->setZoom(KoZoomMode::ZOOM_CONSTANT, 1.0);
177 break;
178 }
179 case FitToViewShortcut: {
180 KoCanvasControllerWidget *controller =
182 controller->setZoom(KoZoomMode::ZOOM_PAGE, 1.0);
183 break;
184 }
185 case FitToWidthShortcut: {
186 KoCanvasControllerWidget *controller =
188 controller->setZoom(KoZoomMode::ZOOM_WIDTH, 1.0);
189 break;
190 }
191 case FitToHeightShortcut: {
192 KoCanvasControllerWidget *controller =
194 controller->setZoom(KoZoomMode::ZOOM_HEIGHT, 1.0);
195 break;
196 }
197 }
198}
199
200void KisZoomAction::end(QEvent *event)
201{
202 d->actionStrategy.reset();
204}
205
206void KisZoomAction::inputEvent( QEvent* event )
207{
208 if(!event) {
209 return;
210 }
211
212 if (d->actionStrategy && d->actionStrategy->supportsEvent(event)) {
213 d->actionStrategy->inputEvent(event);
214 return;
215 } else {
217 }
218}
219
220void KisZoomAction::cursorMovedAbsolute(const QPointF &startPos, const QPointF &pos)
221{
222 QPointF diff = -(pos - startPos);
223
224 const int stepCont = 100;
225 const int stepDisc = 50;
226
227 if (d->mode == ZoomModeShortcut ||
229
230 KisConfig cfg(true);
231
232 const qreal logDistance = std::pow(2.0, qreal(cfg.zoomHorizontal() ? -diff.x() : diff.y()) / qreal(stepCont));
233
234 qreal newZoom = 1.0;
235 if (cfg.readEntry<bool>("InvertMiddleClickZoom", false)) {
236 newZoom = d->startZoom / logDistance;
237 } else {
238 newZoom = d->startZoom * logDistance;
239 }
240
241 KoCanvasControllerWidget *controller =
244
245 if (d->mode == ZoomModeShortcut) {
246 controller->setZoom(KoZoomMode::ZOOM_CONSTANT, newZoom);
247 } else {
248 controller->setZoom(KoZoomMode::ZOOM_CONSTANT, newZoom, d->actionStillPoint);
249 }
250
251 } else if (d->mode == DiscreteZoomModeShortcut ||
253
254 KoCanvasControllerWidget *controller =
257
258 KisConfig cfg(true);
259
260 qreal axisDiff = qreal(cfg.zoomHorizontal() ? -diff.x() : diff.y());
261 qreal currentDiff = axisDiff / stepDisc - d->lastDiscreteZoomDistance;
262
263 const bool zoomIn = currentDiff > 0;
264 while (qAbs(currentDiff) > 1.0) {
265 if (zoomIn) {
267 controller->zoomIn(d->actionStillPoint);
268 } else {
269 controller->zoomIn();
270 }
271 } else {
273 controller->zoomOut(d->actionStillPoint);
274 } else {
275 controller->zoomOut();
276 }
277 }
278 d->lastDiscreteZoomDistance += zoomIn ? 1.0 : -1.0;
279 currentDiff = axisDiff / stepDisc - d->lastDiscreteZoomDistance;
280 }
281 }
282}
283
284bool KisZoomAction::isShortcutRequired(int shortcut) const
285{
286 return shortcut == ZoomModeShortcut;
287}
288
290{
291 Q_UNUSED(shortcut);
292 return true;
293}
294
296{
297 Q_UNUSED(shortcut);
299}
300
KisInputActionGroup
@ ViewTransformActionGroup
Abstract base class for input actions.
virtual void inputEvent(QEvent *event)
static KisInputManager * inputManager
void setShortcutIndexes(const QHash< QString, int > &indexes)
QPoint eventPos(const QEvent *event)
QPointF eventPosF(const QEvent *event)
void setName(const QString &name)
virtual void end(QEvent *event)
void setDescription(const QString &description)
virtual void begin(int shortcut, QEvent *event)
KisCoordinatesConverter * coordinatesConverter
bool zoomHorizontal(bool defaultValue=false) const
T readEntry(const QString &name, const T &defaultValue=T())
Definition kis_config.h:902
KoViewTransformStillPoint makeWidgetStillPoint(const QPointF &viewPoint) const override
Creates a still point that links the viewPoint of the widget to the corresponding point of the image.
static QCursor zoomSmoothCursor()
static QCursor zoomDiscreteCursor()
KisCanvas2 * canvas() const
KoViewTransformStillPoint actionStillPoint
std::unique_ptr< KisCanvasNavigationActionStrategy > actionStrategy
Private(KisZoomAction *qq)
Zoom Canvas implementation of KisAbstractInputAction.
bool isShortcutRequired(int shortcut) const override
~KisZoomAction() override
void deactivate(int shortcut) override
bool supportsHiResInputEvents(int shortcut) const override
void cursorMovedAbsolute(const QPointF &startPos, const QPointF &pos) override
int priority() const override
void end(QEvent *event) override
@ FitToHeightShortcut
Zoom fit to height.
@ ZoomInShortcut
Zoom in by a fixed amount.
@ RelativeDiscreteZoomModeShortcut
Toggle discrete zoom mode relative to cursor.
@ ZoomOutFromCursorShortcut
Zoom out from cursor.
@ ZoomInToCursorShortcut
Zoom in to cursor.
@ ZoomOutShortcut
Zoom out by a fixed amount.
@ DiscreteZoomModeShortcut
Toggle discrete zoom mode.
@ FitToViewShortcut
Zoom fit to page.
@ ZoomModeShortcut
Toggle zoom mode.
@ Zoom100PctShortcut
Reset zoom to 100%.
@ RelativeZoomModeShortcut
Toggle zoom mode relative to cursor.
@ FitToWidthShortcut
Zoom fit to width.
void activate(int shortcut) override
void inputEvent(QEvent *event) override
KisInputActionGroup inputActionGroup(int shortcut) const override
Private *const d
void begin(int shortcut, QEvent *event=0) override
KoCanvasController * canvasController() const
void setZoom(KoZoomMode::Mode mode, qreal zoom) override
virtual void zoomIn(const KoViewTransformStillPoint &stillPoint)=0
zooms in keeping stillPoint not moved.
virtual void zoomOut(const KoViewTransformStillPoint &stillPoint)=0
zooms out keeping stillPoint not moved.
void zoom(qreal *zoomX, qreal *zoomY) const override
@ ZOOM_CONSTANT
zoom x %
Definition KoZoomMode.h:24
@ ZOOM_PAGE
zoom page
Definition KoZoomMode.h:25
@ ZOOM_WIDTH
zoom pagewidth
Definition KoZoomMode.h:26
@ ZOOM_HEIGHT
zoom pageheight
Definition KoZoomMode.h:27
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
KisCanvas2 * canvas