Redesign. Move initialization in ui file. Use QListWidget instead of a custom solution. Basic functions do not work yet.

This commit is contained in:
Roman Telezhynskyi 2020-05-11 17:48:08 +03:00
parent 5fc927b32a
commit f1057de239
6 changed files with 178 additions and 131 deletions

View File

@ -51,4 +51,5 @@ HEADERS += \
FORMS += \
$$PWD/puzzlemainwindow.ui \
$$PWD/dialogs/dialogaboutpuzzle.ui
$$PWD/dialogs/dialogaboutpuzzle.ui \
$$PWD/vpiececarrousel.ui

View File

@ -26,98 +26,57 @@
**
*************************************************************************/
#include "vpiececarrousel.h"
#include "ui_vpiececarrousel.h"
#include <QVBoxLayout>
#include <QMessageBox>
#include <QScrollBar>
#include "../vmisc/backport/qoverload.h"
#include "vpuzzlelayer.h"
#include <QLoggingCategory>
#include <QMenu>
#include <QPainter>
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<VPieceCarrouselLayer *>())
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<int>::of(&QComboBox::currentIndexChanged), this,
&VPieceCarrousel::on_ActiveLayerChanged);
connect(ui->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);
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();
}
}
//---------------------------------------------------------------------------------------------------------------------
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());
// 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;i<layerCount;i++)
{
m_comboBoxLayer->removeItem(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<VPuzzlePiece*> 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<QBoxLayout*>(m_layersContainer->layout());
mainScrollAreaLayout->setDirection(direction);
QBoxLayout* layerContainerWrapper = qobject_cast<QBoxLayout*>(m_scrollArea->widget()->layout());
layerContainerWrapper->setDirection(direction);
for (VPieceCarrouselLayer *widget: m_carrouselLayers) {
QBoxLayout* layerLayout = qobject_cast<QBoxLayout*>(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);
}
}

View File

@ -34,14 +34,18 @@
#include <QScrollArea>
#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<VPieceCarrouselLayer*> m_carrouselLayers;
QList<VPuzzleLayer*> m_layers{};
Qt::Orientation m_orientation{Qt::Vertical};

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VPieceCarrousel</class>
<widget class="QWidget" name="VPieceCarrousel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>583</width>
<height>557</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Carrousel</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QComboBox" name="comboBoxLayer">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="movement">
<enum>QListView::Static</enum>
</property>
<property name="flow">
<enum>QListView::TopToBottom</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="spacing">
<number>6</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -32,7 +32,9 @@
#include "vpuzzlelayer.h"
#include "../vmisc/def.h"
#include <QIcon>
#include <QLoggingCategory>
#include <QPainter>
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<QPointF> 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);
}

View File

@ -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