diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri index e55760817..5ed131c58 100644 --- a/src/app/puzzle/puzzle.pri +++ b/src/app/puzzle/puzzle.pri @@ -51,4 +51,5 @@ HEADERS += \ FORMS += \ $$PWD/puzzlemainwindow.ui \ - $$PWD/dialogs/dialogaboutpuzzle.ui + $$PWD/dialogs/dialogaboutpuzzle.ui \ + $$PWD/vpiececarrousel.ui diff --git a/src/app/puzzle/vpiececarrousel.cpp b/src/app/puzzle/vpiececarrousel.cpp index 65e46a410..5b0abe3b8 100644 --- a/src/app/puzzle/vpiececarrousel.cpp +++ b/src/app/puzzle/vpiececarrousel.cpp @@ -26,98 +26,57 @@ ** *************************************************************************/ #include "vpiececarrousel.h" +#include "ui_vpiececarrousel.h" #include #include #include #include "../vmisc/backport/qoverload.h" +#include "vpuzzlelayer.h" #include +#include +#include Q_LOGGING_CATEGORY(pCarrousel, "p.carrousel") //--------------------------------------------------------------------------------------------------------------------- VPieceCarrousel::VPieceCarrousel(VPuzzleLayout *layout, QWidget *parent) : QWidget(parent), - m_layout(layout), - m_comboBoxLayer(new QComboBox(this)), - m_scrollArea(new QScrollArea(this)), - m_layersContainer(new QWidget(this)), - m_carrouselLayers(QList()) + ui(new Ui::VPieceCarrousel), + m_layout(layout) { - Init(); -} - -//--------------------------------------------------------------------------------------------------------------------- -VPieceCarrousel::~VPieceCarrousel() -{ - delete m_comboBoxLayer; - delete m_layersContainer; -} - - -//--------------------------------------------------------------------------------------------------------------------- -void VPieceCarrousel::Init() -{ - // ------ first we initialize the structure of the carrousel + ui->setupUi(this); // init the combo box - connect(m_comboBoxLayer, QOverload::of(&QComboBox::currentIndexChanged), this, - &VPieceCarrousel::on_ActiveLayerChanged); + connect(ui->comboBoxLayer, QOverload::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); - m_layersContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - QSpacerItem *spacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding); - - - layersContainerWrapperLayout->addWidget(m_layersContainer); - layersContainerWrapperLayout->addSpacerItem(spacer); - - m_scrollArea->setWidgetResizable( true ); - m_scrollArea->setWidget(layersContainerWrapper); - - // init the layout of the piece carrousel - QVBoxLayout *mainLayout = new QVBoxLayout(); - setLayout(mainLayout); - - mainLayout->addWidget(m_comboBoxLayer); - mainLayout->addWidget(m_scrollArea); + ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu); // ------ then we fill the carrousel with the layout content - Refresh(); - } + 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 layers = m_layout->GetLayers(); - layers.prepend(m_layout->GetUnplacedPiecesLayer()); + // Do not rely on m_layout because we do not control it. + m_layers = m_layout->GetLayers(); + m_layers.prepend(m_layout->GetUnplacedPiecesLayer()); - for (auto layer : layers) + for (auto layer : m_layers) { // add layer name to combo - m_comboBoxLayer->addItem(layer->GetName()); - - // add new carrousel layer - VPieceCarrouselLayer *carrouselLayer = new VPieceCarrouselLayer(layer, this); - m_carrouselLayers.append(carrouselLayer); - m_layersContainer->layout()->addWidget(carrouselLayer); + ui->comboBoxLayer->blockSignals(true); + ui->comboBoxLayer->addItem(layer->GetName()); + ui->comboBoxLayer->blockSignals(false); } on_ActiveLayerChanged(0); @@ -129,31 +88,9 @@ void VPieceCarrousel::Refresh() void VPieceCarrousel::Clear() { // remove the combobox entries - int layerCount = m_comboBoxLayer->count(); - for(int i=0;iremoveItem(0); - } + ui->comboBoxLayer->clear(); - // 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 layers from the list - while (!m_carrouselLayers.isEmpty()) - { - VPieceCarrouselLayer *carrouselLayer = m_carrouselLayers.takeLast(); - if(carrouselLayer != nullptr) - { - delete carrouselLayer; - } - } + ui->listWidget->clear(); } //--------------------------------------------------------------------------------------------------------------------- @@ -161,10 +98,21 @@ void VPieceCarrousel::on_ActiveLayerChanged(int index) { qCDebug(pCarrousel, "index changed %i", index); - int j=0; - for (VPieceCarrouselLayer *carrouselLayer: m_carrouselLayers) { - carrouselLayer->setVisible(j == index); - j++; + ui->listWidget->clear(); + + if (index >= 0 && index < m_layers.size()) + { + VPuzzleLayer *layer = m_layers.at(index); + + if (layer) + { + QList pieces = layer->GetPieces(); + + for (auto piece : pieces) + { + new QListWidgetItem(piece->PieceIcon(QSize(120, 120)) , piece->GetName(), ui->listWidget); + } + } } } @@ -178,47 +126,26 @@ void VPieceCarrousel::SetOrientation(Qt::Orientation orientation) //--------------------------------------------------------------------------------------------------------------------- void VPieceCarrousel::RefreshOrientation() { - QBoxLayout::Direction direction = (m_orientation == Qt::Horizontal)? - QBoxLayout::LeftToRight - : - QBoxLayout::TopToBottom; - - // Update the various qlayouts - QBoxLayout* mainScrollAreaLayout = qobject_cast(m_layersContainer->layout()); - mainScrollAreaLayout->setDirection(direction); - - QBoxLayout* layerContainerWrapper = qobject_cast(m_scrollArea->widget()->layout()); - layerContainerWrapper->setDirection(direction); - - for (VPieceCarrouselLayer *widget: m_carrouselLayers) { - QBoxLayout* layerLayout = qobject_cast(widget->layout()); - layerLayout->setDirection(direction); - } - // then update the scrollarea min height / width and scrollbar behaviour if(m_orientation == Qt::Horizontal) { - m_comboBoxLayer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + ui->comboBoxLayer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // scroll bar policy of scroll area - m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - // FIXME: find a nicer way than putting directly the 120 height of the piece - m_scrollArea->setMinimumHeight(128 + m_scrollArea->horizontalScrollBar()->sizeHint().height()+2); - m_scrollArea->setMinimumWidth(0); + ui->listWidget->setFlow(QListView::TopToBottom); } else // Qt::Vertical { - m_comboBoxLayer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + ui->comboBoxLayer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); // scroll bar policy of scroll area - m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_scrollArea->setMinimumHeight(0); - m_scrollArea->setMinimumWidth(124 + m_scrollArea->verticalScrollBar()->sizeHint().width()+2); - // FIXME: find a nicer way than putting directly the 120 width of the piece + ui->listWidget->setFlow(QListView::LeftToRight); } } diff --git a/src/app/puzzle/vpiececarrousel.h b/src/app/puzzle/vpiececarrousel.h index a781b8ac2..569ffc3ac 100644 --- a/src/app/puzzle/vpiececarrousel.h +++ b/src/app/puzzle/vpiececarrousel.h @@ -34,14 +34,18 @@ #include #include "vpuzzlelayout.h" #include "vpuzzlepiece.h" -#include "vpiececarrousellayer.h" + +namespace Ui +{ +class VPieceCarrousel; +} class VPieceCarrousel : public QWidget { Q_OBJECT public: explicit VPieceCarrousel(VPuzzleLayout *layout, QWidget *parent = nullptr); - virtual ~VPieceCarrousel(); + virtual ~VPieceCarrousel() = default; /** * @brief SetOrientation Sets the orientation to the given value and refreshes @@ -56,11 +60,6 @@ public: */ void RefreshOrientation(); - /** - * @brief Inits the carroussel - */ - void Init(); - /** * @brief Refresh Refreshes the content of the carrousel */ @@ -78,14 +77,10 @@ public: private: Q_DISABLE_COPY(VPieceCarrousel) + Ui::VPieceCarrousel *ui; VPuzzleLayout *m_layout; - - QComboBox *m_comboBoxLayer; - QScrollArea *m_scrollArea; - QWidget *m_layersContainer; - - QList m_carrouselLayers; + QList m_layers{}; Qt::Orientation m_orientation{Qt::Vertical}; diff --git a/src/app/puzzle/vpiececarrousel.ui b/src/app/puzzle/vpiececarrousel.ui new file mode 100644 index 000000000..511853607 --- /dev/null +++ b/src/app/puzzle/vpiececarrousel.ui @@ -0,0 +1,77 @@ + + + VPieceCarrousel + + + + 0 + 0 + 583 + 557 + + + + Carrousel + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 0 + 0 + + + + + + + + Qt::ScrollBarAlwaysOn + + + QAbstractItemView::DragOnly + + + + 120 + 120 + + + + QListView::Static + + + QListView::TopToBottom + + + QListView::Adjust + + + 6 + + + QListView::IconMode + + + true + + + + + + + + diff --git a/src/app/puzzle/vpuzzlepiece.cpp b/src/app/puzzle/vpuzzlepiece.cpp index 074bf168e..dc11f77ca 100644 --- a/src/app/puzzle/vpuzzlepiece.cpp +++ b/src/app/puzzle/vpuzzlepiece.cpp @@ -32,7 +32,9 @@ #include "vpuzzlelayer.h" #include "../vmisc/def.h" +#include #include +#include Q_LOGGING_CATEGORY(pPiece, "p.piece") @@ -253,3 +255,46 @@ void VPuzzlePiece::SetLayer(VPuzzleLayer* layer) m_layer = layer; } } + +//--------------------------------------------------------------------------------------------------------------------- +QIcon VPuzzlePiece::PieceIcon(const QSize &size) const +{ + QVector points = GetSeamLine(); + if(points.isEmpty()) + { + points = GetCuttingLine(); + } + + QPolygonF shape(points); + shape << shape.first(); + + QRectF boundingRect = shape.boundingRect(); + qreal canvasSize = qMax(boundingRect.height(), boundingRect.width()); + QRectF canvas = QRectF(0, 0, canvasSize, canvasSize); + + qreal dx = canvas.center().x() - boundingRect.center().x(); + qreal dy = canvas.center().y() - boundingRect.center().y(); + + QPixmap pixmap(size); + pixmap.fill(QColor("white")); + + QPainter painter; + painter.begin(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + + int spacing = 2; + painter.translate(spacing, spacing); + + qreal scaleFactorX = canvasSize * 100 / (size.width() - spacing*2) / 100; + qreal scaleFactorY = canvasSize * 100 / (size.height() - spacing*2) / 100; + painter.scale(1./scaleFactorX, 1./scaleFactorY); + painter.setPen(QPen(Qt::black, 0.8*qMax(scaleFactorX, scaleFactorY))); + + painter.translate(dx, dy); + + painter.drawPolygon(shape); + painter.end(); + + return QIcon(pixmap); +} diff --git a/src/app/puzzle/vpuzzlepiece.h b/src/app/puzzle/vpuzzlepiece.h index b55ffeae0..c859de99e 100644 --- a/src/app/puzzle/vpuzzlepiece.h +++ b/src/app/puzzle/vpuzzlepiece.h @@ -198,6 +198,8 @@ public: */ void SetLayer(VPuzzleLayer* layer); + QIcon PieceIcon(const QSize &size) const; + signals: /** * @brief SelectionChanged emited when the selection of the piece was