Merge branch 'feature/manual-layout' into 'feature/manual-layout'

Feature/manual layout app behaviour optimization

See merge request smart-pattern/valentina!7
This commit is contained in:
Roman Telezhynskyi 2020-05-10 08:27:19 +00:00
commit ddd4d735e8
32 changed files with 2301 additions and 222 deletions

View File

@ -6,11 +6,17 @@ SOURCES += \
$$PWD/puzzlecommands.cpp \ $$PWD/puzzlecommands.cpp \
$$PWD/puzzlemainwindow.cpp \ $$PWD/puzzlemainwindow.cpp \
$$PWD/puzzleapplication.cpp \ $$PWD/puzzleapplication.cpp \
$$PWD/vpiececarrouselpiecepreview.cpp \
$$PWD/vpuzzlecommandline.cpp \ $$PWD/vpuzzlecommandline.cpp \
$$PWD/dialogs/dialogaboutpuzzle.cpp \ $$PWD/dialogs/dialogaboutpuzzle.cpp \
$$PWD/vpiececarrousel.cpp \ $$PWD/vpiececarrousel.cpp \
$$PWD/vpuzzlegraphicslayout.cpp \
$$PWD/vpuzzlegraphicspiece.cpp \
$$PWD/vpuzzlelayout.cpp \ $$PWD/vpuzzlelayout.cpp \
$$PWD/vpuzzlelayer.cpp \ $$PWD/vpuzzlelayer.cpp \
$$PWD/vpuzzlemaingraphicsscene.cpp \
$$PWD/vpuzzlemaingraphicsview.cpp \
$$PWD/vpuzzlemimedatapiece.cpp \
$$PWD/vpuzzlepiece.cpp \ $$PWD/vpuzzlepiece.cpp \
$$PWD/xml/layoutliterals.cpp \ $$PWD/xml/layoutliterals.cpp \
$$PWD/xml/vpuzzlelayoutfilewriter.cpp \ $$PWD/xml/vpuzzlelayoutfilewriter.cpp \
@ -25,11 +31,17 @@ HEADERS += \
$$PWD/puzzlemainwindow.h \ $$PWD/puzzlemainwindow.h \
$$PWD/stable.h \ $$PWD/stable.h \
$$PWD/puzzleapplication.h \ $$PWD/puzzleapplication.h \
$$PWD/vpiececarrouselpiecepreview.h \
$$PWD/vpuzzlecommandline.h \ $$PWD/vpuzzlecommandline.h \
$$PWD/dialogs/dialogaboutpuzzle.h \ $$PWD/dialogs/dialogaboutpuzzle.h \
$$PWD/vpiececarrousel.h \ $$PWD/vpiececarrousel.h \
$$PWD/vpuzzlegraphicslayout.h \
$$PWD/vpuzzlegraphicspiece.h \
$$PWD/vpuzzlelayout.h \ $$PWD/vpuzzlelayout.h \
$$PWD/vpuzzlelayer.h \ $$PWD/vpuzzlelayer.h \
$$PWD/vpuzzlemaingraphicsscene.h \
$$PWD/vpuzzlemaingraphicsview.h \
$$PWD/vpuzzlemimedatapiece.h \
$$PWD/vpuzzlepiece.h \ $$PWD/vpuzzlepiece.h \
$$PWD/xml/layoutliterals.h \ $$PWD/xml/layoutliterals.h \
$$PWD/xml/vpuzzlelayoutfilewriter.h \ $$PWD/xml/vpuzzlelayoutfilewriter.h \

View File

@ -59,9 +59,9 @@ PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *pa
m_layout = new VPuzzleLayout(); m_layout = new VPuzzleLayout();
// ----- for test purposes, to be removed------------------ // ----- for test purposes, to be removed------------------
m_layout->SetLayoutMarginsConverted(1.5, 2.00, 4.21, 0.25); m_layout->SetLayoutMarginsConverted(2, 2, 2, 2);
m_layout->SetLayoutSizeConverted(30.0, 29.7); m_layout->SetLayoutSizeConverted(30.0, 45);
m_layout->SetPiecesGapConverted(1.27); m_layout->SetPiecesGapConverted(1);
m_layout->SetUnit(Unit::Cm); m_layout->SetUnit(Unit::Cm);
m_layout->SetWarningSuperpositionOfPieces(true); m_layout->SetWarningSuperpositionOfPieces(true);
// -------------------------------------------------------- // --------------------------------------------------------
@ -71,6 +71,8 @@ PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *pa
InitMenuBar(); InitMenuBar();
InitProperties(); InitProperties();
InitPieceCarrousel(); InitPieceCarrousel();
InitMainGraphics();
SetPropertiesData(); SetPropertiesData();
} }
@ -142,8 +144,22 @@ void PuzzleMainWindow::ImportRawLayouts(const QStringList &rawLayouts)
{ {
VLayoutPiece rawPiece = data.pieces.at(i); VLayoutPiece rawPiece = data.pieces.at(i);
// TODO for feature "Update piece" : CreateOrUpdate() function indstead of CreatePiece() // We translate the piece, so that the origin of the bounding rect of the piece is at (0,0)
// It makes positioning later on easier.
QRectF boundingRect = rawPiece.DetailBoundingRect();
QPointF topLeft = boundingRect.topLeft();
rawPiece.Translate(-topLeft.x(), -topLeft.y());
// TODO / FIXME: make a few tests, on the data to check for validity. If not
//
// If seam allowance enabled, but the path is empty — invalid.
// If seam line path not hidden, but the path is empty — invalid.
// If seam allowance is built-in, but the seam line path is empty — invalid.
// TODO for feature "Update piece" : CreateOrUpdate() function indstead of CreatePiece()
VPuzzlePiece *piece = CreatePiece(rawPiece); VPuzzlePiece *piece = CreatePiece(rawPiece);
m_layout->GetUnplacedPiecesLayer()->AddPiece(piece); m_layout->GetUnplacedPiecesLayer()->AddPiece(piece);
} }
@ -168,10 +184,25 @@ VPuzzlePiece* PuzzleMainWindow::CreatePiece(const VLayoutPiece &rawPiece)
VPuzzlePiece *piece = new VPuzzlePiece(); VPuzzlePiece *piece = new VPuzzlePiece();
piece->SetName(rawPiece.GetName()); piece->SetName(rawPiece.GetName());
piece->SetUuid(rawPiece.GetUUID()); piece->SetUuid(rawPiece.GetUUID());
piece->SetCuttingLine(rawPiece.GetMappedSeamAllowancePoints()); piece->SetCuttingLine(rawPiece.GetMappedSeamAllowancePoints());
piece->SetSeamLine(rawPiece.GetMappedContourPoints());
piece->SetIsGrainlineEnabled(rawPiece.IsGrainlineEnabled());
if(rawPiece.IsGrainlineEnabled())
{
piece->SetGrainlineAngle(rawPiece.GrainlineAngle());
piece->SetGrainline(rawPiece.GetGrainline());
}
// TODO : set all the information we need for the piece! // TODO : set all the information we need for the piece!
//
connect(piece, &VPuzzlePiece::SelectionChanged, this, &PuzzleMainWindow::on_PieceSelectionChanged);
connect(piece, &VPuzzlePiece::PositionChanged, this, &PuzzleMainWindow::on_PiecePositionChanged);
connect(piece, &VPuzzlePiece::RotationChanged, this, &PuzzleMainWindow::on_PieceRotationChanged);
return piece; return piece;
} }
@ -211,9 +242,9 @@ void PuzzleMainWindow::InitPropertyTabCurrentPiece()
// ------------------------------ placement ----------------------------------- // ------------------------------ placement -----------------------------------
connect(ui->doubleSpinBoxCurrentPieceBoxPositionX, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, connect(ui->doubleSpinBoxCurrentPieceBoxPositionX, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
&PuzzleMainWindow::on_CurrentPiecePositionChanged); &PuzzleMainWindow::on_CurrentPiecePositionEdited);
connect(ui->doubleSpinBoxCurrentPieceBoxPositionY, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, connect(ui->doubleSpinBoxCurrentPieceBoxPositionY, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
&PuzzleMainWindow::on_CurrentPiecePositionChanged); &PuzzleMainWindow::on_CurrentPiecePositionEdited);
} }
@ -293,9 +324,6 @@ void PuzzleMainWindow::InitPieceCarrousel()
connect(ui->dockWidgetPieceCarrousel, QOverload<Qt::DockWidgetArea>::of(&QDockWidget::dockLocationChanged), this, connect(ui->dockWidgetPieceCarrousel, QOverload<Qt::DockWidgetArea>::of(&QDockWidget::dockLocationChanged), this,
&PuzzleMainWindow::on_PieceCarrouselLocationChanged); &PuzzleMainWindow::on_PieceCarrouselLocationChanged);
connect(m_pieceCarrousel, QOverload<VPuzzlePiece*>::of(&VPieceCarrousel::pieceClicked), this,
&PuzzleMainWindow::on_PieceSelected);
} }
@ -318,31 +346,45 @@ void PuzzleMainWindow::SetPropertiesData()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::SetPropertyTabCurrentPieceData() void PuzzleMainWindow::SetPropertyTabCurrentPieceData()
{ {
if(m_selectedPiece == nullptr) if(m_selectedPieces.count() == 0)
{ {
if(false) // check for multiple piece selection // show the content "no piece selected"
{
// TODO in the future
}
else
{
// TODO : update current piece data to show a "no current piece selected"
ui->containerCurrentPieceNoData->setVisible(true); ui->containerCurrentPieceNoData->setVisible(true);
ui->containerCurrentPieceData->setVisible(false); ui->containerCurrentPieceData->setVisible(false);
ui->containerCurrentPieceMultipleData->setVisible(false);
} }
else if(m_selectedPieces.count() == 1)
{
// show the content "selected piece data"
ui->containerCurrentPieceNoData->setVisible(false);
ui->containerCurrentPieceData->setVisible(true);
ui->containerCurrentPieceMultipleData->setVisible(false);
VPuzzlePiece *selectedPiece = m_selectedPieces.first();
// set the value to the current piece
ui->lineEditCurrentPieceName->setText(selectedPiece->GetName());
ui->checkBoxCurrentPieceShowSeamline->setChecked(selectedPiece->GetShowSeamLine());
ui->checkBoxCurrentPieceMirrorPiece->setChecked(selectedPiece->GetPieceMirrored());
QPointF pos = selectedPiece->GetPosition();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX, UnitConvertor(pos.x(), Unit::Px, m_layout->GetUnit()));
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY, UnitConvertor(pos.y(), Unit::Px, m_layout->GetUnit()));
qreal angle = selectedPiece->GetRotation();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
} }
else else
{ {
// show the content "multiple pieces selected"
ui->containerCurrentPieceNoData->setVisible(false); ui->containerCurrentPieceNoData->setVisible(false);
ui->containerCurrentPieceData->setVisible(true); ui->containerCurrentPieceData->setVisible(false);
ui->containerCurrentPieceMultipleData->setVisible(true);
// set the value to the current piece // if needed in the future, we can show some properties that coul be edited for all the pieces
ui->lineEditCurrentPieceName->setText(m_selectedPiece->GetName());
ui->checkBoxCurrentPieceShowSeamline->setChecked(m_selectedPiece->GetShowSeamLine());
ui->checkBoxCurrentPieceMirrorPiece->setChecked(m_selectedPiece->GetPieceMirrored());
// TODO:rotation and placement;
} }
} }
@ -401,6 +443,15 @@ void PuzzleMainWindow::SetPropertyTabLayersData()
} }
//---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::InitMainGraphics()
{
m_graphicsView = new VPuzzleMainGraphicsView(m_layout, this);
ui->centralWidget->layout()->addWidget(m_graphicsView);
m_graphicsView->RefreshLayout();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value) void PuzzleMainWindow::SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value)
@ -644,7 +695,8 @@ void PuzzleMainWindow::on_LayoutSizeChanged()
} }
// TODO Undo / Redo // TODO Undo / Redo
// TODO update the QGraphicView
m_graphicsView->RefreshLayout();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -657,8 +709,11 @@ void PuzzleMainWindow::on_LayoutOrientationChanged()
SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutWidth, length_before); SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutWidth, length_before);
SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutLength, width_before); SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutLength, width_before);
m_layout->SetLayoutSizeConverted(ui->doubleSpinBoxLayoutWidth->value(), ui->doubleSpinBoxLayoutLength->value());
// TODO Undo / Redo // TODO Undo / Redo
// TODO update the QGraphicView
m_graphicsView->RefreshLayout();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -686,7 +741,8 @@ void PuzzleMainWindow::on_LayoutMarginChanged()
); );
// TODO Undo / Redo // TODO Undo / Redo
// TODO update the QGraphicView
m_graphicsView->RefreshLayout();
} }
@ -759,47 +815,42 @@ void PuzzleMainWindow::on_pushButtonLayoutExport_clicked()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_checkBoxCurrentPieceShowSeamline_toggled(bool checked) void PuzzleMainWindow::on_checkBoxCurrentPieceShowSeamline_toggled(bool checked)
{ {
if(m_selectedPiece != nullptr) if(m_selectedPieces.count() == 1)
{ {
m_selectedPiece->SetShowSeamLine(checked); m_selectedPieces.first()->SetShowSeamLine(checked);
} }
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_checkBoxCurrentPieceMirrorPiece_toggled(bool checked) void PuzzleMainWindow::on_checkBoxCurrentPieceMirrorPiece_toggled(bool checked)
{ {
if(m_selectedPiece != nullptr) if(m_selectedPieces.count() == 1)
{ {
m_selectedPiece->SetPieceMirrored(checked); m_selectedPieces.first()->SetPieceMirrored(checked);
} }
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_doubleSpinBoxCurrentPieceAngle_valueChanged(double value) void PuzzleMainWindow::on_doubleSpinBoxCurrentPieceAngle_valueChanged(double value)
{ {
// just for test purpuses, to be removed: if(m_selectedPieces.count() == 1)
QMessageBox msgBox; {
msgBox.setText("TODO PuzzleMainWindow::CurrentPieceAngleChanged"); VPuzzlePiece *piece = m_selectedPieces.first();
int ret = msgBox.exec(); piece->SetRotation(value);
}
Q_UNUSED(value);
Q_UNUSED(ret);
// TODO
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_CurrentPiecePositionChanged() void PuzzleMainWindow::on_CurrentPiecePositionEdited()
{ {
// just for test purpuses, to be removed: if(m_selectedPieces.count() == 1)
QMessageBox msgBox; {
msgBox.setText("TODO PuzzleMainWindow::CurrentPiecePositionChanged"); VPuzzlePiece *piece = m_selectedPieces.first();
int ret = msgBox.exec(); QPointF pos(UnitConvertor(ui->doubleSpinBoxCurrentPieceBoxPositionX->value(), m_layout->GetUnit(), Unit::Px),
UnitConvertor(ui->doubleSpinBoxCurrentPieceBoxPositionY->value(), m_layout->GetUnit(), Unit::Px));
Q_UNUSED(ret); piece->SetPosition(pos);
}
// TODO
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -820,17 +871,37 @@ void PuzzleMainWindow::on_PieceCarrouselLocationChanged(Qt::DockWidgetArea area)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_PieceSelected(VPuzzlePiece* piece) void PuzzleMainWindow::on_PieceSelectionChanged()
{ {
m_selectedPiece = piece; m_selectedPieces = m_layout->GetSelectedPieces();
// update the state of the piece carrousel
m_pieceCarrousel->SelectPiece(piece);
// update the Layout
// TODO
// update the property of the piece currently selected // update the property of the piece currently selected
SetPropertyTabCurrentPieceData(); SetPropertyTabCurrentPieceData();
} }
//---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_PiecePositionChanged()
{
if(m_selectedPieces.count() == 1)
{
VPuzzlePiece *piece = m_selectedPieces.first();
QPointF pos = piece->GetPosition();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX, UnitConvertor(pos.x(), Unit::Px, m_layout->GetUnit()));
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY, UnitConvertor(pos.y(), Unit::Px, m_layout->GetUnit()));
}
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzleMainWindow::on_PieceRotationChanged()
{
if(m_selectedPieces.count() == 1)
{
VPuzzlePiece *piece = m_selectedPieces.first();
qreal angle = piece->GetRotation();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
}
}

View File

@ -34,6 +34,7 @@
#include "../vmisc/def.h" #include "../vmisc/def.h"
#include "vpiececarrousel.h" #include "vpiececarrousel.h"
#include "vpuzzlemaingraphicsview.h"
#include "vpuzzlelayout.h" #include "vpuzzlelayout.h"
#include "vpuzzlepiece.h" #include "vpuzzlepiece.h"
#include "../vlayout/vlayoutpiece.h" #include "../vlayout/vlayoutpiece.h"
@ -86,12 +87,14 @@ protected:
private: private:
Q_DISABLE_COPY(PuzzleMainWindow) Q_DISABLE_COPY(PuzzleMainWindow)
Ui::PuzzleMainWindow *ui; Ui::PuzzleMainWindow *ui;
VPieceCarrousel *m_pieceCarrousel{nullptr}; VPieceCarrousel *m_pieceCarrousel{nullptr};
VPuzzleMainGraphicsView *m_graphicsView{nullptr};
VPuzzleCommandLinePtr m_cmd; VPuzzleCommandLinePtr m_cmd;
VPuzzleLayout *m_layout{nullptr}; VPuzzleLayout *m_layout{nullptr};
QList<VPuzzlePiece *>m_selectedPieces{QList<VPuzzlePiece *>()};
VPuzzlePiece *m_selectedPiece{nullptr};
/** /**
* @brief CreatePiece creates a piece from the given VLayoutPiece data * @brief CreatePiece creates a piece from the given VLayoutPiece data
@ -134,6 +137,10 @@ private:
*/ */
void InitPieceCarrousel(); void InitPieceCarrousel();
/**
* @brief InitMainGraphics Initialises the puzzle main graphics
*/
void InitMainGraphics();
/** /**
* @brief SetPropertiesData Sets the values of UI elements * @brief SetPropertiesData Sets the values of UI elements
@ -347,7 +354,7 @@ private slots:
* @brief on_CurrentPiecePositionChanged When the positionX or the positionY * @brief on_CurrentPiecePositionChanged When the positionX or the positionY
* is changed in the current piece tab * is changed in the current piece tab
*/ */
void on_CurrentPiecePositionChanged(); void on_CurrentPiecePositionEdited();
/** /**
* @brief PieceCarrouselLocationChanged When the piece carrousel's location * @brief PieceCarrouselLocationChanged When the piece carrousel's location
@ -357,10 +364,19 @@ private slots:
void on_PieceCarrouselLocationChanged(Qt::DockWidgetArea area); void on_PieceCarrouselLocationChanged(Qt::DockWidgetArea area);
/** /**
* @brief on_PieceSelected When a piece has been selected * @brief on_PieceSelectionChanged When the piece selection has changed
* @param piece the piece that was selected
*/ */
void on_PieceSelected(VPuzzlePiece* piece); void on_PieceSelectionChanged();
/**
* @brief on_PiecePositionChanged When the current piece position has changed
*/
void on_PiecePositionChanged();
/**
* @brief on_PieceRotationChanged When the current piece rotation has changed
*/
void on_PieceRotationChanged();
}; };

View File

@ -24,9 +24,6 @@
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum> <enum>QLayout::SetDefaultConstraint</enum>
</property> </property>
<item>
<widget class="QGraphicsView" name="graphicsView"/>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QMenuBar" name="menuBar"> <widget class="QMenuBar" name="menuBar">
@ -233,7 +230,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>342</width> <width>342</width>
<height>894</height> <height>1318</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@ -253,31 +250,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="containerCurrentPieceNoData" native="true">
<layout class="QVBoxLayout" name="containerCurrentPieceNoDataLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelCurrentPieceNoPieceSelected">
<property name="minimumSize">
<size>
<width>0</width>
<height>400</height>
</size>
</property>
<property name="text">
<string>No piece selected</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QWidget" name="containerCurrentPieceData" native="true"> <widget class="QWidget" name="containerCurrentPieceData" native="true">
<layout class="QVBoxLayout" name="containerCurrentPieceDataLayout"> <layout class="QVBoxLayout" name="containerCurrentPieceDataLayout">
@ -361,7 +333,7 @@
<double>360.000000000000000</double> <double>360.000000000000000</double>
</property> </property>
<property name="singleStep"> <property name="singleStep">
<double>0.100000000000000</double> <double>1.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@ -383,6 +355,9 @@
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxCurrentPieceBoxPositionX"> <widget class="QDoubleSpinBox" name="doubleSpinBoxCurrentPieceBoxPositionX">
<property name="minimum">
<double>-10000.000000000000000</double>
</property>
<property name="maximum"> <property name="maximum">
<double>10000.000000000000000</double> <double>10000.000000000000000</double>
</property> </property>
@ -400,6 +375,9 @@
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxCurrentPieceBoxPositionY"> <widget class="QDoubleSpinBox" name="doubleSpinBoxCurrentPieceBoxPositionY">
<property name="minimum">
<double>-10000.000000000000000</double>
</property>
<property name="maximum"> <property name="maximum">
<double>10000.000000000000000</double> <double>10000.000000000000000</double>
</property> </property>
@ -414,6 +392,53 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="containerCurrentPieceNoData" native="true">
<layout class="QVBoxLayout" name="containerCurrentPieceNoDataLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelCurrentPieceNoPieceSelected">
<property name="minimumSize">
<size>
<width>0</width>
<height>400</height>
</size>
</property>
<property name="text">
<string>No piece selected</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="containerCurrentPieceMultipleData" native="true">
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QLabel" name="labelCurrentPieceMultiplePieceSelected">
<property name="minimumSize">
<size>
<width>0</width>
<height>400</height>
</size>
</property>
<property name="text">
<string>Multiple pieces selected</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacerCurrentPiece"> <spacer name="verticalSpacerCurrentPiece">
<property name="orientation"> <property name="orientation">
@ -1096,7 +1121,6 @@
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<tabstops> <tabstops>
<tabstop>graphicsView</tabstop>
<tabstop>scrollAreaLayout</tabstop> <tabstop>scrollAreaLayout</tabstop>
<tabstop>doubleSpinBoxLayoutMarginTop</tabstop> <tabstop>doubleSpinBoxLayoutMarginTop</tabstop>
<tabstop>doubleSpinBoxLayoutMarginLeft</tabstop> <tabstop>doubleSpinBoxLayoutMarginLeft</tabstop>

View File

@ -9,5 +9,6 @@
<file>puzzleicon/64x64/iconPortrait.png</file> <file>puzzleicon/64x64/iconPortrait.png</file>
<file>puzzleicon/64x64/iconGrainlineVertical.png</file> <file>puzzleicon/64x64/iconGrainlineVertical.png</file>
<file>puzzleicon/64x64/iconGrainlineHorizontal.png</file> <file>puzzleicon/64x64/iconGrainlineHorizontal.png</file>
<file alias="cursor_rotate">puzzleicon/64x64/cursorRotate.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
viewBox="0 0 33.866666 33.866668"
version="1.1"
id="svg8"
sodipodi:docname="icon_rotate.svg"
inkscape:export-filename="/home/ronan/Desktop/iconRotate.png"
inkscape:export-xdpi="48"
inkscape:export-ydpi="48"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="-73.50406"
inkscape:cy="-5.7476577"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1487"
inkscape:window-height="906"
inkscape:window-x="648"
inkscape:window-y="365"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-263.13332)">
<path
style="fill:#000000;fill-opacity:0.99622641;stroke:#000000;stroke-width:0.56587124;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 7.0186194,287.41283 -6.32117702,-9.61886 4.59283552,0.0718 c 0.2260142,-13.99266 14.6277861,-19.32352 24.6168741,-9.04316 8.326613,8.56942 1.645094,23.6663 -11.704329,23.56294 l -0.02016,4.07882 -9.3161816,-5.90315 9.3649386,-5.23047 -0.0097,3.75053 c 12.855101,-0.23223 15.657569,-13.03558 9.321879,-19.01152 -6.380838,-6.01853 -18.7084318,-6.45152 -19.0255146,7.87916 l 4.6551916,0.099 z"
id="path873"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccscccccsccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -28,11 +28,11 @@
#include "vpiececarrousel.h" #include "vpiececarrousel.h"
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QMessageBox> #include <QMessageBox>
#include <QScrollBar>
#include "../vmisc/backport/qoverload.h" #include "../vmisc/backport/qoverload.h"
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QScrollBar>
Q_LOGGING_CATEGORY(pCarrousel, "p.carrousel") Q_LOGGING_CATEGORY(pCarrousel, "p.carrousel")
@ -75,8 +75,10 @@ void VPieceCarrousel::Init()
QVBoxLayout *layersContainerLayout = new QVBoxLayout(); QVBoxLayout *layersContainerLayout = new QVBoxLayout();
layersContainerLayout->setMargin(0); layersContainerLayout->setMargin(0);
m_layersContainer->setLayout(layersContainerLayout); m_layersContainer->setLayout(layersContainerLayout);
m_layersContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QSpacerItem *spacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding); QSpacerItem *spacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
layersContainerWrapperLayout->addWidget(m_layersContainer); layersContainerWrapperLayout->addWidget(m_layersContainer);
layersContainerWrapperLayout->addSpacerItem(spacer); layersContainerWrapperLayout->addSpacerItem(spacer);
@ -92,9 +94,6 @@ void VPieceCarrousel::Init()
// ------ then we fill the carrousel with the layout content // ------ then we fill the carrousel with the layout content
Refresh(); Refresh();
// ------ and make sure the calculation for the qlayout is right
SetOrientation(Qt::Vertical);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -119,13 +118,11 @@ void VPieceCarrousel::Refresh()
VPieceCarrouselLayer *carrouselLayer = new VPieceCarrouselLayer(layer, this); VPieceCarrouselLayer *carrouselLayer = new VPieceCarrouselLayer(layer, this);
m_carrouselLayers.append(carrouselLayer); m_carrouselLayers.append(carrouselLayer);
m_layersContainer->layout()->addWidget(carrouselLayer); m_layersContainer->layout()->addWidget(carrouselLayer);
connect(carrouselLayer, QOverload<VPieceCarrouselPiece*>::of(&VPieceCarrouselLayer::pieceClicked), this,
&VPieceCarrousel::on_PieceClicked);
} }
on_ActiveLayerChanged(0); on_ActiveLayerChanged(0);
RefreshOrientation();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -159,20 +156,6 @@ void VPieceCarrousel::Clear()
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrousel::SelectPiece(VPuzzlePiece* piece)
{
for (auto layer : m_carrouselLayers)
{
QList<VPieceCarrouselPiece*> carrouselPieces = layer->GetCarrouselPieces();
for (auto carrouselPiece : carrouselPieces)
{
carrouselPiece->SetIsSelected(carrouselPiece->GetPiece() == piece);
}
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrousel::on_ActiveLayerChanged(int index) void VPieceCarrousel::on_ActiveLayerChanged(int index)
{ {
@ -188,8 +171,14 @@ void VPieceCarrousel::on_ActiveLayerChanged(int index)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrousel::SetOrientation(Qt::Orientation orientation) void VPieceCarrousel::SetOrientation(Qt::Orientation orientation)
{ {
m_orientation = orientation;
RefreshOrientation();
}
QBoxLayout::Direction direction = (orientation == Qt::Horizontal)? //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrousel::RefreshOrientation()
{
QBoxLayout::Direction direction = (m_orientation == Qt::Horizontal)?
QBoxLayout::LeftToRight QBoxLayout::LeftToRight
: :
QBoxLayout::TopToBottom; QBoxLayout::TopToBottom;
@ -207,7 +196,7 @@ void VPieceCarrousel::SetOrientation(Qt::Orientation orientation)
} }
// then update the scrollarea min height / width and scrollbar behaviour // then update the scrollarea min height / width and scrollbar behaviour
if(orientation == Qt::Horizontal) if(m_orientation == Qt::Horizontal)
{ {
m_comboBoxLayer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_comboBoxLayer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
@ -223,7 +212,6 @@ void VPieceCarrousel::SetOrientation(Qt::Orientation orientation)
{ {
m_comboBoxLayer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); m_comboBoxLayer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
// scroll bar policy of scroll area // scroll bar policy of scroll area
m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
@ -232,13 +220,10 @@ void VPieceCarrousel::SetOrientation(Qt::Orientation orientation)
m_scrollArea->setMinimumWidth(124 + m_scrollArea->verticalScrollBar()->sizeHint().width()+2); m_scrollArea->setMinimumWidth(124 + m_scrollArea->verticalScrollBar()->sizeHint().width()+2);
// FIXME: find a nicer way than putting directly the 120 width of the piece // FIXME: find a nicer way than putting directly the 120 width of the piece
} }
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrousel::on_PieceClicked(VPieceCarrouselPiece* carrouselPiece) void VPieceCarrousel::ClearSelection()
{ {
emit pieceClicked(carrouselPiece->GetPiece()); m_layout->ClearSelection();
} }

View File

@ -43,8 +43,19 @@ public:
explicit VPieceCarrousel(VPuzzleLayout *layout, QWidget *parent = nullptr); explicit VPieceCarrousel(VPuzzleLayout *layout, QWidget *parent = nullptr);
virtual ~VPieceCarrousel(); virtual ~VPieceCarrousel();
/**
* @brief SetOrientation Sets the orientation to the given value and refreshes
* the orientation of the carrousel.
* @param orientation the orientation to set the carrousel to.
*/
void SetOrientation(Qt::Orientation orientation); void SetOrientation(Qt::Orientation orientation);
/**
* @brief RefreshOrientation Refreshes the orientation of the carrousel with the
* m_orientation value;
*/
void RefreshOrientation();
/** /**
* @brief Inits the carroussel * @brief Inits the carroussel
*/ */
@ -61,18 +72,9 @@ public:
void Clear(); void Clear();
/** /**
* @brief SelectPiece Updates the carrousel so that the given piece is selected * @brief ClearSelection Clears the selection of the carrousel.
* @param piece the piece to select
*/ */
void SelectPiece(VPuzzlePiece* piece); void ClearSelection();
signals:
void pieceClicked(VPuzzlePiece* piece);
public slots:
void on_PieceClicked(VPieceCarrouselPiece* carrouselPiece);
private: private:
Q_DISABLE_COPY(VPieceCarrousel) Q_DISABLE_COPY(VPieceCarrousel)
@ -85,8 +87,15 @@ private:
QList<VPieceCarrouselLayer*> m_carrouselLayers; QList<VPieceCarrouselLayer*> m_carrouselLayers;
Qt::Orientation m_orientation{Qt::Vertical};
private slots: private slots:
/**
* @brief on_ActiveLayerChanged Called when the active layer is changed
* @param index
*/
void on_ActiveLayerChanged(int index); void on_ActiveLayerChanged(int index);
}; };

View File

@ -27,6 +27,7 @@
*************************************************************************/ *************************************************************************/
#include "vpiececarrousellayer.h" #include "vpiececarrousellayer.h"
#include "vpiececarrousel.h"
#include "../vmisc/backport/qoverload.h" #include "../vmisc/backport/qoverload.h"
#include <QVBoxLayout> #include <QVBoxLayout>
@ -36,9 +37,9 @@
Q_LOGGING_CATEGORY(pCarrouselLayer, "p.carrouselLayer") Q_LOGGING_CATEGORY(pCarrouselLayer, "p.carrouselLayer")
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPieceCarrouselLayer::VPieceCarrouselLayer(VPuzzleLayer *layer, QWidget *parent) : VPieceCarrouselLayer::VPieceCarrouselLayer(VPuzzleLayer *layer, VPieceCarrousel *carrousel) :
QWidget(parent),
m_layer(layer), m_layer(layer),
m_carrousel(carrousel),
m_carrouselPieces(QList<VPieceCarrouselPiece*>()) m_carrouselPieces(QList<VPieceCarrouselPiece*>())
{ {
Init(); Init();
@ -47,7 +48,7 @@ VPieceCarrouselLayer::VPieceCarrouselLayer(VPuzzleLayer *layer, QWidget *parent)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPieceCarrouselLayer::~VPieceCarrouselLayer() VPieceCarrouselLayer::~VPieceCarrouselLayer()
{ {
// TODO Clear();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -60,13 +61,16 @@ void VPieceCarrouselLayer::Init()
// then refresh the content // then refresh the content
Refresh(); Refresh();
// add the connections
connect(m_layer, &VPuzzleLayer::PieceAdded, this, &VPieceCarrouselLayer::on_PieceAdded);
connect(m_layer, &VPuzzleLayer::PieceRemoved, this, &VPieceCarrouselLayer::on_PieceRemoved);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselLayer::Refresh() void VPieceCarrouselLayer::Refresh()
{ {
// remove the existing carrousel pieces Clear();
// TODO
// Updates the carrousel pieces from the pieces list // Updates the carrousel pieces from the pieces list
QList<VPuzzlePiece*> pieces = m_layer->GetPieces(); QList<VPuzzlePiece*> pieces = m_layer->GetPieces();
@ -77,24 +81,33 @@ void VPieceCarrouselLayer::Refresh()
// create the corresponding carrousel pieces // create the corresponding carrousel pieces
bool _isVisible = isVisible();
setVisible(true);
for (auto piece : pieces) for (auto piece : pieces)
{ {
// qCDebug(pCarrouselLayer, "piece name : %s", piece->GetName().toStdString().c_str()); VPieceCarrouselPiece *carrouselPiece = new VPieceCarrouselPiece(piece, this);
VPieceCarrouselPiece *carrouselPiece = new VPieceCarrouselPiece(piece);
m_carrouselPieces.append(carrouselPiece); m_carrouselPieces.append(carrouselPiece);
layout()->addWidget(carrouselPiece); layout()->addWidget(carrouselPiece);
carrouselPiece->CleanPreview(); // fitInView only works if the widget is displayed.
// FIXME? the fitInView inside the refresh of the piece doesn't workd properly.
// only by doing the following I did get it to work:
setVisible(true);
carrouselPiece->CleanPreview();
setVisible(false);
connect(carrouselPiece, QOverload<VPieceCarrouselPiece*>::of(&VPieceCarrouselPiece::clicked), this,
&VPieceCarrouselLayer::on_PieceClicked);
} }
setVisible(_isVisible);
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselLayer::Clear()
{
// Removes and deletes the carrousel pieces from the layer
while (!m_carrouselPieces.isEmpty())
{
VPieceCarrouselPiece *carrouselPiece = m_carrouselPieces.takeLast();
if(carrouselPiece != nullptr)
{
layout()->removeWidget(carrouselPiece);
delete carrouselPiece;
}
}
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -104,7 +117,39 @@ QList<VPieceCarrouselPiece*> VPieceCarrouselLayer::GetCarrouselPieces()
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselLayer::on_PieceClicked(VPieceCarrouselPiece* carrouselPiece) VPieceCarrousel* VPieceCarrouselLayer::GetCarrousel()
{ {
emit pieceClicked(carrouselPiece); return m_carrousel;
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleLayer* VPieceCarrouselLayer::GetLayer()
{
return m_layer;
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselLayer::on_PieceAdded(VPuzzlePiece* piece)
{
Q_UNUSED(piece)
// TODO/ FIXME: see if we find a solution more efficient refreshing the complete layout everytime.
Refresh();
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselLayer::on_PieceRemoved(VPuzzlePiece* piece)
{
for (auto carrouselPiece : m_carrouselPieces)
{
if(carrouselPiece->GetPiece() == piece)
{
m_carrouselPieces.removeAll(carrouselPiece);
layout()->removeWidget(carrouselPiece);
delete carrouselPiece;
return;
}
}
} }

View File

@ -33,32 +33,52 @@
#include "vpuzzlelayer.h" #include "vpuzzlelayer.h"
#include "vpiececarrouselpiece.h" #include "vpiececarrouselpiece.h"
class VPieceCarrousel;
class VPieceCarrouselLayer : public QWidget class VPieceCarrouselLayer : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit VPieceCarrouselLayer(VPuzzleLayer *layer, QWidget *parent = nullptr); VPieceCarrouselLayer(VPuzzleLayer *layer, VPieceCarrousel *carrousel);
~VPieceCarrouselLayer(); ~VPieceCarrouselLayer();
void Init(); void Init();
void Refresh(); void Refresh();
/**
* @brief Clear it clears the carrousel layer from its pieces
*/
void Clear();
QList<VPieceCarrouselPiece*> GetCarrouselPieces(); QList<VPieceCarrouselPiece*> GetCarrouselPieces();
signals: VPieceCarrousel* GetCarrousel();
void pieceClicked(VPieceCarrouselPiece* carrouselPiece);
public slots: /**
void on_PieceClicked(VPieceCarrouselPiece* carrouselPiece); * @brief GetPuzzleLayer Returns the corresponding VPuzzleLayer
* @return the VPuzzleLayer
*/
VPuzzleLayer* GetLayer();
private: private:
Q_DISABLE_COPY(VPieceCarrouselLayer) Q_DISABLE_COPY(VPieceCarrouselLayer)
VPuzzleLayer *m_layer; VPuzzleLayer *m_layer;
VPieceCarrousel *m_carrousel;
QList<VPieceCarrouselPiece*> m_carrouselPieces; QList<VPieceCarrouselPiece*> m_carrouselPieces;
private slots: private slots:
/**
* @brief on_PieceUpdated This slot is called when a piece was added
*/
void on_PieceAdded(VPuzzlePiece* piece);
/**
* @brief on_PieceUpdated This slot is called when a piece was removed
*/
void on_PieceRemoved(VPuzzlePiece* piece);
}; };
#endif // VPIECECARROUSELLAYER_H #endif // VPIECECARROUSELLAYER_H

View File

@ -27,19 +27,30 @@
*************************************************************************/ *************************************************************************/
#include "vpiececarrouselpiece.h" #include "vpiececarrouselpiece.h"
#include <QLabel> #include <QLabel>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QPainter> #include <QPainter>
#include <QDrag>
#include <QPainter>
#include <QApplication>
#include <QMenu>
#include "vpuzzlemimedatapiece.h"
#include "vpiececarrousellayer.h"
#include "vpiececarrousel.h"
#include <QLoggingCategory> #include <QLoggingCategory>
Q_LOGGING_CATEGORY(pCarrouselPiece, "p.carrouselPiece") Q_LOGGING_CATEGORY(pCarrouselPiece, "p.carrouselPiece")
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPieceCarrouselPiece::VPieceCarrouselPiece(VPuzzlePiece *piece, QWidget *parent) : VPieceCarrouselPiece::VPieceCarrouselPiece(VPuzzlePiece *piece, VPieceCarrouselLayer *carrouselLayer) :
QFrame(parent), m_piece(piece),
m_piece(piece) m_carrouselLayer(carrouselLayer),
m_dragStart(QPoint())
{ {
Init(); Init();
} }
@ -48,7 +59,7 @@ VPieceCarrouselPiece::VPieceCarrouselPiece(VPuzzlePiece *piece, QWidget *parent)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPieceCarrouselPiece::~VPieceCarrouselPiece() VPieceCarrouselPiece::~VPieceCarrouselPiece()
{ {
delete m_graphicsView; delete m_piecePreview;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -64,14 +75,15 @@ void VPieceCarrouselPiece::Init()
setStyleSheet("background-color:white; border: 2px solid transparent;"); setStyleSheet("background-color:white; border: 2px solid transparent;");
// define the preview of the piece // define the preview of the piece
m_graphicsView = new QGraphicsView(this); m_piecePreview = new VPieceCarrouselPiecePreview(this);
// m_graphicsView = new VMainGraphicsView(this); // m_graphicsView = new VMainGraphicsView(this);
// --> undefined reference to 'VMainGraphicsView::VMainGraphicView(QWidget*)' // --> undefined reference to 'VMainGraphicsView::VMainGraphicView(QWidget*)'
QGraphicsScene *graphicsScene = new QGraphicsScene(this); QGraphicsScene *graphicsScene = new QGraphicsScene(this);
m_graphicsView->setScene(graphicsScene); m_piecePreview->setScene(graphicsScene);
m_graphicsView->setFixedSize(120,100); m_piecePreview->setFixedSize(120,100);
m_graphicsView->setStyleSheet("border: 4px solid transparent;"); m_piecePreview->setStyleSheet("border: 4px solid transparent;");
m_piecePreview->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
// define the label // define the label
m_label = new QLabel(); m_label = new QLabel();
@ -79,10 +91,15 @@ void VPieceCarrouselPiece::Init()
m_label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); m_label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
m_label->setFixedSize(120,24); m_label->setFixedSize(120,24);
m_label->setStyleSheet("border: 0px;"); m_label->setStyleSheet("border: 0px;");
m_label->setMouseTracking(false);
pieceLayout->addWidget(m_graphicsView); pieceLayout->addWidget(m_piecePreview);
pieceLayout->addWidget(m_label); pieceLayout->addWidget(m_label);
// connect the signals
connect(m_piece, &VPuzzlePiece::SelectionChanged, this, &VPieceCarrouselPiece::on_PieceSelectionChanged);
// then refresh the data // then refresh the data
Refresh(); Refresh();
} }
@ -90,7 +107,7 @@ void VPieceCarrouselPiece::Init()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselPiece::CleanPreview() void VPieceCarrouselPiece::CleanPreview()
{ {
m_graphicsView->fitInView(m_graphicsView->scene()->sceneRect(), Qt::KeepAspectRatio); m_piecePreview->fitInView(m_piecePreview->scene()->sceneRect(), Qt::KeepAspectRatio);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -98,9 +115,11 @@ void VPieceCarrouselPiece::Refresh()
{ {
// update the graphic view / the scene // update the graphic view / the scene
// TODO / FIXME : not perfect and maybe not the right way, still need to work on this QVector<QPointF> points = m_piece->GetSeamLine();
// for instance: use a painter to habve a better quality, less pixeled. if(points.isEmpty())
QVector<QPointF> points = m_piece->GetCuttingLine(); {
points = m_piece->GetCuttingLine();
}
QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pen.setCosmetic(true); pen.setCosmetic(true);
@ -110,9 +129,9 @@ void VPieceCarrouselPiece::Refresh()
path.moveTo(points.first()); path.moveTo(points.first());
for (int i = 1; i < points.size(); ++i) for (int i = 1; i < points.size(); ++i)
path.lineTo(points.at(i)); path.lineTo(points.at(i));
m_graphicsView->scene()->addPath(path, pen, noBrush); m_piecePreview->scene()->addPath(path, pen, noBrush);
m_graphicsView->fitInView(m_graphicsView->scene()->sceneRect(), Qt::KeepAspectRatio); m_piecePreview->fitInView(m_piecePreview->scene()->sceneRect(), Qt::KeepAspectRatio);
// update the label of the piece // update the label of the piece
QFontMetrics metrix(m_label->font()); QFontMetrics metrix(m_label->font());
@ -122,6 +141,9 @@ void VPieceCarrouselPiece::Refresh()
// set the tooltip // set the tooltip
setToolTip(m_piece->GetName()); setToolTip(m_piece->GetName());
// set the selection state correctly.
on_PieceSelectionChanged();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -131,11 +153,9 @@ VPuzzlePiece * VPieceCarrouselPiece::GetPiece()
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselPiece::SetIsSelected(bool value) void VPieceCarrouselPiece::on_PieceSelectionChanged()
{ {
m_isSelected = value; if(m_piece->GetIsSelected())
if(value)
{ {
setStyleSheet("background-color:white; border: 2px solid red;"); setStyleSheet("background-color:white; border: 2px solid red;");
} }
@ -146,20 +166,120 @@ void VPieceCarrouselPiece::SetIsSelected(bool value)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VPieceCarrouselPiece::GetIsSelected() void VPieceCarrouselPiece::mousePressEvent(QMouseEvent *event)
{ {
return m_isSelected; qCDebug(pCarrouselPiece, "mouse pressed");
if (event->button() == Qt::LeftButton)
{
if(!(event->modifiers() & Qt::ControlModifier))
{
m_carrouselLayer->GetCarrousel()->ClearSelection();
m_piece->SetIsSelected(true);
}
else
{
m_piece->SetIsSelected(!m_piece->GetIsSelected());
}
m_dragStart = event->pos();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselPiece::mouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton))
{
return;
}
if(m_piece->GetLayer() != m_piece->GetLayer()->GetLayout()->GetUnplacedPiecesLayer())
{
return;
}
if((event->pos() - m_dragStart).manhattanLength() < QApplication::startDragDistance())
{
return;
}
// make sure the multiple selection is removed
m_carrouselLayer->GetCarrousel()->ClearSelection();
m_piece->SetIsSelected(true);
// starts the dragging
QDrag *drag = new QDrag(this);
VPuzzleMimeDataPiece *mimeData = new VPuzzleMimeDataPiece();
mimeData->SetPiecePtr(m_piece);
mimeData->setObjectName("piecePointer");
// in case we would want to have the pieces original size:
//drag->setHotSpot(QPoint(0,0));
//QPixmap pixmap(m_piecePreview->sceneRect().size().toSize());
QPixmap pixmap(112,92);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
m_piecePreview->scene()->render(&painter);
drag->setPixmap(pixmap);
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::mousePressEvent(QMouseEvent *event) void VPieceCarrouselPiece::on_ActionPieceMovedToLayer()
{ {
if (event->button() == Qt::LeftButton) QAction *act = qobject_cast<QAction *>(sender());
QVariant v = act->data();
VPuzzleLayer *layer = (VPuzzleLayer *) v.value<VPuzzleLayer *>();
if(layer != nullptr)
{ {
if(!m_isSelected) layer->GetLayout()->MovePieceToLayer(m_piece, layer);
{
emit clicked(this);
} }
} }
}

View File

@ -34,13 +34,16 @@
#include <QMouseEvent> #include <QMouseEvent>
#include "vpuzzlepiece.h" #include "vpuzzlepiece.h"
#include "vpiececarrouselpiecepreview.h"
class VPieceCarrouselLayer;
class VPieceCarrouselPiece : public QFrame class VPieceCarrouselPiece : public QFrame
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit VPieceCarrouselPiece(VPuzzlePiece *piece, QWidget *parent = nullptr); explicit VPieceCarrouselPiece(VPuzzlePiece *piece, VPieceCarrouselLayer *carrouselLayer);
~VPieceCarrouselPiece(); ~VPieceCarrouselPiece();
void Init(); void Init();
@ -57,34 +60,34 @@ public:
*/ */
VPuzzlePiece * GetPiece(); VPuzzlePiece * GetPiece();
/**
* @brief SetSelected sets the selected state to the given value
* @param value the new selected state
*/
void SetIsSelected(bool value);
/**
* @brief GetSelected Returns wether the piece is selected or not
* @return true if the piece is selected
*/
bool GetIsSelected();
signals:
void clicked(VPieceCarrouselPiece* m_piece);
public slots: public slots:
void on_PieceSelectionChanged();
protected: protected:
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override;
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: private:
Q_DISABLE_COPY(VPieceCarrouselPiece) Q_DISABLE_COPY(VPieceCarrouselPiece)
VPuzzlePiece *m_piece; VPuzzlePiece *m_piece;
QLabel *m_label{nullptr};
QGraphicsView *m_graphicsView{nullptr};
bool m_isSelected = false; VPieceCarrouselLayer *m_carrouselLayer;
QLabel *m_label{nullptr};
VPieceCarrouselPiecePreview *m_piecePreview{nullptr};
QPoint m_dragStart;
private slots: private slots:

View File

@ -0,0 +1,55 @@
/************************************************************************
**
** @file vpiececarrouselpiecepreview.cpp
** @author Ronan Le Tiec
** @date 3 5, 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 "vpiececarrouselpiecepreview.h"
#include <QMouseEvent>
//---------------------------------------------------------------------------------------------------------------------
VPieceCarrouselPiecePreview::VPieceCarrouselPiecePreview(QWidget *parent):
QGraphicsView(parent)
{
}
//---------------------------------------------------------------------------------------------------------------------
VPieceCarrouselPiecePreview::~VPieceCarrouselPiecePreview()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselPiecePreview::mousePressEvent(QMouseEvent *event)
{
event->ignore();
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceCarrouselPiecePreview::mouseMoveEvent(QMouseEvent *event)
{
event->ignore();
}

View File

@ -0,0 +1,45 @@
/************************************************************************
**
** @file vpiececarrouselpiecepreview.h
** @author Ronan Le Tiec
** @date 3 5, 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 VPUZZLEPIECECARROUSELPIECEPREVIEW_H
#define VPUZZLEPIECECARROUSELPIECEPREVIEW_H
#include <QGraphicsView>
class VPieceCarrouselPiecePreview: public QGraphicsView
{
public:
VPieceCarrouselPiecePreview(QWidget *parent = nullptr);
~VPieceCarrouselPiecePreview();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
};
#endif // VPUZZLEPIECECARROUSELPIECEPREVIEW_H

View File

@ -0,0 +1,92 @@
/************************************************************************
**
** @file vpuzzlegraphicslayout.cpp
** @author Ronan Le Tiec
** @date 3 5, 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 "vpuzzlegraphicslayout.h"
//---------------------------------------------------------------------------------------------------------------------
VPuzzleGraphicsLayout::VPuzzleGraphicsLayout(VPuzzleLayout *layout, QGraphicsItem *parent):
QGraphicsItem(parent),
m_layout(layout),
m_boundingRect(GetLayoutRect())
{
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleGraphicsLayout::~VPuzzleGraphicsLayout()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsLayout::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
QPen pen(QColor(0,179,255), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pen.setCosmetic(true);
QBrush noBrush(Qt::NoBrush);
painter->setPen(pen);
painter->setBrush(noBrush);
painter->drawRect(GetMarginsRect());
pen.setColor(Qt::black);
painter->setPen(pen);
painter->drawRect(GetLayoutRect());
m_boundingRect = GetLayoutRect();
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPuzzleGraphicsLayout::GetLayoutRect() const
{
QRectF rect = QRectF(QPointF(0,0), m_layout->GetLayoutSize());
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPuzzleGraphicsLayout::GetMarginsRect() const
{
QMarginsF margins = m_layout->GetLayoutMargins();
QSizeF size = m_layout->GetLayoutSize();
QRectF rect = QRectF(
QPointF(margins.left(),margins.top()),
QPointF(size.width()-margins.right(), size.height()-margins.bottom())
);
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPuzzleGraphicsLayout::boundingRect() const
{
return m_boundingRect;
}

View File

@ -0,0 +1,58 @@
/************************************************************************
**
** @file vpuzzlegraphicslayout.h
** @author Ronan Le Tiec
** @date 3 5, 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 VPUZZLEGRAPHICSLAYOUT_H
#define VPUZZLEGRAPHICSLAYOUT_H
#include <QGraphicsItem>
#include <QPainter>
#include "vpuzzlelayout.h"
class VPuzzleGraphicsLayout : public QGraphicsItem
{
public:
VPuzzleGraphicsLayout(VPuzzleLayout *layout, QGraphicsItem *parent = nullptr);
~VPuzzleGraphicsLayout();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
QRectF GetLayoutRect() const;
QRectF GetMarginsRect() const;
private:
Q_DISABLE_COPY(VPuzzleGraphicsLayout)
VPuzzleLayout *m_layout{nullptr};
QRectF m_boundingRect;
};
#endif // VPUZZLEGRAPHICSLAYOUT_H

View File

@ -0,0 +1,376 @@
/************************************************************************
**
** @file vpuzzlegraphicspiece.cpp
** @author Ronan Le Tiec
** @date 4 5, 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 "vpuzzlegraphicspiece.h"
#include <QPen>
#include <QBrush>
#include <QPainter>
#include <QCursor>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneContextMenuEvent>
#include <QMenu>
#include <QtMath>
#include <QGraphicsScene>
#include "vpuzzlepiece.h"
#include "vpuzzlelayer.h"
#include "vpuzzlelayout.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
//---------------------------------------------------------------------------------------------------------------------
VPuzzleGraphicsPiece::VPuzzleGraphicsPiece(VPuzzlePiece *piece, QGraphicsItem *parent) :
QGraphicsObject(parent),
m_piece(piece),
m_cuttingLine(QPainterPath()),
m_seamLine(QPainterPath()),
m_grainline(QPainterPath()),
m_rotationStartPoint(QPointF())
{
Init();
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleGraphicsPiece::~VPuzzleGraphicsPiece()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::Init()
{
// set some infos
setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
setAcceptHoverEvents(true);
setCursor(QCursor(Qt::OpenHandCursor));
// initialises the seam line
QVector<QPointF> seamLinePoints = m_piece->GetSeamLine();
m_seamLine.moveTo(seamLinePoints.first());
for (int i = 1; i < seamLinePoints.size(); ++i)
m_seamLine.lineTo(seamLinePoints.at(i));
// initiliases the cutting line
QVector<QPointF> cuttingLinepoints = m_piece->GetCuttingLine();
m_cuttingLine.moveTo(cuttingLinepoints.first());
for (int i = 1; i < cuttingLinepoints.size(); ++i)
m_cuttingLine.lineTo(cuttingLinepoints.at(i));
// initialises the grainline
QVector<QPointF> grainLinepoints = m_piece->GetGrainline();
m_grainline.moveTo(grainLinepoints.first());
for (int i = 1; i < grainLinepoints.size(); ++i)
m_grainline.lineTo(grainLinepoints.at(i));
// TODO : initialises the other elements labels, passmarks etc.
// Initialises the connectors
connect(m_piece, &VPuzzlePiece::SelectionChanged, this, &VPuzzleGraphicsPiece::on_PieceSelectionChanged);
connect(m_piece, &VPuzzlePiece::PositionChanged, this, &VPuzzleGraphicsPiece::on_PiecePositionChanged);
connect(m_piece, &VPuzzlePiece::RotationChanged, this, &VPuzzleGraphicsPiece::on_PieceRotationChanged);
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzlePiece* VPuzzleGraphicsPiece::GetPiece()
{
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPuzzleGraphicsPiece::boundingRect() const
{
if(!m_cuttingLine.isEmpty())
{
return m_cuttingLine.boundingRect();
}
return m_seamLine.boundingRect();
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPuzzleGraphicsPiece::shape() const
{
if(!m_cuttingLine.isEmpty())
{
return m_cuttingLine;
}
return m_seamLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
QBrush noBrush(Qt::NoBrush);
QBrush selectionBrush(QColor(255,160,160,60));
painter->setPen(pen);
if(isSelected())
{
painter->setBrush(selectionBrush);
}
else
{
painter->setBrush(noBrush);
}
// paint the cutting line
if(!m_cuttingLine.isEmpty())
{
painter->drawPath(m_cuttingLine);
painter->setBrush(noBrush);
}
// paint the seam line
if(!m_seamLine.isEmpty())
{
painter->drawPath(m_seamLine);
}
painter->setBrush(noBrush);
// paint the grainline
if(!m_grainline.isEmpty())
{
painter->drawPath(m_grainline);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
bool selectionState = isSelected();
//perform the default behaviour
QGraphicsItem::mousePressEvent(event);
// change the cursor when clicking left button
if (event->button() == Qt::LeftButton)
{
setSelected(true);
setCursor(Qt::ClosedHandCursor);
if (event->modifiers() & Qt::ControlModifier)
{
setSelected(!selectionState);
}
else
{
setSelected(true);
}
}
if((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
{
m_rotationStartPoint = event->scenePos();
QPixmap cursor_pixmap = QPixmap(":/cursor_rotate");
cursor_pixmap = cursor_pixmap.scaledToWidth(32);
QCursor cursor_rotate = QCursor(cursor_pixmap, 16, 16);
setCursor(cursor_rotate);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
if((event->buttons() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
{
QPointF rotationNewPoint = event->scenePos();
QPointF rotationCenter = sceneBoundingRect().center();
// get the angle from the center to the initial click point
qreal init_x = m_rotationStartPoint.x() - rotationCenter.x();
qreal init_y = m_rotationStartPoint.y() - rotationCenter.y();
qreal initial_angle = qAtan2(init_y, init_x);
qreal x = rotationNewPoint.x() - rotationCenter.x();
qreal y = rotationNewPoint.y() - rotationCenter.y();
qreal mv_angle = qAtan2(y,x);
qreal angle = (initial_angle-mv_angle)*180/M_PI;
setTransformOriginPoint(boundingRect().center());
setRotation(-(angle+m_piece->GetRotation()));
event->accept();
}
else
{
QGraphicsItem::mouseMoveEvent(event);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
bool selectionState = isSelected();
//perform the default behaviour
QGraphicsItem::mouseReleaseEvent(event);
// change the cursor when clicking left button
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::OpenHandCursor);
setSelected(selectionState);
if(m_piece->GetPosition() != pos())
{
m_piece->SetPosition(pos());
}
}
if((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
{
m_piece->SetRotation(-rotation());
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if(event->modifiers() & Qt::AltModifier)
{
// TODO FIXME: find a more efficient way
QPixmap cursor_pixmap = QPixmap(":/cursor_rotate");
cursor_pixmap = cursor_pixmap.scaledToWidth(32);
QCursor cursor_rotate = QCursor(cursor_pixmap, 16, 16);
setCursor(cursor_rotate);
}
else
{
setCursor(QCursor(Qt::OpenHandCursor));
}
}
//---------------------------------------------------------------------------------------------------------------------
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 = v.value<VPuzzleLayer *>();
if(layer != nullptr)
{
layer->GetLayout()->MovePieceToLayer(m_piece, layer);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::on_PieceSelectionChanged()
{
setSelected(m_piece->GetIsSelected());
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::on_PiecePositionChanged()
{
setPos(m_piece->GetPosition());
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleGraphicsPiece::on_PieceRotationChanged()
{
setTransformOriginPoint(boundingRect().center());
setRotation(-m_piece->GetRotation());
}
//---------------------------------------------------------------------------------------------------------------------
QVariant VPuzzleGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (scene()) {
// we do this in the mouseRelease button to avoid updated this property all the time.
// if(change == ItemPositionHasChanged)
// {
// blockSignals(true);
// m_piece->SetPosition(pos());
// blockSignals(false);
// }
if(change == ItemSelectedHasChanged)
{
if(m_piece->GetIsSelected() != isSelected())
{
m_piece->SetIsSelected(isSelected());
}
}
}
return QGraphicsObject::itemChange(change, value);
}

View File

@ -0,0 +1,100 @@
/************************************************************************
**
** @file vpuzzlegraphicspiece.h
** @author Ronan Le Tiec
** @date 4 5, 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 VPUZZLEGRAPHICSPIECE_H
#define VPUZZLEGRAPHICSPIECE_H
#include <QGraphicsItem>
class VPuzzlePiece;
class VPuzzleGraphicsPiece : public QGraphicsObject
{
Q_OBJECT
public:
VPuzzleGraphicsPiece(VPuzzlePiece *piece, QGraphicsItem *parent = nullptr);
~VPuzzleGraphicsPiece();
void Init();
/**
* @brief GetPiece Returns the piece that corresponds to the graphics piece
* @return the piece
*/
VPuzzlePiece* GetPiece();
public slots:
/**
* @brief on_PieceSelectionChanged Slot called when the piece selection was changed
*/
void on_PieceSelectionChanged();
/**
* @brief on_PiecePositionChanged Slot called when the piece position was changed
*/
void on_PiecePositionChanged();
/**
* @brief on_PieceRotationChanged Slot called when the piece rotation was changed
*/
void on_PieceRotationChanged();
protected:
QRectF boundingRect() const override;
QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
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;
QPainterPath m_cuttingLine;
QPainterPath m_seamLine;
QPainterPath m_grainline;
QPointF m_rotationStartPoint;
};
#endif // VPUZZLEGRAPHICSPIECE_H

View File

@ -27,8 +27,15 @@
*************************************************************************/ *************************************************************************/
#include "vpuzzlelayer.h" #include "vpuzzlelayer.h"
#include "vpuzzlelayout.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pLayer, "p.layer")
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPuzzleLayer::VPuzzleLayer() VPuzzleLayer::VPuzzleLayer(VPuzzleLayout *layout):
m_layout(layout)
{ {
} }
@ -39,22 +46,46 @@ VPuzzleLayer::~VPuzzleLayer()
} }
//---------------------------------------------------------------------------------------------------------------------
VPuzzleLayout* VPuzzleLayer::GetLayout()
{
return m_layout;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QList<VPuzzlePiece *> VPuzzleLayer::GetPieces() QList<VPuzzlePiece *> VPuzzleLayer::GetPieces()
{ {
return m_pieces; return m_pieces;
} }
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayer::ClearSelection()
{
for (auto piece: m_pieces)
{
piece->SetIsSelected(false);
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayer::AddPiece(VPuzzlePiece *piece) void VPuzzleLayer::AddPiece(VPuzzlePiece *piece)
{ {
qCDebug(pLayer(), "piece -- %s -- added to %s", qUtf8Printable(piece->GetName()), qUtf8Printable(this->GetName()));
m_pieces.append(piece); m_pieces.append(piece);
piece->SetLayer(this);
emit PieceAdded(piece);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayer::RemovePiece(VPuzzlePiece *piece) void VPuzzleLayer::RemovePiece(VPuzzlePiece *piece)
{ {
m_pieces.removeAll(piece); m_pieces.removeAll(piece);
piece->SetLayer(nullptr);
emit PieceRemoved(piece);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -31,10 +31,13 @@
#include <QList> #include <QList>
#include "vpuzzlepiece.h" #include "vpuzzlepiece.h"
class VPuzzleLayer class VPuzzleLayout;
class VPuzzleLayer : public QObject
{ {
Q_OBJECT
public: public:
VPuzzleLayer(); VPuzzleLayer(VPuzzleLayout *layout);
~VPuzzleLayer(); ~VPuzzleLayer();
QList<VPuzzlePiece *> GetPieces(); QList<VPuzzlePiece *> GetPieces();
@ -50,10 +53,36 @@ public:
void SetIsVisible(bool value); void SetIsVisible(bool value);
bool GetIsVisible() const; bool GetIsVisible() const;
/**
* @brief GetLayout Returns the layout in which this layer is
* @return the layout of this layer
*/
VPuzzleLayout* GetLayout();
/**
* @brief ClearSelection Clears the selection of the pieces in this layer
*/
void ClearSelection();
signals:
/**
* @brief PieceAdded The signal is emited when a piece was added
*/
void PieceAdded(VPuzzlePiece *piece);
/**
* @brief PieceRemoved The signal is emited when a piece was removed
*/
void PieceRemoved(VPuzzlePiece *piece);
private: private:
Q_DISABLE_COPY(VPuzzleLayer)
QString m_name{}; QString m_name{};
QList<VPuzzlePiece *> m_pieces{}; QList<VPuzzlePiece *> m_pieces{};
VPuzzleLayout *m_layout{nullptr};
// control // control
bool m_isVisible{true}; bool m_isVisible{true};

View File

@ -31,14 +31,17 @@
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPuzzleLayout::VPuzzleLayout() : VPuzzleLayout::VPuzzleLayout() :
m_unplacedPiecesLayer(new VPuzzleLayer()) m_unplacedPiecesLayer(new VPuzzleLayer(this))
{ {
m_unplacedPiecesLayer->SetName(QObject::tr("Unplaced pieces")); m_unplacedPiecesLayer->SetName(QObject::tr("Unplaced pieces"));
// create a standard default layer: // create a standard default layer:
VPuzzleLayer *layer = new VPuzzleLayer(); VPuzzleLayer *layer = new VPuzzleLayer(this);
layer->SetName(QObject::tr("Layout")); layer->SetName(QObject::tr("Layout"));
AddLayer(layer); AddLayer(layer);
// sets the default active layer
SetFocusedLayer();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -57,7 +60,7 @@ VPuzzleLayer* VPuzzleLayout::GetUnplacedPiecesLayer()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPuzzleLayer* VPuzzleLayout::AddLayer() VPuzzleLayer* VPuzzleLayout::AddLayer()
{ {
VPuzzleLayer *newLayer = new VPuzzleLayer(); VPuzzleLayer *newLayer = new VPuzzleLayer(this);
m_layers.append(newLayer); m_layers.append(newLayer);
return newLayer; return newLayer;
} }
@ -75,6 +78,29 @@ QList<VPuzzleLayer *> VPuzzleLayout::GetLayers()
return m_layers; return m_layers;
} }
//---------------------------------------------------------------------------------------------------------------------
QList<VPuzzlePiece *> VPuzzleLayout::GetSelectedPieces()
{
QList<VPuzzlePiece *> result = QList<VPuzzlePiece *>();
QList<VPuzzleLayer *> layers = m_layers;
layers.prepend(m_unplacedPiecesLayer);
for (auto layer : layers)
{
for (auto piece : layer->GetPieces())
{
if(piece->GetIsSelected())
{
result.append(piece);
}
}
}
return result;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayout::SetUnit(Unit unit) void VPuzzleLayout::SetUnit(Unit unit)
{ {
@ -245,3 +271,48 @@ bool VPuzzleLayout::GetStickyEdges() const
{ {
return m_stickyEdges; return m_stickyEdges;
} }
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayout::ClearSelection()
{
m_unplacedPiecesLayer->ClearSelection();
for (auto layer : m_layers)
{
layer->ClearSelection();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayout::SetFocusedLayer(VPuzzleLayer* focusedLayer)
{
if(focusedLayer == nullptr)
{
m_focusedLayer = m_layers.first();
}
else
{
m_focusedLayer = focusedLayer;
}
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleLayer* VPuzzleLayout::GetFocusedLayer()
{
return m_focusedLayer;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayout::MovePieceToLayer(VPuzzlePiece* piece, VPuzzleLayer* layer)
{
VPuzzleLayer* layerBefore = piece->GetLayer();
if(layerBefore != nullptr)
{
piece->GetLayer()->RemovePiece(piece);
}
layer->AddPiece(piece);
// signal, that a piece was moved
emit PieceMovedToLayer(piece, layerBefore,layer);
}

View File

@ -35,12 +35,14 @@
#include "def.h" #include "def.h"
class VPuzzleLayer; class VPuzzleLayer;
class VPuzzlePiece;
// is this the right place for the definition? // is this the right place for the definition?
enum class FollowGrainline : qint8 { No = 0, Follow90 = 1, Follow180 = 2}; enum class FollowGrainline : qint8 { No = 0, Follow90 = 1, Follow180 = 2};
class VPuzzleLayout class VPuzzleLayout : public QObject
{ {
Q_OBJECT
public: public:
VPuzzleLayout(); VPuzzleLayout();
virtual ~VPuzzleLayout(); virtual ~VPuzzleLayout();
@ -51,7 +53,22 @@ public:
VPuzzleLayer* AddLayer(VPuzzleLayer *layer); VPuzzleLayer* AddLayer(VPuzzleLayer *layer);
QList<VPuzzleLayer *> GetLayers(); QList<VPuzzleLayer *> GetLayers();
/**
* @brief GetSelectedPieces Returns the list of the selected pieces
* @return the selected pieces
*/
QList<VPuzzlePiece *> GetSelectedPieces();
/**
* @brief SetUnit Sets the unit of the layout to the given unit
* @param unit the new unit
*/
void SetUnit(Unit unit); void SetUnit(Unit unit);
/**
* @brief GetUnit Returns the current unit of the layout
* @return the unit
*/
Unit GetUnit() const; Unit GetUnit() const;
/** /**
@ -133,7 +150,16 @@ public:
*/ */
QMarginsF GetLayoutMarginsConverted() const; QMarginsF GetLayoutMarginsConverted() const;
/**
* @brief SetFollowGrainline Sets the type of grainline for the pieces to follow
* @param state the type of grainline
*/
void SetFollowGrainline(FollowGrainline state); void SetFollowGrainline(FollowGrainline state);
/**
* @brief GetFollowGrainline Returns if the layout's pieces follow a grainline or not
* @return wether the pieces follow a grainline and if so, which grainline
*/
FollowGrainline GetFollowGrainline() const; FollowGrainline GetFollowGrainline() const;
/** /**
@ -169,11 +195,49 @@ public:
void SetStickyEdges(bool state); void SetStickyEdges(bool state);
bool GetStickyEdges() const; bool GetStickyEdges() const;
/**
* @brief ClearSelection goes through the layers & pieces and calls
* SetIsSelected(false) for the pieces that were selected.
*/
void ClearSelection();
/**
* @brief SetFocusedLayer Sets the focused layer, to which pieces are added from the carrousel via drag
* and drop
* @param focusedLayer the new active layer. If nullptr, then it sets automaticaly the first layer from m_layers
*/
void SetFocusedLayer(VPuzzleLayer* focusedLayer = nullptr);
/**
* @brief GetFocusedLayer Returns the focused layer, to which pieces are added from the carrousel via drag
* and drop
* @return the focused layer
*/
VPuzzleLayer* GetFocusedLayer();
/**
* @brief MovePieceToLayer Moves the given piece to the given layer
* @param piece the piece to move
* @param layer the layer to move the piece to
*/
void MovePieceToLayer(VPuzzlePiece* piece, VPuzzleLayer* layer);
signals:
void PieceMovedToLayer(VPuzzlePiece *piece, VPuzzleLayer *layerBefore, VPuzzleLayer *layerAfter);
private: private:
Q_DISABLE_COPY(VPuzzleLayout) Q_DISABLE_COPY(VPuzzleLayout)
VPuzzleLayer *m_unplacedPiecesLayer; VPuzzleLayer *m_unplacedPiecesLayer;
QList<VPuzzleLayer *> m_layers{}; QList<VPuzzleLayer *> m_layers{};
/**
* @brief m_focusedLayer pointer the the focused layer, to which pieces will be
* added via drag and drop, or if no layer is defined.
*/
VPuzzleLayer *m_focusedLayer{nullptr};
// format // format
Unit m_unit{Unit::Cm}; Unit m_unit{Unit::Cm};
/** /**

View File

@ -0,0 +1,35 @@
/************************************************************************
**
** @file vpuzzlemaingraphicsscene.cpp
** @author Ronan Le Tiec
** @date 3 5, 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 "vpuzzlemaingraphicsscene.h"
//---------------------------------------------------------------------------------------------------------------------
VPuzzleMainGraphicsScene::VPuzzleMainGraphicsScene(QObject *parent): QGraphicsScene(parent)
{
}

View File

@ -0,0 +1,44 @@
/************************************************************************
**
** @file vpuzzlemaingraphicsscene.cpp
** @author Ronan Le Tiec
** @date 3 5, 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 VPUZZLEMAINGRAPHICSSCENE_H
#define VPUZZLEMAINGRAPHICSSCENE_H
#include <QGraphicsScene>
// TODO: When ready, extend from QGraphicsScene instead
class VPuzzleMainGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
VPuzzleMainGraphicsScene(QObject *parent = nullptr);
};
#endif // VPUZZLEMAINGRAPHICSSCENE_H

View File

@ -0,0 +1,205 @@
/************************************************************************
**
** @file vpuzzlemaingraphicsview.cpp
** @author Ronan Le Tiec
** @date 3 5, 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 "vpuzzlemaingraphicsview.h"
#include <QDragEnterEvent>
#include <QMimeData>
#include <QKeyEvent>
#include "vpuzzlemimedatapiece.h"
#include "vpuzzlelayer.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pMainGraphicsView, "p.mainGraphicsView")
//---------------------------------------------------------------------------------------------------------------------
VPuzzleMainGraphicsView::VPuzzleMainGraphicsView(VPuzzleLayout *layout, QWidget *parent) :
QGraphicsView(parent),
m_layout(layout),
m_graphicsPieces(QList<VPuzzleGraphicsPiece*>())
{
m_scene = new VPuzzleMainGraphicsScene(this);
setScene(m_scene);
m_graphicsLayout = new VPuzzleGraphicsLayout(layout);
m_graphicsLayout->setPos(0,0);
m_scene->addItem(m_graphicsLayout);
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
setAcceptDrops(true);
// add the connections
connect(m_layout, &VPuzzleLayout::PieceMovedToLayer, this, &VPuzzleMainGraphicsView::on_PieceMovedToLayer);
connect(m_scene, &VPuzzleMainGraphicsScene::selectionChanged, this, &VPuzzleMainGraphicsView::on_SceneSelectionChanged);
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleMainGraphicsView::~VPuzzleMainGraphicsView()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::RefreshLayout()
{
// FIXME: Is that the way to go?
m_graphicsLayout->update();
m_scene->update();
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::dragEnterEvent(QDragEnterEvent *event)
{
const QMimeData *mime = event->mimeData();
if(mime->objectName() == "piecePointer")
{
qCDebug(pMainGraphicsView(), "drag enter");
event->acceptProposedAction();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::dragMoveEvent(QDragMoveEvent *event)
{
const QMimeData *mime = event->mimeData();
if(mime->objectName() == "piecePointer")
{
event->acceptProposedAction();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::dragLeaveEvent(QDragLeaveEvent *event)
{
event->accept();
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::dropEvent(QDropEvent *event)
{
const QMimeData *mime = event->mimeData();
qCDebug(pMainGraphicsView(), "drop enter , %s", qUtf8Printable(mime->objectName()));
if(mime->objectName() == "piecePointer")
{
const VPuzzleMimeDataPiece *mimePiece = qobject_cast<const VPuzzleMimeDataPiece *> (mime);
VPuzzlePiece *piece = mimePiece->GetPiecePtr();
if(piece != nullptr)
{
qCDebug(pMainGraphicsView(), "element dropped, %s", qUtf8Printable(piece->GetName()));
event->acceptProposedAction();
QPoint point = event->pos();
piece->SetPosition(mapToScene(point));
// change the layer of the piece
VPuzzleLayer *focusedLayer = m_layout->GetFocusedLayer();
if(focusedLayer != nullptr)
{
m_layout->MovePieceToLayer(piece, focusedLayer);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete)
{
QList<VPuzzleGraphicsPiece*> tmpGraphicsPieces = m_graphicsPieces;
for(auto graphicsPiece : tmpGraphicsPieces)
{
VPuzzlePiece *piece = graphicsPiece->GetPiece();
if(piece->GetIsSelected())
{
piece->SetIsSelected(false);
m_layout->MovePieceToLayer(piece, m_layout->GetUnplacedPiecesLayer());
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::on_PieceMovedToLayer(VPuzzlePiece *piece, VPuzzleLayer *layerBefore, VPuzzleLayer *layerAfter)
{
Q_UNUSED(layerBefore)
VPuzzleGraphicsPiece *_graphicsPiece = nullptr;
for(auto graphicPiece : m_graphicsPieces)
{
if(graphicPiece->GetPiece() == piece)
{
_graphicsPiece = graphicPiece;
}
}
if(layerAfter == m_layout->GetUnplacedPiecesLayer() && _graphicsPiece != nullptr)
{
scene()->removeItem(_graphicsPiece);
m_graphicsPieces.removeAll(_graphicsPiece);
}
else if(layerAfter != m_layout->GetUnplacedPiecesLayer())
{
if(_graphicsPiece == nullptr)
{
_graphicsPiece = new VPuzzleGraphicsPiece(piece);
m_graphicsPieces.append(_graphicsPiece);
}
scene()->addItem(_graphicsPiece);
// not very clean to directly call slots
_graphicsPiece->on_PieceSelectionChanged();
_graphicsPiece->on_PiecePositionChanged();
_graphicsPiece->on_PieceRotationChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMainGraphicsView::on_SceneSelectionChanged()
{
// most of the selection behaviour taks place automatically
// but we need to make sure that the unplaced pieces are unselected when the scene selection has changed
// because as they are not part of the scene, they are not updated
m_layout->GetUnplacedPiecesLayer()->ClearSelection();
}

View File

@ -0,0 +1,87 @@
/************************************************************************
**
** @file vpuzzlemaingraphicsview.h
** @author Ronan Le Tiec
** @date 3 5, 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 VPUZZLEMAINGRAPHICSVIEW_H
#define VPUZZLEMAINGRAPHICSVIEW_H
#include <QGraphicsView>
#include "vpuzzlegraphicslayout.h"
#include "vpuzzlemaingraphicsscene.h"
#include "vpuzzlegraphicspiece.h"
// TODO: when ready, extend the VMainGrapchisView instead
class VPuzzleMainGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
VPuzzleMainGraphicsView(VPuzzleLayout *layout, QWidget *parent);
~VPuzzleMainGraphicsView();
/**
* @brief RefreshLayout Refreshes the rectangles for the layout border and the margin
*/
void RefreshLayout();
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dragLeaveEvent(QDragLeaveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private slots:
/**
* @brief on_PieceMovedToLayer The slot is called when the given piece was moved from the given layer to the other given layer
* @param piece the piece that was moved
* @param layerBefore the layer before the move
* @param layerAfter the layer after the move
*/
void on_PieceMovedToLayer(VPuzzlePiece *piece, VPuzzleLayer *layerBefore, VPuzzleLayer *layerAfter);
/**
* @brief on_SceneSelectionChanged Slot is called when the scene selection has changed
*/
void on_SceneSelectionChanged();
private:
Q_DISABLE_COPY(VPuzzleMainGraphicsView)
VPuzzleMainGraphicsScene *m_scene{nullptr};
VPuzzleGraphicsLayout *m_graphicsLayout{nullptr};
VPuzzleLayout *m_layout{nullptr};
QList<VPuzzleGraphicsPiece*> m_graphicsPieces;
};
#endif // VPUZZLEMAINGRAPHICVIEW_H

View File

@ -0,0 +1,53 @@
/************************************************************************
**
** @file vpuzzlemimedatapiece.cpp
** @author Ronan Le Tiec
** @date 4 5, 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 "vpuzzlemimedatapiece.h"
//---------------------------------------------------------------------------------------------------------------------
VPuzzleMimeDataPiece::VPuzzleMimeDataPiece()
{
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleMimeDataPiece::~VPuzzleMimeDataPiece()
{
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzlePiece* VPuzzleMimeDataPiece::GetPiecePtr() const
{
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzleMimeDataPiece::SetPiecePtr(VPuzzlePiece* piece)
{
m_piece = piece;
}

View File

@ -0,0 +1,65 @@
/************************************************************************
**
** @file vpuzzlemimedatapiece.h
** @author Ronan Le Tiec
** @date 4 5, 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 VPUZZLEMIMEDATAPIECE_H
#define VPUZZLEMIMEDATAPIECE_H
#include <QMimeData>
#include "vpuzzlepiece.h"
class VPuzzleMimeDataPiece : public QMimeData
{
Q_OBJECT
public:
VPuzzleMimeDataPiece();
~VPuzzleMimeDataPiece();
/**
* @brief GetPiecePtr Returns the piece pointer of the mime data
* @return piece pointer
*/
VPuzzlePiece* GetPiecePtr() const;
/**
* @brief SetPiecePtr sets the piece pointer to the given value
* @param piece the piece pointer
*/
void SetPiecePtr(VPuzzlePiece* piece);
private:
Q_DISABLE_COPY(VPuzzleMimeDataPiece)
VPuzzlePiece *m_piece{nullptr};
};
#endif // VPUZZLEMIMEDATAPIECE_H

View File

@ -27,6 +27,14 @@
*************************************************************************/ *************************************************************************/
#include "vpuzzlepiece.h" #include "vpuzzlepiece.h"
#include <QtMath>
#include "vpuzzlelayer.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pPiece, "p.piece")
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPuzzlePiece::VPuzzlePiece() VPuzzlePiece::VPuzzlePiece()
{ {
@ -79,6 +87,17 @@ void VPuzzlePiece::SetCuttingLine(const QVector<QPointF> &cuttingLine)
m_cuttingLine = cuttingLine; m_cuttingLine = cuttingLine;
} }
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VPuzzlePiece::GetSeamLine() const
{
return m_seamLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetSeamLine(const QVector<QPointF> &seamLine)
{
m_seamLine = seamLine;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VPuzzlePiece::GetShowSeamLine() const bool VPuzzlePiece::GetShowSeamLine() const
@ -90,6 +109,8 @@ bool VPuzzlePiece::GetShowSeamLine() const
void VPuzzlePiece::SetShowSeamLine(bool value) void VPuzzlePiece::SetShowSeamLine(bool value)
{ {
m_showSeamline = value; m_showSeamline = value;
emit PropertiesChanged();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -102,5 +123,133 @@ bool VPuzzlePiece::GetPieceMirrored() const
void VPuzzlePiece::SetPieceMirrored(bool value) void VPuzzlePiece::SetPieceMirrored(bool value)
{ {
m_mirrorPiece = value; m_mirrorPiece = value;
emit PropertiesChanged();
} }
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetPosition(QPointF point)
{
m_transform.translate(point.x() - m_transform.dx(), point.y() - m_transform.dy());
emit PositionChanged();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VPuzzlePiece::GetPosition()
{
return QPointF(m_transform.dx(), m_transform.dy());
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetRotation(qreal angle)
{
// qreal currentAngle = GetRotation();
// qreal newAngle = angle - currentAngle;
// m_transform.rotate(newAngle);
if(m_pieceAngle != angle)
{
m_pieceAngle = angle;
// make sure the angle is [0 <= angle < 360]
while(m_pieceAngle >= 360)
{
m_pieceAngle -= 360;
}
while(m_pieceAngle < 0)
{
m_pieceAngle += 360;
}
emit RotationChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
qreal VPuzzlePiece::GetRotation()
{
return m_pieceAngle;
// We don't use the QTransform vor now because the math behind it to retrieve the angle is not trivial.
// TODO / FIXME: we can use QTransform later for optimization
// QTransform tmpTransform = m_transform;
// tmpTransform.translate(-tmpTransform.dx(), -tmpTransform.dy()); // make sure there is only the rotation in the matrix
// qreal angle = qRadiansToDegrees(qAcos(tmpTransform.m11()));
// qCDebug(pPiece, "new angle : %f", angle);
// return angle;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetIsSelected(bool value)
{
if(m_isSelected != value)
{
m_isSelected = value;
emit SelectionChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
bool VPuzzlePiece::GetIsSelected()
{
return m_isSelected;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetIsGrainlineEnabled(bool value)
{
m_isGrainlineEnabled = value;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPuzzlePiece::GetIsGrainlineEnabled()
{
return m_isGrainlineEnabled;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetGrainlineAngle(qreal value)
{
m_grainlineAngle = value;
}
//---------------------------------------------------------------------------------------------------------------------
qreal VPuzzlePiece::GetGrainlineAngle()
{
return m_grainlineAngle;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetGrainline(QVector<QPointF> grainline)
{
m_grainline = grainline;
}
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VPuzzlePiece::GetGrainline()
{
return m_grainline;
}
//---------------------------------------------------------------------------------------------------------------------
VPuzzleLayer* VPuzzlePiece::GetLayer()
{
return m_layer;
}
//---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetLayer(VPuzzleLayer* layer)
{
if(layer != m_layer)
{
m_layer = layer;
}
}

View File

@ -31,9 +31,13 @@
#include <QUuid> #include <QUuid>
#include <QVector> #include <QVector>
#include <QPoint> #include <QPoint>
#include <QTransform>
class VPuzzlePiece class VPuzzleLayer;
class VPuzzlePiece : public QObject
{ {
Q_OBJECT
public: public:
VPuzzlePiece(); VPuzzlePiece();
~VPuzzlePiece(); ~VPuzzlePiece();
@ -61,10 +65,30 @@ public:
*/ */
void SetUuid(const QUuid &uuid); void SetUuid(const QUuid &uuid);
/**
* @brief GetCuttingLine Returns the vector points of the cutting line
* @return the vector points of the cutting line
*/
QVector<QPointF> GetCuttingLine() const; QVector<QPointF> GetCuttingLine() const;
/**
* @brief SetCuttingLine Sets the vector points of the cutting line to the given value
* @param cuttingLine the new vector points for the cutting line
*/
void SetCuttingLine(const QVector<QPointF> &cuttingLine); void SetCuttingLine(const QVector<QPointF> &cuttingLine);
/**
* @brief GetSeamLine Returns the vector points of the seam line
* @return the vector points of the seam line
*/
QVector<QPointF> GetSeamLine() const;
/**
* @brief SetSeamLine Sets the vector points of the seam line to the given value
* @param seamLine the new vector points for the seam line
*/
void SetSeamLine(const QVector<QPointF> &seamLine);
/** /**
* @brief GetShowSeamLine returns wether the seam line of the piece has to be shown or not * @brief GetShowSeamLine returns wether the seam line of the piece has to be shown or not
* @return true if the seamline has to be shown * @return true if the seamline has to be shown
@ -89,13 +113,136 @@ public:
*/ */
void SetPieceMirrored(bool value); void SetPieceMirrored(bool value);
/**
* @brief SetPosition Sets the position of the piece, in relation to the origin of the scene
* @param point the point where to set the piece
*/
void SetPosition(QPointF point);
/**
* @brief GetPosition Returns the position of the piece
* @return the position of the piece
*/
QPointF GetPosition();
/**
* @brief SetRotation Sets the rotation of the piece to the given angle.
* @param angle the angle of the rotation in degree
*/
void SetRotation(qreal angle);
/**
* @brief GetRotation Returns the angle of rotation
* @return the angle of rotation
*/
qreal GetRotation();
/**
* @brief SetIsGrainlineEnabled Wether the piece has a grainline or not
* @param value true or false
*/
void SetIsGrainlineEnabled(bool value);
/**
* @brief GetIsGrainlineEnabled Returns wether the grainline is enabled for this piece
* @return true if enabled
*/
bool GetIsGrainlineEnabled();
/**
* @brief SetGrainlineAngle Sets the angle of the grainline
* @param value
*/
void SetGrainlineAngle(qreal value);
/**
* @brief GetGrainlineAngle Returns the angle of the grainline for this piece
* @return the angle
*/
qreal GetGrainlineAngle();
/**
* @brief SetGrainline Sets the grainline to the given vector of points
* @param grainline the grainline
*/
void SetGrainline(QVector<QPointF> grainline);
/**
* @brief GetGrainline Returns the grainline for this piece
* @return the vector
*/
QVector<QPointF> GetGrainline();
/**
* @brief SetIsSelected Sets wether the piece is selected
* @param value true if the piece is selected
*/
void SetIsSelected(bool value);
/**
* @brief GetIsSelected Returns wether the piece is selected. It emit the signal SelectionChanged
* @return true if the piece is selected
*/
bool GetIsSelected();
/**
* @brief GetLayer Returns the layer in which the piece is.
* @return layer of the piece
*/
VPuzzleLayer* GetLayer();
/**
* @brief SetLayer Sets the layer of the piece to the given layer
* @param layer
*/
void SetLayer(VPuzzleLayer* layer);
signals:
/**
* @brief SelectionChanged emited when the selection of the piece was
* changed through the SetIsSelected function
*/
void SelectionChanged();
/**
* @brief PositionChanged emited when the position of the piece was
* changed through the SetPosition function
*/
void PositionChanged();
/**
* @brief RotationChanged emited when the position of the piece was
* changed through the function SetRotation
*/
void RotationChanged();
/**
* @brief PropertiesChanged emited when of the properties showSemaline
* or mirrorpiece where changed.
*/
void PropertiesChanged();
private: private:
Q_DISABLE_COPY(VPuzzlePiece)
QUuid m_uuid{QUuid()}; QUuid m_uuid{QUuid()};
QString m_name{QString()}; QString m_name{QString()};
QVector<QPointF> m_cuttingLine{QVector<QPointF>()}; QVector<QPointF> m_cuttingLine{QVector<QPointF>()};
QVector<QPointF> m_seamLine{QVector<QPointF>()};
QVector<QPointF> m_grainline{QVector<QPointF>()};
bool m_isGrainlineEnabled{false};
qreal m_grainlineAngle{0};
QTransform m_transform{QTransform()};
// use a separate value for now because it's not easy to get the angle from the transform matrix
qreal m_pieceAngle{0};
bool m_showSeamline{true}; bool m_showSeamline{true};
bool m_mirrorPiece{false}; bool m_mirrorPiece{false};
bool m_isSelected{false};
VPuzzleLayer *m_layer{nullptr};
}; };
#endif // VPUZZLEPIECE_H #endif // VPUZZLEPIECE_H