From bf09544d87b9ab587c50d5649e9257ada28b4cd9 Mon Sep 17 00:00:00 2001
From: Ronan Le Tiec <ronanletiec@gmail.com>
Date: Sun, 26 Apr 2020 12:09:28 +0200
Subject: [PATCH] Piece Carrousel

---
 src/app/puzzle/puzzle.pri               |   8 +-
 src/app/puzzle/puzzlemainwindow.cpp     |  98 +++++++----
 src/app/puzzle/puzzlemainwindow.h       |  13 +-
 src/app/puzzle/vpiececarrousel.cpp      | 209 ++++++++++++++----------
 src/app/puzzle/vpiececarrousel.h        |  35 +++-
 src/app/puzzle/vpiececarrousellayer.cpp |  78 +++++++++
 src/app/puzzle/vpiececarrousellayer.h   |  60 +++++++
 src/app/puzzle/vpiececarrouselpiece.cpp |  87 ++++++++++
 src/app/puzzle/vpiececarrouselpiece.h   |  60 +++++++
 src/app/puzzle/vpuzzlelayout.cpp        |   6 +
 src/app/puzzle/vpuzzlelayout.h          |   1 -
 src/app/puzzle/vpuzzlepiece.cpp         |  26 +++
 src/app/puzzle/vpuzzlepiece.h           |  30 +++-
 13 files changed, 583 insertions(+), 128 deletions(-)
 create mode 100644 src/app/puzzle/vpiececarrousellayer.cpp
 create mode 100644 src/app/puzzle/vpiececarrousellayer.h
 create mode 100644 src/app/puzzle/vpiececarrouselpiece.cpp
 create mode 100644 src/app/puzzle/vpiececarrouselpiece.h

diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri
index c6a0ccadb..4cd78670e 100644
--- a/src/app/puzzle/puzzle.pri
+++ b/src/app/puzzle/puzzle.pri
@@ -14,7 +14,9 @@ SOURCES += \
     $$PWD/vpuzzlepiece.cpp \
     $$PWD/xml/layoutliterals.cpp \
     $$PWD/xml/vpuzzlelayoutfilewriter.cpp \
-    $$PWD/xml/vpuzzlelayoutfilereader.cpp
+    $$PWD/xml/vpuzzlelayoutfilereader.cpp \
+    $$PWD/vpiececarrousellayer.cpp \
+    $$PWD/vpiececarrouselpiece.cpp
 
 *msvc*:SOURCES += $$PWD/stable.cpp
 
@@ -31,7 +33,9 @@ HEADERS += \
     $$PWD/vpuzzlepiece.h \
     $$PWD/xml/layoutliterals.h \
     $$PWD/xml/vpuzzlelayoutfilewriter.h \
-    $$PWD/xml/vpuzzlelayoutfilereader.h
+    $$PWD/xml/vpuzzlelayoutfilereader.h \
+    $$PWD/vpiececarrousellayer.h \
+    $$PWD/vpiececarrouselpiece.h
 
 FORMS += \
     $$PWD/puzzlemainwindow.ui \
diff --git a/src/app/puzzle/puzzlemainwindow.cpp b/src/app/puzzle/puzzlemainwindow.cpp
index a76d220f8..bcc90cb9e 100644
--- a/src/app/puzzle/puzzlemainwindow.cpp
+++ b/src/app/puzzle/puzzlemainwindow.cpp
@@ -53,17 +53,21 @@ QT_WARNING_POP
 PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::PuzzleMainWindow),
-    pieceCarrousel(new VPieceCarrousel),
     m_cmd(cmd)
 {
 
-    // ----- for test purposes, to be removed------------------
     m_layout = new VPuzzleLayout();
+
+    // ----- for test purposes, to be removed------------------
     m_layout->SetLayoutMarginsConverted(1.5, 2.00, 4.21, 0.25);
     m_layout->SetLayoutSizeConverted(30.0, 29.7);
     m_layout->SetPiecesGapConverted(1.27);
     m_layout->SetUnit(Unit::Cm);
     m_layout->SetWarningSuperpositionOfPieces(true);
+    VPuzzleLayer *unplacedLayer = m_layout->GetUnplacedPiecesLayer();
+    VPuzzlePiece *piece = new VPuzzlePiece();
+    piece->SetName("Hello");
+    unplacedLayer->AddPiece(piece);
     // --------------------------------------------------------
 
     ui->setupUi(this);
@@ -80,23 +84,23 @@ PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *pa
 PuzzleMainWindow::~PuzzleMainWindow()
 {
     delete ui;
-    delete pieceCarrousel;
+    delete m_pieceCarrousel;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 bool PuzzleMainWindow::LoadFile(QString path)
 {
-    try
-    {
-        VLayoutConverter converter(path);
-        path = converter.Convert();
-    }
-    catch (VException &e)
-    {
-        qCCritical(pWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")),
-                   qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation()));
-        return false;
-    }
+//    try
+//    {
+//        VLayoutConverter converter(path);
+//        path = converter.Convert();
+//    }
+//    catch (VException &e)
+//    {
+//        qCCritical(pWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")),
+//                   qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation()));
+//        return false;
+//    }
 
     QFile file(path);
     file.open(QIODevice::ReadOnly);
@@ -130,21 +134,28 @@ bool PuzzleMainWindow::SaveFile(const QString &path)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void PuzzleMainWindow::ImportRawLayouts(const QStringList &layouts)
+void PuzzleMainWindow::ImportRawLayouts(const QStringList &rawLayouts)
 {
-    VRawLayout layoutReader;
+    VRawLayout rawLayoutReader;
 
-    for(auto &path : layouts)
+    for(auto &path : rawLayouts)
     {
         VRawLayoutData data;
-        if (layoutReader.ReadFile(path, data))
+        if (rawLayoutReader.ReadFile(path, data))
         {
-            // Do somethinmg with raw layout data
+            for (int i = 0; i < data.pieces.size(); ++i)
+            {
+                VLayoutPiece rawPiece = data.pieces.at(i);
+                VPuzzlePiece *piece = CreatePiece(rawPiece);
+                m_layout->GetUnplacedPiecesLayer()->AddPiece(piece);
+            }
+
+            m_pieceCarrousel->Refresh();
         }
         else
         {
             qCCritical(pWindow, "%s\n", qPrintable(tr("Could not extract data from file '%1'. %2")
-                                                    .arg(path, layoutReader.ErrorString())));
+                                                    .arg(path, rawLayoutReader.ErrorString())));
             if (m_cmd != nullptr && not m_cmd->IsGuiEnabled())
             {
                 m_cmd->ShowHelp(V_EX_DATAERR);
@@ -153,6 +164,18 @@ void PuzzleMainWindow::ImportRawLayouts(const QStringList &layouts)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+VPuzzlePiece* PuzzleMainWindow::CreatePiece(const VLayoutPiece &rawPiece)
+{
+    VPuzzlePiece *piece = new VPuzzlePiece();
+    piece->SetName(rawPiece.GetName());
+    piece->SetUuid(rawPiece.GetUUID());
+
+    // TODO : set all the information we need for the piece!
+
+    return piece;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void PuzzleMainWindow::InitMenuBar()
 {
@@ -266,7 +289,8 @@ void PuzzleMainWindow::InitPropertyTabLayers()
 //---------------------------------------------------------------------------------------------------------------------
 void PuzzleMainWindow::InitPieceCarrousel()
 {
-    ui->dockWidgetPieceCarrousel->setWidget(pieceCarrousel);
+    m_pieceCarrousel = new VPieceCarrousel(m_layout);
+    ui->dockWidgetPieceCarrousel->setWidget(m_pieceCarrousel);
 
     connect(ui->dockWidgetPieceCarrousel, QOverload<Qt::DockWidgetArea>::of(&QDockWidget::dockLocationChanged), this,
               &PuzzleMainWindow::on_PieceCarrouselLocationChanged);
@@ -498,14 +522,30 @@ void PuzzleMainWindow::on_actionSaveAs_triggered()
 //---------------------------------------------------------------------------------------------------------------------
 void PuzzleMainWindow::on_actionImportRawLayout_triggered()
 {
-    // just for test purpuses, to be removed:
-    QMessageBox msgBox;
-    msgBox.setText("TODO PuzzleMainWindow::ImportRawLayout");
-    int ret = msgBox.exec();
+    // TODO: here the code is probably just bad, to be edited
 
-    Q_UNUSED(ret);
+    QString dir;
+    if (true)
+    {
+        dir = QDir::homePath();
+    }
+    else
+    {
+        // TODO / FIXME get the default path for raw layouts
+    }
+
+    const QString filter(tr("Raw Layout files") + QLatin1String(" (*.rld)"));
+
+    qCDebug(pWindow, "Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir));
+    const QString filePath = QFileDialog::getOpenFileName(this, tr("Open file"), dir, filter, nullptr);
+
+    QStringList rawLayouts = QStringList();
+    rawLayouts.append(filePath);
+
+    ImportRawLayouts(rawLayouts);
+
+    // TODO / FIXME : better error handling
 
-    // TODO
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -764,13 +804,13 @@ void PuzzleMainWindow::on_PieceCarrouselLocationChanged(Qt::DockWidgetArea area)
 {
     if(area == Qt::BottomDockWidgetArea || area == Qt::TopDockWidgetArea)
     {
-        pieceCarrousel->setOrientation(Qt::Horizontal);
+        m_pieceCarrousel->SetOrientation(Qt::Horizontal);
         ui->dockWidgetPieceCarrousel->setMaximumHeight(208);
         ui->dockWidgetPieceCarrousel->setMaximumWidth(10000);
     }
     else if (area == Qt::LeftDockWidgetArea || area == Qt::RightDockWidgetArea)
     {
-        pieceCarrousel->setOrientation(Qt::Vertical);
+        m_pieceCarrousel->SetOrientation(Qt::Vertical);
         ui->dockWidgetPieceCarrousel->setMaximumHeight(10000);
         ui->dockWidgetPieceCarrousel->setMaximumWidth(160);
     }
diff --git a/src/app/puzzle/puzzlemainwindow.h b/src/app/puzzle/puzzlemainwindow.h
index 6578b1a3d..3432d50e5 100644
--- a/src/app/puzzle/puzzlemainwindow.h
+++ b/src/app/puzzle/puzzlemainwindow.h
@@ -36,6 +36,7 @@
 #include "vpiececarrousel.h"
 #include "vpuzzlelayout.h"
 #include "vpuzzlepiece.h"
+#include "../vlayout/vlayoutpiece.h"
 #include "vpuzzlecommandline.h"
 
 namespace Ui
@@ -68,15 +69,14 @@ public:
 
     /**
      * @brief ImportRawLayouts The function imports the raw layouts of given paths
-     * @param layouts paths of the layouts to import
+     * @param rawLayouts paths of the layouts to import
      */
-    void ImportRawLayouts(const QStringList &layouts);
+    void ImportRawLayouts(const QStringList &rawLayouts);
 
 public slots:
     /**
      * @brief on_actionNew_triggered When the menu action File > New
      * is triggered
-     *
      */
     void on_actionNew_triggered();
 
@@ -86,13 +86,18 @@ protected:
 private:
     Q_DISABLE_COPY(PuzzleMainWindow)
     Ui::PuzzleMainWindow *ui;
-    VPieceCarrousel *pieceCarrousel;
+    VPieceCarrousel *m_pieceCarrousel{nullptr};
     VPuzzleCommandLinePtr m_cmd;
 
     VPuzzleLayout *m_layout{nullptr};
 
     VPuzzlePiece *m_selectedPiece{nullptr};
 
+    /**
+     * @brief CreatePiece creates a piece from the given VLayoutPiece data
+     * @param rawPiece the raw piece data
+     */
+    VPuzzlePiece* CreatePiece(const VLayoutPiece &rawPiece);
 
     /**
      * @brief InitMenuBar Inits the menu bar (File, Edit, Help ...)
diff --git a/src/app/puzzle/vpiececarrousel.cpp b/src/app/puzzle/vpiececarrousel.cpp
index 02b85c0a1..1bf2ee2de 100644
--- a/src/app/puzzle/vpiececarrousel.cpp
+++ b/src/app/puzzle/vpiececarrousel.cpp
@@ -27,131 +27,170 @@
  *************************************************************************/
 #include "vpiececarrousel.h"
 #include <QVBoxLayout>
-#include <QLabel>
 #include <QMessageBox>
 
 #include "../vmisc/backport/qoverload.h"
 
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(pCarrousel, "p.carrousel")
+
 //---------------------------------------------------------------------------------------------------------------------
-VPieceCarrousel::VPieceCarrousel(QWidget *parent) :
+VPieceCarrousel::VPieceCarrousel(VPuzzleLayout *layout, QWidget *parent) :
     QWidget(parent),
-    comboBoxLayer(new QComboBox),
-    mainScrollArea(new QScrollArea(this)),
-    layers(QList<QWidget *>())
+    m_layout(layout),
+    m_comboBoxLayer(new QComboBox(this)),
+    m_layersContainer(new QWidget(this)),
+    m_carrouselLayers(QList<VPieceCarrouselLayer *>())
 {
-
-    QVBoxLayout *mainLayout = new QVBoxLayout();
-    setLayout(mainLayout);
-
-    setMinimumSize(140,140);
-
-    mainLayout->addWidget(comboBoxLayer);
-    comboBoxLayer->addItem(tr("Unplaced pieces"));
-    comboBoxLayer->addItem(tr("Layout"));
-    comboBoxLayer->setCurrentIndex(0);
-    connect(comboBoxLayer, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
-              &VPieceCarrousel::ActiveLayerChanged);
-
-    QWidget *widget = new QWidget();
-    QVBoxLayout *mainScrollAreaLayout = new QVBoxLayout();
-    mainScrollAreaLayout->setMargin(0);
-    widget->setLayout(mainScrollAreaLayout);
-    mainScrollArea->setWidget(widget);
-
-    mainLayout->addWidget(mainScrollArea);
-//    mainScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
-    mainScrollArea->setWidgetResizable( true );
-
-
-    // this code is for test purpuses, it needs to be updated when we have proper data!
-
-    QWidget *unplacedPieces = new QWidget();
-    QVBoxLayout *unplacedPiecesLayout = new QVBoxLayout();
-    unplacedPiecesLayout->setMargin(0);
-    unplacedPieces->setLayout(unplacedPiecesLayout);
-    for(int i=0; i<=10; ++i)
-    {
-        QLabel *myLabel = new QLabel();
-        myLabel->setText(QString ("Element A.%1").arg(i));
-        myLabel->setFixedSize(120,120);
-        myLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
-        if(i%2 ==0)
-        {
-            myLabel->setStyleSheet("background-color:white");
-        }
-        else {
-            myLabel->setStyleSheet("background-color:red");
-        }
-        unplacedPiecesLayout->addWidget(myLabel);
-    }
-    mainScrollAreaLayout->addWidget(unplacedPieces);
-    layers.append(unplacedPieces);
-
-    QWidget *layoutPieces = new QWidget();
-    QVBoxLayout *layoutPiecesLayout = new QVBoxLayout();
-    layoutPiecesLayout->setMargin(0);
-    layoutPieces->setLayout(layoutPiecesLayout);
-    for(int i=0; i<=5; ++i)
-    {
-        QLabel *myLabel = new QLabel();
-        myLabel->setText(QString ("Element B.%1").arg(i));
-        myLabel->setFixedSize(120,120);
-        myLabel->sizePolicy();
-        myLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
-        myLabel->setStyleSheet("background-color:cornflowerblue");
-        layoutPiecesLayout->addWidget(myLabel);
-    }
-    mainScrollAreaLayout->addWidget(layoutPieces);
-    layers.append(layoutPieces);
-
-    QSpacerItem *spacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
-    mainScrollAreaLayout->addSpacerItem(spacer);
-
-    // -------------------- init the layers combobox ---------------------
-    ActiveLayerChanged(0);
+    Init();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 VPieceCarrousel::~VPieceCarrousel()
 {
-    delete comboBoxLayer;
-    delete mainScrollArea;
+    delete m_comboBoxLayer;
+    delete m_layersContainer;
 }
 
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPieceCarrousel::ActiveLayerChanged(int index)
+void VPieceCarrousel::Init()
 {
+    // ------ first we initialize the structure of the carrousel
+
+    // init the combo box
+    connect(m_comboBoxLayer, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+              &VPieceCarrousel::on_ActiveLayerChanged);
+
+    // init the layers container and corresponding scroll area
+    QWidget *layersContainerWrapper = new QWidget();
+    QVBoxLayout *layersContainerWrapperLayout = new QVBoxLayout();
+    layersContainerWrapperLayout->setMargin(0);
+    layersContainerWrapper->setLayout(layersContainerWrapperLayout);
+
+    QVBoxLayout *layersContainerLayout = new QVBoxLayout();
+    layersContainerLayout->setMargin(0);
+    m_layersContainer->setLayout(layersContainerLayout);
+    QSpacerItem *spacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+    layersContainerWrapperLayout->addWidget(m_layersContainer);
+    layersContainerWrapperLayout->addSpacerItem(spacer);
+
+    QScrollArea *scrollArea = new QScrollArea();
+    scrollArea->setWidgetResizable( true );
+    scrollArea->setWidget(layersContainerWrapper);
+
+    // init the layout of the piece carrousel
+    QVBoxLayout *mainLayout = new QVBoxLayout();
+    setLayout(mainLayout);
+    setMinimumSize(140,140);
+
+    mainLayout->addWidget(m_comboBoxLayer);
+    mainLayout->addWidget(scrollArea);
+
+    // ------ then we fill the carrousel with the layout content
+    Refresh();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrousel::Refresh()
+{
+
+    // NOTE: alternative to clearing the carrousel and adding things again, we could make comparision
+
+    // --- clears the content of the carrousel
+    Clear();
+
+    // --- add the content saved in the layout to the carrousel.
+    QList<VPuzzleLayer*> layers = m_layout->GetLayers();
+    layers.prepend(m_layout->GetUnplacedPiecesLayer());
+
+    for (auto layer : layers)
+    {
+        // add layer name to combo
+        m_comboBoxLayer->addItem(layer->GetName());
+
+        qCDebug(pCarrousel, "layer name : %s", layer->GetName().toStdString().c_str());
+
+        // add new carrousel layer
+        VPieceCarrouselLayer *carrouselLayer = new VPieceCarrouselLayer(layer, this);
+        m_carrouselLayers.append(carrouselLayer);
+        m_layersContainer->layout()->addWidget(carrouselLayer);
+    }
+
+    m_comboBoxLayer->setCurrentIndex(0);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrousel::Clear()
+{
+    // remove the combobox entries
+    int layerCount = m_comboBoxLayer->count();
+    for(int i=0;i<layerCount;i++)
+    {
+        m_comboBoxLayer->removeItem(0);
+    }
+
+    // remove the carrousel layers from the qlayout
+    while(!m_layersContainer->layout()->isEmpty())
+    {
+        QLayoutItem* item = m_layersContainer->layout()->takeAt(0);
+        if(item != nullptr)
+        {
+            delete item;
+        }
+    }
+
+    // Removes and deletes the carrousel layer from the list
+    while (!m_carrouselLayers.isEmpty())
+    {
+        VPieceCarrouselLayer *carrouselLayer = m_carrouselLayers.takeLast();
+        if(carrouselLayer != nullptr)
+        {
+            delete carrouselLayer;
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrousel::on_ActiveLayerChanged(int index)
+{
+    qCDebug(pCarrousel, "index changed %i", index);
+
     int j=0;
-    for (QWidget *widget: layers) {
-        widget->setVisible(j == index);
+    for (VPieceCarrouselLayer *carrouselLayer: m_carrouselLayers) {
+        carrouselLayer->setVisible(j == index);
         j++;
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPieceCarrousel::setOrientation(Qt::Orientation orientation)
+void VPieceCarrousel::SetOrientation(Qt::Orientation orientation)
 {
     QBoxLayout::Direction direction = QBoxLayout::LeftToRight;
 
     if(orientation == Qt::Horizontal)
     {
-        comboBoxLayer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+        m_comboBoxLayer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
         setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
     }
     else // Qt::Vertical
     {
         direction = QBoxLayout::TopToBottom;
-        comboBoxLayer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+        m_comboBoxLayer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
         setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
     }
 
-    QBoxLayout* mainScrollAreaLayout = qobject_cast<QBoxLayout*>(mainScrollArea->widget()->layout());
+    // TODO: it's not updated anymore:
+
+    QBoxLayout* mainScrollAreaLayout = qobject_cast<QBoxLayout*>(m_layersContainer->layout());
     mainScrollAreaLayout->setDirection(direction);
 
-    for (QWidget *widget: layers) {
+    for (VPieceCarrouselLayer *widget: m_carrouselLayers) {
         QBoxLayout* layerLayout = qobject_cast<QBoxLayout*>(widget->layout());
         layerLayout->setDirection(direction);
     }
 }
 
+
diff --git a/src/app/puzzle/vpiececarrousel.h b/src/app/puzzle/vpiececarrousel.h
index 009d5348e..22a08cd79 100644
--- a/src/app/puzzle/vpiececarrousel.h
+++ b/src/app/puzzle/vpiececarrousel.h
@@ -32,27 +32,50 @@
 #include <QWidget>
 #include <QComboBox>
 #include <QScrollArea>
+#include "vpuzzlelayout.h"
+#include "vpiececarrousellayer.h"
 
 class VPieceCarrousel : public QWidget
 {
     Q_OBJECT
 public:
-    explicit VPieceCarrousel(QWidget *parent = nullptr); 
+    explicit VPieceCarrousel(VPuzzleLayout *layout, QWidget *parent = nullptr);
     virtual ~VPieceCarrousel();
 
-    void setOrientation(Qt::Orientation orientation);
+    void SetOrientation(Qt::Orientation orientation);
+
+    /**
+     * @brief Inits the carroussel
+     */
+    void Init();
+
+    /**
+     * @brief Refresh Refreshes the content of the carrousel
+     */
+    void Refresh();
+
+    /**
+     * @brief Clear Clears the carrousel (removes everything)
+     */
+    void Clear();
+
 signals:
 
 public slots:
 
 private:
     Q_DISABLE_COPY(VPieceCarrousel)
-    QComboBox *comboBoxLayer;
-    QScrollArea *mainScrollArea;
-    QList<QWidget *> layers;
+
+    VPuzzleLayout *m_layout;
+
+    QComboBox *m_comboBoxLayer;
+    QWidget *m_layersContainer;
+
+    QList<VPieceCarrouselLayer*> m_carrouselLayers;
+
 
 private slots:
-    void ActiveLayerChanged(int index);
+    void on_ActiveLayerChanged(int index);
 };
 
 #endif // VPIECECARROUSEL_H
diff --git a/src/app/puzzle/vpiececarrousellayer.cpp b/src/app/puzzle/vpiececarrousellayer.cpp
new file mode 100644
index 000000000..7a28c7fd0
--- /dev/null
+++ b/src/app/puzzle/vpiececarrousellayer.cpp
@@ -0,0 +1,78 @@
+/************************************************************************
+ **
+ **  @file   vpiececarrousellayer.cpp
+ **  @author Ronan Le Tiec
+ **  @date   25 4, 2020
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentina project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2020 Valentina project
+ **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
+ **
+ **  Valentina is free software: you can redistribute it and/or modify
+ **  it under the terms of the GNU General Public License as published by
+ **  the Free Software Foundation, either version 3 of the License, or
+ **  (at your option) any later version.
+ **
+ **  Valentina 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 Valentina.  If not, see <http://www.gnu.org/licenses/>.
+ **
+ *************************************************************************/
+
+#include "vpiececarrousellayer.h"
+
+#include <QVBoxLayout>
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(pCarrouselLayer, "p.carrouselLayer")
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceCarrouselLayer::VPieceCarrouselLayer(VPuzzleLayer *layer, QWidget *parent) : QWidget(parent), m_layer(layer)
+{
+    Init();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceCarrouselLayer::~VPieceCarrouselLayer()
+{
+    // TODO
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrouselLayer::Init()
+{
+    // initiales the structure
+    QVBoxLayout *layoutPiecesLayout = new QVBoxLayout();
+    layoutPiecesLayout->setMargin(0);
+    setLayout(layoutPiecesLayout);
+
+    // then refresh the content
+    Refresh();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrouselLayer::Refresh()
+{
+    // remove the existing carrousel pieces
+    // TODO
+
+    // Updates the carrousel pieces from the pieces list
+    QList<VPuzzlePiece*> pieces = m_layer->GetPieces();
+
+    for (auto piece : pieces)
+    {
+        qCDebug(pCarrouselLayer, "piece name : %s", piece->GetName().toStdString().c_str());
+
+        VPieceCarrouselPiece *carrouselPiece = new VPieceCarrouselPiece(piece);
+        m_carrouselPieces.append(carrouselPiece);
+        layout()->addWidget(carrouselPiece);
+    }
+}
diff --git a/src/app/puzzle/vpiececarrousellayer.h b/src/app/puzzle/vpiececarrousellayer.h
new file mode 100644
index 000000000..82dcad530
--- /dev/null
+++ b/src/app/puzzle/vpiececarrousellayer.h
@@ -0,0 +1,60 @@
+/************************************************************************
+ **
+ **  @file   vpiececarrousellayer.h
+ **  @author Ronan Le Tiec
+ **  @date   25 4, 2020
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentina project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2020 Valentina project
+ **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
+ **
+ **  Valentina is free software: you can redistribute it and/or modify
+ **  it under the terms of the GNU General Public License as published by
+ **  the Free Software Foundation, either version 3 of the License, or
+ **  (at your option) any later version.
+ **
+ **  Valentina 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 Valentina.  If not, see <http://www.gnu.org/licenses/>.
+ **
+ *************************************************************************/
+
+#ifndef VPIECECARROUSELLAYER_H
+#define VPIECECARROUSELLAYER_H
+
+#include <QWidget>
+#include "vpuzzlelayer.h"
+#include "vpiececarrouselpiece.h"
+
+class VPieceCarrouselLayer : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit VPieceCarrouselLayer(VPuzzleLayer *layer, QWidget *parent = nullptr);
+    ~VPieceCarrouselLayer();
+
+    void Init();
+    void Refresh();
+
+signals:
+
+public slots:
+
+private:
+    Q_DISABLE_COPY(VPieceCarrouselLayer)
+
+    VPuzzleLayer *m_layer;
+    QList<VPieceCarrouselPiece*> m_carrouselPieces;
+
+private slots:
+
+};
+
+#endif // VPIECECARROUSELLAYER_H
diff --git a/src/app/puzzle/vpiececarrouselpiece.cpp b/src/app/puzzle/vpiececarrouselpiece.cpp
new file mode 100644
index 000000000..553ff8db0
--- /dev/null
+++ b/src/app/puzzle/vpiececarrouselpiece.cpp
@@ -0,0 +1,87 @@
+/************************************************************************
+ **
+ **  @file   vpiececarrouselpiece.cpp
+ **  @author Ronan Le Tiec
+ **  @date   25 4, 2020
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentina project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2020 Valentina project
+ **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
+ **
+ **  Valentina is free software: you can redistribute it and/or modify
+ **  it under the terms of the GNU General Public License as published by
+ **  the Free Software Foundation, either version 3 of the License, or
+ **  (at your option) any later version.
+ **
+ **  Valentina 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 Valentina.  If not, see <http://www.gnu.org/licenses/>.
+ **
+ *************************************************************************/
+
+#include "vpiececarrouselpiece.h"
+#include <QLabel>
+#include <QVBoxLayout>
+
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(pCarrouselPiece, "p.carrouselPiece")
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceCarrouselPiece::VPieceCarrouselPiece(VPuzzlePiece *piece, QWidget *parent) : QWidget(parent), m_piece(piece)
+{
+    Init();
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceCarrouselPiece::~VPieceCarrouselPiece()
+{
+
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrouselPiece::Init()
+{
+    // first define the structure
+    
+    QVBoxLayout *pieceLayout = new QVBoxLayout();
+    pieceLayout->setMargin(0);
+    setLayout(pieceLayout);
+
+    // NOTE: this label structure is for test purpuses, it has to be changed when we see the piece preview
+    m_label = new QLabel();
+    m_label->setFixedSize(120,120);
+    m_label->sizePolicy();
+    m_label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+    m_label->setStyleSheet("background-color:cornflowerblue");
+
+    pieceLayout->addWidget(m_label);
+
+    // then refresh the data
+    Refresh();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceCarrouselPiece::Refresh()
+{
+    // update the label of the piece
+
+    QFontMetrics metrix(m_label->font());
+    int width = m_label->width() - 8;
+    QString clippedText = metrix.elidedText(m_piece->GetName(), Qt::ElideRight, width);
+    m_label->setText(clippedText);
+
+    m_label->setToolTip(m_piece->GetName());
+
+
+    // update the graphic preview of the piece
+    // TODO
+}
diff --git a/src/app/puzzle/vpiececarrouselpiece.h b/src/app/puzzle/vpiececarrouselpiece.h
new file mode 100644
index 000000000..29e8cdc28
--- /dev/null
+++ b/src/app/puzzle/vpiececarrouselpiece.h
@@ -0,0 +1,60 @@
+/************************************************************************
+ **
+ **  @file   vpiececarrouselpiece.h
+ **  @author Ronan Le Tiec
+ **  @date   25 4, 2020
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentina project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2020 Valentina project
+ **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
+ **
+ **  Valentina is free software: you can redistribute it and/or modify
+ **  it under the terms of the GNU General Public License as published by
+ **  the Free Software Foundation, either version 3 of the License, or
+ **  (at your option) any later version.
+ **
+ **  Valentina 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 Valentina.  If not, see <http://www.gnu.org/licenses/>.
+ **
+ *************************************************************************/
+#ifndef VPIECECARROUSELPIECE_H
+#define VPIECECARROUSELPIECE_H
+
+#include <QWidget>
+#include <QLabel>
+
+#include "vpuzzlepiece.h"
+
+class VPieceCarrouselPiece : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit VPieceCarrouselPiece(VPuzzlePiece *piece, QWidget *parent = nullptr);
+    ~VPieceCarrouselPiece();
+
+    void Init();
+    void Refresh();
+
+signals:
+
+public slots:
+
+private:
+    Q_DISABLE_COPY(VPieceCarrouselPiece)
+
+    VPuzzlePiece *m_piece;
+    QLabel *m_label;
+
+private slots:
+
+};
+
+#endif // VPIECECARROUSELPIECE_H
diff --git a/src/app/puzzle/vpuzzlelayout.cpp b/src/app/puzzle/vpuzzlelayout.cpp
index e1f7603cc..61290add7 100644
--- a/src/app/puzzle/vpuzzlelayout.cpp
+++ b/src/app/puzzle/vpuzzlelayout.cpp
@@ -27,12 +27,18 @@
  *************************************************************************/
 #include "vpuzzlelayout.h"
 #include "vpuzzlelayer.h"
+#include "vpuzzlepiece.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 VPuzzleLayout::VPuzzleLayout() :
     m_unplacedPiecesLayer(new VPuzzleLayer())
 {
+    m_unplacedPiecesLayer->SetName(QObject::tr("Unplaced pieces"));
 
+    // create a standard default layer:
+    VPuzzleLayer *layer = new VPuzzleLayer();
+    layer->SetName(QObject::tr("Layout"));
+    AddLayer(layer);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/app/puzzle/vpuzzlelayout.h b/src/app/puzzle/vpuzzlelayout.h
index f26e753dd..436957475 100644
--- a/src/app/puzzle/vpuzzlelayout.h
+++ b/src/app/puzzle/vpuzzlelayout.h
@@ -41,7 +41,6 @@ enum class FollowGrainline : qint8 { No = 0, Follow90 = 1, Follow180 = 2};
 
 class VPuzzleLayout
 {
-
 public:
     VPuzzleLayout();
     virtual ~VPuzzleLayout();
diff --git a/src/app/puzzle/vpuzzlepiece.cpp b/src/app/puzzle/vpuzzlepiece.cpp
index 8c9a708f5..cd3df00c4 100644
--- a/src/app/puzzle/vpuzzlepiece.cpp
+++ b/src/app/puzzle/vpuzzlepiece.cpp
@@ -39,3 +39,29 @@ VPuzzlePiece::~VPuzzlePiece()
 
 }
 
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VPuzzlePiece::GetName() const
+{
+    return m_name;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPuzzlePiece::SetName(const QString &name)
+{
+    m_name = name;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+QUuid VPuzzlePiece::GetUuid() const
+{
+    return m_uuid;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPuzzlePiece::SetUuid(const QUuid &uuid)
+{
+    m_uuid = uuid;
+}
diff --git a/src/app/puzzle/vpuzzlepiece.h b/src/app/puzzle/vpuzzlepiece.h
index f20473764..beef8072c 100644
--- a/src/app/puzzle/vpuzzlepiece.h
+++ b/src/app/puzzle/vpuzzlepiece.h
@@ -28,14 +28,42 @@
 #ifndef VPUZZLEPIECE_H
 #define VPUZZLEPIECE_H
 
+#include <QUuid>
+
 class VPuzzlePiece
 {
 public:
     VPuzzlePiece();
     ~VPuzzlePiece();
 
-private:
+    /**
+     * @brief GetName Returns the name of the piece
+     * @return the piece's name
+     */
+    QString GetName() const;
 
+    /**
+     * @brief SetName Sets the piece's name to the given name
+     * @param name new name of the piece
+     */
+    void SetName(const QString &name);
+
+    /**
+     * @brief GetUuid Returns the uuid of the piece
+     * @return the uuid of the piece
+     */
+    QUuid GetUuid() const;
+
+    /**
+     * @brief SetUuid Sets the uuid of the piece to the given value
+     * @return the uuid of the piece
+     */
+    void SetUuid(const QUuid &uuid);
+
+
+private:
+    QUuid m_uuid{QUuid()};
+    QString m_name{QString()};
 };
 
 #endif // VPUZZLEPIECE_H