File indexing completed on 2024-04-28 04:21:28

0001 // SPDX-FileCopyrightText: 2003-2010 Jesper K. Pedersen <blackie@kde.org>
0002 // SPDX-FileCopyrightText: 2022 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0003 //
0004 // SPDX-License-Identifier: GPL-2.0-or-later
0005 
0006 #include "ViewHandler.h"
0007 
0008 #include <QMouseEvent>
0009 #include <QRubberBand>
0010 #include <qapplication.h>
0011 #include <qcursor.h>
0012 #include <qpainter.h>
0013 
0014 /**
0015  * \class Viewer::ViewHandler
0016  * \brief Mouse handler used during zooming and panning actions
0017  */
0018 
0019 Viewer::ViewHandler::ViewHandler(Viewer::ImageDisplay *display)
0020     : QObject(display)
0021     , m_scale(false)
0022     , m_pan(false)
0023     , m_errorX(0)
0024     , m_errorY(0)
0025     , m_rubberBand(new QRubberBand(QRubberBand::Rectangle, display))
0026     , m_display(display)
0027 {
0028 }
0029 
0030 bool Viewer::ViewHandler::mousePressEvent(QMouseEvent *e, const QPoint &unTranslatedPos, double /*scaleFactor*/)
0031 {
0032     m_pan = false;
0033     m_scale = false;
0034 
0035     if ((e->button() & Qt::LeftButton)) {
0036         if ((e->modifiers() & Qt::ControlModifier)) {
0037             m_pan = true;
0038         } else {
0039             m_scale = true;
0040         }
0041     } else if (e->button() & Qt::MiddleButton) {
0042         m_pan = true;
0043     }
0044 
0045     if (m_pan) {
0046         // panning
0047         m_last = unTranslatedPos;
0048         qApp->setOverrideCursor(Qt::SizeAllCursor);
0049         m_errorX = 0;
0050         m_errorY = 0;
0051         return true;
0052     } else if (m_scale) {
0053         // scaling
0054         m_start = e->pos();
0055         m_untranslatedStart = unTranslatedPos;
0056         qApp->setOverrideCursor(Qt::CrossCursor);
0057         return true;
0058     } else {
0059         return true;
0060     }
0061 }
0062 
0063 bool Viewer::ViewHandler::mouseMoveEvent(QMouseEvent *,
0064                                          const QPoint &unTranslatedPos, double scaleFactor)
0065 {
0066     if (m_scale) {
0067         m_rubberBand->setGeometry(QRect(m_untranslatedStart, unTranslatedPos).normalized());
0068         m_rubberBand->show();
0069         return true;
0070     } else if (m_pan) {
0071         // This code need to be taking the error into account, consider this situation:
0072         // The user moves the mouse very slowly, only 1 pixel at a time, scale factor is 3
0073         // Then translated delta would be 1/3 which every time would be
0074         // rounded down to 0, and the panning would never move any pixels.
0075         double deltaX = m_errorX + (m_last.x() - unTranslatedPos.x()) / scaleFactor;
0076         double deltaY = m_errorY + (m_last.y() - unTranslatedPos.y()) / scaleFactor;
0077         QPoint deltaPoint = QPoint((int)deltaX, (int)deltaY);
0078         m_errorX = deltaX - ((double)((int)deltaX));
0079         m_errorY = deltaY - ((double)((int)deltaY));
0080 
0081         m_display->pan(deltaPoint);
0082         m_last = unTranslatedPos;
0083         return true;
0084     } else
0085         return false;
0086 }
0087 
0088 bool Viewer::ViewHandler::mouseReleaseEvent(QMouseEvent *e, const QPoint & /*unTranslatedPos*/, double /*scaleFactor*/)
0089 {
0090     if (m_scale) {
0091         qApp->restoreOverrideCursor();
0092         m_rubberBand->hide();
0093         m_scale = false;
0094         if ((e->pos() - m_start).manhattanLength() > 1) {
0095             m_display->zoom(m_start, e->pos());
0096             return true;
0097         } else
0098             return false;
0099     } else if (m_pan) {
0100         qApp->restoreOverrideCursor();
0101         m_pan = false;
0102         return true;
0103     } else
0104         return false;
0105 }
0106 
0107 void Viewer::ViewHandler::hideEvent()
0108 {
0109     // In case the escape key is pressed while viewing or scaling, then we need to restore the override cursor
0110     // (As in that case we will not see a key release event)
0111     if (m_pan || m_scale) {
0112         qApp->restoreOverrideCursor();
0113         m_pan = false;
0114         m_scale = false;
0115     }
0116 }
0117 // vi:expandtab:tabstop=4 shiftwidth=4:
0118 
0119 #include "moc_ViewHandler.cpp"