11#include <klocalizedstring.h>
39 setName(i18n(
"Zoom and Rotate Canvas"));
40 QHash<QString, int> shortcuts;
67 QTouchEvent *touchEvent =
dynamic_cast<QTouchEvent *
>(event);
69 if (touchEvent && touchEvent->touchPoints().size() > 0) {
70 d->shortcutIndex = shortcut;
71 d->lastPosition = touchEvent->touchPoints().at(0).pos();
74 d->initialReferenceAngle = 0;
75 d->accumRotationAngle = 0;
87 return std::fmod(angle - 2, 45) + 2;
89 return std::fmod(angle + 2, 45) - 2;
95 switch (event->type()) {
96 case QEvent::TouchUpdate: {
97 QTouchEvent *tevent =
dynamic_cast<QTouchEvent *
>(event);
98 if (tevent && tevent->touchPoints().size() > 1) {
100 const QPointF
p0 = tevent->touchPoints().at(0).pos();
101 const QPointF
p1 = tevent->touchPoints().at(1).pos();
104 const float dist = QLineF(
p0,
p1).length();
105 const float scaleDelta =
qFuzzyCompare(1.0f, 1.0f +
d->lastDistance) ? 1.f : dist /
d->lastDistance;
111 adjustedStillPoint.second =
p0;
113 controller->
rotateCanvas(rotationAngle, adjustedStillPoint);
115 d->lastPosition =
p0;
116 d->lastDistance = dist;
135 const QPointF slope =
p1 -
p0;
136 const qreal currentAngle = std::atan2(slope.y(), slope.x());
138 switch (
d->shortcutIndex) {
140 if (!
d->previousAngle) {
141 d->previousAngle = currentAngle;
144 qreal rotationAngle = (180 /
M_PI) * (currentAngle -
d->previousAngle);
145 d->previousAngle = currentAngle;
149 const qreal canvasAnglePostRotation = controller->
rotation() + rotationAngle;
152 if (abs(snapDelta) <= 2 && abs(
d->accumRotationAngle) <= 2) {
154 d->accumRotationAngle += rotationAngle;
155 rotationAngle = rotationAngle - snapDelta;
158 rotationAngle +=
d->accumRotationAngle;
159 d->accumRotationAngle = 0;
162 return rotationAngle;
165 if (!
d->initialReferenceAngle) {
166 d->initialReferenceAngle = currentAngle;
169 qreal rotationAngle = 0;
170 const qreal relativeAngle = (180 /
M_PI) * (currentAngle -
d->initialReferenceAngle);
171 const qreal rotationThreshold = 15;
175 if (std::abs(relativeAngle) >= rotationThreshold && std::abs(relativeAngle) <= (360 - rotationThreshold)) {
177 d->initialReferenceAngle = currentAngle;
179 if (std::abs(relativeAngle) <= 180) {
188 return rotationAngle;
191 qWarning() <<
"KisZoomAndRotateAction: Unrecognized shortcut" <<
d->shortcutIndex;
KisCoordinatesConverter * coordinatesConverter
const KoViewConverter * viewConverter() const override
void rotateCanvas(qreal angle, const std::optional< KoViewTransformStillPoint > &stillPoint, bool isNativeGesture=false)
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.
qreal initialReferenceAngle
KoViewTransformStillPoint actionStillPoint
void cursorMovedAbsolute(const QPointF &lastPos, const QPointF &pos) override
int priority() const override
void deactivate(int shortcut) override
KisInputActionGroup inputActionGroup(int shortcut) const override
~KisZoomAndRotateAction()
void begin(int shortcut, QEvent *event) override
void activate(int shortcut) override
const QScopedPointer< Private > d
void inputEvent(QEvent *event) override
qreal canvasRotationAngle(QPointF p0, QPointF p1)
KoCanvasController * canvasController() const
virtual void zoom(qreal *zoomX, qreal *zoomY) const
static bool qFuzzyCompare(half p1, half p2)
qreal angleForSnapping(qreal angle)