diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri index 66396d8cc..40cfdef6f 100644 --- a/src/app/puzzle/puzzle.pri +++ b/src/app/puzzle/puzzle.pri @@ -8,7 +8,12 @@ SOURCES += \ $$PWD/puzzleapplication.cpp \ $$PWD/vpuzzlecommandline.cpp \ $$PWD/dialogs/dialogaboutpuzzle.cpp \ - $$PWD/vpiececarrousel.cpp + $$PWD/vpiececarrousel.cpp \ + $$PWD/vpuzzlelayout.cpp \ + $$PWD/vpuzzlelayer.cpp \ + $$PWD/vpuzzlepiece.cpp \ + $$PWD/xml/vpuzzlelayoutfilewriter.cpp \ + $$PWD/xml/vpuzzlelayoutfilereader.cpp *msvc*:SOURCES += $$PWD/stable.cpp @@ -19,7 +24,12 @@ HEADERS += \ $$PWD/puzzleapplication.h \ $$PWD/vpuzzlecommandline.h \ $$PWD/dialogs/dialogaboutpuzzle.h \ - $$PWD/vpiececarrousel.h + $$PWD/vpiececarrousel.h \ + $$PWD/vpuzzlelayout.h \ + $$PWD/vpuzzlelayer.h \ + $$PWD/vpuzzlepiece.h \ + $$PWD/xml/vpuzzlelayoutfilewriter.h \ + $$PWD/xml/vpuzzlelayoutfilereader.h FORMS += \ $$PWD/puzzlemainwindow.ui \ diff --git a/src/app/puzzle/puzzlemainwindow.cpp b/src/app/puzzle/puzzlemainwindow.cpp index bbf781b5e..ff2ccd065 100644 --- a/src/app/puzzle/puzzlemainwindow.cpp +++ b/src/app/puzzle/puzzlemainwindow.cpp @@ -26,8 +26,14 @@ ** *************************************************************************/ #include "puzzlemainwindow.h" + +#include + #include "ui_puzzlemainwindow.h" #include "dialogs/dialogaboutpuzzle.h" +#include "xml/vpuzzlelayoutfilewriter.h" +#include "xml/vpuzzlelayoutfilereader.h" +#include "puzzleapplication.h" #include "../vlayout/vrawlayout.h" #include "../vmisc/vsysexits.h" @@ -46,6 +52,8 @@ PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *pa QMainWindow(parent), ui(new Ui::PuzzleMainWindow), pieceCarrousel(new VPieceCarrousel), + m_layout (nullptr), + m_selectedPiece (nullptr), m_cmd(cmd) { ui->setupUi(this); @@ -53,6 +61,16 @@ PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *pa InitMenuBar(); InitProperties(); InitPieceCarrousel(); + + // ----- for test purposes, to be removed------------------ + m_layout = new VPuzzleLayout(); + m_layout->SetLayoutMarginsConverted(1.5, 2.00, 4.21, 0.25); + m_layout->SetLayoutSizeConverted(30.0, 29.7); + m_layout->SetPiecesGapConverted(1.27); + m_layout->SetUnit(Unit::Cm); + m_layout->SetWarningSuperpositionOfPieces(true); + + SetPropertiesData(); } //--------------------------------------------------------------------------------------------------------------------- @@ -65,7 +83,34 @@ PuzzleMainWindow::~PuzzleMainWindow() //--------------------------------------------------------------------------------------------------------------------- bool PuzzleMainWindow::LoadFile(const QString &path) { - Q_UNUSED(path) + QFile file(path); + file.open(QIODevice::ReadOnly); + + VPuzzleLayoutFileReader *fileReader = new VPuzzleLayoutFileReader(); + + if(m_layout == nullptr) + { + m_layout = new VPuzzleLayout(); + } + + fileReader->ReadFile(m_layout, &file); + + // TODO / FIXME : better return value and error handling + + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool PuzzleMainWindow::SaveFile(const QString &path) +{ + QFile file(path); + file.open(QIODevice::WriteOnly); + + VPuzzleLayoutFileWriter *fileWriter = new VPuzzleLayoutFileWriter(); + fileWriter->WriteFile(m_layout, &file); + + // TODO / FIXME : better return value and error handling + return true; } @@ -254,6 +299,114 @@ void PuzzleMainWindow::InitPieceCarrousel() } +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetPropertiesData() +{ + if(m_layout == nullptr) + { + // TODO : hide the tabs when there is no layout + } + else + { + SetPropertyTabCurrentPieceData(); + SetPropertyTabLayoutData(); + SetPropertyTabTilesData(); + SetPropertyTabLayersData(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetPropertyTabCurrentPieceData() +{ + if(m_selectedPiece == nullptr) + { + if(false) // check for multiple piece selection + { + // TODO in the future + } + else + { + // TODO : update current piece data to show a "no current piece selected" + } + } + else + { + // TODO set the values of the piece currently selected + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetPropertyTabLayoutData() +{ + // set Unit + int index = ui->comboBoxLayoutUnit->findData(QVariant(UnitsToStr(m_layout->getUnit()))); + if(index != -1) + { + ui->comboBoxLayoutUnit->blockSignals(true); // FIXME: is there a better way to block the signals? + ui->comboBoxLayoutUnit->setCurrentIndex(index); + ui->comboBoxLayoutUnit->blockSignals(false); + } + + // set Width / Length + QSizeF size = m_layout->GetLayoutSizeConverted(); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutWidth, size.width()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutLength, size.height()); + + // Set Orientation + if(size.width() <= size.height()) + { + ui->radioButtonLayoutPortrait->setChecked(true); + } + else + { + ui->radioButtonLayoutLandscape->setChecked(true); + } + + // set margins + QMarginsF margins = m_layout->GetLayoutMarginsConverted(); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutMarginLeft, margins.left()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutMarginTop, margins.top()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutMarginRight, margins.right()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutMarginBottom, margins.bottom()); + + // set pieces gap + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutPiecesGap, m_layout->GetPiecesGapConverted()); + + // set the checkboxes + SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesOutOfBound, m_layout->GetWarningPiecesOutOfBound()); + SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition, m_layout->GetWarningSuperpositionOfPieces()); + SetCheckBoxValue(ui->checkBoxLayoutStickyEdges, m_layout->GetStickyEdges()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetPropertyTabTilesData() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetPropertyTabLayersData() +{ + +} + + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value) +{ + spinBox->blockSignals(true); + spinBox->setValue(value); + spinBox->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::SetCheckBoxValue(QCheckBox *checkbox, bool value) +{ + checkbox->blockSignals(true); + checkbox->setChecked(value); + checkbox->blockSignals(false); +} + //--------------------------------------------------------------------------------------------------------------------- @@ -274,14 +427,60 @@ void PuzzleMainWindow::New() //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::Open() { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::Open"); - int ret = msgBox.exec(); + qCDebug(pWindow, "Openning puzzle layout file."); - Q_UNUSED(ret); + const QString filter(tr("Layout files") + QLatin1String(" (*.vlt)")); - // TODO + //Get list last open files + QStringList recentFiles = qApp->PuzzleSettings()->GetRecentFileList(); + QString dir; + if (recentFiles.isEmpty()) + { + dir = QDir::homePath(); + } + else + { + //Absolute path to last open file + dir = QFileInfo(recentFiles.first()).absolutePath(); + } + qCDebug(pWindow, "Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir)); + const QString filePath = QFileDialog::getOpenFileName( + this, tr("Open file"), dir, filter, nullptr, +#ifdef Q_OS_LINUX + QFileDialog::DontUseNativeDialog +#endif + ); + + if (filePath.isEmpty()) + { + return; + } + + + // TODO : if m_layout == nullptr, open in current window + // otherwise open in new window + + // TODO : if layout file has a lock, warning message + + + if(!LoadFile(filePath)) + { + return; + } + + // Updates the list of recent files + recentFiles.removeAll(filePath); + recentFiles.prepend(filePath); + while (recentFiles.size() > MaxRecentFiles) + { + recentFiles.removeLast(); + } + qApp->PuzzleSettings()->SetRecentFileList(recentFiles); + + // updates the properties with the loaded data + SetPropertiesData(); + + // TODO : update the Carrousel and the QGraphicView } //--------------------------------------------------------------------------------------------------------------------- @@ -300,14 +499,31 @@ void PuzzleMainWindow::Save() //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::SaveAs() { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::SaveAs"); - int ret = msgBox.exec(); + // TODO / FIXME : See valentina how the save is done over there. we need to add the extension .vlt, check for empty file names etc. - Q_UNUSED(ret); + //Get list last open files + QStringList recentFiles = qApp->PuzzleSettings()->GetRecentFileList(); + QString dir; + if (recentFiles.isEmpty()) + { + dir = QDir::homePath(); + } + else + { + //Absolute path to last open file + dir = QFileInfo(recentFiles.first()).absolutePath(); + } - // TODO + QString filters(tr("Layout files") + QLatin1String("(*.vlt)")); + QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), + dir + QLatin1String("/") + tr("Layout") + QLatin1String(".vlt"), + filters, nullptr +#ifdef Q_OS_LINUX + , QFileDialog::DontUseNativeDialog +#endif + ); + + SaveFile(fileName); } //--------------------------------------------------------------------------------------------------------------------- @@ -353,17 +569,24 @@ void PuzzleMainWindow::AboutPuzzle() //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutUnitChanged(int index) { - - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutUnitChanged"); - int ret = msgBox.exec(); - Q_UNUSED(index); - Q_UNUSED(ret); + QVariant comboBoxValue = ui->comboBoxLayoutUnit->currentData(); + if(comboBoxValue == QVariant(UnitsToStr(Unit::Cm))) + { + m_layout->SetUnit(Unit::Cm); + } + else if(comboBoxValue == QVariant(UnitsToStr(Unit::Mm))) + { + m_layout->SetUnit(Unit::Mm); + } + else if(comboBoxValue == QVariant(UnitsToStr(Unit::Inch))) + { + m_layout->SetUnit(Unit::Inch); + } - // TODO + SetPropertyTabLayoutData(); + SetPropertyTabCurrentPieceData(); } //--------------------------------------------------------------------------------------------------------------------- @@ -384,27 +607,36 @@ void PuzzleMainWindow::LayoutTemplateChanged(int index) //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutSizeChanged() { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutSizeChanged"); - int ret = msgBox.exec(); + m_layout->SetLayoutSizeConverted(ui->doubleSpinBoxLayoutWidth->value(), ui->doubleSpinBoxLayoutLength->value()); - Q_UNUSED(ret); + // updates orientation - no need to block signals because the signal reacts on "clicked" + if(ui->doubleSpinBoxLayoutWidth->value() <= ui->doubleSpinBoxLayoutLength->value()) + { + //portrait + ui->radioButtonLayoutPortrait->setChecked(true); + } + else + { + //landscape + ui->radioButtonLayoutLandscape->setChecked(true); + } - // TODO + // TODO Undo / Redo + // TODO update the QGraphicView } //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutOrientationChanged() { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutOrientationChanged"); - int ret = msgBox.exec(); + // swap the width and length + qreal width_before = ui->doubleSpinBoxLayoutWidth->value(); + qreal length_before = ui->doubleSpinBoxLayoutLength->value(); - Q_UNUSED(ret); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutWidth, length_before); + SetDoubleSpinBoxValue(ui->doubleSpinBoxLayoutLength, width_before); - // TODO + // TODO Undo / Redo + // TODO update the QGraphicView } //--------------------------------------------------------------------------------------------------------------------- @@ -424,14 +656,15 @@ void PuzzleMainWindow::LayoutRemoveUnusedLength() //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutMarginChanged() { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutMarginChanged"); - int ret = msgBox.exec(); + m_layout->SetLayoutMarginsConverted( + ui->doubleSpinBoxLayoutMarginLeft->value(), + ui->doubleSpinBoxLayoutMarginTop->value(), + ui->doubleSpinBoxLayoutMarginRight->value(), + ui->doubleSpinBoxLayoutMarginBottom->value() + ); - Q_UNUSED(ret); - - // TODO + // TODO Undo / Redo + // TODO update the QGraphicView } @@ -452,60 +685,37 @@ void PuzzleMainWindow::LayoutFollowGrainlineChanged() //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutPiecesGapChanged(double value) { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutPieceGapChanged"); - int ret = msgBox.exec(); + m_layout->SetPiecesGapConverted(value); - Q_UNUSED(value); - Q_UNUSED(ret); - - // TODO + // TODO Undo / Redo + // TODO update the QGraphicView } //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutWarningPiecesSuperpositionChanged(bool checked) { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutWarningPiecesSuperpositionChanged"); - int ret = msgBox.exec(); + m_layout->SetWarningSuperpositionOfPieces(checked); - Q_UNUSED(checked); - Q_UNUSED(ret); - - // TODO + // TODO Undo / Redo + // TODO update the QGraphicView } //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutWarningPiecesOutOfBoundChanged(bool checked) { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutWarningPiecesOutOfBoundChanged"); - int ret = msgBox.exec(); - - Q_UNUSED(checked); - Q_UNUSED(ret); - - // TODO + m_layout->SetWarningPiecesOutOfBound(checked); + // TODO Undo / Redo + // TODO update the QGraphicView } //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::LayoutStickyEdgesChanged(bool checked) { - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO PuzzleMainWindow::LayoutStickyEdgesChanged"); - int ret = msgBox.exec(); - - Q_UNUSED(checked); - Q_UNUSED(ret); - - - // TODO + m_layout->SetStickyEdges(checked); + // TODO Undo / Redo + // TODO update the QGraphicView } diff --git a/src/app/puzzle/puzzlemainwindow.h b/src/app/puzzle/puzzlemainwindow.h index 8275373d2..a3518f391 100644 --- a/src/app/puzzle/puzzlemainwindow.h +++ b/src/app/puzzle/puzzlemainwindow.h @@ -30,9 +30,12 @@ #include #include +#include #include "../vmisc/def.h" #include "vpiececarrousel.h" +#include "vpuzzlelayout.h" +#include "vpuzzlepiece.h" #include "vpuzzlecommandline.h" namespace Ui @@ -48,19 +51,40 @@ public: PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *parent = nullptr); virtual ~PuzzleMainWindow(); + /** + * @brief LoadFile Loads the layout file of given path in m_layout. + * This function doesn't update the gui. + * @param path + * @return + */ bool LoadFile(const QString &path); + /** + * @brief SaveFile Saves the current layout to the layout file of given path + * @param path + * @return + */ + bool SaveFile(const QString &path); + void ImportRawLayouts(const QStringList &layouts); public slots: void New(); +protected: + enum { MaxRecentFiles = 5 }; + private: Q_DISABLE_COPY(PuzzleMainWindow) Ui::PuzzleMainWindow *ui; VPieceCarrousel *pieceCarrousel; VPuzzleCommandLinePtr m_cmd; + VPuzzleLayout *m_layout; + + VPuzzlePiece *m_selectedPiece; + + void InitMenuBar(); void InitProperties(); void InitPropertyTabCurrentPiece(); @@ -69,6 +93,53 @@ private: void InitPropertyTabLayers(); void InitPieceCarrousel(); + + /** + * @brief SetPropertiesData Sets the values of UI elements + * in all the property tabs to the values saved in m_layout + */ + void SetPropertiesData(); + + /** + * @brief SetPropertyTabCurrentPieceData Sets the values of UI elements + * in the Current Piece Tab to the values saved in m_layout + */ + void SetPropertyTabCurrentPieceData(); + + /** + * @brief SetPropertyTabLayoutData Sets the values of UI elements + * in the Layout Tab to the values saved in m_layout + */ + void SetPropertyTabLayoutData(); + + /** + * @brief SetPropertyTabTilesData Sets the values of UI elements + * in the Tiles Tab to the values saved in m_layout + */ + void SetPropertyTabTilesData(); + + /** + * @brief SetPropertyTabLayersData Sets the values of UI elements + * in the Layers Tab to the values saved in m_layout + */ + void SetPropertyTabLayersData(); + + /** + * @brief SetDoubleSpinBoxValue sets the given spinbox to the given value. + * the signals are blocked before changing the value and unblocked after + * @param spinbox + * @param value + */ + void SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value); + + /** + * @brief SetCheckBoxValue sets the given checkbox to the given value. + * the signals are blocked before changing the value and unblocked after + * @param checkbox + * @param value + */ + void SetCheckBoxValue(QCheckBox *checkbox, bool value); + private slots: void Open(); void Save(); diff --git a/src/app/puzzle/puzzlemainwindow.ui b/src/app/puzzle/puzzlemainwindow.ui index 7855f9b00..d8516accc 100644 --- a/src/app/puzzle/puzzlemainwindow.ui +++ b/src/app/puzzle/puzzlemainwindow.ui @@ -228,8 +228,8 @@ 0 0 - 356 - 760 + 170 + 452 @@ -495,10 +495,18 @@ - + + + 100000.000000000000000 + + - + + + 100000.000000000000000 + + @@ -850,8 +858,8 @@ 0 0 - 356 - 760 + 98 + 41 @@ -930,8 +938,8 @@ 0 0 - 356 - 760 + 98 + 41 @@ -1064,6 +1072,7 @@ + diff --git a/src/app/puzzle/vpuzzlelayer.cpp b/src/app/puzzle/vpuzzlelayer.cpp new file mode 100644 index 000000000..a50ac7d3c --- /dev/null +++ b/src/app/puzzle/vpuzzlelayer.cpp @@ -0,0 +1,85 @@ +/************************************************************************ + ** + ** @file vpuzzlelayer.cpp + ** @author Ronan Le Tiec + ** @date 13 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ +#include "vpuzzlelayer.h" + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayer::VPuzzleLayer() : + m_name(QString("")), + m_pieces(QList()), + m_isVisible(true) +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayer::~VPuzzleLayer() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +QList VPuzzleLayer::GetPieces() +{ + return m_pieces; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayer::AddPiece(VPuzzlePiece *piece) +{ + m_pieces.append(piece); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayer::RemovePiece(VPuzzlePiece *piece) +{ + m_pieces.removeAll(piece); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString VPuzzleLayer::GetName() +{ + return m_name; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayer::SetName(QString name) +{ + m_name = name; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayer::SetIsVisible(bool value) +{ + m_isVisible = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VPuzzleLayer::GetIsVisible() +{ + return m_isVisible; +} diff --git a/src/app/puzzle/vpuzzlelayer.h b/src/app/puzzle/vpuzzlelayer.h new file mode 100644 index 000000000..b4fc20038 --- /dev/null +++ b/src/app/puzzle/vpuzzlelayer.h @@ -0,0 +1,62 @@ +/************************************************************************ + ** + ** @file vpuzzlelayer.h + ** @author Ronan Le Tiec + ** @date 13 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ +#ifndef VPUZZLELAYER_H +#define VPUZZLELAYER_H + +#include +#include "vpuzzlepiece.h" + +class VPuzzleLayer +{ +public: + VPuzzleLayer(); + ~VPuzzleLayer(); + + QList GetPieces(); + void AddPiece(VPuzzlePiece *piece); + void RemovePiece(VPuzzlePiece *piece); + + // here add some more function if we want to add/move a piece at a + // certain position in the list + + QString GetName(); + void SetName(QString name); + + void SetIsVisible(bool value); + bool GetIsVisible(); + +private: + QString m_name; + QList m_pieces; + + // control + bool m_isVisible; + +}; + +#endif // VPUZZLELAYER_H diff --git a/src/app/puzzle/vpuzzlelayout.cpp b/src/app/puzzle/vpuzzlelayout.cpp new file mode 100644 index 000000000..94a17547d --- /dev/null +++ b/src/app/puzzle/vpuzzlelayout.cpp @@ -0,0 +1,249 @@ +/************************************************************************ + ** + ** @file vpuzzlelayout.cpp + ** @author Ronan Le Tiec + ** @date 13 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ +#include "vpuzzlelayout.h" + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayout::VPuzzleLayout() : + m_unplacedPiecesLayer(new VPuzzleLayer()), + m_layers(QList()), + m_unit(Unit::Cm), + m_size(QSizeF()), + m_margins(QMarginsF()), + m_followGrainLine(FollowGrainline::No), + m_piecesGap(0), + m_warningSuperpositionOfPieces(false), + m_warningPiecesOutOfBound(false), + m_stickyEdges(false) +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayout::~VPuzzleLayout() +{ + // TODO +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayer* VPuzzleLayout::GetUnplacedPiecesLayer() +{ + return m_unplacedPiecesLayer; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayer* VPuzzleLayout::AddLayer() +{ + VPuzzleLayer *newLayer = new VPuzzleLayer(); + m_layers.append(newLayer); + return newLayer; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayer* VPuzzleLayout::AddLayer(VPuzzleLayer *layer) +{ + m_layers.append(layer); + return layer; +} + +//--------------------------------------------------------------------------------------------------------------------- +QList VPuzzleLayout::GetLayers() +{ + return m_layers; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetUnit(Unit unit) +{ + m_unit = unit; +} + +//--------------------------------------------------------------------------------------------------------------------- +Unit VPuzzleLayout::getUnit() +{ + return m_unit; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutSize(qreal width, qreal height) +{ + m_size.setWidth(width); + m_size.setHeight(height); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutSizeConverted(qreal width, qreal height) +{ + m_size.setWidth(UnitConvertor(width, m_unit,Unit::Px)); + m_size.setHeight(UnitConvertor(height, m_unit,Unit::Px)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutSize(QSizeF size) +{ + m_size = size; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutSizeConverted(QSizeF size) +{ + m_size = QSizeF( + UnitConvertor(size.width(), m_unit,Unit::Px), + UnitConvertor(size.height(), m_unit,Unit::Px) + ); +} + +//--------------------------------------------------------------------------------------------------------------------- +QSizeF VPuzzleLayout::GetLayoutSize() +{ + return m_size; +} + +//--------------------------------------------------------------------------------------------------------------------- +QSizeF VPuzzleLayout::GetLayoutSizeConverted() +{ + QSizeF convertedSize = QSizeF( + UnitConvertor(m_size.width(), Unit::Px, m_unit), + UnitConvertor(m_size.height(), Unit::Px, m_unit) + ); + + return convertedSize; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutMargins(qreal left, qreal top, qreal right, qreal bottom) +{ + m_margins.setLeft(left); + m_margins.setTop(top); + m_margins.setRight(right); + m_margins.setBottom(bottom); +} +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutMarginsConverted(qreal left, qreal top, qreal right, qreal bottom) +{ + m_margins.setLeft(UnitConvertor(left, m_unit, Unit::Px)); + m_margins.setTop(UnitConvertor(top, m_unit, Unit::Px)); + m_margins.setRight(UnitConvertor(right, m_unit, Unit::Px)); + m_margins.setBottom(UnitConvertor(bottom, m_unit, Unit::Px)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutMargins(QMarginsF margins) +{ + m_margins = margins; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetLayoutMarginsConverted(QMarginsF margins) +{ + m_margins = UnitConvertor(margins, m_unit, Unit::Px); +} + +//--------------------------------------------------------------------------------------------------------------------- +QMarginsF VPuzzleLayout::GetLayoutMargins() +{ + return m_margins; +} + +//--------------------------------------------------------------------------------------------------------------------- +QMarginsF VPuzzleLayout::GetLayoutMarginsConverted() +{ + return UnitConvertor(m_margins, Unit::Px, m_unit); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetFollowGrainline(FollowGrainline state) +{ + m_followGrainLine = state; +} + +//--------------------------------------------------------------------------------------------------------------------- +FollowGrainline VPuzzleLayout::SetFollowGrainline() +{ + return m_followGrainLine; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetPiecesGap(qreal value) +{ + m_piecesGap = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetPiecesGapConverted(qreal value) +{ + m_piecesGap = UnitConvertor(value, m_unit, Unit::Px); +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VPuzzleLayout::GetPiecesGap() +{ + return m_piecesGap; +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VPuzzleLayout::GetPiecesGapConverted() +{ + return UnitConvertor(m_piecesGap, Unit::Px, m_unit); +} + + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetWarningSuperpositionOfPieces(bool state) +{ + m_warningSuperpositionOfPieces = state; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VPuzzleLayout::GetWarningSuperpositionOfPieces() +{ + return m_warningSuperpositionOfPieces; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetWarningPiecesOutOfBound(bool state) +{ + m_warningPiecesOutOfBound = state; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VPuzzleLayout::GetWarningPiecesOutOfBound() +{ + return m_warningPiecesOutOfBound; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayout::SetStickyEdges(bool state) +{ + m_stickyEdges = state; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VPuzzleLayout::GetStickyEdges() +{ + return m_stickyEdges; +} diff --git a/src/app/puzzle/vpuzzlelayout.h b/src/app/puzzle/vpuzzlelayout.h new file mode 100644 index 000000000..be8e198f8 --- /dev/null +++ b/src/app/puzzle/vpuzzlelayout.h @@ -0,0 +1,202 @@ +/************************************************************************ + ** + ** @file vpuzzlelayout.h + ** @author Ronan Le Tiec + ** @date 13 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ +#ifndef VPUZZLELAYOUT_H +#define VPUZZLELAYOUT_H + +#include +#include +#include +#include "vpuzzlelayer.h" +#include "def.h" + +// is this the right place for the definition? +enum class FollowGrainline : qint8 { No = 0, Follow90 = 1, Follow180 = 2}; + +class VPuzzleLayout +{ + +public: + VPuzzleLayout(); + virtual ~VPuzzleLayout(); + + VPuzzleLayer* GetUnplacedPiecesLayer(); + + VPuzzleLayer* AddLayer(); + VPuzzleLayer* AddLayer(VPuzzleLayer *layer); + QList GetLayers(); + + void SetUnit(Unit unit); + Unit getUnit(); + + /** + * @brief SetLayoutSize sets the size of the layout, the values have to be in Unit::Px + * @param width + * @param height + */ + void SetLayoutSize(qreal width, qreal height); + + /** + * @brief SetLayoutSize sets the size of the layout, the values have to be in the layout's unit + * @param width + * @param height + */ + void SetLayoutSizeConverted(qreal width, qreal height); + + /** + * @brief SetLayoutSize sets the size of the layout, the values have to be in Unit::Px + * @param size + */ + void SetLayoutSize(QSizeF size); + /** + * @brief SetLayoutSizeConverted sets the size of the layout, the values have to be in the layout's unit + * @param size + */ + void SetLayoutSizeConverted(QSizeF size); + + /** + * @brief GetLayoutSize Returns the size in Unit::Px + * @return + */ + QSizeF GetLayoutSize(); + + /** + * @brief GetLayoutSizeConverted Returns the size in the layout's unit + * @return + */ + QSizeF GetLayoutSizeConverted(); + + /** + * @brief SetLayoutMargins, set the margins of the layout, the values have to be in Unit::Px + * @param left in Unit::Px + * @param top in Unit::Px + * @param right in Unit::Px + * @param bottom in Unit::Px + */ + void SetLayoutMargins(qreal left, qreal top, qreal right, qreal bottom); + + /** + * @brief SetLayoutMargins, set the margins of the layout, the values have to be in the unit of the layout + * @param left in Unit::Px + * @param top in Unit::Px + * @param right in Unit::Px + * @param bottom in Unit::Px + */ + void SetLayoutMarginsConverted(qreal left, qreal top, qreal right, qreal bottom); + + /** + * @brief SetLayoutMargins set the margins of the layout, the values have to be in Unit::Px + * @param margins + */ + void SetLayoutMargins(QMarginsF margins); + + /** + * @brief SetLayoutMargins set the margins of the layout, the values have to be in the unit of the layout + * @param margins + */ + void SetLayoutMarginsConverted(QMarginsF margins); + + /** + * @brief GetLayoutMargins Returns the size in Unit::Px + * @return + */ + QMarginsF GetLayoutMargins(); + + /** + * @brief GetLayoutMarginsConverted Returns the margins in the layout's unit + * @return + */ + QMarginsF GetLayoutMarginsConverted(); + + void SetFollowGrainline(FollowGrainline state); + FollowGrainline SetFollowGrainline(); + + /** + * @brief SetPiecesGap sets the pieces gap to the given value, the unit has to be in Unit::Px + * @param value + */ + void SetPiecesGap(qreal value); + + /** + * @brief SetPiecesGapConverted sets the pieces gap to the given value, the unit has to be in the layout's unit + * @param value + */ + void SetPiecesGapConverted(qreal value); + + /** + * @brief GetPiecesGap returns the pieces gap in Unit::Px + * @return + */ + qreal GetPiecesGap(); + + /** + * @brief GetPiecesGapConverted returns the pieces gap in the layout's unit + * @return + */ + qreal GetPiecesGapConverted(); + + void SetWarningSuperpositionOfPieces(bool state); + bool GetWarningSuperpositionOfPieces(); + + void SetWarningPiecesOutOfBound(bool state); + bool GetWarningPiecesOutOfBound(); + + void SetStickyEdges(bool state); + bool GetStickyEdges(); + +private: + Q_DISABLE_COPY(VPuzzleLayout) + VPuzzleLayer *m_unplacedPiecesLayer; + QList m_layers; + + // format + Unit m_unit; + /** + * @brief m_size the Size in Unit::Px + */ + QSizeF m_size; + + // margins + /** + * @brief m_margins the margins in Unit::Px + */ + QMarginsF m_margins; + + // control + FollowGrainline m_followGrainLine; + + /** + * @brief m_piecesGap the pieces gap in Unit::Px + */ + qreal m_piecesGap; + bool m_warningSuperpositionOfPieces; + bool m_warningPiecesOutOfBound; + bool m_stickyEdges; + +}; + +#endif // VPUZZLELAYOUT_H diff --git a/src/app/puzzle/vpuzzlepiece.cpp b/src/app/puzzle/vpuzzlepiece.cpp new file mode 100644 index 000000000..8c9a708f5 --- /dev/null +++ b/src/app/puzzle/vpuzzlepiece.cpp @@ -0,0 +1,41 @@ +/************************************************************************ + ** + ** @file vpuzzlepiece.cpp + ** @author Ronan Le Tiec + ** @date 13 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ +#include "vpuzzlepiece.h" + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzlePiece::VPuzzlePiece() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzlePiece::~VPuzzlePiece() +{ + +} + diff --git a/src/app/puzzle/vpuzzlepiece.h b/src/app/puzzle/vpuzzlepiece.h new file mode 100644 index 000000000..f20473764 --- /dev/null +++ b/src/app/puzzle/vpuzzlepiece.h @@ -0,0 +1,41 @@ +/************************************************************************ + ** + ** @file vpuzzlepiece.h + ** @author Ronan Le Tiec + ** @date 13 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ +#ifndef VPUZZLEPIECE_H +#define VPUZZLEPIECE_H + +class VPuzzlePiece +{ +public: + VPuzzlePiece(); + ~VPuzzlePiece(); + +private: + +}; + +#endif // VPUZZLEPIECE_H diff --git a/src/app/puzzle/xml/vpuzzlelayoutfilereader.cpp b/src/app/puzzle/xml/vpuzzlelayoutfilereader.cpp new file mode 100644 index 000000000..bc650617f --- /dev/null +++ b/src/app/puzzle/xml/vpuzzlelayoutfilereader.cpp @@ -0,0 +1,305 @@ +/************************************************************************ + ** + ** @file vpuzzlelayoutfilereader.cpp + ** @author Ronan Le Tiec + ** @date 18 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + ** *************************************************************************/ + +#include +#include "vpuzzlelayoutfilereader.h" +#include "vpuzzlelayoutfilewriter.h" + +VPuzzleLayoutFileReader::VPuzzleLayoutFileReader() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayoutFileReader::~VPuzzleLayoutFileReader() +{ + // TODO +} + + +//--------------------------------------------------------------------------------------------------------------------- +bool VPuzzleLayoutFileReader::ReadFile(VPuzzleLayout *layout, QFile *file) +{ + setDevice(file); + + if (readNextStartElement()) + { + + // TODO extend the handling + // if it doesn't start with layout, error + // if it starts with version > than current version, error + + if (name() == QString("layout")) + { + QString versionStr = attributes().value(QString("version")).toString(); + QStringList versionStrParts = versionStr.split('.'); + m_layoutFormatVersion = FORMAT_VERSION(versionStrParts.at(0).toInt(),versionStrParts.at(1).toInt(),versionStrParts.at(2).toInt()); + + if(VPuzzleLayoutFileWriter::LayoutFileFormatVersion >= m_layoutFormatVersion) + { + ReadLayout(layout); + } + else + { + // TODO better error handling + raiseError(QObject::tr("You're trying to open a layout that was created with a newer version of puzzle")); + } + } + else + { + raiseError(QObject::tr("Wrong file structure")); + } + } + + return !error(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileReader::ReadLayout(VPuzzleLayout *layout) +{ + Q_ASSERT(isStartElement() && name() == QString("layout")); + + while (readNextStartElement()) { + if (name() == QString("properties")) + { + ReadProperties(layout); + } + else if (name() == QString("layers")) + { + ReadLayers(layout); + } + else + { + // TODO error handling, we encountered a tag that isn't defined in the specification + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileReader::ReadProperties(VPuzzleLayout *layout) +{ + Q_ASSERT(isStartElement() && name() == QString("properties")); + + while (readNextStartElement()) { + qDebug(name().toString().toLatin1()); + + if (name() == QString("unit")) + { + qDebug("read unit"); + QString unit = readElementText(); + if(unit == UnitsToStr(Unit::Inch)) + { + layout->SetUnit(Unit::Inch); + } + else if(unit == UnitsToStr(Unit::Mm)) + { + layout->SetUnit(Unit::Cm); + } + else // no condition here to have a default value just in case + { + layout->SetUnit(Unit::Cm); + } + } + else if (name() == QString("description")) + { + qDebug("read description"); + QString description = readElementText(); + // TODO read the description info + + } + else if (name() == QString("size")) + { + qDebug("read size"); + QSizeF size = ReadSize(); + layout->SetLayoutSize(size); + readElementText(); + } + else if (name() == QString("margin")) + { + qDebug("read margin"); + QMarginsF margins = ReadMargins(); + layout->SetLayoutMargins(margins); + readElementText(); + } + else if (name() == QString("control")) + { + qDebug("read control"); + QXmlStreamAttributes attribs = attributes(); + + // attribs.value("followGrainLine"); // TODO + + layout->SetWarningSuperpositionOfPieces(attribs.value("warningSuperposition") == "true"); + layout->SetWarningPiecesOutOfBound(attribs.value("warningOutOfBound") == "true"); + layout->SetStickyEdges(attribs.value("stickyEdges") == "true"); + + layout->SetPiecesGap(attribs.value("piecesGap").toDouble()); + readElementText(); + } + else if (name() == QString("tiles")) + { + qDebug("read tiles"); + ReadTiles(layout); + readElementText(); + } + else + { + // TODO error handling, we encountered a tag that isn't defined in the specification + skipCurrentElement(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileReader::ReadTiles(VPuzzleLayout *layout) +{ + Q_UNUSED(layout); // to be removed when used + + Q_ASSERT(isStartElement() && name() == QString("tiles")); + + QXmlStreamAttributes attribs = attributes(); + // attribs.value("visible"); // TODO + // attribs.value("matchingMarks"); // TODO + + while (readNextStartElement()) { + if (name() == QString("size")) + { + QSizeF size = ReadSize(); + // TODO set layout tiled size + Q_UNUSED(size); + readElementText(); + } + else if (name() == QString("margin")) + { + QMarginsF margins = ReadMargins(); + // TODO set layout tiled margins + Q_UNUSED(margins); + readElementText(); + } + else + { + // TODO error handling, we encountered a tag that isn't defined in the specification + skipCurrentElement(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileReader::ReadLayers(VPuzzleLayout *layout) +{ + Q_ASSERT(isStartElement() && name() == QString("layers")); + + while (readNextStartElement()) { + if (name() == QString("unplacedPiecesLayer")) + { + ReadLayer(layout->GetUnplacedPiecesLayer()); + } + else if (name() == QString("layer")) + { + VPuzzleLayer *layer = layout->AddLayer(); + ReadLayer(layer); + } + else + { + // TODO error handling, we encountered a tag that isn't defined in the specification + skipCurrentElement(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileReader::ReadLayer(VPuzzleLayer *layer) +{ + Q_ASSERT(isStartElement() && name() == QString("layer")); + + QXmlStreamAttributes attribs = attributes(); + layer->SetName(attribs.value("name").toString()); + layer->SetIsVisible(attribs.value("visible") == "true"); + + while (readNextStartElement()) { + if (name() == QString("piece")) + { + VPuzzlePiece *piece = new VPuzzlePiece(); + ReadPiece(piece); + layer->AddPiece(piece); + } + else + { + // TODO error handling, we encountered a tag that isn't defined in the specification + skipCurrentElement(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileReader::ReadPiece(VPuzzlePiece *piece) +{ + Q_UNUSED(piece); + Q_ASSERT(isStartElement() && name() == QString("piece")); + + // TODO read the attributes + + while (readNextStartElement()) { + if (name() == QString("...")) + { + // TODO + readElementText(); + } + else + { + // TODO error handling, we encountered a tag that isn't defined in the specification + skipCurrentElement(); + } + } + +} + +//--------------------------------------------------------------------------------------------------------------------- +QMarginsF VPuzzleLayoutFileReader::ReadMargins() +{ + QMarginsF margins = QMarginsF(); + + QXmlStreamAttributes attribs = attributes(); + margins.setLeft(attribs.value("left").toDouble()); + margins.setTop(attribs.value("top").toDouble()); + margins.setRight(attribs.value("right").toDouble()); + margins.setBottom(attribs.value("bottom").toDouble()); + + return margins; +} + +//--------------------------------------------------------------------------------------------------------------------- +QSizeF VPuzzleLayoutFileReader::ReadSize() +{ + QSizeF size = QSize(); + + QXmlStreamAttributes attribs = attributes(); + size.setWidth(attribs.value("width").toDouble()); + size.setHeight(attribs.value("length").toDouble()); + + return size; +} diff --git a/src/app/puzzle/xml/vpuzzlelayoutfilereader.h b/src/app/puzzle/xml/vpuzzlelayoutfilereader.h new file mode 100644 index 000000000..4a97f1b39 --- /dev/null +++ b/src/app/puzzle/xml/vpuzzlelayoutfilereader.h @@ -0,0 +1,64 @@ +/************************************************************************ + ** + ** @file vpuzzlelayoutfilereader.h + ** @author Ronan Le Tiec + ** @date 18 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + ** *************************************************************************/ + +#ifndef VPUZZLELAYOUTFILEREADER_H +#define VPUZZLELAYOUTFILEREADER_H + +#include +#include "../ifc/xml/vabstractconverter.h" +#include "vpuzzlelayout.h" +#include "vpuzzlelayer.h" +#include "vpuzzlepiece.h" + +class VPuzzleLayoutFileReader : public QXmlStreamReader +{ +public: + VPuzzleLayoutFileReader(); + ~VPuzzleLayoutFileReader(); + + bool ReadFile(VPuzzleLayout *layout, QFile *file); + +private: + /** + * @brief m_layoutFormatVersion holds the version of the layout currently being read + */ + int m_layoutFormatVersion; + + void ReadLayout(VPuzzleLayout *layout); + void ReadProperties(VPuzzleLayout *layout); + void ReadTiles(VPuzzleLayout *layout); + void ReadLayers(VPuzzleLayout *layout); + void ReadLayer(VPuzzleLayer *layer); + void ReadPiece(VPuzzlePiece *piece); + + QMarginsF ReadMargins(); + QSizeF ReadSize(); + +}; + +#endif // VPUZZLELAYOUTFILEREADER_H diff --git a/src/app/puzzle/xml/vpuzzlelayoutfilewriter.cpp b/src/app/puzzle/xml/vpuzzlelayoutfilewriter.cpp new file mode 100644 index 000000000..8c265e0c0 --- /dev/null +++ b/src/app/puzzle/xml/vpuzzlelayoutfilewriter.cpp @@ -0,0 +1,207 @@ +/************************************************************************ + ** + ** @file vpuzzlelayoutfilewriter.cpp + ** @author Ronan Le Tiec + ** @date 18 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + *************************************************************************/ + +#include "vpuzzlelayoutfilewriter.h" + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayoutFileWriter::VPuzzleLayoutFileWriter() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +VPuzzleLayoutFileWriter::~VPuzzleLayoutFileWriter() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteFile(VPuzzleLayout *layout, QFile *file) +{ + setDevice(file); + setAutoFormatting(true); + + writeStartDocument(); + WriteLayout(layout); + writeEndDocument(); + + file->close(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteLayout(VPuzzleLayout *layout) +{ + writeStartElement("layout"); + writeAttribute("version", LayoutFileFormatVersionStr); + + WriteProperties(layout); + WriteLayers(layout); + + writeEndElement(); //layout +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteProperties(VPuzzleLayout *layout) +{ + writeStartElement("properties"); + + writeTextElement("unit", UnitsToStr(layout->getUnit())); + + writeTextElement("description", ""); // TODO : define the value in layout + + WriteSize(layout->GetLayoutSize()); + + WriteMargins(layout->GetLayoutMargins()); + + writeStartElement("control"); + writeAttribute("followGrainLine", "no"); // TODO / Fixme get the right value + writeAttribute("warningSuperposition", QString(layout->GetWarningSuperpositionOfPieces() ? "true" : "false")); + writeAttribute("warningOutOfBound", QString(layout->GetWarningPiecesOutOfBound() ? "true" : "false")); + writeAttribute("stickyEdges", QString(layout->GetStickyEdges() ? "true" : "false")); + writeAttribute("piecesGap", QString::number(layout->GetPiecesGap())); + writeEndElement(); // control + + // WriteTiles(layout); TODO: when tile functionality implemented, then uncomment this line + + writeEndElement(); // properties +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteTiles(VPuzzleLayout *layout) +{ + Q_UNUSED(layout); // to be removed + + writeStartElement("tiles"); + writeAttribute("visible", QString(false ? "true" : "false")); // TODO / Fixme get the right value + writeAttribute("matchingMarks", "standard"); // TODO / Fixme get the right value + + QSizeF size = QSizeF(); // TODO get the right size + WriteSize(size); + + QMarginsF margins = QMarginsF(); // TODO get the right margins + WriteMargins(margins); + + writeEndElement(); // tiles +} + + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteLayers(VPuzzleLayout *layout) +{ + writeStartElement("layers"); + + WriteLayer(layout->GetUnplacedPiecesLayer(), "unplacedPieces"); + + QList layers = layout->GetLayers(); + for (auto layer : layers) + { + WriteLayer(layer); + } + + writeEndElement(); // layers +} + + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteLayer(VPuzzleLayer *layer) +{ + WriteLayer(layer, "layer"); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteLayer(VPuzzleLayer *layer, const QString &tagName) +{ + writeStartElement(tagName); // layer + writeAttribute("name", layer->GetName()); + writeAttribute("visible", QString(layer->GetIsVisible()? "true" : "false")); + // TODO selected info. Not sure how it's saved yet + //writeAttribute("selected", QString(layer->GetIsSelected()? "true" : "false")); + + + QList pieces = layer->GetPieces(); + for (auto piece : pieces) + { + WritePiece(piece); + } + + writeEndElement(); // layer +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WritePiece(VPuzzlePiece *piece) +{ + Q_UNUSED(piece); + + writeStartElement("piece"); + writeAttribute("id", "uuid1"); // TODO / Fixme get the right value + writeAttribute("name", "Piece name"); // TODO / Fixme get the right value + writeAttribute("mirrored", "false"); // TODO / Fixme get the right value + writeAttribute("transform", "string representation of the transformation"); // TODO / Fixme get the right value + + // TODO cuttingLine + // TODO seamLine + // TODO grainline + // TODO passmarks + // TODO internal paths + // TODO placeLabels (buttonholes etc.) + + // TODO labels + + writeEndElement(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteMargins(QMarginsF margins) +{ + writeStartElement("margin"); + writeAttribute("left", QString::number(margins.left())); + writeAttribute("top", QString::number(margins.top())); + writeAttribute("right", QString::number(margins.right())); + writeAttribute("bottom", QString::number(margins.bottom())); + writeEndElement(); // margin +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleLayoutFileWriter::WriteSize(QSizeF size) +{ + // maybe not necessary to test this, the writer should "stupidly write", the application should take care of these tests + qreal width = size.width(); + if(width < 0) { + width = 0; + } + + qreal length = size.height(); + if(length < 0) { + length = 0; + } + + writeStartElement("size"); + writeAttribute("width", QString::number(width)); + writeAttribute("length", QString::number(length)); + writeEndElement(); // size +} diff --git a/src/app/puzzle/xml/vpuzzlelayoutfilewriter.h b/src/app/puzzle/xml/vpuzzlelayoutfilewriter.h new file mode 100644 index 000000000..6f25e6a10 --- /dev/null +++ b/src/app/puzzle/xml/vpuzzlelayoutfilewriter.h @@ -0,0 +1,76 @@ +/************************************************************************ + ** + ** @file vpuzzlelayoutfilewriter.h + ** @author Ronan Le Tiec + ** @date 18 4, 2020 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2020 Valentina project + ** 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 . + ** + ** *************************************************************************/ + +#ifndef VPUZZLELAYOUTFILEWRITER_H +#define VPUZZLELAYOUTFILEWRITER_H + +#include +#include "../ifc/xml/vabstractconverter.h" +#include "vpuzzlelayout.h" +#include "vpuzzlelayer.h" +#include "vpuzzlepiece.h" + +class VPuzzleLayoutFileWriter : public QXmlStreamWriter +{ +public: + VPuzzleLayoutFileWriter(); + ~VPuzzleLayoutFileWriter(); + + void WriteFile(VPuzzleLayout *layout, QFile *file); + + /* + * Version rules: + * 1. Version have three parts "major.minor.patch"; + * 2. major part only for stable releases; + * 3. minor - 10 or more patch changes, or one big change; + * 4. patch - little change. + */ + /** + * @brief LayoutFileFormatVersion holds the version + * + */ + static Q_DECL_CONSTEXPR const int LayoutFileFormatVersion = FORMAT_VERSION(1, 0, 0); + const QString LayoutFileFormatVersionStr = QStringLiteral("1.0.0"); + +private: + + void WriteLayout(VPuzzleLayout *layout); + void WriteProperties(VPuzzleLayout *layout); + void WriteTiles(VPuzzleLayout *layout); + void WriteLayers(VPuzzleLayout *layout); + void WriteLayer(VPuzzleLayer *layer); + void WriteLayer(VPuzzleLayer *layer, const QString &tagName); + void WritePiece(VPuzzlePiece *piece); + + void WriteMargins(QMarginsF margins); + void WriteSize(QSizeF size); + + +}; + +#endif // VPUZZLELAYOUTFILEWRITER_H