From e72a664c8a3ea475ce77f32b85eef4e19df26365 Mon Sep 17 00:00:00 2001
From: Ronan Le Tiec <ronanletiec@gmail.com>
Date: Sat, 9 May 2020 09:54:56 +0200
Subject: [PATCH] context menu for carrousel piece and graphics piece

---
 src/app/puzzle/vpiececarrouselpiece.cpp | 54 ++++++++++++++++++++++++
 src/app/puzzle/vpiececarrouselpiece.h   |  9 ++++
 src/app/puzzle/vpuzzlegraphicspiece.cpp | 55 ++++++++++++++++++++++---
 src/app/puzzle/vpuzzlegraphicspiece.h   |  9 ++++
 4 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/src/app/puzzle/vpiececarrouselpiece.cpp b/src/app/puzzle/vpiececarrouselpiece.cpp
index 722b5752c..3602ce054 100644
--- a/src/app/puzzle/vpiececarrouselpiece.cpp
+++ b/src/app/puzzle/vpiececarrouselpiece.cpp
@@ -35,6 +35,7 @@
 #include <QDrag>
 #include <QPainter>
 #include <QApplication>
+#include <QMenu>
 
 #include "vpuzzlemimedatapiece.h"
 #include "vpiececarrousellayer.h"
@@ -229,3 +230,56 @@ void VPieceCarrouselPiece::mouseMoveEvent(QMouseEvent *event)
     drag->setMimeData(mimeData);
     drag->exec();
 }
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrouselPiece::contextMenuEvent(QContextMenuEvent *event)
+{
+    QMenu contextMenu;
+
+    VPuzzleLayer* unplacedLayer = m_piece->GetLayer()->GetLayout()->GetUnplacedPiecesLayer();
+    QList<VPuzzleLayer*> layers = m_piece->GetLayer()->GetLayout()->GetLayers();
+
+    // move to layer actions  -- TODO : To be tested properly when we have several layers
+    layers.removeAll(m_piece->GetLayer());
+    if(layers.count() > 0)
+    {
+        QMenu *moveMenu = contextMenu.addMenu(tr("Move to"));
+
+        // TODO order in alphabetical order
+
+        for (auto layer : layers)
+        {
+            QAction* moveToLayer = moveMenu->addAction(layer->GetName());
+            QVariant data = QVariant::fromValue(layer);
+            moveToLayer->setData(data);
+
+            connect(moveToLayer, &QAction::triggered, this, &VPieceCarrouselPiece::on_ActionPieceMovedToLayer);
+        }
+    }
+
+    // remove from layout action
+    if(m_piece->GetLayer() != unplacedLayer)
+    {
+        QAction *removeAction = contextMenu.addAction(tr("Remove from Layout"));
+        QVariant data = QVariant::fromValue(m_piece->GetLayer()->GetLayout()->GetUnplacedPiecesLayer());
+        removeAction->setData(data);
+        connect(removeAction, &QAction::triggered, this, &VPieceCarrouselPiece::on_ActionPieceMovedToLayer);
+    }
+
+    contextMenu.exec(event->globalPos());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrouselPiece::on_ActionPieceMovedToLayer()
+{
+    QAction *act = qobject_cast<QAction *>(sender());
+    QVariant v = act->data();
+    VPuzzleLayer *layer = (VPuzzleLayer *) v.value<VPuzzleLayer *>();
+    if(layer != nullptr)
+    {
+        layer->GetLayout()->MovePieceToLayer(m_piece, layer);
+    }
+}
diff --git a/src/app/puzzle/vpiececarrouselpiece.h b/src/app/puzzle/vpiececarrouselpiece.h
index ecbf24095..96264e0d0 100644
--- a/src/app/puzzle/vpiececarrouselpiece.h
+++ b/src/app/puzzle/vpiececarrouselpiece.h
@@ -68,6 +68,15 @@ protected:
 
     void mouseMoveEvent(QMouseEvent *event) override;
 
+    void contextMenuEvent(QContextMenuEvent *event) override;
+
+private slots:
+    /**
+     * @brief on_ActionPieceMovedToLayer Slot called when the piece is moved via the
+     * context menu to anoter layer
+     */
+    void on_ActionPieceMovedToLayer();
+
 private:
     Q_DISABLE_COPY(VPieceCarrouselPiece)
 
diff --git a/src/app/puzzle/vpuzzlegraphicspiece.cpp b/src/app/puzzle/vpuzzlegraphicspiece.cpp
index 26b90e42f..6b221427f 100644
--- a/src/app/puzzle/vpuzzlegraphicspiece.cpp
+++ b/src/app/puzzle/vpuzzlegraphicspiece.cpp
@@ -34,8 +34,12 @@
 #include <QCursor>
 #include <QGraphicsSceneMouseEvent>
 #include <QStyleOptionGraphicsItem>
+#include <QGraphicsSceneContextMenuEvent>
+#include <QMenu>
 
 #include "vpuzzlepiece.h"
+#include "vpuzzlelayer.h"
+#include "vpuzzlelayout.h"
 
 #include <QLoggingCategory>
 Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
@@ -193,20 +197,61 @@ void VPuzzleGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
     //perform the default behaviour
     QGraphicsItem::mouseReleaseEvent(event);
 
-    qCDebug(pGraphicsPiece, "piiiiieeece --- mouse release");
-
     // change the cursor when clicking left button
-
     if (event->button() == Qt::LeftButton)
     {
         setCursor(Qt::OpenHandCursor);
 
-        qCDebug(pGraphicsPiece, "piiiiieeece --- left button");
-
         setSelected(selectionState);
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPuzzleGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+    QMenu contextMenu;
+
+    // move to layer actions  -- TODO : To be tested properly when we have several layers
+    QList<VPuzzleLayer*> layers = m_piece->GetLayer()->GetLayout()->GetLayers();
+    layers.removeAll(m_piece->GetLayer());
+
+    if(layers.count() > 0)
+    {
+        QMenu *moveMenu = contextMenu.addMenu(tr("Move to"));
+
+        // TODO order in alphabetical order
+
+        for (auto layer : layers)
+        {
+            QAction* moveToLayer = moveMenu->addAction(layer->GetName());
+            QVariant data = QVariant::fromValue(layer);
+            moveToLayer->setData(data);
+
+            connect(moveToLayer, &QAction::triggered, this, &VPuzzleGraphicsPiece::on_ActionPieceMovedToLayer);
+        }
+    }
+
+    // remove from layout action
+    QAction *removeAction = contextMenu.addAction(tr("Remove from Layout"));
+    QVariant data = QVariant::fromValue(m_piece->GetLayer()->GetLayout()->GetUnplacedPiecesLayer());
+    removeAction->setData(data);
+    connect(removeAction, &QAction::triggered, this, &VPuzzleGraphicsPiece::on_ActionPieceMovedToLayer);
+
+    contextMenu.exec(event->screenPos());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPuzzleGraphicsPiece::on_ActionPieceMovedToLayer()
+{
+    QAction *act = qobject_cast<QAction *>(sender());
+    QVariant v = act->data();
+    VPuzzleLayer *layer = (VPuzzleLayer *) v.value<VPuzzleLayer *>();
+    if(layer != nullptr)
+    {
+        layer->GetLayout()->MovePieceToLayer(m_piece, layer);
+    }
+}
+
 
 //---------------------------------------------------------------------------------------------------------------------
 void VPuzzleGraphicsPiece::on_PieceSelectionChanged()
diff --git a/src/app/puzzle/vpuzzlegraphicspiece.h b/src/app/puzzle/vpuzzlegraphicspiece.h
index a7aebe10b..c11680008 100644
--- a/src/app/puzzle/vpuzzlegraphicspiece.h
+++ b/src/app/puzzle/vpuzzlegraphicspiece.h
@@ -68,6 +68,15 @@ protected:
 
     QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
 
+    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
+
+private slots:
+    /**
+     * @brief on_ActionPieceMovedToLayer Slot called when the piece is moved via the
+     * context menu to anoter layer
+     */
+    void on_ActionPieceMovedToLayer();
+
 private:
     Q_DISABLE_COPY(VPuzzleGraphicsPiece)
     VPuzzlePiece *m_piece;