diff --git a/dist/OBS_debian/debian.control b/dist/OBS_debian/debian.control index 63e057ff6..8f3c4651c 100644 --- a/dist/OBS_debian/debian.control +++ b/dist/OBS_debian/debian.control @@ -12,11 +12,12 @@ Build-Depends: debhelper (>= 8.0.0), libqt5opengl5-dev (>= 5.4.0) Standards-Version: 3.9.5 Homepage: https://valentinaproject.bitbucket.io/ -Vcs-Browser: https://bitbucket.org/dismine/valentina +Vcs-Browser: https://gitlab.com/smart-pattern/valentina Package: valentina Architecture: i386 amd64 -Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libqt5core5a (>= 5.4.0) | libqt5core5 (>= 5.4.0), libqt5gui5 (>= 5.4.0) | libqt5gui5-gles (>= 5.4.0), libqt5printsupport5 (>= 5.4.0), libqt5svg5 (>= 5.4.0), libqt5widgets5 (>= 5.4.0), libqt5xml5 (>= 5.4.0), libqt5xmlpatterns5 (>= 5.4.0), libqt5concurrent5(>= 5.4.0), libqt5opengl5 (>= 5.4.0), libstdc++6 (>= 4.8), xpdf +Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libqt5core5a (>= 5.4.0) | libqt5core5 (>= 5.4.0), libqt5gui5 (>= 5.4.0) | libqt5gui5-gles (>= 5.4.0), libqt5printsupport5 (>= 5.4.0), libqt5svg5 (>= 5.4.0), libqt5widgets5 (>= 5.4.0), libqt5xml5 (>= 5.4.0), libqt5xmlpatterns5 (>= 5.4.0), libqt5concurrent5(>= 5.4.0), libqt5opengl5 (>= 5.4.0), libstdc++6 (>= 4.8) +Suggests: xpdf Conflicts: seamly2d Description: Pattern making program. Valentina is a cross-platform patternmaking program which allows designers diff --git a/dist/debian/control b/dist/debian/control index 63e057ff6..8f3c4651c 100644 --- a/dist/debian/control +++ b/dist/debian/control @@ -12,11 +12,12 @@ Build-Depends: debhelper (>= 8.0.0), libqt5opengl5-dev (>= 5.4.0) Standards-Version: 3.9.5 Homepage: https://valentinaproject.bitbucket.io/ -Vcs-Browser: https://bitbucket.org/dismine/valentina +Vcs-Browser: https://gitlab.com/smart-pattern/valentina Package: valentina Architecture: i386 amd64 -Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libqt5core5a (>= 5.4.0) | libqt5core5 (>= 5.4.0), libqt5gui5 (>= 5.4.0) | libqt5gui5-gles (>= 5.4.0), libqt5printsupport5 (>= 5.4.0), libqt5svg5 (>= 5.4.0), libqt5widgets5 (>= 5.4.0), libqt5xml5 (>= 5.4.0), libqt5xmlpatterns5 (>= 5.4.0), libqt5concurrent5(>= 5.4.0), libqt5opengl5 (>= 5.4.0), libstdc++6 (>= 4.8), xpdf +Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libqt5core5a (>= 5.4.0) | libqt5core5 (>= 5.4.0), libqt5gui5 (>= 5.4.0) | libqt5gui5-gles (>= 5.4.0), libqt5printsupport5 (>= 5.4.0), libqt5svg5 (>= 5.4.0), libqt5widgets5 (>= 5.4.0), libqt5xml5 (>= 5.4.0), libqt5xmlpatterns5 (>= 5.4.0), libqt5concurrent5(>= 5.4.0), libqt5opengl5 (>= 5.4.0), libstdc++6 (>= 4.8) +Suggests: xpdf Conflicts: seamly2d Description: Pattern making program. Valentina is a cross-platform patternmaking program which allows designers diff --git a/dist/rpm/valentina.spec b/dist/rpm/valentina.spec index 8d75c2025..ce1341b8e 100644 --- a/dist/rpm/valentina.spec +++ b/dist/rpm/valentina.spec @@ -83,7 +83,7 @@ Requires: poppler-utils Version: 0.7.0 Release: 0 -URL: https://bitbucket.org/dismine/valentina +URL: https://gitlab.com/smart-pattern/valentina License: GPL-3.0+ Source0: %{name}-%{version}.tar.gz Group: Graphics diff --git a/src/app/puzzle/puzzle.pro b/src/app/puzzle/puzzle.pro index 7463ba832..be7037a9e 100644 --- a/src/app/puzzle/puzzle.pro +++ b/src/app/puzzle/puzzle.pro @@ -7,7 +7,7 @@ # File with common stuff for whole project include(../../../common.pri) -QT += core gui widgets network xml xmlpatterns printsupport +QT += core gui widgets network xml xmlpatterns printsupport concurrent # Name of binary file TARGET = puzzle @@ -187,7 +187,7 @@ noRunPath{ # For enable run qmake with CONFIG+=noRunPath # When the GNU linker sees a library, it discards all symbols that it doesn't need. # Dependent library go first. -#VTools static library (depend on VWidgets, VMisc, VPatternDB) +##VTools static library (depend on VWidgets, VMisc, VPatternDB) #unix|win32: LIBS += -L$$OUT_PWD/../../libs/vtools/$${DESTDIR}/ -lvtools #INCLUDEPATH += $$PWD/../../libs/vtools @@ -215,14 +215,23 @@ noRunPath{ # For enable run qmake with CONFIG+=noRunPath #win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/vformat.lib #else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/libvformat.a -##VPatternDB static library (depend on vgeometry, vmisc, VLayout) -#unix|win32: LIBS += -L$$OUT_PWD/../../libs/vpatterndb/$${DESTDIR} -lvpatterndb +# VLayout static library (depend on VGeometry) +unix|win32: LIBS += -L$$OUT_PWD/../../libs/vlayout/$${DESTDIR}/ -lvlayout -#INCLUDEPATH += $$PWD/../../libs/vpatterndb -#DEPENDPATH += $$PWD/../../libs/vpatterndb +INCLUDEPATH += $$PWD/../../libs/vlayout +DEPENDPATH += $$PWD/../../libs/vlayout -#win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/vpatterndb.lib -#else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/libvpatterndb.a +win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/vlayout.lib +else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/libvlayout.a + +#VPatternDB static library (depend on vgeometry, vmisc) +unix|win32: LIBS += -L$$OUT_PWD/../../libs/vpatterndb/$${DESTDIR} -lvpatterndb + +INCLUDEPATH += $$PWD/../../libs/vpatterndb +DEPENDPATH += $$PWD/../../libs/vpatterndb + +win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/vpatterndb.lib +else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/libvpatterndb.a # Fervor static library (depend on VMisc, IFC) unix|win32: LIBS += -L$$OUT_PWD/../../libs/fervor/$${DESTDIR}/ -lfervor @@ -251,31 +260,22 @@ DEPENDPATH += $$PWD/../../libs/vmisc win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/vmisc.lib else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/libvmisc.a -## VLayout static library (depend on VGeometry) -#unix|win32: LIBS += -L$$OUT_PWD/../../libs/vlayout/$${DESTDIR}/ -lvlayout +# VGeometry static library (depend on ifc) +unix|win32: LIBS += -L$$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/ -lvgeometry -#INCLUDEPATH += $$PWD/../../libs/vlayout -#DEPENDPATH += $$PWD/../../libs/vlayout +INCLUDEPATH += $$PWD/../../libs/vgeometry +DEPENDPATH += $$PWD/../../libs/vgeometry -#win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/vlayout.lib -#else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/libvlayout.a +win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/vgeometry.lib +else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/libvgeometry.a -## VGeometry static library (depend on ifc) -#unix|win32: LIBS += -L$$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/ -lvgeometry +# QMuParser library +win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2 +else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2 +else:unix: LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser -#INCLUDEPATH += $$PWD/../../libs/vgeometry -#DEPENDPATH += $$PWD/../../libs/vgeometry - -#win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/vgeometry.lib -#else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/libvgeometry.a - -## QMuParser library -#win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2 -#else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2 -#else:unix: LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser - -#INCLUDEPATH += $${PWD}/../../libs/qmuparser -#DEPENDPATH += $${PWD}/../../libs/qmuparser +INCLUDEPATH += $${PWD}/../../libs/qmuparser +DEPENDPATH += $${PWD}/../../libs/qmuparser ## VPropertyExplorer library #win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/vpropertyexplorer/$${DESTDIR} -lvpropertyexplorer diff --git a/src/app/puzzle/puzzleapplication.cpp b/src/app/puzzle/puzzleapplication.cpp index 0a43246b2..32e84e1bd 100644 --- a/src/app/puzzle/puzzleapplication.cpp +++ b/src/app/puzzle/puzzleapplication.cpp @@ -337,7 +337,7 @@ PuzzleMainWindow *PuzzleApplication::MainWindow() { VPuzzleCommandLinePtr cmd; VPuzzleCommandLine::ProcessInstance(cmd, QStringList()); - NewMainWindow(true); + NewMainWindow(VPuzzleCommandLinePtr()); } return mainWindows[0]; } @@ -355,11 +355,11 @@ QList PuzzleApplication::MainWindows() } //--------------------------------------------------------------------------------------------------------------------- -PuzzleMainWindow *PuzzleApplication::NewMainWindow(bool guiMode) +PuzzleMainWindow *PuzzleApplication::NewMainWindow(const VPuzzleCommandLinePtr &cmd) { - PuzzleMainWindow *puzzle = new PuzzleMainWindow(); + PuzzleMainWindow *puzzle = new PuzzleMainWindow(cmd); mainWindows.prepend(puzzle); - if (guiMode) + if (cmd->IsGuiEnabled()) { puzzle->show(); } @@ -505,7 +505,7 @@ void PuzzleApplication::ProcessArguments(const VPuzzleCommandLinePtr &cmd) for (auto &arg : args) { - NewMainWindow(cmd->IsGuiEnabled()); + NewMainWindow(cmd); if (not MainWindow()->LoadFile(arg)) { if (not cmd->IsGuiEnabled()) @@ -516,10 +516,10 @@ void PuzzleApplication::ProcessArguments(const VPuzzleCommandLinePtr &cmd) continue; } -// if (rawLayouts.size() > 0) -// { -// MainWindow()->ImportRawLayouts(rawLayouts); -// } + if (rawLayouts.size() > 0) + { + MainWindow()->ImportRawLayouts(rawLayouts); + } } } else @@ -530,12 +530,12 @@ void PuzzleApplication::ProcessArguments(const VPuzzleCommandLinePtr &cmd) cmd.get()->parser.showHelp(V_EX_USAGE); } - NewMainWindow(cmd->IsGuiEnabled()); -// if (rawLayouts.size() > 0) -// { + NewMainWindow(cmd); + if (rawLayouts.size() > 0) + { // MainWindow()->New(); // prepare layout settings -// MainWindow()->ImportRawLayouts(rawLayouts); -// } + MainWindow()->ImportRawLayouts(rawLayouts); + } } if (not cmd->IsGuiEnabled()) diff --git a/src/app/puzzle/puzzleapplication.h b/src/app/puzzle/puzzleapplication.h index c0dcf24ed..d93748835 100644 --- a/src/app/puzzle/puzzleapplication.h +++ b/src/app/puzzle/puzzleapplication.h @@ -58,7 +58,7 @@ public: virtual bool IsAppInGUIMode() const override; PuzzleMainWindow *MainWindow(); QList MainWindows(); - PuzzleMainWindow *NewMainWindow(bool guiMode); + PuzzleMainWindow *NewMainWindow(const VPuzzleCommandLinePtr &cmd); void InitOptions(); diff --git a/src/app/puzzle/puzzlemainwindow.cpp b/src/app/puzzle/puzzlemainwindow.cpp index ad6254d17..ff2ccd065 100644 --- a/src/app/puzzle/puzzlemainwindow.cpp +++ b/src/app/puzzle/puzzlemainwindow.cpp @@ -34,17 +34,27 @@ #include "xml/vpuzzlelayoutfilewriter.h" #include "xml/vpuzzlelayoutfilereader.h" #include "puzzleapplication.h" +#include "../vlayout/vrawlayout.h" +#include "../vmisc/vsysexits.h" -Q_LOGGING_CATEGORY(vPuzzleMainWindow, "v.puzzlemainwindow") +#include +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes") +QT_WARNING_DISABLE_INTEL(1418) + +Q_LOGGING_CATEGORY(pWindow, "p.window") + +QT_WARNING_POP //--------------------------------------------------------------------------------------------------------------------- -PuzzleMainWindow::PuzzleMainWindow(QWidget *parent) : +PuzzleMainWindow::PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *parent) : QMainWindow(parent), ui(new Ui::PuzzleMainWindow), pieceCarrousel(new VPieceCarrousel), m_layout (nullptr), - m_selectedPiece (nullptr) + m_selectedPiece (nullptr), + m_cmd(cmd) { ui->setupUi(this); @@ -107,7 +117,25 @@ bool PuzzleMainWindow::SaveFile(const QString &path) //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::ImportRawLayouts(const QStringList &layouts) { - Q_UNUSED(layouts) + VRawLayout layoutReader; + + for(auto &path : layouts) + { + VRawLayoutData data; + if (layoutReader.ReadFile(path, data)) + { + // Do somethinmg with raw layout data + } + else + { + qCCritical(pWindow, "%s\n", qPrintable(tr("Could not extract data from file '%1'. %2") + .arg(path, layoutReader.ErrorString()))); + if (m_cmd != nullptr && not m_cmd->IsGuiEnabled()) + { + m_cmd->ShowHelp(V_EX_DATAERR); + } + } + } } //--------------------------------------------------------------------------------------------------------------------- @@ -399,7 +427,7 @@ void PuzzleMainWindow::New() //--------------------------------------------------------------------------------------------------------------------- void PuzzleMainWindow::Open() { - qCDebug(vPuzzleMainWindow, "Openning puzzle layout file."); + qCDebug(pWindow, "Openning puzzle layout file."); const QString filter(tr("Layout files") + QLatin1String(" (*.vlt)")); @@ -415,7 +443,7 @@ void PuzzleMainWindow::Open() //Absolute path to last open file dir = QFileInfo(recentFiles.first()).absolutePath(); } - qCDebug(vPuzzleMainWindow, "Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir)); + 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 diff --git a/src/app/puzzle/puzzlemainwindow.h b/src/app/puzzle/puzzlemainwindow.h index 8d60638eb..a3518f391 100644 --- a/src/app/puzzle/puzzlemainwindow.h +++ b/src/app/puzzle/puzzlemainwindow.h @@ -36,6 +36,7 @@ #include "vpiececarrousel.h" #include "vpuzzlelayout.h" #include "vpuzzlepiece.h" +#include "vpuzzlecommandline.h" namespace Ui { @@ -47,7 +48,7 @@ class PuzzleMainWindow : public QMainWindow Q_OBJECT public: - explicit PuzzleMainWindow(QWidget *parent = nullptr); + PuzzleMainWindow(const VPuzzleCommandLinePtr &cmd, QWidget *parent = nullptr); virtual ~PuzzleMainWindow(); /** @@ -77,6 +78,7 @@ private: Q_DISABLE_COPY(PuzzleMainWindow) Ui::PuzzleMainWindow *ui; VPieceCarrousel *pieceCarrousel; + VPuzzleCommandLinePtr m_cmd; VPuzzleLayout *m_layout; diff --git a/src/app/puzzle/vpuzzlecommandline.cpp b/src/app/puzzle/vpuzzlecommandline.cpp index 13d0d71c6..bc08399eb 100644 --- a/src/app/puzzle/vpuzzlecommandline.cpp +++ b/src/app/puzzle/vpuzzlecommandline.cpp @@ -96,6 +96,12 @@ bool VPuzzleCommandLine::IsNoScalingEnabled() const return IsOptionSet(LONG_OPTION_NO_HDPI_SCALING); } +//---------------------------------------------------------------------------------------------------------------------- +void VPuzzleCommandLine::ShowHelp(int exitCode) +{ + parser.showHelp(exitCode); +} + //---------------------------------------------------------------------------------------------- VPuzzleCommandLine::VPuzzleCommandLine(): parser(), diff --git a/src/app/puzzle/vpuzzlecommandline.h b/src/app/puzzle/vpuzzlecommandline.h index 6c923fcfc..0bd64c8e2 100644 --- a/src/app/puzzle/vpuzzlecommandline.h +++ b/src/app/puzzle/vpuzzlecommandline.h @@ -61,6 +61,8 @@ public: /** @brief if high dpi scaling is enabled */ bool IsNoScalingEnabled() const; + + Q_NORETURN void ShowHelp(int exitCode = 0); protected: VPuzzleCommandLine(); diff --git a/src/app/valentina/core/vapplication.cpp b/src/app/valentina/core/vapplication.cpp index 493a5392e..91514f439 100644 --- a/src/app/valentina/core/vapplication.cpp +++ b/src/app/valentina/core/vapplication.cpp @@ -62,6 +62,28 @@ QT_WARNING_POP Q_DECL_CONSTEXPR auto DAYS_TO_KEEP_LOGS = 3; +namespace +{ +QString AppFilePath(const QString &appName) +{ + QString appNameExe = appName; +#ifdef Q_OS_WIN + appNameExe += ".exe"; +#endif + QFileInfo canonicalFile(QString("%1/%2").arg(QCoreApplication::applicationDirPath(), appNameExe)); + if (canonicalFile.exists()) + { + return canonicalFile.absoluteFilePath(); + } + else + { + QFileInfo debugFile(QString("%1/../../%2/bin/%3") + .arg(QCoreApplication::applicationDirPath(), appName, appNameExe)); + return debugFile.exists() ? debugFile.absoluteFilePath() : appNameExe; + } +} +} + //--------------------------------------------------------------------------------------------------------------------- inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { @@ -447,54 +469,13 @@ void VApplication::ActivateDarkMode() //--------------------------------------------------------------------------------------------------------------------- QString VApplication::TapeFilePath() const { - const QString tape = QStringLiteral("tape"); -#ifdef Q_OS_WIN - QFileInfo tapeFile(QCoreApplication::applicationDirPath() + "/" + tape + ".exe"); - if (tapeFile.exists()) - { - return tapeFile.absoluteFilePath(); - } - else - { - return QCoreApplication::applicationDirPath() + "/../../tape/bin/" + tape + ".exe"; - } -#elif defined(Q_OS_MAC) - QFileInfo tapeFile(QCoreApplication::applicationDirPath() + "/" + tape); - if (tapeFile.exists()) - { - return tapeFile.absoluteFilePath(); - } - else - { - QFileInfo file(QCoreApplication::applicationDirPath() + "/../../tape/bin/" + tape); - if (file.exists()) - { - return file.absoluteFilePath(); - } - else - { - return tape; - } - } -#else // Unix - QFileInfo file(QCoreApplication::applicationDirPath() + "/../../tape/bin/" + tape); - if (file.exists()) - { - return file.absoluteFilePath(); - } - else - { - QFileInfo tapeFile(QCoreApplication::applicationDirPath() + "/" + tape); - if (tapeFile.exists()) - { - return tapeFile.absoluteFilePath(); - } - else - { - return tape; - } - } -#endif + return AppFilePath(QStringLiteral("tape")); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString VApplication::PuzzleFilePath() const +{ + return AppFilePath(QStringLiteral("puzzle")); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/core/vapplication.h b/src/app/valentina/core/vapplication.h index d01d0f2ab..94dc56eff 100644 --- a/src/app/valentina/core/vapplication.h +++ b/src/app/valentina/core/vapplication.h @@ -58,6 +58,7 @@ public: void InitOptions(); QString TapeFilePath() const; + QString PuzzleFilePath() const; QTimer *getAutoSaveTimer() const; void setAutoSaveTimer(QTimer *value); diff --git a/src/app/valentina/dialogs/configpages/preferencespathpage.cpp b/src/app/valentina/dialogs/configpages/preferencespathpage.cpp index 9d9195630..182ab1c35 100644 --- a/src/app/valentina/dialogs/configpages/preferencespathpage.cpp +++ b/src/app/valentina/dialogs/configpages/preferencespathpage.cpp @@ -72,6 +72,7 @@ QStringList PreferencesPathPage::Apply() settings->SetPathLayout(ui->pathTable->item(3, 1)->text()); settings->SetPathTemplate(ui->pathTable->item(4, 1)->text()); settings->SetPathLabelTemplate(ui->pathTable->item(5, 1)->text()); + settings->SetPathManualLayouts(ui->pathTable->item(6, 1)->text()); return QStringList(); // No changes those require restart. } @@ -118,6 +119,9 @@ void PreferencesPathPage::DefaultPath() case 5: // label templates path = VCommonSettings::GetDefPathLabelTemplate(); break; + case 6: // manual layouts + path = VCommonSettings::GetDefPathManualLayouts(); + break; default: break; } @@ -155,6 +159,9 @@ void PreferencesPathPage::EditPath() case 5: // label templates path = qApp->ValentinaSettings()->GetPathLabelTemplate(); break; + case 6: // manual layouts + path = qApp->ValentinaSettings()->GetPathManualLayouts(); + break; default: break; } @@ -196,7 +203,7 @@ void PreferencesPathPage::EditPath() void PreferencesPathPage::InitTable() { ui->pathTable->clearContents(); - ui->pathTable->setRowCount(6); + ui->pathTable->setRowCount(7); ui->pathTable->setColumnCount(2); const VSettings *settings = qApp->ValentinaSettings(); @@ -243,6 +250,13 @@ void PreferencesPathPage::InitTable() ui->pathTable->setItem(5, 1, item); } + { + ui->pathTable->setItem(6, 0, new QTableWidgetItem(tr("My manual layouts"))); + QTableWidgetItem *item = new QTableWidgetItem(settings->GetPathManualLayouts()); + item->setToolTip(settings->GetPathManualLayouts()); + ui->pathTable->setItem(6, 1, item); + } + ui->pathTable->verticalHeader()->setDefaultSectionSize(20); ui->pathTable->resizeColumnsToContents(); ui->pathTable->resizeRowsToContents(); diff --git a/src/app/valentina/dialogs/dialogsavelayout.cpp b/src/app/valentina/dialogs/dialogsavelayout.cpp index ecac7451b..58ec2458a 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.cpp +++ b/src/app/valentina/dialogs/dialogsavelayout.cpp @@ -110,6 +110,7 @@ DialogSaveLayout::DialogSaveLayout(int count, Draw mode, const QString &fileName } else { + RemoveFormatFromList(LayoutExportFormats::RLD); ui->checkBoxTextAsPaths->setVisible(false); } @@ -238,6 +239,7 @@ void DialogSaveLayout::SetBinaryDXFFormat(bool binary) case LayoutExportFormats::PS: case LayoutExportFormats::EPS: case LayoutExportFormats::NC: + case LayoutExportFormats::RLD: default: ui->checkBoxBinaryDXF->setChecked(false); break; @@ -285,6 +287,7 @@ bool DialogSaveLayout::IsBinaryDXFFormat() const case LayoutExportFormats::PS: case LayoutExportFormats::EPS: case LayoutExportFormats::NC: + case LayoutExportFormats::RLD: default: return false; } @@ -424,6 +427,8 @@ QString DialogSaveLayout::ExportFormatDescription(LayoutExportFormats format) return QStringLiteral("PDF %1 %2 (*.pdf)").arg(tr("tiled"), filesStr); case LayoutExportFormats::NC: return QStringLiteral("%1 %2 (*.nc)").arg(tr("Numerical control"), filesStr); + case LayoutExportFormats::RLD: + return QStringLiteral("%1 %2 (*.rld)").arg(tr("Raw Layout Data"), filesStr); default: return QString(); } @@ -477,6 +482,8 @@ QString DialogSaveLayout::ExportFormatSuffix(LayoutExportFormats format) return QStringLiteral(".dxf"); case LayoutExportFormats::NC: return QStringLiteral(".nc"); + case LayoutExportFormats::RLD: + return QStringLiteral(".rld"); default: return QString(); } @@ -566,6 +573,7 @@ void DialogSaveLayout::ShowExample() ui->checkBoxBinaryDXF->setEnabled(false); ui->groupBoxPaperFormat->setEnabled(false); ui->groupBoxMargins->setEnabled(false); + ui->checkBoxTextAsPaths->setEnabled(true); switch(currentFormat) { @@ -602,6 +610,9 @@ void DialogSaveLayout::ShowExample() ui->groupBoxPaperFormat->setEnabled(true); ui->groupBoxMargins->setEnabled(true); break; + case LayoutExportFormats::RLD: + ui->checkBoxTextAsPaths->setEnabled(false); + break; case LayoutExportFormats::SVG: case LayoutExportFormats::PDF: case LayoutExportFormats::PNG: @@ -869,6 +880,7 @@ QVector > DialogSaveLayout::InitFormats( InitFormat(LayoutExportFormats::DXF_AC1027_ASTM); InitFormat(LayoutExportFormats::PDFTiled); // InitFormat(LayoutExportFormats::NC); + InitFormat(LayoutExportFormats::RLD); return list; } diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index f5bb15524..9b12bdc46 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -2143,13 +2143,13 @@ void MainWindow::ToolBarDraws() connect(ui->actionOptionDraw, &QAction::triggered, this, [this]() { - const QString activDraw = doc->GetNameActivPP(); - const QString nameDraw = PatternPieceName(activDraw); - if (nameDraw.isEmpty() || activDraw == nameDraw) + QString draw = doc->GetNameActivPP(); + bool ok = PatternPieceName(draw); + if (not ok) { return; } - qApp->getUndoStack()->push(new RenamePP(doc, nameDraw, comboBoxDraws)); + qApp->getUndoStack()->push(new RenamePP(doc, draw, comboBoxDraws)); }); } @@ -3149,6 +3149,148 @@ void MainWindow::on_actionOpen_triggered() LoadPattern(filePath); } +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::on_actionOpenPuzzle_triggered() +{ + const QString puzzle = qApp->PuzzleFilePath(); + const QString workingDirectory = QFileInfo(puzzle).absoluteDir().absolutePath(); + + QStringList arguments; + if (isNoScaling) + { + arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); + } + + QProcess::startDetached(puzzle, arguments, workingDirectory); +} + +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::on_actionCreateManualLayout_triggered() +{ + QTemporaryFile rldFile(QDir::tempPath()+"/puzzle.rld.XXXXXX"); + if (rldFile.open()) + { + QVector detailsInLayout = SortDetailsForLayout(pattern->DataPieces()); + + if (detailsInLayout.count() == 0) + { + QMessageBox::information(this, tr("Layout mode"), tr("You don't have enough details to export. Please, " + "include at least one detail in layout."), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + + QVector listDetails; + try + { + listDetails = PrepareDetailsForLayout(detailsInLayout); + } + catch (VException &e) + { + QMessageBox::warning(this, tr("Export details"), + tr("Can't export details.") + QLatin1String(" \n") + e.ErrorMessage(), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + + RLDFile(rldFile.fileName(), listDetails); + + QStringList arguments {"-r", rldFile.fileName()}; + if (isNoScaling) + { + arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); + } + + rldFile.setAutoRemove(false); + + const QString puzzle = qApp->PuzzleFilePath(); + const QString workingDirectory = QFileInfo(puzzle).absoluteDir().absolutePath(); + QProcess::startDetached(puzzle, arguments, workingDirectory); + } + else + { + qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Unable to prepare raw layout data."))); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::on_actionUpdateManualLayout_triggered() +{ + const QString filter(tr("Manual layout files") + QLatin1String(" (*.vlt)")); + + //Use standard path to manual layouts + const QString path = qApp->ValentinaSettings()->GetPathManualLayouts(); + + bool usedNotExistedDir = false; + QDir directory(path); + if (not directory.exists()) + { + usedNotExistedDir = directory.mkpath(QChar('.')); + } + + auto RemoveUnsuded = qScopeGuard([usedNotExistedDir, path]() + { + if (usedNotExistedDir) + { + QDir directory(path); + directory.rmpath(QChar('.')); + } + }); + + const QString filePath = QFileDialog::getOpenFileName(this, tr("Select manual layout"), path, filter, nullptr); + + if (filePath.isEmpty()) + { + return; + } + + QTemporaryFile rldFile(QDir::tempPath()+"/puzzle.rld.XXXXXX"); + rldFile.setAutoRemove(false); + if (rldFile.open()) + { + QVector detailsInLayout = SortDetailsForLayout(pattern->DataPieces()); + + if (detailsInLayout.count() == 0) + { + QMessageBox::information(this, tr("Layout mode"), tr("You don't have enough details to export. Please, " + "include at least one detail in layout."), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + + QVector listDetails; + try + { + listDetails = PrepareDetailsForLayout(detailsInLayout); + } + catch (VException &e) + { + QMessageBox::warning(this, tr("Export details"), + tr("Can't export details.") + QLatin1String(" \n") + e.ErrorMessage(), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + + RLDFile(rldFile.fileName(), listDetails); + + QStringList arguments {filePath, "-r", rldFile.fileName()}; + if (isNoScaling) + { + arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); + } + + rldFile.setAutoRemove(false); + + const QString puzzle = qApp->PuzzleFilePath(); + const QString workingDirectory = QFileInfo(puzzle).absoluteDir().absolutePath(); + QProcess::startDetached(puzzle, arguments, workingDirectory); + } + else + { + qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Unable to prepare raw layout data."))); + } +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief Clear reset to default window. @@ -3554,7 +3696,9 @@ void MainWindow::SetEnableWidgets(bool enable) { const bool drawStage = (qApp->GetDrawMode() == Draw::Calculation); const bool detailsStage = (qApp->GetDrawMode() == Draw::Modeling); + const bool layoutStage = (qApp->GetDrawMode() == Draw::Layout); const bool designStage = (drawStage || detailsStage); + const bool piecesStage = (detailsStage || layoutStage); comboBoxDraws->setEnabled(enable && drawStage); ui->actionOptionDraw->setEnabled(enable && drawStage); @@ -3588,6 +3732,8 @@ void MainWindow::SetEnableWidgets(bool enable) ui->actionDecreaseLabelFont->setEnabled(enable); ui->actionOriginalLabelFont->setEnabled(enable); ui->actionHideLabels->setEnabled(enable); + ui->actionCreateManualLayout->setEnabled(enable && piecesStage); + ui->actionUpdateManualLayout->setEnabled(enable && piecesStage); ui->actionLoadWatermark->setEnabled(enable); ui->actionRemoveWatermark->setEnabled(enable && not doc->GetWatermarkPath().isEmpty()); @@ -4524,11 +4670,10 @@ void MainWindow::CreateActions() qCDebug(vMainWindow, "Generated PP name: %s", qUtf8Printable(patternPieceName)); qCDebug(vMainWindow, "PP count %d", comboBoxDraws->count()); - patternPieceName = PatternPieceName(patternPieceName); + bool ok = PatternPieceName(patternPieceName); qCDebug(vMainWindow, "PP name: %s", qUtf8Printable(patternPieceName)); - if (patternPieceName.isEmpty()) + if (not ok) { - qCDebug(vMainWindow, "Name empty."); return; } @@ -4733,7 +4878,7 @@ void MainWindow::InitAutoSave() } //--------------------------------------------------------------------------------------------------------------------- -QString MainWindow::PatternPieceName(const QString &text) +bool MainWindow::PatternPieceName(QString &name) { QScopedPointer dlg(new QInputDialog(this)); dlg->setInputMode( QInputDialog::TextInput ); @@ -4741,23 +4886,29 @@ QString MainWindow::PatternPieceName(const QString &text) dlg->setTextEchoMode(QLineEdit::Normal); dlg->setWindowTitle(tr("Enter a new label for the pattern piece.")); dlg->resize(300, 100); - dlg->setTextValue(text); + dlg->setTextValue(name); QString nameDraw; while (1) { const bool bOk = dlg->exec(); nameDraw = dlg->textValue(); - if (bOk == false || nameDraw.isEmpty() || text == nameDraw) + if (not bOk) { - return text; + return false; + } + + if (nameDraw.isEmpty()) + { + continue; } if (comboBoxDraws->findText(nameDraw) == -1) { - break;//repeate show dialog + name = nameDraw; + break;// unique name } } - return nameDraw; + return true; } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h index 9602839d0..2e4dbe494 100644 --- a/src/app/valentina/mainwindow.h +++ b/src/app/valentina/mainwindow.h @@ -184,6 +184,10 @@ private slots: bool on_actionSave_triggered(); void on_actionOpen_triggered(); + void on_actionOpenPuzzle_triggered(); + void on_actionCreateManualLayout_triggered(); + void on_actionUpdateManualLayout_triggered(); + void ClosedDialogUnionDetails(int result); void ClosedDialogDuplicateDetail(int result); void ClosedDialogGroup(int result); @@ -335,7 +339,7 @@ private: void CreateMenus(); void CreateActions(); void InitAutoSave(); - QString PatternPieceName(const QString &text); + bool PatternPieceName(QString &name); QString CheckPathToMeasurements(const QString &patternPath, const QString &path); QComboBox *SetGradationList(QLabel *label, const QStringList &list); void ChangePP(int index, bool zoomBestFit = true); diff --git a/src/app/valentina/mainwindow.ui b/src/app/valentina/mainwindow.ui index 0a78e70ba..c45ac3910 100644 --- a/src/app/valentina/mainwindow.ui +++ b/src/app/valentina/mainwindow.ui @@ -372,7 +372,7 @@ 0 0 - 104 + 140 108 @@ -481,7 +481,7 @@ 0 0 - 104 + 126 243 @@ -746,7 +746,7 @@ 0 0 - 104 + 126 282 @@ -1037,7 +1037,7 @@ 0 0 - 98 + 140 102 @@ -1120,7 +1120,7 @@ 0 0 - 104 + 126 192 @@ -1324,7 +1324,7 @@ 0 0 - 104 + 126 237 @@ -1589,8 +1589,8 @@ 0 0 - 104 - 57 + 140 + 170 @@ -1690,7 +1690,7 @@ 0 0 1100 - 22 + 21 @@ -1804,12 +1804,21 @@ + + + Manual Layout + + + + + + @@ -3026,6 +3035,36 @@ Create or edit a watermark + + + Open Puzzle + + + Open the Puzzle app + + + + + false + + + Create + + + Create manual layout + + + + + false + + + Update + + + Update manual layout + + diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index 559a02dcd..adfb73090 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -53,6 +53,7 @@ #include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vvitconverter.h" #include "../ifc/xml/vwatermarkconverter.h" +#include "../vlayout/vrawlayout.h" #include #include @@ -523,7 +524,8 @@ void MainWindowsNoGUI::ExportData(const QVector &listDetails) format == LayoutExportFormats::DXF_AC1018_ASTM || format == LayoutExportFormats::DXF_AC1021_ASTM || format == LayoutExportFormats::DXF_AC1024_ASTM || - format == LayoutExportFormats::DXF_AC1027_ASTM) + format == LayoutExportFormats::DXF_AC1027_ASTM || + format == LayoutExportFormats::RLD) { if (m_dialogSaveLayout->Mode() == Draw::Layout) { @@ -731,6 +733,9 @@ void MainWindowsNoGUI::ExportApparelLayout(const QVector &details, case LayoutExportFormats::DXF_AC1027_AAMA: AAMADxfFile(name, DRW::AC1027, m_dialogSaveLayout->IsBinaryDXFFormat(), size, details); break; + case LayoutExportFormats::RLD: + RLDFile(name, details, m_dialogSaveLayout->GetXScale(), m_dialogSaveLayout->GetYScale()); + break; default: qDebug() << "Can't recognize file type." << Q_FUNC_INFO; break; @@ -1488,6 +1493,25 @@ void MainWindowsNoGUI::ASTMDxfFile(const QString &name, int version, bool binary generator.ExportToASTM(details); } +//--------------------------------------------------------------------------------------------------------------------- +void MainWindowsNoGUI::RLDFile(const QString &name, QVector details, qreal xScale, qreal yScale) const +{ + for(auto detail : details) + { + detail.Scale(xScale, yScale); + } + + VRawLayoutData layoutDate; + layoutDate.pieces = details; + + VRawLayout generator; + if (not generator.WriteFile(name, layoutDate)) + { + const QString errorMsg = tr("Export raw layout data failed. %1.").arg(generator.ErrorString()); + qApp->IsPedantic() ? throw VException(errorMsg) : qCritical() << errorMsg; + } +} + QT_WARNING_POP //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/mainwindowsnogui.h b/src/app/valentina/mainwindowsnogui.h index 77a69eb86..ac0bac08c 100644 --- a/src/app/valentina/mainwindowsnogui.h +++ b/src/app/valentina/mainwindowsnogui.h @@ -150,6 +150,8 @@ protected: QSharedPointer OpenMeasurementFile(const QString &path) const; void CheckRequiredMeasurements(const VMeasurements *m) const; + + void RLDFile(const QString &name, QVector details, qreal xScale=1, qreal yScale=1) const; private slots: void PrintPages (QPrinter *printer); private: diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index 763ae9415..f3a6824cb 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -829,6 +829,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse VToolSeamAllowanceInitData initData; initData.id = GetParametrId(domElement); initData.detail.SetName(GetParametrString(domElement, AttrName, tr("Detail"))); + initData.detail.SetUUID(GetParametrEmptyString(domElement, AttrUUID)); initData.detail.SetMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, QStringLiteral("0.0")))); initData.detail.SetMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, QStringLiteral("0.0")))); initData.detail.SetSeamAllowance(GetParametrBool(domElement, VToolSeamAllowance::AttrSeamAllowance, falseStr)); diff --git a/src/libs/ifc/ifcdef.cpp b/src/libs/ifc/ifcdef.cpp index e592264c6..2bd0d6095 100644 --- a/src/libs/ifc/ifcdef.cpp +++ b/src/libs/ifc/ifcdef.cpp @@ -47,6 +47,7 @@ const QString AttrType = QStringLiteral("type"); const QString AttrMx = QStringLiteral("mx"); const QString AttrMy = QStringLiteral("my"); const QString AttrName = QStringLiteral("name"); +const QString AttrUUID = QStringLiteral("uuid"); const QString AttrMx1 = QStringLiteral("mx1"); const QString AttrMy1 = QStringLiteral("my1"); const QString AttrName1 = QStringLiteral("name1"); diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h index ae91d264e..788dc86fd 100644 --- a/src/libs/ifc/ifcdef.h +++ b/src/libs/ifc/ifcdef.h @@ -65,6 +65,7 @@ extern const QString AttrType; extern const QString AttrMx; extern const QString AttrMy; extern const QString AttrName; +extern const QString AttrUUID; extern const QString AttrMx1; extern const QString AttrMy1; extern const QString AttrName1; diff --git a/src/libs/ifc/schema.qrc b/src/libs/ifc/schema.qrc index 5d41d6883..79d978c82 100644 --- a/src/libs/ifc/schema.qrc +++ b/src/libs/ifc/schema.qrc @@ -59,6 +59,7 @@ schema/pattern/v0.8.5.xsd schema/pattern/v0.8.6.xsd schema/pattern/v0.8.7.xsd + schema/pattern/v0.8.8.xsd schema/standard_measurements/v0.3.0.xsd schema/standard_measurements/v0.4.0.xsd schema/standard_measurements/v0.4.1.xsd diff --git a/src/libs/ifc/schema/pattern/v0.8.8.xsd b/src/libs/ifc/schema/pattern/v0.8.8.xsd new file mode 100644 index 000000000..514cd8f0d --- /dev/null +++ b/src/libs/ifc/schema/pattern/v0.8.8.xsd @@ -0,0 +1,1260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp index a38a9dbfc..40790aa98 100644 --- a/src/libs/ifc/xml/vpatternconverter.cpp +++ b/src/libs/ifc/xml/vpatternconverter.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include "../exception/vexception.h" #include "../exception/vexceptionemptyparameter.h" @@ -59,8 +60,8 @@ class QDomElement; */ const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.4"); -const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.8.7"); -const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.8.7.xsd"); +const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.8.8"); +const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.8.8.xsd"); //VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!! //VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!! @@ -135,6 +136,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, strMy, (QLatin1String("my"))) //Q_GLOBAL_STATIC_WITH_ARGS(const QString, strForbidFlipping, (QLatin1String("forbidFlipping"))) //Q_GLOBAL_STATIC_WITH_ARGS(const QString, strInLayout, (QLatin1String("inLayout"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, strSeamAllowance, (QLatin1String("seamAllowance"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, strUUID, (QLatin1String("uuid"))) //Q_GLOBAL_STATIC_WITH_ARGS(const QString, strNodeType, (QLatin1String("nodeType"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, strDet, (QLatin1String("det"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, strTypeObject, (QLatin1String("typeObject"))) @@ -237,7 +239,8 @@ QString VPatternConverter::XSDSchema(int ver) const std::make_pair(FORMAT_VERSION(0, 8, 4), QStringLiteral("://schema/pattern/v0.8.4.xsd")), std::make_pair(FORMAT_VERSION(0, 8, 5), QStringLiteral("://schema/pattern/v0.8.5.xsd")), std::make_pair(FORMAT_VERSION(0, 8, 6), QStringLiteral("://schema/pattern/v0.8.6.xsd")), - std::make_pair(FORMAT_VERSION(0, 8, 7), CurrentSchema) + std::make_pair(FORMAT_VERSION(0, 8, 7), QStringLiteral("://schema/pattern/v0.8.7.xsd")), + std::make_pair(FORMAT_VERSION(0, 8, 8), CurrentSchema) }; if (schemas.contains(ver)) @@ -486,6 +489,10 @@ void VPatternConverter::ApplyPatches() ValidateXML(XSDSchema(FORMAT_VERSION(0, 8, 7))); Q_FALLTHROUGH(); case (FORMAT_VERSION(0, 8, 7)): + ToV0_8_8(); + ValidateXML(XSDSchema(FORMAT_VERSION(0, 8, 8))); + Q_FALLTHROUGH(); + case (FORMAT_VERSION(0, 8, 8)): break; default: InvalidVersion(m_ver); @@ -503,7 +510,7 @@ void VPatternConverter::DowngradeToCurrentMaxVersion() bool VPatternConverter::IsReadOnly() const { // Check if attribute readOnly was not changed in file format - Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FORMAT_VERSION(0, 8, 7), + Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FORMAT_VERSION(0, 8, 8), "Check attribute readOnly."); // Possibly in future attribute readOnly will change position etc. @@ -1143,6 +1150,17 @@ void VPatternConverter::ToV0_8_7() Save(); } +//--------------------------------------------------------------------------------------------------------------------- +void VPatternConverter::ToV0_8_8() +{ + // TODO. Delete if minimal supported version is 0.8.8 + Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FORMAT_VERSION(0, 8, 8), + "Time to refactor the code."); + SetVersion(QStringLiteral("0.8.8")); + AddPieceUUIDV0_8_8(); + Save(); +} + //--------------------------------------------------------------------------------------------------------------------- void VPatternConverter::TagUnitToV0_2_0() { @@ -2662,6 +2680,25 @@ void VPatternConverter::AddTagPreviewCalculationsV0_6_2() } } +//--------------------------------------------------------------------------------------------------------------------- +void VPatternConverter::AddPieceUUIDV0_8_8() +{ + // TODO. Delete if minimal supported version is 0.8.8 + Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FORMAT_VERSION(0, 8, 8), + "Time to refactor the code."); + + const QDomNodeList list = elementsByTagName(*strDetail); + for (int i=0; i < list.size(); ++i) + { + QDomElement dom = list.at(i).toElement(); + + if (not dom.isNull()) + { + dom.setAttribute(*strUUID, QUuid::createUuid().toString()); + } + } +} + //--------------------------------------------------------------------------------------------------------------------- void VPatternConverter::TagUnionDetailsToV0_4_0() { diff --git a/src/libs/ifc/xml/vpatternconverter.h b/src/libs/ifc/xml/vpatternconverter.h index 1adaabee3..6c0367932 100644 --- a/src/libs/ifc/xml/vpatternconverter.h +++ b/src/libs/ifc/xml/vpatternconverter.h @@ -53,7 +53,7 @@ public: static const QString PatternMaxVerStr; static const QString CurrentSchema; static Q_DECL_CONSTEXPR const int PatternMinVer = FORMAT_VERSION(0, 1, 4); - static Q_DECL_CONSTEXPR const int PatternMaxVer = FORMAT_VERSION(0, 8, 7); + static Q_DECL_CONSTEXPR const int PatternMaxVer = FORMAT_VERSION(0, 8, 8); protected: virtual int MinVer() const override; @@ -130,6 +130,7 @@ private: void ToV0_8_5(); void ToV0_8_6(); void ToV0_8_7(); + void ToV0_8_8(); void TagUnitToV0_2_0(); void TagIncrementToV0_2_0(); @@ -182,6 +183,8 @@ private: void RemoveUniqueTagV0_6_0(const QString &tag); void AddTagPreviewCalculationsV0_6_2(); + + void AddPieceUUIDV0_8_8(); }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp index ff7eef16b..8869ad633 100644 --- a/src/libs/vlayout/vabstractpiece.cpp +++ b/src/libs/vlayout/vabstractpiece.cpp @@ -49,7 +49,7 @@ #include const quint32 VAbstractPieceData::streamHeader = 0x05CDD73A; // CRC-32Q string "VAbstractPieceData" -const quint16 VAbstractPieceData::classVersion = 2; +const quint16 VAbstractPieceData::classVersion = 3; const qreal maxL = 3.5; @@ -1652,6 +1652,25 @@ void VAbstractPiece::SetPriority(uint value) d->m_priority = value; } +//--------------------------------------------------------------------------------------------------------------------- +QUuid VAbstractPiece::GetUUID() const +{ + return d->m_uuid; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractPiece::SetUUID(const QUuid &uuid) +{ + d->m_uuid = uuid; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractPiece::SetUUID(const QString &uuid) +{ + const QUuid temp = QUuid(uuid); + d->m_uuid = temp.isNull() ? QUuid::createUuid() : temp; +} + //--------------------------------------------------------------------------------------------------------------------- qreal VSAPoint::GetSABefore(qreal width) const { diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h index adff3056b..f787503a6 100644 --- a/src/libs/vlayout/vabstractpiece.h +++ b/src/libs/vlayout/vabstractpiece.h @@ -91,6 +91,10 @@ public: uint GetPriority() const; void SetPriority(uint value); + QUuid GetUUID() const; + void SetUUID(const QUuid &uuid); + void SetUUID(const QString &uuid); + static QVector Equidistant(QVector points, qreal width, const QString &name); static qreal SumTrapezoids(const QVector &points); static QVector CheckLoops(const QVector &points); diff --git a/src/libs/vlayout/vabstractpiece_p.h b/src/libs/vlayout/vabstractpiece_p.h index 91d0efbe5..6aa88ad06 100644 --- a/src/libs/vlayout/vabstractpiece_p.h +++ b/src/libs/vlayout/vabstractpiece_p.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "../vmisc/diagnostic.h" #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) @@ -62,7 +63,8 @@ public: m_width(piece.m_width), m_mx(piece.m_mx), m_my(piece.m_my), - m_priority(piece.m_priority) + m_priority(piece.m_priority), + m_uuid(piece.m_uuid) {} ~VAbstractPieceData() Q_DECL_EQ_DEFAULT; @@ -81,6 +83,7 @@ public: qreal m_mx{0}; qreal m_my{0}; uint m_priority{0}; + QUuid m_uuid{QUuid::createUuid()}; private: Q_DISABLE_ASSIGN(VAbstractPieceData) @@ -111,6 +114,9 @@ inline QDataStream &operator<<(QDataStream &dataStream, const VAbstractPieceData // Added in classVersion = 2 dataStream << piece.m_priority; + // Added in classVersion = 3 + dataStream << piece.m_uuid; + return dataStream; } @@ -155,6 +161,11 @@ inline QDataStream &operator>>(QDataStream &dataStream, VAbstractPieceData &piec dataStream >> piece.m_priority; } + if (actualClassVersion >= 3) + { + dataStream >> piece.m_uuid; + } + return dataStream; } diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri index fe16ecc40..752c7f27a 100644 --- a/src/libs/vlayout/vlayout.pri +++ b/src/libs/vlayout/vlayout.pri @@ -13,6 +13,7 @@ HEADERS += \ $$PWD/vcontour_p.h \ $$PWD/vbestsquare.h \ $$PWD/vposition.h \ + $$PWD/vrawlayout.h \ $$PWD/vsapoint.h \ $$PWD/vtextmanager.h \ $$PWD/vposter.h \ @@ -34,6 +35,7 @@ SOURCES += \ $$PWD/vcontour.cpp \ $$PWD/vbestsquare.cpp \ $$PWD/vposition.cpp \ + $$PWD/vrawlayout.cpp \ $$PWD/vtextmanager.cpp \ $$PWD/vposter.cpp \ $$PWD/vgraphicsfillitem.cpp \ diff --git a/src/libs/vlayout/vlayoutdef.h b/src/libs/vlayout/vlayoutdef.h index c6a3ed070..f110864b7 100644 --- a/src/libs/vlayout/vlayoutdef.h +++ b/src/libs/vlayout/vlayoutdef.h @@ -72,6 +72,7 @@ enum class LayoutExportFormats : qint8 DXF_AC1027_ASTM = 32, /* ACAD 2013. */ PDFTiled = 33, NC = 34, /*G-code. Reserved for future*/ + RLD = 35, /*Raw Layout Data*/ COUNT /*Use only for validation*/ }; diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp index 7d4fbb5cb..ed6b5a2bb 100644 --- a/src/libs/vlayout/vlayoutpiece.cpp +++ b/src/libs/vlayout/vlayoutpiece.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "../vpatterndb/floatItemData/vpatternlabeldata.h" #include "../vpatterndb/floatItemData/vpiecelabeldata.h" @@ -452,6 +453,7 @@ VLayoutPiece VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContai det.SetMy(piece.GetMy()); det.SetName(piece.GetName()); + det.SetUUID(piece.GetUUID()); det.SetSAWidth(qApp->toPixel(piece.GetSAWidth())); det.SetForbidFlipping(piece.IsForbidFlipping()); diff --git a/src/libs/vlayout/vrawlayout.cpp b/src/libs/vlayout/vrawlayout.cpp new file mode 100644 index 000000000..42d404530 --- /dev/null +++ b/src/libs/vlayout/vrawlayout.cpp @@ -0,0 +1,248 @@ +/************************************************************************ + ** + ** @file vrawlayout.cpp + ** @author Roman Telezhynskyi + ** @date 21 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 "vrawlayout.h" + +#include +#include +#include +#include + +#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) +#include "../vmisc/backport/qscopeguard.h" +#else +#include +#endif + +#include "../vmisc/def.h" +#include "../vmisc/vdatastreamenum.h" +#include "../ifc/exception/vexception.h" + +const QByteArray VRawLayout::fileHeaderByteArray = QByteArray("RLD!..."); +const quint16 VRawLayout::fileVersion = 1; + +const quint32 VRawLayoutData::streamHeader = 0x8B0E8A27; // CRC-32Q string "VRawLayoutData" +const quint16 VRawLayoutData::classVersion = 1; + +//--------------------------------------------------------------------------------------------------------------------- +QDataStream &operator<<(QDataStream &dataStream, const VRawLayoutData &data) +{ + dataStream << VRawLayoutData::streamHeader << VRawLayoutData::classVersion; + + // Added in classVersion = 1 + dataStream << data.pieces; + + // Added in classVersion = 2 + + return dataStream; +} + +//--------------------------------------------------------------------------------------------------------------------- +QDataStream &operator>>(QDataStream &dataStream, VRawLayoutData &data) +{ + quint32 actualStreamHeader = 0; + dataStream >> actualStreamHeader; + + if (actualStreamHeader != VRawLayoutData::streamHeader) + { + QString message = QCoreApplication::tr("VRawLayoutData prefix mismatch error: actualStreamHeader = 0x%1 and " + "streamHeader = 0x%2") + .arg(actualStreamHeader, 8, 0x10, QChar('0')) + .arg(VRawLayoutData::streamHeader, 8, 0x10, QChar('0')); + throw VException(message); + } + + quint16 actualClassVersion = 0; + dataStream >> actualClassVersion; + + if (actualClassVersion > VRawLayoutData::classVersion) + { + QString message = QCoreApplication::tr("VRawLayoutData compatibility error: actualClassVersion = %1 and " + "classVersion = %2") + .arg( actualClassVersion ).arg(VRawLayoutData::classVersion); + throw VException(message); + } + + dataStream >> data.pieces; + +// if (actualClassVersion >= 2) +// { +// // read value in version 2 +// } + + return dataStream; +} + +//--------------------------------------------------------------------------------------------------------------------- +VRawLayout::VRawLayout() +{} + +//--------------------------------------------------------------------------------------------------------------------- +bool VRawLayout::WriteFile(QIODevice *ioDevice, const VRawLayoutData &data) +{ + SCASSERT(ioDevice != nullptr) + m_errorString.clear(); + + const bool wasOpen = ioDevice->isOpen(); + + if (wasOpen || ioDevice->open(QIODevice::WriteOnly)) + { + QDataStream dataStream(ioDevice); + dataStream.setVersion(QDataStream::Qt_5_4); + + // Don't use the << operator for QByteArray. See the note in ReadFile() below. + dataStream.writeRawData(fileHeaderByteArray.constData(), fileHeaderByteArray.size()); + dataStream << fileVersion; + dataStream << data; + + if (not wasOpen) + { + ioDevice->close(); // Only close this if it was opened by this function. + } + return true; + } + else + { + m_errorString = ioDevice->errorString(); + return false; + } + + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VRawLayout::ReadFile(QIODevice *ioDevice, VRawLayoutData &data) +{ + SCASSERT(ioDevice != nullptr) + m_errorString.clear(); + + const bool wasOpen = ioDevice->isOpen(); + + if (wasOpen || ioDevice->open(QIODevice::ReadOnly)) + { + auto CloseFile = qScopeGuard([wasOpen, ioDevice]() + { + if (not wasOpen) // Only close this if it was opened by this function. + { + ioDevice->close(); + } + }); + + QDataStream dataStream(ioDevice); + dataStream.setVersion(QDataStream::Qt_5_4); + + // Note: we could have used the QDataStream << and >> operators on QByteArray but since the first + // bytes of the stream will be the size of the array, we might end up attempting to allocate + // a large amount of memory if the wrong file type was read. Instead, we'll just read the + // same number of bytes that are in the array we are comparing it to. No size was written. + const int len = fileHeaderByteArray.size(); + QByteArray actualFileHeaderByteArray( len, '\0' ); + dataStream.readRawData( actualFileHeaderByteArray.data(), len ); + + if (actualFileHeaderByteArray != fileHeaderByteArray) + { + // prefixes don't match + m_errorString = tr("VRawLayout::ReadFile() failed. Raw layout format prefix mismatch error."); + return false; + } + + quint16 actualFileVersion = 0; + dataStream >> actualFileVersion; + + if (actualFileVersion > fileVersion) + { + // file is from a future version that we don't know how to load + m_errorString = tr("VRawLayout::ReadFile() failed.\n" + "Raw layout format compatibility error: actualFileVersion = %1 and fileVersion = %2" ) + .arg(actualFileVersion).arg(fileVersion); + return false; + } + + try + { + // This may throw an exception if one of the VRawLayoutData objects is corrupt or unsupported. + // For example, if this file is from a future version of this code. + dataStream >> data; + } + catch (const VException& e) + { + qCritical() << e.ErrorMessage(); + + m_errorString = e.ErrorMessage(); + return false; + } + + return true; + } + else + { + m_errorString = ioDevice->errorString(); + return false; + } + + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VRawLayout::WriteFile(const QString &filePath, const VRawLayoutData &data) +{ + QFile file(filePath); + if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) + { + auto CloseFile = qScopeGuard([&file]() + { + file.flush(); + file.close(); + }); + return WriteFile(&file, data); + } + else + { + m_errorString = file.errorString(); + return false; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VRawLayout::ReadFile(const QString &filePath, VRawLayoutData &data) +{ + QFile file(filePath); + if (file.open(QIODevice::ReadOnly)) + { + auto CloseFile = qScopeGuard([&file]() + { + file.flush(); + file.close(); + }); + return ReadFile(&file, data); + } + else + { + m_errorString = file.errorString(); + return false; + } +} diff --git a/src/libs/vlayout/vrawlayout.h b/src/libs/vlayout/vrawlayout.h new file mode 100644 index 000000000..6521f62e7 --- /dev/null +++ b/src/libs/vlayout/vrawlayout.h @@ -0,0 +1,73 @@ +/************************************************************************ + ** + ** @file vrawlayout.h + ** @author Roman Telezhynskyi + ** @date 21 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 VRAWLAYOUT_H +#define VRAWLAYOUT_H + +#include "vlayoutpiece.h" + +struct VRawLayoutData +{ + QVector pieces{}; + + friend QDataStream& operator<< (QDataStream& dataStream, const VRawLayoutData& date); + friend QDataStream& operator>> (QDataStream& dataStream, VRawLayoutData& date); + +private: + static const quint32 streamHeader; + static const quint16 classVersion; +}; + + +class VRawLayout +{ + Q_DECLARE_TR_FUNCTIONS(VRawLayout) +public: + VRawLayout(); + + bool WriteFile(QIODevice* ioDevice, const VRawLayoutData& data); + bool ReadFile(QIODevice* ioDevice, VRawLayoutData& data); + + bool WriteFile(const QString& filePath, const VRawLayoutData& data); + bool ReadFile(const QString& filePath, VRawLayoutData& data); + + QString ErrorString() const; + +private: + QString m_errorString{}; + + static const QByteArray fileHeaderByteArray; + static const quint16 fileVersion; +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline QString VRawLayout::ErrorString() const +{ + return m_errorString; +} + +#endif // VRAWLAYOUT_H diff --git a/src/libs/vmisc/vcommonsettings.cpp b/src/libs/vmisc/vcommonsettings.cpp index 5a4bfa8b4..c394aafcf 100644 --- a/src/libs/vmisc/vcommonsettings.cpp +++ b/src/libs/vmisc/vcommonsettings.cpp @@ -54,6 +54,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsMultisizeMeasurements, (QLa Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsPattern, (QLatin1String("paths/pattern"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsTemplates, (QLatin1String("paths/templates"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsLabelTemplate, (QLatin1String("paths/labels"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsManualLayouts, (QLatin1String("paths/manualLayouts"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingConfigurationOsSeparator, (QLatin1String("configuration/osSeparator"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingConfigurationAutosaveState, (QLatin1String("configuration/autosave/state"))) @@ -425,6 +426,24 @@ void VCommonSettings::SetPathLabelTemplate(const QString &value) setValue(*settingPathsLabelTemplate, value); } +//--------------------------------------------------------------------------------------------------------------------- +QString VCommonSettings::GetDefPathManualLayouts() +{ + return QDir::homePath() + QLatin1String("/valentina/") + tr("manual layouts"); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString VCommonSettings::GetPathManualLayouts() const +{ + return value(*settingPathsManualLayouts, GetDefPathManualLayouts()).toString(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCommonSettings::SetPathManualLayouts(const QString &value) +{ + setValue(*settingPathsManualLayouts, value); +} + //--------------------------------------------------------------------------------------------------------------------- bool VCommonSettings::GetOsSeparator() const { diff --git a/src/libs/vmisc/vcommonsettings.h b/src/libs/vmisc/vcommonsettings.h index 26f5acd17..c8ff8bba9 100644 --- a/src/libs/vmisc/vcommonsettings.h +++ b/src/libs/vmisc/vcommonsettings.h @@ -75,6 +75,10 @@ public: QString GetPathLabelTemplate() const; void SetPathLabelTemplate(const QString &value); + static QString GetDefPathManualLayouts(); + QString GetPathManualLayouts() const; + void SetPathManualLayouts(const QString &value); + bool GetOsSeparator() const; void SetOsSeparator(const bool &value); diff --git a/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp index 86db51444..ba2738625 100644 --- a/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp +++ b/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.cpp @@ -53,6 +53,7 @@ #include #include +#include #include enum TabOrder {Paths=0, Pins=1, Labels=2, Grainline=3, Passmarks=4, PlaceLabels=5, Count=6}; @@ -117,6 +118,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, quint32 toolId, flagFormulaAfter(true), flagMainPathIsValid(true), flagName(true), //We have default name of piece. + flagUUID(true), flagFormula(true), m_bAddMode(true), m_dialog(), @@ -149,6 +151,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, quint32 toolId, EnableApply(applyAllowed); InitMainPathTab(); + InitPieceTab(); InitSeamAllowanceTab(); InitInternalPathsTab(); InitPatternPieceDataTab(); @@ -318,6 +321,7 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece) uiTabPaths->checkBoxSeams->setChecked(piece.IsSeamAllowance()); uiTabPaths->checkBoxBuiltIn->setChecked(piece.IsSeamAllowanceBuiltIn()); uiTabPaths->lineEditName->setText(piece.GetName()); + uiTabPaths->lineEditUUID->setText(piece.GetUUID().toString()); uiTabPaths->spinBoxPriority->setValue(static_cast(piece.GetPriority())); uiTabPaths->plainTextEditFormulaWidth->setPlainText( @@ -493,7 +497,7 @@ void DialogSeamAllowance::CheckState() if (flagFormula && flagFormulaBefore && flagFormulaAfter) { - if (flagMainPathIsValid && flagName) + if (flagMainPathIsValid && flagName && flagUUID) { m_ftb->SetTabText(TabOrder::Paths, tr("Paths")); } @@ -508,9 +512,9 @@ void DialogSeamAllowance::CheckState() uiTabPaths->tabWidget->setTabIcon(uiTabPaths->tabWidget->indexOf(uiTabPaths->tabSeamAllowance), icon); } - if (flagMainPathIsValid && flagName) + if (flagMainPathIsValid) { - if (flagFormula && flagFormulaBefore && flagFormulaAfter) + if (flagFormula && flagFormulaBefore && flagFormulaAfter && flagName && flagUUID) { m_ftb->SetTabText(TabOrder::Paths, tr("Paths")); } @@ -532,6 +536,22 @@ void DialogSeamAllowance::CheckState() uiTabPaths->tabWidget->setTabIcon(uiTabPaths->tabWidget->indexOf(uiTabPaths->tabMainPath), icon); } + if (flagName && flagUUID) + { + if (flagFormula && flagFormulaBefore && flagFormulaAfter && flagMainPathIsValid) + { + m_ftb->SetTabText(TabOrder::Paths, tr("Paths")); + } + uiTabPaths->tabWidget->setTabIcon(uiTabPaths->tabWidget->indexOf(uiTabPaths->tabPiece), QIcon()); + } + else + { + m_ftb->SetTabText(TabOrder::Paths, tr("Paths") + '*'); + const QIcon icon = QIcon::fromTheme("dialog-warning", + QIcon(":/icons/win.icon.theme/16x16/status/dialog-warning.png")); + uiTabPaths->tabWidget->setTabIcon(uiTabPaths->tabWidget->indexOf(uiTabPaths->tabPiece), icon); + } + uiTabPaths->comboBoxNodes->setEnabled(flagFormulaBefore && flagFormulaAfter); if (uiTabPassmarks->comboBoxPassmarks->count() == 0) @@ -620,6 +640,30 @@ void DialogSeamAllowance::NameDetailChanged() CheckState(); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogSeamAllowance::DetailUUIDChanged() +{ + QLineEdit* edit = qobject_cast(sender()); + if (edit) + { + QRegularExpression re("^$|^{[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-" + "[0-9a-fA-F]{12}}$"); + QRegularExpressionMatch match = re.match(edit->text()); + + if (match.hasMatch()) + { + flagUUID = true; + ChangeColor(uiTabPaths->labelEditUUID, OkColor(this)); + } + else + { + flagUUID = false; + ChangeColor(uiTabPaths->labelEditUUID, errorColor); + } + } + CheckState(); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos) { @@ -2454,6 +2498,7 @@ VPiece DialogSeamAllowance::CreatePiece() const piece.SetSeamAllowanceBuiltIn(uiTabPaths->checkBoxBuiltIn->isChecked()); piece.SetHideMainPath(uiTabPaths->checkBoxHideMainPath->isChecked()); piece.SetName(uiTabPaths->lineEditName->text()); + piece.SetUUID(uiTabPaths->lineEditUUID->text()); piece.SetPriority(static_cast(uiTabPaths->spinBoxPriority->value())); piece.SetFormulaSAWidth(GetFormulaFromUser(uiTabPaths->plainTextEditFormulaWidth), m_saWidth); piece.GetPatternPieceData().SetLetter(uiTabLabels->lineEditLetter->text()); @@ -2831,6 +2876,29 @@ void DialogSeamAllowance::InitFancyTabBar() //--------------------------------------------------------------------------------------------------------------------- void DialogSeamAllowance::InitMainPathTab() +{ + uiTabPaths->checkBoxHideMainPath->setChecked(qApp->Settings()->IsHideMainPath()); + + uiTabPaths->listWidgetMainPath->setContextMenuPolicy(Qt::CustomContextMenu); + connect(uiTabPaths->listWidgetMainPath, &QListWidget::customContextMenuRequested, this, + &DialogSeamAllowance::ShowMainPathContextMenu); + connect(uiTabPaths->listWidgetMainPath->model(), &QAbstractItemModel::rowsMoved, this, + &DialogSeamAllowance::ListChanged); + connect(uiTabPaths->listWidgetMainPath, &QListWidget::itemSelectionChanged, this, + &DialogSeamAllowance::SetMoveControls); + + connect(uiTabPaths->toolButtonTop, &QToolButton::clicked, this, + [this](){MoveListRowTop(uiTabPaths->listWidgetMainPath);}); + connect(uiTabPaths->toolButtonUp, &QToolButton::clicked, this, + [this](){MoveListRowUp(uiTabPaths->listWidgetMainPath);}); + connect(uiTabPaths->toolButtonDown, &QToolButton::clicked, this, + [this](){MoveListRowDown(uiTabPaths->listWidgetMainPath);}); + connect(uiTabPaths->toolButtonBottom, &QToolButton::clicked, this, + [this](){MoveListRowBottom(uiTabPaths->listWidgetMainPath);}); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSeamAllowance::InitPieceTab() { connect(uiTabPaths->lineEditName, &QLineEdit::textChanged, this, &DialogSeamAllowance::NameDetailChanged); @@ -2855,24 +2923,8 @@ void DialogSeamAllowance::InitMainPathTab() uiTabPaths->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping()); uiTabPaths->checkBoxForceFlipping->setChecked(qApp->Settings()->GetForceWorkpieceFlipping()); - uiTabPaths->checkBoxHideMainPath->setChecked(qApp->Settings()->IsHideMainPath()); - uiTabPaths->listWidgetMainPath->setContextMenuPolicy(Qt::CustomContextMenu); - connect(uiTabPaths->listWidgetMainPath, &QListWidget::customContextMenuRequested, this, - &DialogSeamAllowance::ShowMainPathContextMenu); - connect(uiTabPaths->listWidgetMainPath->model(), &QAbstractItemModel::rowsMoved, this, - &DialogSeamAllowance::ListChanged); - connect(uiTabPaths->listWidgetMainPath, &QListWidget::itemSelectionChanged, this, - &DialogSeamAllowance::SetMoveControls); - - connect(uiTabPaths->toolButtonTop, &QToolButton::clicked, this, - [this](){MoveListRowTop(uiTabPaths->listWidgetMainPath);}); - connect(uiTabPaths->toolButtonUp, &QToolButton::clicked, this, - [this](){MoveListRowUp(uiTabPaths->listWidgetMainPath);}); - connect(uiTabPaths->toolButtonDown, &QToolButton::clicked, this, - [this](){MoveListRowDown(uiTabPaths->listWidgetMainPath);}); - connect(uiTabPaths->toolButtonBottom, &QToolButton::clicked, this, - [this](){MoveListRowBottom(uiTabPaths->listWidgetMainPath);}); + connect(uiTabPaths->lineEditUUID, &QLineEdit::textChanged, this, &DialogSeamAllowance::DetailUUIDChanged); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.h index 6a7250ef6..c51e9054d 100644 --- a/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.h +++ b/src/libs/vtools/dialogs/tools/piece/dialogseamallowance.h @@ -85,6 +85,7 @@ protected: private slots: void NameDetailChanged(); + void DetailUUIDChanged(); void ShowMainPathContextMenu(const QPoint &pos); void ShowCustomSAContextMenu(const QPoint &pos); void ShowInternalPathsContextMenu(const QPoint &pos); @@ -192,6 +193,7 @@ private: bool flagFormulaPassmarkLength{true}; bool flagMainPathIsValid; bool flagName; + bool flagUUID; bool flagFormula; bool m_bAddMode; @@ -247,6 +249,7 @@ private: void InitFancyTabBar(); void InitMainPathTab(); + void InitPieceTab(); void InitSeamAllowanceTab(); void InitNodesList(); void InitPassmarksList(); @@ -292,7 +295,7 @@ private: //--------------------------------------------------------------------------------------------------------------------- inline bool DialogSeamAllowance::IsValid() const { - return flagName && flagMainPathIsValid && flagFormula && flagFormulaBefore && flagFormulaAfter + return flagName && flagUUID && flagMainPathIsValid && flagFormula && flagFormulaBefore && flagFormulaAfter && (flagGFormulas || flagGPin) && flagDLAngle && (flagDLFormulas || flagDPin) && flagPLAngle && (flagPLFormulas || flagPPin) && flagFormulaPassmarkLength; } diff --git a/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui b/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui index ed9beef50..32b77c95c 100644 --- a/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui +++ b/src/libs/vtools/dialogs/tools/piece/tabs/tabpaths.ui @@ -6,8 +6,8 @@ 0 0 - 426 - 637 + 422 + 624 @@ -28,8 +28,8 @@ 0 0 - 406 - 617 + 402 + 604 @@ -73,64 +73,6 @@ - - - - QFormLayout::ExpandingFieldsGrow - - - - - Name of detail: - - - - - - - Detail - - - Name can't be empty - - - - - - - Priority: - - - - - - - Controls priority in layout. 0 - no priority. - - - - - - - - - Forbid piece be mirrored in a layout. - - - Forbid flipping - - - - - - - Force piece to be always flipped in a layout. - - - Force flipping - - - @@ -248,6 +190,101 @@ + + + Piece + + + + + + + + UUID: + + + + + + + Priority: + + + + + + + Name of detail: + + + + + + + Controls priority in layout. 0 - no priority. + + + + + + + Detail + + + Name can't be empty + + + + + + + Universally Unique IDentifier of piece. Used to identifier piece while updating manual layout. Left empty to generate new value. + + + {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + + + true + + + + + + + + + Forbid piece be mirrored in a layout. + + + Forbid flipping + + + + + + + Force piece to be always flipped in a layout. + + + Force flipping + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + Seam allowance diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp index 1e6e65f9a..ab6a16476 100644 --- a/src/libs/vtools/tools/vtoolseamallowance.cpp +++ b/src/libs/vtools/tools/vtoolseamallowance.cpp @@ -64,6 +64,7 @@ #include #include #include +#include // Current version of seam allowance tag need for backward compatibility const quint8 VToolSeamAllowance::pieceVersion = 2; @@ -270,6 +271,7 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl doc->SetAttribute(domElement, VDomDocument::AttrId, id); doc->SetAttribute(domElement, AttrName, piece.GetName()); + doc->SetAttribute(domElement, AttrUUID, piece.GetUUID().toString()); doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion)); doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx())); doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));