From 201ee398dbb7a13facd8cc8caef397f27e6faea6 Mon Sep 17 00:00:00 2001
From: Raphael Grimm <raphael.grimm@student.kit.edu>
Date: Wed, 23 Aug 2017 15:56:54 +0200
Subject: [PATCH] Add EnhancedGraphicsView (a QGraphicsView with zoom, rotation
 and translation via keyboard and mouse)

---
 .../libraries/ArmarXGuiBase/CMakeLists.txt    |   3 +
 .../widgets/EnhancedGraphicsView.cpp          | 178 ++++++++++++++++++
 .../widgets/EnhancedGraphicsView.h            |  92 +++++++++
 3 files changed, 273 insertions(+)
 create mode 100644 source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.cpp
 create mode 100644 source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.h

diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt b/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt
index 5b09eedb..c6b71816 100644
--- a/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt
+++ b/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt
@@ -32,6 +32,7 @@ set(LIB_FILES   ArmarXWidgetController.cpp
                 widgets/IceProxyFinder.cpp
                 widgets/VariantItem.cpp
                 widgets/JoystickControlWidget.cpp
+                widgets/EnhancedGraphicsView.cpp
                 widgets/EnhancedTreeWidget.cpp
                 widgets/FilterableTreeView.cpp
                 widgets/MarkdownEditor.cpp
@@ -53,6 +54,7 @@ set(LIB_HEADERS ArmarXGuiInterface.h
                 widgets/IceProxyFinder.h
                 widgets/VariantItem.h
                 widgets/JoystickControlWidget.h
+                widgets/EnhancedGraphicsView.h
                 widgets/EnhancedTreeWidget.h
                 widgets/FilterableTreeView.h
                 widgets/MarkdownEditor.h
@@ -82,6 +84,7 @@ qt4_wrap_cpp(LIB_FILES
     widgets/FilterableTreeView.h
     widgets/IceProxyFinder.h
     widgets/JoystickControlWidget.h
+    widgets/EnhancedGraphicsView.h
     widgets/EnhancedTreeWidget.h
     widgets/MarkdownEditor.h
     widgets/TipDialog.h
diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.cpp b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.cpp
new file mode 100644
index 00000000..0bfa7138
--- /dev/null
+++ b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.cpp
@@ -0,0 +1,178 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    ArmarXGui::EnhancedGraphicsView
+ * @author     Raphael Grimm ( raphael dot grimm at student dot kit dot edu )
+ * @date       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#include "EnhancedGraphicsView.h"
+
+namespace armarx
+{
+
+    Qt::KeyboardModifier EnhancedGraphicsView::getRotationKeyboardModifier() const
+    {
+        return rotationModifier;
+    }
+
+    qreal EnhancedGraphicsView::getRotationFactor() const
+    {
+        return rotationFactor;
+    }
+
+    Qt::KeyboardModifier EnhancedGraphicsView::getZoomKeyboardModifier() const
+    {
+        return zoomModifier;
+    }
+
+    qreal EnhancedGraphicsView::getZoomFactor() const
+    {
+        return zoomFacor;
+    }
+
+    Qt::KeyboardModifier EnhancedGraphicsView::getDraggingKeyboardModifier() const
+    {
+        return draggingModifier;
+    }
+
+    Qt::MouseButton EnhancedGraphicsView::getDraggingMouseButton() const
+    {
+        return draggingButton;
+    }
+
+    void EnhancedGraphicsView::setRotationEnabled(bool enabled)
+    {
+        rotationEnabled = enabled;
+    }
+
+    void EnhancedGraphicsView::setRotationDisabled(bool disabled)
+    {
+        rotationEnabled = !disabled;
+    }
+
+    void EnhancedGraphicsView::setRotationKeyboardModifier(Qt::KeyboardModifier mod)
+    {
+        rotationModifier = mod;
+    }
+
+    void EnhancedGraphicsView::setRotationFactor(qreal factor)
+    {
+        rotationFactor = factor;
+    }
+
+    void EnhancedGraphicsView::setZoomEnabled(bool enabled)
+    {
+        zoomEnabled = enabled;
+    }
+
+    void EnhancedGraphicsView::setZoomDisabled(bool disabled)
+    {
+        zoomEnabled = !disabled;
+    }
+
+    void EnhancedGraphicsView::setZoomKeyboardModifier(Qt::KeyboardModifier mod)
+    {
+        zoomModifier = mod;
+    }
+
+    void EnhancedGraphicsView::setZoomFactor(qreal factor)
+    {
+        zoomFacor = factor;
+    }
+
+    void EnhancedGraphicsView::setDraggingEnabled(bool enabled)
+    {
+        draggingEnabled = enabled;
+    }
+
+    void EnhancedGraphicsView::setDraggingDisabled(bool disabled)
+    {
+        draggingEnabled = !disabled;
+    }
+
+    void EnhancedGraphicsView::setDraggingKeyboardModifier(Qt::KeyboardModifier mod)
+    {
+        draggingModifier = mod;
+    }
+
+    void EnhancedGraphicsView::setDraggingMouseButton(Qt::MouseButton button)
+    {
+        draggingButton = button;
+    }
+
+    void EnhancedGraphicsView::mousePressEvent(QMouseEvent* e)
+    {
+        draggingStartPosition = mapToScene(e->pos());
+        QGraphicsView::mousePressEvent(e);
+    }
+
+    void EnhancedGraphicsView::mouseMoveEvent(QMouseEvent* e)
+    {
+        if (
+            (e->modifiers() & draggingModifier) == draggingModifier &&
+            (e->buttons() & draggingButton) == draggingButton
+        )
+        {
+            const auto oldAnchor = transformationAnchor();
+            setTransformationAnchor(QGraphicsView::NoAnchor);
+
+            const QPointF vector = mapToScene(e->pos()) - draggingStartPosition;
+            translate(vector.x(), vector.y());
+            draggingStartPosition = mapToScene(e->pos());
+            e->accept();
+
+            setTransformationAnchor(oldAnchor);
+            return;
+        }
+        QGraphicsView::mouseMoveEvent(e);
+    }
+
+    void EnhancedGraphicsView::wheelEvent(QWheelEvent* e)
+    {
+        bool used = false;
+        if ((e->modifiers() & zoomModifier) == zoomModifier)
+        {
+            const auto oldAnchor = transformationAnchor();
+            setTransformationAnchor(QGraphicsView::NoAnchor);
+
+            float factor = std::pow(zoomFacor, e->delta() < 0 ? -1 : +1);
+            scale(factor, factor);
+            used = true;
+
+            setTransformationAnchor(oldAnchor);
+        }
+        if ((e->modifiers() & rotationModifier) == rotationModifier)
+        {
+            const auto oldAnchor = transformationAnchor();
+            setTransformationAnchor(QGraphicsView::NoAnchor);
+
+            rotate(e->delta() * rotationFactor);
+            used = true;
+
+            setTransformationAnchor(oldAnchor);
+        }
+        if (used)
+        {
+            e->accept();
+        }
+        else
+        {
+            QGraphicsView::wheelEvent(e);
+        }
+    }
+
+}
diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.h b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.h
new file mode 100644
index 00000000..2fd97e40
--- /dev/null
+++ b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/EnhancedGraphicsView.h
@@ -0,0 +1,92 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    ArmarXGui::EnhancedGraphicsView
+ * @author     Raphael Grimm ( raphael dot grimm at student dot kit dot edu )
+ * @date       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#ifndef _ARMARX_ArmarXGui_EnhancedGraphicsView_H
+#define _ARMARX_ArmarXGui_EnhancedGraphicsView_H
+
+#include <QGraphicsView>
+#include <QPointF>
+#include <QMouseEvent>
+#include <QWheelEvent>
+#include <cmath>
+namespace armarx
+{
+    /**
+     * @brief The EnhancedGraphicsView is a QGraphicsView with some additional
+     * functions.
+     *
+     * Additional functions are:
+     * - Zooming (default ctrl+scroll)
+     * - Roatating (default shift+scroll)
+     * - Dragging the scene (default ctrl+left click+dragging)
+     */
+    class EnhancedGraphicsView: public QGraphicsView
+    {
+        Q_OBJECT
+    public:
+        using QGraphicsView::QGraphicsView;
+
+        Qt::KeyboardModifier getRotationKeyboardModifier() const;
+        qreal getRotationFactor() const;
+
+        Qt::KeyboardModifier getZoomKeyboardModifier() const;
+        qreal setZoomFactor();
+        qreal getZoomFactor() const;
+
+        Qt::KeyboardModifier getDraggingKeyboardModifier() const;
+        Qt::MouseButton getDraggingMouseButton() const;
+    public slots:
+        void setRotationEnabled(bool enabled = true);
+        void setRotationDisabled(bool disabled = true);
+        void setRotationKeyboardModifier(Qt::KeyboardModifier mod);
+        void setRotationFactor(qreal factor);
+
+        void setZoomEnabled(bool enabled = true);
+        void setZoomDisabled(bool disabled = true);
+        void setZoomKeyboardModifier(Qt::KeyboardModifier mod);
+        void setZoomFactor(qreal factor);
+
+        void setDraggingEnabled(bool enabled = true);
+        void setDraggingDisabled(bool disabled = true);
+        void setDraggingKeyboardModifier(Qt::KeyboardModifier mod);
+        void setDraggingMouseButton(Qt::MouseButton button);
+
+    protected:
+        virtual void mousePressEvent(QMouseEvent* e) override;
+        virtual void mouseMoveEvent(QMouseEvent* e) override;
+        virtual void wheelEvent(QWheelEvent* e) override;
+
+        bool rotationEnabled {true};
+        Qt::KeyboardModifier rotationModifier {Qt::ShiftModifier};
+        qreal rotationFactor {0.01};
+
+        bool zoomEnabled {true};
+        Qt::KeyboardModifier zoomModifier {Qt::ControlModifier};
+        qreal zoomFacor {1.05};
+
+        bool draggingEnabled {true};
+        Qt::KeyboardModifier draggingModifier {Qt::ControlModifier};
+        Qt::MouseButton draggingButton {Qt::LeftButton};
+        QPointF draggingStartPosition;
+    };
+}
+#endif
-- 
GitLab