diff --git a/ChangeLog.txt b/ChangeLog.txt index 14647ee41..1b6413f74 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -22,6 +22,7 @@ - Raise the minimum value for curve approximation to 0.2. - Make piece labels transparent. - New layout option --nestQuantity. +- New feature Pattern recipe. # Version 0.6.2 (unreleased) - [#903] Bug in tool Cut Spline path. diff --git a/src/app/tape/mapplication.cpp b/src/app/tape/mapplication.cpp index 9f11396e3..5ae40b36b 100644 --- a/src/app/tape/mapplication.cpp +++ b/src/app/tape/mapplication.cpp @@ -38,6 +38,7 @@ #include "../vmisc/diagnostic.h" #include "../vmisc/qt_dispatch/qt_dispatch.h" #include "../qmuparser/qmuparsererror.h" +#include "../vpatterndb/variables/vmeasurement.h" #include #include diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index 446c1c416..f6094760b 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -32,6 +32,7 @@ #include "dialogs/dialognewmeasurements.h" #include "dialogs/dialogmdatabase.h" #include "dialogs/dialogtapepreferences.h" +#include "../vpatterndb/vcontainer.h" #include "../vpatterndb/calculator.h" #include "../vpatterndb/pmsystems.h" #include "../vpatterndb/measurements.h" diff --git a/src/app/valentina/core/vcmdexport.cpp b/src/app/valentina/core/vcmdexport.cpp index a5cb85371..176956c0c 100644 --- a/src/app/valentina/core/vcmdexport.cpp +++ b/src/app/valentina/core/vcmdexport.cpp @@ -35,6 +35,7 @@ #include "../vmisc/vsettings.h" #include "../vmisc/dialogs/dialogexporttocsv.h" #include "../vlayout/vlayoutgenerator.h" +#include "../vpatterndb/variables/vmeasurement.h" #include #include diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index 1288aad7d..ff88eba71 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -64,6 +64,7 @@ #include "../vpatterndb/vpiecepath.h" #include "../qmuparser/qmuparsererror.h" #include "../vtools/dialogs/support/dialogeditlabel.h" +#include "../vformat/vpatternrecipe.h" #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) #include "../vmisc/backport/qscopeguard.h" @@ -3058,6 +3059,7 @@ void MainWindow::Clear() ui->actionZoomFitBestCurrent->setEnabled(false); ui->actionZoomOriginal->setEnabled(false); ui->actionHistory->setEnabled(false); + ui->actionExportRecipe->setEnabled(false); ui->actionTable->setEnabled(false); ui->actionExportIncrementsToCSV->setEnabled(false); ui->actionExportFinalMeasurementsToCSV->setEnabled(false); @@ -3426,6 +3428,7 @@ void MainWindow::SetEnableWidgets(bool enable) ui->actionZoomOut->setEnabled(enable); ui->actionArrowTool->setEnabled(enable && designStage); ui->actionHistory->setEnabled(enable && drawStage); + ui->actionExportRecipe->setEnabled(enable && drawStage); ui->actionNewDraw->setEnabled(enable && drawStage); ui->actionDraw->setEnabled(enable); ui->actionDetails->setEnabled(enable); @@ -4350,6 +4353,26 @@ void MainWindow::CreateActions() } }); + connect(ui->actionExportRecipe, &QAction::triggered, this, [this]() + { + QString filters(tr("Recipe files") + QStringLiteral("(*.vpr)")); + QString fileName = + QFileDialog::getSaveFileName(this, tr("Export recipe"), + QDir::homePath() + '/' + tr("recipe") + QStringLiteral(".vpr"), + filters, nullptr); + if (fileName.isEmpty()) + { + return; + } + + VPatternRecipe recipe(pattern, doc); + QString error; + if (not recipe.SaveDocument(fileName, error)) + { + qCWarning(vMainWindow, "%s", qUtf8Printable(tr("Could not save recipe. %1").arg(error))); + } + }); + connect(ui->actionNewDraw, &QAction::triggered, this, [this]() { qCDebug(vMainWindow, "New PP."); diff --git a/src/app/valentina/mainwindow.ui b/src/app/valentina/mainwindow.ui index 250072cca..1d8fcf1e6 100644 --- a/src/app/valentina/mainwindow.ui +++ b/src/app/valentina/mainwindow.ui @@ -372,7 +372,7 @@ 0 0 - 126 + 140 108 @@ -481,7 +481,7 @@ 0 0 - 126 + 140 243 @@ -743,7 +743,7 @@ 0 0 - 126 + 140 282 @@ -1034,7 +1034,7 @@ 0 0 - 126 + 140 102 @@ -1321,7 +1321,7 @@ 0 0 - 126 + 140 237 @@ -1781,6 +1781,7 @@ History + @@ -2821,6 +2822,17 @@ Hide labels + + + false + + + false + + + Export recipe + + diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index f8e507393..124bdacff 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -122,16 +122,8 @@ void VPattern::CreateEmptyFile() SetAttribute(patternElement, AttrLabelPrefix, DefLabelLanguage()); patternElement.appendChild(createComment(FileComment())); - - QDomElement version = createElement(TagVersion); - QDomText newNodeText = createTextNode(VPatternConverter::PatternMaxVerStr); - version.appendChild(newNodeText); - patternElement.appendChild(version); - - QDomElement unit = createElement(TagUnit); - newNodeText = createTextNode(UnitsToStr(qApp->patternUnit())); - unit.appendChild(newNodeText); - patternElement.appendChild(unit); + patternElement.appendChild(CreateElementWithText(TagVersion, VPatternConverter::PatternMaxVerStr)); + patternElement.appendChild(CreateElementWithText(TagUnit, UnitsToStr(qApp->patternUnit()))); patternElement.appendChild(createElement(TagDescription)); patternElement.appendChild(createElement(TagNotes)); diff --git a/src/libs/ifc/exception/exception.pri b/src/libs/ifc/exception/exception.pri index d1df21748..617905305 100644 --- a/src/libs/ifc/exception/exception.pri +++ b/src/libs/ifc/exception/exception.pri @@ -10,7 +10,8 @@ HEADERS += \ $$PWD/vexceptionterminatedposition.h \ $$PWD/vexceptionwrongid.h \ $$PWD/vexceptionundo.h \ - $$PWD/vexceptioninvalidnotch.h + $$PWD/vexceptioninvalidnotch.h \ + $$PWD/vexceptioninvalidhistory.h SOURCES += \ $$PWD/vexceptionobjecterror.cpp \ @@ -21,4 +22,5 @@ SOURCES += \ $$PWD/vexceptionterminatedposition.cpp \ $$PWD/vexceptionwrongid.cpp \ $$PWD/vexceptionundo.cpp \ - $$PWD/vexceptioninvalidnotch.cpp + $$PWD/vexceptioninvalidnotch.cpp \ + $$PWD/vexceptioninvalidhistory.cpp diff --git a/src/libs/ifc/exception/vexceptioninvalidhistory.cpp b/src/libs/ifc/exception/vexceptioninvalidhistory.cpp new file mode 100644 index 000000000..3ef9ae72f --- /dev/null +++ b/src/libs/ifc/exception/vexceptioninvalidhistory.cpp @@ -0,0 +1,49 @@ +/************************************************************************ + ** + ** @file vexceptioninvalidhistory.cpp + ** @author Roman Telezhynskyi + ** @date 10 7, 2019 + ** + ** @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) 2019 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 "vexceptioninvalidhistory.h" + +//--------------------------------------------------------------------------------------------------------------------- +VExceptionInvalidHistory::VExceptionInvalidHistory(const QString &error) + :VException(error) +{} + +//--------------------------------------------------------------------------------------------------------------------- +VExceptionInvalidHistory::VExceptionInvalidHistory(const VExceptionInvalidHistory &e) + :VException(e) +{} + +//--------------------------------------------------------------------------------------------------------------------- +VExceptionInvalidHistory &VExceptionInvalidHistory::operator=(const VExceptionInvalidHistory &e) +{ + if ( &e == this ) + { + return *this; + } + VException::operator=(e); + return *this; +} diff --git a/src/libs/ifc/exception/vexceptioninvalidhistory.h b/src/libs/ifc/exception/vexceptioninvalidhistory.h new file mode 100644 index 000000000..1f9fa23eb --- /dev/null +++ b/src/libs/ifc/exception/vexceptioninvalidhistory.h @@ -0,0 +1,47 @@ +/************************************************************************ + ** + ** @file vexceptioninvalidhistory.h + ** @author Roman Telezhynskyi + ** @date 10 7, 2019 + ** + ** @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) 2019 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 VEXCEPTIONINVALIDHISTORY_H +#define VEXCEPTIONINVALIDHISTORY_H + +#include "vexception.h" + +class VExceptionInvalidHistory : public VException +{ +public: + explicit VExceptionInvalidHistory(const QString &error); + VExceptionInvalidHistory(const VExceptionInvalidHistory &e); + VExceptionInvalidHistory &operator=(const VExceptionInvalidHistory &e); + virtual ~VExceptionInvalidHistory() V_NOEXCEPT_EXPR (true) Q_DECL_EQ_DEFAULT; + + Q_NORETURN virtual void raise() const override { throw *this; } + + Q_REQUIRED_RESULT virtual VExceptionInvalidHistory *clone() const override + { return new VExceptionInvalidHistory(*this); } +}; + +#endif // VEXCEPTIONINVALIDHISTORY_H diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp index 43a043e25..231a4e70f 100644 --- a/src/libs/ifc/xml/vdomdocument.cpp +++ b/src/libs/ifc/xml/vdomdocument.cpp @@ -742,6 +742,14 @@ QString VDomDocument::UnitsHelpString() return r; } +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VDomDocument::CreateElementWithText(const QString &tagName, const QString &text) +{ + QDomElement tag = createElement(tagName); + tag.appendChild(createTextNode(text)); + return tag; +} + //--------------------------------------------------------------------------------------------------------------------- bool VDomDocument::SaveDocument(const QString &fileName, QString &error) { diff --git a/src/libs/ifc/xml/vdomdocument.h b/src/libs/ifc/xml/vdomdocument.h index 5049c19b7..751d1493b 100644 --- a/src/libs/ifc/xml/vdomdocument.h +++ b/src/libs/ifc/xml/vdomdocument.h @@ -123,6 +123,8 @@ public: virtual void setXMLContent(const QString &fileName); static QString UnitsHelpString(); + QDomElement CreateElementWithText(const QString& tagName, const QString& text); + virtual bool SaveDocument(const QString &fileName, QString &error); QString Major() const; QString Minor() const; diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp index e61e32647..aba3b81be 100644 --- a/src/libs/ifc/xml/vpatternconverter.cpp +++ b/src/libs/ifc/xml/vpatternconverter.cpp @@ -1120,12 +1120,9 @@ void VPatternConverter::TagUnitToV0_2_0() Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FORMAT_VERSION(0, 2, 0), "Time to refactor the code."); - QDomElement unit = createElement(*strUnit); - QDomText newNodeText = createTextNode(MUnitV0_1_4()); - unit.appendChild(newNodeText); - QDomElement patternElement = documentElement(); - patternElement.insertAfter(unit, patternElement.firstChildElement(*strVersion)); + patternElement.insertAfter(CreateElementWithText(*strUnit, MUnitV0_1_4()), + patternElement.firstChildElement(*strVersion)); } //--------------------------------------------------------------------------------------------------------------------- @@ -1611,8 +1608,7 @@ void VPatternConverter::TagMeasurementsToV0_2_0() ms.removeAttribute(*strType); ms.removeAttribute(*strPath); - QDomText newNodeText = createTextNode(QFileInfo(m_convertedFileName).absoluteDir().relativeFilePath(path)); - ms.appendChild(newNodeText); + ms.appendChild(createTextNode(QFileInfo(m_convertedFileName).absoluteDir().relativeFilePath(path))); } //--------------------------------------------------------------------------------------------------------------------- @@ -1777,9 +1773,7 @@ void VPatternConverter::SaveChildrenToolUnionToV0_2_4(quint32 id, const QVector< for (auto child : children) { - QDomElement tagChild = createElement(*strChild); - tagChild.appendChild(createTextNode(QString().setNum(child))); - tagChildren.appendChild(tagChild); + tagChildren.appendChild(CreateElementWithText(*strChild, QString().setNum(child))); } toolUnion.appendChild(tagChildren); diff --git a/src/libs/ifc/xml/vvitconverter.cpp b/src/libs/ifc/xml/vvitconverter.cpp index 5c319c499..51d442650 100644 --- a/src/libs/ifc/xml/vvitconverter.cpp +++ b/src/libs/ifc/xml/vvitconverter.cpp @@ -168,18 +168,12 @@ void VVITConverter::AddNewTagsForV0_3_0() "Time to refactor the code."); QDomElement rootElement = this->documentElement(); - QDomNode refChild = rootElement.firstChildElement("version"); - - QDomElement ro = createElement(QStringLiteral("read-only")); - const QDomText roNodeText = createTextNode(falseStr); - ro.appendChild(roNodeText); - refChild = rootElement.insertAfter(ro, refChild); + QDomNode refChild = rootElement.firstChildElement(QStringLiteral("version")); + refChild = rootElement.insertAfter(CreateElementWithText(QStringLiteral("read-only"), falseStr), refChild); refChild = rootElement.insertAfter(createElement(QStringLiteral("notes")), refChild); - QDomElement unit = createElement("unit"); - unit.appendChild(createTextNode(MUnitV0_2_0())); - rootElement.insertAfter(unit, refChild); + rootElement.insertAfter(CreateElementWithText(QStringLiteral("unit"), MUnitV0_2_0()), refChild); } //--------------------------------------------------------------------------------------------------------------------- @@ -261,12 +255,8 @@ void VVITConverter::GenderV0_3_1() const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("sex")); QDomElement sex = nodeList.at(0).toElement(); - - QDomElement gender = createElement(QStringLiteral("gender")); - gender.appendChild(createTextNode(sex.text())); - QDomElement parent = sex.parentNode().toElement(); - parent.replaceChild(gender, sex); + parent.replaceChild(CreateElementWithText(QStringLiteral("gender"), sex.text()), sex); } //--------------------------------------------------------------------------------------------------------------------- @@ -276,14 +266,11 @@ void VVITConverter::PM_SystemV0_3_2() Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < FORMAT_VERSION(0, 3, 2), "Time to refactor the code."); - QDomElement pm_system = createElement(QStringLiteral("pm_system")); - pm_system.appendChild(createTextNode(QStringLiteral("998"))); - const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("personal")); QDomElement personal = nodeList.at(0).toElement(); QDomElement parent = personal.parentNode().toElement(); - parent.insertBefore(pm_system, personal); + parent.insertBefore(CreateElementWithText(QStringLiteral("pm_system"), QStringLiteral("998")), personal); } //--------------------------------------------------------------------------------------------------------------------- @@ -351,8 +338,6 @@ void VVITConverter::ConverCustomerNameToV0_4_0() personal.removeChild(familyNameNode); } - QDomElement customer = createElement(*strCustomer); - QString customerName; if (not givenName.isEmpty() && not familyName.isEmpty()) { @@ -367,11 +352,8 @@ void VVITConverter::ConverCustomerNameToV0_4_0() customerName = familyName; } - if (not customerName.isEmpty()) - { - customer.appendChild(createTextNode(customerName)); - } - personal.insertBefore(customer, personal.firstChild()); + personal.insertBefore(CreateElementWithText(*strCustomer, not customerName.isEmpty() ? customerName : QString()), + personal.firstChild()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/ifc/xml/vvstconverter.cpp b/src/libs/ifc/xml/vvstconverter.cpp index b6698739f..5e159bf29 100644 --- a/src/libs/ifc/xml/vvstconverter.cpp +++ b/src/libs/ifc/xml/vvstconverter.cpp @@ -158,21 +158,12 @@ void VVSTConverter::AddNewTagsForV0_4_0() "Time to refactor the code."); QDomElement rootElement = this->documentElement(); - QDomNode refChild = rootElement.firstChildElement("version"); + QDomNode refChild = rootElement.firstChildElement(QStringLiteral("version")); - { - QDomElement ro = createElement(QStringLiteral("read-only")); - const QDomText roNodeText = createTextNode(falseStr); - ro.appendChild(roNodeText); - refChild = rootElement.insertAfter(ro, refChild); - } + refChild = rootElement.insertAfter(CreateElementWithText(QStringLiteral("read-only"), falseStr), refChild); - { - QDomElement notes = createElement(QStringLiteral("notes")); - const QDomText nodeText = createTextNode(UniqueTagText(QStringLiteral("description"))); - notes.appendChild(nodeText); - rootElement.insertAfter(notes, refChild); - } + rootElement.insertAfter(CreateElementWithText(QStringLiteral("notes"), + UniqueTagText(QStringLiteral("description"))), refChild); } //--------------------------------------------------------------------------------------------------------------------- @@ -277,14 +268,11 @@ void VVSTConverter::PM_SystemV0_4_1() Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < FORMAT_VERSION(0, 4, 1), "Time to refactor the code."); - QDomElement pm_system = createElement(QStringLiteral("pm_system")); - pm_system.appendChild(createTextNode(QStringLiteral("998"))); - const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("size")); QDomElement personal = nodeList.at(0).toElement(); QDomElement parent = personal.parentNode().toElement(); - parent.insertBefore(pm_system, personal); + parent.insertBefore(CreateElementWithText(QStringLiteral("pm_system"), QStringLiteral("998")), personal); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vformat/vformat.pri b/src/libs/vformat/vformat.pri index 2d8f8f3ad..f3b883b34 100644 --- a/src/libs/vformat/vformat.pri +++ b/src/libs/vformat/vformat.pri @@ -3,11 +3,13 @@ SOURCES += \ $$PWD/vmeasurements.cpp \ - $$PWD/vlabeltemplate.cpp + $$PWD/vlabeltemplate.cpp \ + $$PWD/vpatternrecipe.cpp *msvc*:SOURCES += $$PWD/stable.cpp HEADERS += \ $$PWD/vmeasurements.h \ $$PWD/stable.h \ - $$PWD/vlabeltemplate.h + $$PWD/vlabeltemplate.h \ + $$PWD/vpatternrecipe.h diff --git a/src/libs/vformat/vlabeltemplate.cpp b/src/libs/vformat/vlabeltemplate.cpp index 4f97f5ee8..4cd759140 100644 --- a/src/libs/vformat/vlabeltemplate.cpp +++ b/src/libs/vformat/vlabeltemplate.cpp @@ -42,16 +42,12 @@ void VLabelTemplate::CreateEmptyTemplate() { clear(); QDomElement templateElement = this->createElement(TagTemplate); - - QDomElement version = createElement(TagVersion); - QDomText newNodeText = createTextNode(VLabelTemplateConverter::LabelTemplateMaxVerStr); - version.appendChild(newNodeText); - templateElement.appendChild(version); - + templateElement.appendChild(CreateElementWithText(TagVersion, VLabelTemplateConverter::LabelTemplateMaxVerStr)); templateElement.appendChild(createElement(TagLines)); this->appendChild(templateElement); - insertBefore(createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""), this->firstChild()); + insertBefore(createProcessingInstruction(QStringLiteral("xml"), + QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")), this->firstChild()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp index 9c11e28b5..521c4f0f7 100644 --- a/src/libs/vformat/vmeasurements.cpp +++ b/src/libs/vformat/vmeasurements.cpp @@ -664,27 +664,11 @@ void VMeasurements::CreateEmptyMultisizeFile(Unit unit, int baseSize, int baseHe QDomElement mElement = this->createElement(TagVST); mElement.appendChild(createComment(FileComment())); - - QDomElement version = createElement(TagVersion); - const QDomText newNodeText = createTextNode(VVSTConverter::MeasurementMaxVerStr); - version.appendChild(newNodeText); - mElement.appendChild(version); - - QDomElement ro = createElement(TagReadOnly); - const QDomText roNodeText = createTextNode(falseStr); - ro.appendChild(roNodeText); - mElement.appendChild(ro); - + mElement.appendChild(CreateElementWithText(TagVersion, VVSTConverter::MeasurementMaxVerStr)); + mElement.appendChild(CreateElementWithText(TagReadOnly, falseStr)); mElement.appendChild(createElement(TagNotes)); - - QDomElement mUnit = createElement(TagUnit); - const QDomText unitText = createTextNode(UnitsToStr(unit)); - mUnit.appendChild(unitText); - mElement.appendChild(mUnit); - - QDomElement system = createElement(TagPMSystem); - system.appendChild(createTextNode(ClearPMCode(p998_S))); - mElement.appendChild(system); + mElement.appendChild(CreateElementWithText(TagUnit, UnitsToStr(unit))); + mElement.appendChild(CreateElementWithText(TagPMSystem, ClearPMCode(p998_S))); QDomElement size = createElement(TagSize); SetAttribute(size, AttrBase, QString().setNum(baseSize)); @@ -697,7 +681,8 @@ void VMeasurements::CreateEmptyMultisizeFile(Unit unit, int baseSize, int baseHe mElement.appendChild(createElement(TagBodyMeasurements)); this->appendChild(mElement); - insertBefore(createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""), this->firstChild()); + insertBefore(createProcessingInstruction(QStringLiteral("xml"), + QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")), this->firstChild()); } //--------------------------------------------------------------------------------------------------------------------- @@ -707,37 +692,16 @@ void VMeasurements::CreateEmptyIndividualFile(Unit unit) QDomElement mElement = this->createElement(TagVIT); mElement.appendChild(createComment(FileComment())); - - QDomElement version = createElement(TagVersion); - const QDomText newNodeText = createTextNode(VVITConverter::MeasurementMaxVerStr); - version.appendChild(newNodeText); - mElement.appendChild(version); - - QDomElement ro = createElement(TagReadOnly); - const QDomText roNodeText = createTextNode(falseStr); - ro.appendChild(roNodeText); - mElement.appendChild(ro); - + mElement.appendChild(CreateElementWithText(TagVersion, VVITConverter::MeasurementMaxVerStr)); + mElement.appendChild(CreateElementWithText(TagReadOnly, falseStr)); mElement.appendChild(createElement(TagNotes)); - - QDomElement mUnit = createElement(TagUnit); - mUnit.appendChild(createTextNode(UnitsToStr(unit))); - mElement.appendChild(mUnit); - - QDomElement system = createElement(TagPMSystem); - system.appendChild(createTextNode(ClearPMCode(p998_S))); - mElement.appendChild(system); + mElement.appendChild(CreateElementWithText(TagUnit, UnitsToStr(unit))); + mElement.appendChild(CreateElementWithText(TagPMSystem, ClearPMCode(p998_S))); QDomElement personal = createElement(TagPersonal); personal.appendChild(createElement(TagCustomer)); - - QDomElement date = createElement(TagBirthDate); - date.appendChild(createTextNode(*defBirthDate)); - personal.appendChild(date); - - QDomElement gender = createElement(TagGender); - gender.appendChild(createTextNode(GenderToStr(GenderType::Unknown))); - personal.appendChild(gender); + personal.appendChild(CreateElementWithText(TagBirthDate, *defBirthDate)); + personal.appendChild(CreateElementWithText(TagGender, GenderToStr(GenderType::Unknown))); personal.appendChild(createElement(TagEmail)); mElement.appendChild(personal); @@ -745,7 +709,8 @@ void VMeasurements::CreateEmptyIndividualFile(Unit unit) mElement.appendChild(createElement(TagBodyMeasurements)); this->appendChild(mElement); - insertBefore(createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""), this->firstChild()); + insertBefore(createProcessingInstruction(QStringLiteral("xml"), + QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")), this->firstChild()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h index dadaec42c..214e00519 100644 --- a/src/libs/vformat/vmeasurements.h +++ b/src/libs/vformat/vmeasurements.h @@ -38,7 +38,8 @@ #include "../ifc/xml/vdomdocument.h" #include "../vmisc/def.h" -#include "../vpatterndb/vcontainer.h" + +class VContainer; enum class GenderType : char { Male, Female, Unknown }; diff --git a/src/libs/vformat/vpatternrecipe.cpp b/src/libs/vformat/vpatternrecipe.cpp new file mode 100644 index 000000000..5ebcf200a --- /dev/null +++ b/src/libs/vformat/vpatternrecipe.cpp @@ -0,0 +1,984 @@ +/************************************************************************ + ** + ** @file vpatternrecipe.cpp + ** @author Roman Telezhynskyi + ** @date 8 7, 2019 + ** + ** @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) 2019 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 "vpatternrecipe.h" +#include "../vmisc/projectversion.h" +#include "../vmisc/vabstractapplication.h" +#include "../ifc/xml/vabstractpattern.h" +#include "../ifc/exception/vexceptioninvalidhistory.h" +#include "../vpatterndb/vcontainer.h" +#include "../vgeometry/vpointf.h" +#include "../vgeometry/vcubicbezier.h" +#include "../vgeometry/vsplinepath.h" +#include "../vgeometry/vcubicbezierpath.h" +#include "../vtools/tools/drawTools/drawtools.h" + +namespace +{ +#define TagStep QStringLiteral("step") + +#define AttrLabel QStringLiteral("label") +#define AttrLengthValue QStringLiteral("lengthValue") +#define AttrAngleValue QStringLiteral("angleValue") +#define AttrAngle1Value QStringLiteral("angle1Value") +#define AttrAngle2Value QStringLiteral("angle2Value") +#define AttrLength1Value QStringLiteral("length1Value") +#define AttrLength2Value QStringLiteral("length2Value") +#define AttrRadiusValue QStringLiteral("radiusValue") +#define AttrC1RadiusValue QStringLiteral("c1RadiusValue") +#define AttrC2RadiusValue QStringLiteral("c2RadiusValue") +#define AttrCRadiusValue QStringLiteral("cRadiusValue") +#define AttrRadius1Value QStringLiteral("radius1Value") +#define AttrRadius2Value QStringLiteral("radius2Value") +#define AttrRotationAngleValue QStringLiteral("rotationAngleValue") + +//--------------------------------------------------------------------------------------------------------------------- +inline QString FileComment() +{ + return QStringLiteral("Recipe created with Valentina v%1 (https://valentinaproject.bitbucket.io/).") + .arg(APP_VERSION_STR); +} + +//--------------------------------------------------------------------------------------------------------------------- +template +T *GetPatternTool(quint32 id) +{ + T* tool = qobject_cast(VAbstractPattern::getTool(id)); + if (not tool) + { + throw VExceptionInvalidHistory(QObject::tr("Cannot cast tool with id '%1'.").arg(id)); + } + return tool; +} +} + +//--------------------------------------------------------------------------------------------------------------------- +VPatternRecipe::VPatternRecipe(VContainer *data, VAbstractPattern *pattern, QObject *parent) + : VDomDocument(parent), + m_data(data), + m_pattern(pattern) +{ + SCASSERT(data != nullptr) + SCASSERT(pattern != nullptr) + + QDomElement recipeElement = createElement(QStringLiteral("recipe")); + recipeElement.appendChild(createComment(FileComment())); + SetAttribute(recipeElement, QStringLiteral("version"), QStringLiteral("0.1")); + + recipeElement.appendChild(Prerequisite()); + recipeElement.appendChild(Content()); + + appendChild(recipeElement); + insertBefore(createProcessingInstruction(QStringLiteral("xml"), + QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")), firstChild()); +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Prerequisite() +{ + /* + + + + + + + + + + + + */ + QDomElement prerequisiteElement = createElement(QStringLiteral("prerequisite")); + + prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("valentina"), APP_VERSION_STR)); + prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("unit"), UnitsToStr(qApp->patternUnit()))); + prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("description"), m_pattern->GetDescription())); + prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("notes"), m_pattern->GetNotes())); + prerequisiteElement.appendChild(Measurements()); + prerequisiteElement.appendChild(Increments()); + prerequisiteElement.appendChild(PreviewCalculations()); + + return prerequisiteElement; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Measurements() +{ + QDomElement measurements = createElement(QStringLiteral("measurements")); + + QList> patternMeasurements = m_data->DataMeasurements().values(); + + // Resore order + std::sort(patternMeasurements.begin(), patternMeasurements.end(), + [](const QSharedPointer &a, const QSharedPointer &b) + {return a->Index() > b->Index();}); + + for(auto &m : patternMeasurements) + { + measurements.appendChild(Measurement(m)); + } + + return measurements; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Measurement(const QSharedPointer &m) +{ + /* + * + * + * + */ + QDomElement measurement = createElement(QStringLiteral("measurement")); + + SetAttribute(measurement, QStringLiteral("description"), m->GetDescription()); + SetAttribute(measurement, QStringLiteral("fullName"), m->GetGuiText()); + SetAttribute(measurement, QStringLiteral("name"), m->GetName()); + SetAttribute(measurement, QStringLiteral("formula"), m->GetFormula()); // TODO: localize + SetAttribute(measurement, QStringLiteral("value"), *m->GetValue()); + + return measurement; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Increments() +{ + QDomElement increments = createElement(QStringLiteral("increments")); + + QList> patternIncrements = m_data->DataIncrements().values(); + + // Resore order + std::sort(patternIncrements.begin(), patternIncrements.end(), + [](const QSharedPointer &a, const QSharedPointer &b) + {return a->GetIndex() > b->GetIndex();}); + + for(auto &incr : patternIncrements) + { + if (not incr->IsPreviewCalculation()) + { + increments.appendChild(Increment(incr)); + } + } + + return increments; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PreviewCalculations() +{ + QDomElement previewCalculations = createElement(QStringLiteral("previewCalculations")); + + QList> patternIncrements = m_data->DataIncrements().values(); + + // Resore order + std::sort(patternIncrements.begin(), patternIncrements.end(), + [](const QSharedPointer &a, const QSharedPointer &b) + {return a->GetIndex() > b->GetIndex();}); + + for(auto &incr : patternIncrements) + { + if (incr->IsPreviewCalculation()) + { + previewCalculations.appendChild(Increment(incr)); + } + } + + return previewCalculations; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Increment(const QSharedPointer &incr) +{ + QDomElement measurement = createElement(QStringLiteral("increment")); + + SetAttribute(measurement, QStringLiteral("description"), incr->GetDescription()); + SetAttribute(measurement, QStringLiteral("name"), incr->GetName()); + + if (incr->GetType() != VarType::IncrementSeparator) + { + SetAttribute(measurement, QStringLiteral("formula"), incr->GetFormula()); // TODO: localize + SetAttribute(measurement, QStringLiteral("value"), *incr->GetValue()); + } + else + { + SetAttribute(measurement, QStringLiteral("separator"), true); + } + + return measurement; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Content() +{ + QDomElement content = createElement(QStringLiteral("content")); + + const QDomNodeList draws = m_pattern->documentElement().elementsByTagName(VAbstractPattern::TagDraw); + for (int i=0; i < draws.size(); ++i) + { + QDomElement draw = draws.at(i).toElement(); + if (draw.isNull()) + { + throw VExceptionInvalidHistory(tr("Invalid tag %1").arg(VAbstractPattern::TagDraw)); + } + + content.appendChild(Draft(draw)); + } + + return content; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Draft(const QDomElement &draft) +{ + QDomElement recipeDraft = createElement(QStringLiteral("draft")); + + const QString draftName = draft.attribute(QStringLiteral("name")); + SetAttribute(recipeDraft, QStringLiteral("name"), draftName); + + QVector *history = m_pattern->getHistory(); + for (auto &record : *history) + { + if (record.getNameDraw() == draftName) + { + QDomElement step = Step(record); + if (not step.isNull()) + { + recipeDraft.appendChild(step); + } + } + } + + return recipeDraft; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Step(const VToolRecord &tool) +{ + // This check helps to find missed tools in the switch + Q_STATIC_ASSERT_X(static_cast(Tool::LAST_ONE_DO_NOT_USE) == 55, "Not all tools were used in history."); + + const QDomElement domElem = m_pattern->elementById(tool.getId()); + if (not domElem.isElement()) + { + throw VExceptionInvalidHistory(tr("Can't find element by id '%1'").arg(tool.getId())); + } + try + { +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wswitch-default") + switch (tool.getTypeTool()) + { + case Tool::Arrow: + case Tool::SinglePoint: + case Tool::DoublePoint: + case Tool::LinePoint: + case Tool::AbstractSpline: + case Tool::Cut: + case Tool::Midpoint:// Same as Tool::AlongLine, but tool will never has such type + case Tool::ArcIntersectAxis:// Same as Tool::CurveIntersectAxis, but tool will never has such type + case Tool::LAST_ONE_DO_NOT_USE: + Q_UNREACHABLE(); //-V501 + break; + case Tool::BasePoint: + return BasePoint(tool); + case Tool::EndLine: + return EndLine(tool); + case Tool::Line: + return Line(tool); + case Tool::AlongLine: + return AlongLine(tool); + case Tool::ShoulderPoint: + return ShoulderPoint(tool); + case Tool::Normal: + return Normal(tool); + case Tool::Bisector: + return Bisector(tool); + case Tool::LineIntersect: + return LineIntersect(tool); + case Tool::Spline: + return Spline(tool); + case Tool::CubicBezier: + return CubicBezier(tool); + case Tool::Arc: + return Arc(tool); + case Tool::ArcWithLength: + return ArcWithLength(tool); + case Tool::SplinePath: + return SplinePath(tool); + case Tool::CubicBezierPath: + return CubicBezierPath(tool); + case Tool::PointOfContact: + return PointOfContact(tool); + case Tool::Height: + return Height(tool); + case Tool::Triangle: + return Triangle(tool); + case Tool::PointOfIntersection: + return PointOfIntersection(tool); + case Tool::CutArc: + return CutArc(tool); + case Tool::CutSpline: + return CutSpline(tool); + case Tool::CutSplinePath: + return CutSplinePath(tool); + case Tool::LineIntersectAxis: + return LineIntersectAxis(tool); + case Tool::CurveIntersectAxis: + return CurveIntersectAxis(tool); + case Tool::PointOfIntersectionArcs: + return PointOfIntersectionArcs(tool); + case Tool::PointOfIntersectionCircles: + return PointOfIntersectionCircles(tool); + case Tool::PointOfIntersectionCurves: + return PointOfIntersectionCurves(tool); + case Tool::PointFromCircleAndTangent: + return PointFromCircleAndTangent(tool); + case Tool::PointFromArcAndTangent: + return PointFromArcAndTangent(tool); + case Tool::TrueDarts: + return TrueDarts(tool); + case Tool::EllipticalArc: + return EllipticalArc(tool); + //Because "history" not only show history of pattern, but help restore current data for each pattern's + //piece, we need add record about details and nodes, but don't show them. + case Tool::Piece: + case Tool::UnionDetails: + case Tool::NodeArc: + case Tool::NodeElArc: + case Tool::NodePoint: + case Tool::NodeSpline: + case Tool::NodeSplinePath: + case Tool::Group: + case Tool::Rotation: + case Tool::FlippingByLine: + case Tool::FlippingByAxis: + case Tool::Move: + case Tool::PiecePath: + case Tool::Pin: + case Tool::PlaceLabel: + case Tool::InsertNode: + case Tool::DuplicateDetail: + return QDomElement(); + } +QT_WARNING_POP + } + catch (const VExceptionBadId &e) + { + throw VExceptionInvalidHistory(e.ErrorMessage()); + } + + throw VExceptionInvalidHistory(tr("Can't create history record for the tool.")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::BasePoint(const VToolRecord &record) +{ + VToolBasePoint *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + ToolAttributes(step, tool); + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::EndLine(const VToolRecord &record) +{ + VToolEndLine *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrBasePoint, tool->BasePointName()); + Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue); + Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Line(const VToolRecord &record) +{ + VToolLine *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + SetAttribute(step, AttrType, QStringLiteral("segment")); + SetAttribute(step, AttrFirstPoint, tool->FirstPointName()); + SetAttribute(step, AttrSecondPoint, tool->SecondPointName()); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::AlongLine(const VToolRecord &record) +{ + VToolAlongLine *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrBasePoint, tool->BasePointName()); + SetAttribute(step, AttrSecondPoint, tool->SecondPointName()); + Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::ShoulderPoint(const VToolRecord &record) +{ + VToolShoulderPoint *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrP1Line, tool->BasePointName()); + SetAttribute(step, AttrP2Line, tool->SecondPointName()); + SetAttribute(step, AttrPShoulder, tool->ShoulderPointName()); + Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Normal(const VToolRecord &record) +{ + VToolNormal *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrFirstPoint, tool->BasePointName()); + SetAttribute(step, AttrSecondPoint, tool->SecondPointName()); + Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue); + SetAttribute(step, AttrAngle, tool->GetAngle()); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Bisector(const VToolRecord &record) +{ + VToolBisector *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrFirstPoint, tool->FirstPointName()); + SetAttribute(step, AttrSecondPoint, tool->BasePointName()); + SetAttribute(step, AttrSecondPoint, tool->ThirdPointName()); + Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::LineIntersect(const VToolRecord &record) +{ + VToolLineIntersect *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + + SetAttribute(step, AttrP1Line1, tool->Line1P1Name()); + SetAttribute(step, AttrP1Line2, tool->Line1P2Name()); + SetAttribute(step, AttrP1Line2, tool->Line2P1Name()); + SetAttribute(step, AttrP2Line2, tool->Line2P2Name()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Spline(const VToolRecord &record) +{ + VToolSpline *tool = GetPatternTool(record.getId()); + VSpline spl = tool->getSpline(); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + + SetAttribute(step, AttrPoint1, spl.GetP1().name()); + SetAttribute(step, AttrPoint4, spl.GetP4().name()); + + SetAttribute(step, AttrAngle1, spl.GetStartAngleFormula()); + SetAttribute(step, AttrAngle1Value, spl.GetStartAngle()); + + SetAttribute(step, AttrAngle2, spl.GetEndAngleFormula()); + SetAttribute(step, AttrAngle2Value, spl.GetEndAngle()); + + SetAttribute(step, AttrLength1, spl.GetC1LengthFormula()); + SetAttribute(step, AttrLength1Value, spl.GetC1Length()); + + SetAttribute(step, AttrLength2, spl.GetC2LengthFormula()); + SetAttribute(step, AttrLength2Value, spl.GetC2Length()); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::CubicBezier(const VToolRecord &record) +{ + VToolCubicBezier *tool = GetPatternTool(record.getId()); + VCubicBezier spl = tool->getSpline(); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrPoint1, spl.GetP1().name()); + SetAttribute(step, AttrPoint2, spl.GetP2().name()); + SetAttribute(step, AttrPoint3, spl.GetP3().name()); + SetAttribute(step, AttrPoint4, spl.GetP4().name()); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Arc(const VToolRecord &record) +{ + VToolArc *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrCenter, tool->CenterPointName()); + Formula(step, tool->GetFormulaRadius(), AttrRadius, AttrRadiusValue); + Formula(step, tool->GetFormulaF1(), AttrAngle1, AttrAngle1Value); + Formula(step, tool->GetFormulaF2(), AttrAngle2, AttrAngle2Value); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::ArcWithLength(const VToolRecord &record) +{ + VToolArcWithLength *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrCenter, tool->CenterPointName()); + Formula(step, tool->GetFormulaRadius(), AttrRadius, AttrRadiusValue); + Formula(step, tool->GetFormulaF1(), AttrAngle1, AttrAngle1Value); + Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::SplinePath(const VToolRecord &record) +{ + VToolSplinePath *tool = GetPatternTool(record.getId()); + VSplinePath spl = tool->getSplinePath(); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + + QDomElement nodes = createElement(QStringLiteral("nodes")); + QVector path = spl.GetSplinePath(); + + if (path.isEmpty()) + { + throw VExceptionInvalidHistory(QObject::tr("Empty list of nodes for tool with id '%1'.").arg(record.getId())); + } + + for (auto &pathNode : path) + { + QDomElement node = createElement(QStringLiteral("node")); + + SetAttribute(node, AttrPSpline, pathNode.P().name()); + + SetAttribute(node, AttrAngle1, pathNode.Angle1Formula()); + SetAttribute(node, AttrAngle1Value, pathNode.Angle1()); + + SetAttribute(node, AttrAngle2, pathNode.Angle2Formula()); + SetAttribute(node, AttrAngle2Value, pathNode.Angle2()); + + SetAttribute(node, AttrLength1, pathNode.Length1Formula()); + SetAttribute(node, AttrLength1Value, pathNode.Length1()); + + SetAttribute(node, AttrLength2, pathNode.Length2Formula()); + SetAttribute(node, AttrLength2Value, pathNode.Length2()); + + nodes.appendChild(node); + } + + step.appendChild(nodes); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::CubicBezierPath(const VToolRecord &record) +{ + VToolCubicBezierPath *tool = GetPatternTool(record.getId()); + VCubicBezierPath spl = tool->getSplinePath(); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + + QDomElement nodes = createElement(QStringLiteral("nodes")); + QVector path = spl.GetSplinePath(); + + if (path.isEmpty()) + { + throw VExceptionInvalidHistory(QObject::tr("Empty list of nodes for tool with id '%1'.").arg(record.getId())); + } + + for (auto &pathNode : path) + { + QDomElement node = createElement(QStringLiteral("node")); + + SetAttribute(node, AttrPSpline, pathNode.P().name()); + + nodes.appendChild(node); + } + + step.appendChild(nodes); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointOfContact(const VToolRecord &record) +{ + VToolPointOfContact *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrCenter, tool->ArcCenterPointName()); + SetAttribute(step, AttrFirstPoint, tool->FirstPointName()); + SetAttribute(step, AttrSecondPoint, tool->SecondPointName()); + Formula(step, tool->getArcRadius(), AttrRadius, AttrRadiusValue); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Height(const VToolRecord &record) +{ + VToolHeight *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrBasePoint, tool->BasePointName()); + SetAttribute(step, AttrP1Line, tool->FirstLinePointName()); + SetAttribute(step, AttrP2Line, tool->SecondLinePointName()); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::Triangle(const VToolRecord &record) +{ + VToolTriangle *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrAxisP1, tool->AxisP1Name()); + SetAttribute(step, AttrAxisP2, tool->AxisP2Name()); + SetAttribute(step, AttrFirstPoint, tool->FirstPointName()); + SetAttribute(step, AttrSecondPoint, tool->SecondPointName()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointOfIntersection(const VToolRecord &record) +{ + VToolPointOfIntersection *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrFirstPoint, tool->FirstPointName()); + SetAttribute(step, AttrSecondPoint, tool->SecondPointName()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::CutArc(const VToolRecord &record) +{ + VToolCutArc *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + Formula(step, tool->GetFormula(), AttrLength, AttrLengthValue); + SetAttribute(step, AttrArc, tool->CurveName()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::CutSpline(const VToolRecord &record) +{ + VToolCutSpline *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + Formula(step, tool->GetFormula(), AttrLength, AttrLengthValue); + SetAttribute(step, VToolCutSpline::AttrSpline, tool->CurveName()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::CutSplinePath(const VToolRecord &record) +{ + VToolCutSplinePath *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + Formula(step, tool->GetFormula(), AttrLength, AttrLengthValue); + SetAttribute(step, VToolCutSplinePath::AttrSplinePath, tool->CurveName()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::LineIntersectAxis(const VToolRecord &record) +{ + VToolLineIntersectAxis *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrBasePoint, tool->BasePointName()); + SetAttribute(step, AttrP1Line, tool->FirstLinePoint()); + SetAttribute(step, AttrP2Line, tool->SecondLinePoint()); + Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::CurveIntersectAxis(const VToolRecord &record) +{ + VToolCurveIntersectAxis *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrBasePoint, tool->BasePointName()); + SetAttribute(step, AttrCurve, tool->CurveName()); + Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue); + LineAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointOfIntersectionArcs(const VToolRecord &record) +{ + VToolPointOfIntersectionArcs *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrFirstArc, tool->FirstArcName()); + SetAttribute(step, AttrSecondArc, tool->FirstArcName()); + SetAttribute(step, AttrCrossPoint, static_cast(tool->GetCrossCirclesPoint())); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointOfIntersectionCircles(const VToolRecord &record) +{ + VToolPointOfIntersectionCircles *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrC1Center, tool->FirstCircleCenterPointName()); + SetAttribute(step, AttrC2Center, tool->SecondCircleCenterPointName()); + Formula(step, tool->GetFirstCircleRadius(), AttrC1Radius, AttrC1RadiusValue); + Formula(step, tool->GetSecondCircleRadius(), AttrC2Radius, AttrC2RadiusValue); + SetAttribute(step, AttrCrossPoint, static_cast(tool->GetCrossCirclesPoint())); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointOfIntersectionCurves(const VToolRecord &record) +{ + VToolPointOfIntersectionCurves *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrCurve1, tool->FirstCurveName()); + SetAttribute(step, AttrCurve2, tool->FirstCurveName()); + SetAttribute(step, AttrVCrossPoint, static_cast(tool->GetVCrossPoint())); + SetAttribute(step, AttrHCrossPoint, static_cast(tool->GetHCrossPoint())); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointFromCircleAndTangent(const VToolRecord &record) +{ + VToolPointFromCircleAndTangent *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrCCenter, tool->CircleCenterPointName()); + SetAttribute(step, AttrTangent, tool->TangentPointName()); + Formula(step, tool->GetCircleRadius(), AttrCRadius, AttrCRadiusValue); + SetAttribute(step, AttrCrossPoint, static_cast(tool->GetCrossCirclesPoint())); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::PointFromArcAndTangent(const VToolRecord &record) +{ + VToolPointFromArcAndTangent *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrArc, tool->ArcName()); + SetAttribute(step, AttrTangent, tool->TangentPointName()); + SetAttribute(step, AttrCrossPoint, static_cast(tool->GetCrossCirclesPoint())); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::TrueDarts(const VToolRecord &record) +{ + VToolTrueDarts *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + SetAttribute(step, AttrType, VToolTrueDarts::ToolType); + SetAttribute(step, AttrPoint1, tool->nameP1()); + SetAttribute(step, AttrPoint2, tool->nameP2()); + SetAttribute(step, AttrBaseLineP1, tool->BaseLineP1Name()); + SetAttribute(step, AttrBaseLineP2, tool->BaseLineP2Name()); + SetAttribute(step, AttrDartP1, tool->DartP1Name()); + SetAttribute(step, AttrDartP2, tool->DartP2Name()); + SetAttribute(step, AttrDartP3, tool->DartP3Name()); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDomElement VPatternRecipe::EllipticalArc(const VToolRecord &record) +{ + VToolEllipticalArc *tool = GetPatternTool(record.getId()); + + QDomElement step = createElement(TagStep); + + ToolAttributes(step, tool); + SetAttribute(step, AttrCenter, tool->CenterPointName()); + Formula(step, tool->GetFormulaRadius1(), AttrRadius1, AttrRadius1Value); + Formula(step, tool->GetFormulaRadius2(), AttrRadius2, AttrRadius2Value); + Formula(step, tool->GetFormulaF1(), AttrAngle1, AttrAngle1Value); + Formula(step, tool->GetFormulaF2(), AttrAngle2, AttrAngle2Value); + Formula(step, tool->GetFormulaRotationAngle(), AttrRotationAngle, AttrRotationAngleValue); + + CurveAttributes(step, tool); + + return step; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VPatternRecipe::Formula(QDomElement &step, const VFormula &formula, const QString &formulaStr, + const QString &formulaValue) +{ + if (formula.error()) + { + throw VExceptionInvalidHistory(QObject::tr("Invalid formula '%1' for tool with id '%2'. %3.") + .arg(formula.GetFormula(FormulaType::FromSystem)) + .arg(formula.getToolId()) + .arg(formula.Reason())); + } + + SetAttribute(step, formulaStr, formula.GetFormula(FormulaType::FromSystem)); + SetAttribute(step, formulaValue, formula.getDoubleValue()); +} + +//--------------------------------------------------------------------------------------------------------------------- +template +inline void VPatternRecipe::LineAttributes(QDomElement &step, T *tool) +{ + SetAttribute(step, AttrLineColor, tool->GetLineColor()); + SetAttribute(step, AttrTypeLine, tool->getLineType()); +} + +//--------------------------------------------------------------------------------------------------------------------- +template +void VPatternRecipe::CurveAttributes(QDomElement &step, T *tool) +{ + SetAttribute(step, AttrLineColor, tool->GetLineColor()); + SetAttribute(step, AttrPenStyle, tool->GetPenStyle()); + SetAttribute(step, AttrAScale, tool->GetApproximationScale()); + SetAttribute(step, AttrDuplicate, tool->GetDuplicate()); +} + +//--------------------------------------------------------------------------------------------------------------------- +template +inline void VPatternRecipe::ToolAttributes(QDomElement &step, T *tool) +{ + SetAttribute(step, AttrType, T::ToolType); + SetAttribute(step, AttrLabel, tool->name()); +} diff --git a/src/libs/vformat/vpatternrecipe.h b/src/libs/vformat/vpatternrecipe.h new file mode 100644 index 000000000..a65206adc --- /dev/null +++ b/src/libs/vformat/vpatternrecipe.h @@ -0,0 +1,110 @@ +/************************************************************************ + ** + ** @file vpatternrecipe.h + ** @author Roman Telezhynskyi + ** @date 8 7, 2019 + ** + ** @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) 2019 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 VPATTERNRECIPE_H +#define VPATTERNRECIPE_H + +#include "../ifc/xml/vdomdocument.h" + +class VContainer; +class VAbstractPattern; +class VMeasurement; +class VIncrement; +class VToolRecord; +class VFormula; + +class VPatternRecipe : public VDomDocument +{ + Q_DECLARE_TR_FUNCTIONS(VPatternRecipe) +public: + VPatternRecipe(VContainer *data, VAbstractPattern *pattern, QObject *parent = nullptr); + virtual ~VPatternRecipe() Q_DECL_EQ_DEFAULT; + +private: + Q_DISABLE_COPY(VPatternRecipe) + + VContainer *m_data; + VAbstractPattern *m_pattern; + + QDomElement Prerequisite(); + + QDomElement Measurements(); + QDomElement Measurement(const QSharedPointer &m); + + QDomElement Increments(); + QDomElement PreviewCalculations(); + QDomElement Increment(const QSharedPointer &incr); + + QDomElement Content(); + + QDomElement Draft(const QDomElement &draft); + QDomElement Step(const VToolRecord &tool); + + QDomElement BasePoint(const VToolRecord &record); + QDomElement EndLine(const VToolRecord &record); + QDomElement Line(const VToolRecord &record); + QDomElement AlongLine(const VToolRecord &record); + QDomElement ShoulderPoint(const VToolRecord &record); + QDomElement Normal(const VToolRecord &record); + QDomElement Bisector(const VToolRecord &record); + QDomElement LineIntersect(const VToolRecord &record); + QDomElement Spline(const VToolRecord &record); + QDomElement CubicBezier(const VToolRecord &record); + QDomElement Arc(const VToolRecord &record); + QDomElement ArcWithLength(const VToolRecord &record); + QDomElement SplinePath(const VToolRecord &record); + QDomElement CubicBezierPath(const VToolRecord &record); + QDomElement PointOfContact(const VToolRecord &record); + QDomElement Height(const VToolRecord &record); + QDomElement Triangle(const VToolRecord &record); + QDomElement PointOfIntersection(const VToolRecord &record); + QDomElement CutArc(const VToolRecord &record); + QDomElement CutSpline(const VToolRecord &record); + QDomElement CutSplinePath(const VToolRecord &record); + QDomElement LineIntersectAxis(const VToolRecord &record); + QDomElement CurveIntersectAxis(const VToolRecord &record); + QDomElement PointOfIntersectionArcs(const VToolRecord &record); + QDomElement PointOfIntersectionCircles(const VToolRecord &record); + QDomElement PointOfIntersectionCurves(const VToolRecord &record); + QDomElement PointFromCircleAndTangent(const VToolRecord &record); + QDomElement PointFromArcAndTangent(const VToolRecord &record); + QDomElement TrueDarts(const VToolRecord &record); + QDomElement EllipticalArc(const VToolRecord &record); + + void Formula(QDomElement &step, const VFormula &formula, const QString &formulaStr, const QString &formulaValue); + + template + void ToolAttributes(QDomElement &step, T* tool); + + template + void LineAttributes(QDomElement &step, T* tool); + + template + void CurveAttributes(QDomElement &step, T* tool); +}; + +#endif // VPATTERNRECIPE_H diff --git a/src/libs/vpatterndb/vformula.h b/src/libs/vpatterndb/vformula.h index a645d292a..5f5eb4cf8 100644 --- a/src/libs/vpatterndb/vformula.h +++ b/src/libs/vpatterndb/vformula.h @@ -36,7 +36,13 @@ #include #include -enum class FormulaType : char{ToUser, FromUser}; +enum class FormulaType : char +{ + ToUser = 0, + FromUser = 1, + ToSystem = FromUser, + FromSystem = ToUser +}; class VContainer; class VFormulaData; @@ -55,7 +61,7 @@ public: bool operator!=(const VFormula &formula) const; QString GetFormula(FormulaType type = FormulaType::ToUser) const; - void SetFormula(const QString &value, FormulaType type = FormulaType::ToUser); + void SetFormula(const QString &value, FormulaType type = FormulaType::FromSystem); QString getStringValue() const; qreal getDoubleValue() const; diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.cpp index 8260beb7d..f0821dcca 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.cpp @@ -487,6 +487,18 @@ QString VAbstractSpline::name() const return ObjectName(m_id); } +//--------------------------------------------------------------------------------------------------------------------- +qreal VAbstractSpline::GetApproximationScale() const +{ + return VAbstractTool::data.GeometricObject(m_id)->GetApproximationScale(); +} + +//--------------------------------------------------------------------------------------------------------------------- +quint32 VAbstractSpline::GetDuplicate() const +{ + return VAbstractTool::data.GeometricObject(m_id)->GetDuplicate(); +} + //--------------------------------------------------------------------------------------------------------------------- void VAbstractSpline::GroupVisibility(quint32 object, bool visible) { diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.h b/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.h index 3c3c25811..b50e9dd5e 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.h +++ b/src/libs/vtools/tools/drawTools/toolcurve/vabstractspline.h @@ -90,6 +90,10 @@ public: QString name() const; + qreal GetApproximationScale() const; + + quint32 GetDuplicate() const; + virtual void GroupVisibility(quint32 object, bool visible) override; public slots: virtual void FullUpdateFromFile () override; diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp index 06ff00855..4a0070e8b 100644 --- a/src/libs/vtools/tools/vtoolseamallowance.cpp +++ b/src/libs/vtools/tools/vtoolseamallowance.cpp @@ -1930,9 +1930,8 @@ void VToolSeamAllowance::AddPointRecords(VAbstractPattern *doc, QDomElement &dom QDomElement pinsElement = doc->createElement(tag); for (auto record : records) { - QDomElement recordNode = doc->createElement(VToolSeamAllowance::TagRecord); - recordNode.appendChild(doc->createTextNode(QString().setNum(record))); - pinsElement.appendChild(recordNode); + pinsElement.appendChild(doc->CreateElementWithText(VToolSeamAllowance::TagRecord, + QString().setNum(record))); } domElement.appendChild(pinsElement); } diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp index 12407d267..13c5b753c 100644 --- a/src/libs/vtools/tools/vtooluniondetails.cpp +++ b/src/libs/vtools/tools/vtooluniondetails.cpp @@ -816,9 +816,7 @@ void SaveChildren(VAbstractPattern *doc, quint32 id, QDomElement section, const { for (auto child : children) { - QDomElement tagChild = doc->createElement(VToolUnionDetails::TagChild); - tagChild.appendChild(doc->createTextNode(QString().setNum(child))); - section.appendChild(tagChild); + section.appendChild(doc->CreateElementWithText(VToolUnionDetails::TagChild, QString().setNum(child))); } GetTagChildren(doc, id).appendChild(section); diff --git a/src/test/ValentinaTest/tst_vmeasurements.cpp b/src/test/ValentinaTest/tst_vmeasurements.cpp index 69fd07b35..96068026e 100644 --- a/src/test/ValentinaTest/tst_vmeasurements.cpp +++ b/src/test/ValentinaTest/tst_vmeasurements.cpp @@ -30,6 +30,7 @@ #include "../vformat/vmeasurements.h" #include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vvitconverter.h" +#include "../vpatterndb/vcontainer.h" #include "../vpatterndb/pmsystems.h" #include