diff --git a/src/libs/ifc/ifc.qbs b/src/libs/ifc/ifc.qbs
index 84f01269d..12cb978bd 100644
--- a/src/libs/ifc/ifc.qbs
+++ b/src/libs/ifc/ifc.qbs
@@ -86,6 +86,8 @@ VLib {
"vabstractmconverter.cpp",
"vlabeltemplateconverter.cpp",
"vwatermarkconverter.cpp",
+ "vknownmeasurementsconverter.cpp",
+ "vknownmeasurementsconverter.h",
]
}
diff --git a/src/libs/ifc/ifcdef.cpp b/src/libs/ifc/ifcdef.cpp
index 1a59f8f8e..c9c02c351 100644
--- a/src/libs/ifc/ifcdef.cpp
+++ b/src/libs/ifc/ifcdef.cpp
@@ -148,6 +148,7 @@ const QString AttrCurve1Alias2 = QStringLiteral("curve1Alias2");
const QString AttrCurve2Alias1 = QStringLiteral("curve2Alias1");
const QString AttrCurve2Alias2 = QStringLiteral("curve2Alias2");
const QString AttrLayoutVersion = QStringLiteral("version");
+const QString AttrKMVersion = QStringLiteral("version");
const QString TypeLineDefault = QStringLiteral("default");
const QString TypeLineNone = QStringLiteral("none");
diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h
index 4ffdf942d..9034112fe 100644
--- a/src/libs/ifc/ifcdef.h
+++ b/src/libs/ifc/ifcdef.h
@@ -165,6 +165,7 @@ extern const QString AttrCurve1Alias2;
extern const QString AttrCurve2Alias1;
extern const QString AttrCurve2Alias2;
extern const QString AttrLayoutVersion;
+extern const QString AttrKMVersion;
extern const QString TypeLineDefault;
extern const QString TypeLineNone;
diff --git a/src/libs/ifc/schema.qrc b/src/libs/ifc/schema.qrc
index 27c49af91..fd39d015e 100644
--- a/src/libs/ifc/schema.qrc
+++ b/src/libs/ifc/schema.qrc
@@ -101,5 +101,6 @@
schema/layout/v0.1.4.xsd
schema/layout/v0.1.5.xsd
schema/layout/v0.1.6.xsd
+ schema/known_measurements/v1.0.0.xsd
diff --git a/src/libs/ifc/schema/known_measurements/v1.0.0.xsd b/src/libs/ifc/schema/known_measurements/v1.0.0.xsd
new file mode 100644
index 000000000..5d4d5c84e
--- /dev/null
+++ b/src/libs/ifc/schema/known_measurements/v1.0.0.xsd
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp
index 57d303e77..f0d185cb3 100644
--- a/src/libs/ifc/xml/vdomdocument.cpp
+++ b/src/libs/ifc/xml/vdomdocument.cpp
@@ -832,7 +832,7 @@ auto VDomDocument::SaveDocument(const QString &fileName, QString &error) -> bool
// cppcheck-suppress unusedFunction
auto VDomDocument::Major() const -> QString
{
- QString version = UniqueTagText(TagVersion, "0.0.0");
+ QString version = UniqueTagText(TagVersion, "0.0.0"_L1);
QStringList v = version.split('.'_L1);
return v.at(0);
}
@@ -841,7 +841,7 @@ auto VDomDocument::Major() const -> QString
// cppcheck-suppress unusedFunction
auto VDomDocument::Minor() const -> QString
{
- QString version = UniqueTagText(TagVersion, "0.0.0");
+ QString version = UniqueTagText(TagVersion, "0.0.0"_L1);
QStringList v = version.split('.'_L1);
return v.at(1);
}
@@ -850,7 +850,7 @@ auto VDomDocument::Minor() const -> QString
// cppcheck-suppress unusedFunction
auto VDomDocument::Patch() const -> QString
{
- QString version = UniqueTagText(TagVersion, "0.0.0");
+ QString version = UniqueTagText(TagVersion, "0.0.0"_L1);
QStringList v = version.split('.'_L1);
return v.at(2);
}
@@ -880,7 +880,7 @@ auto VDomDocument::GetFormatVersionStr() const -> QString
return domElement.text();
}
}
- return QString(QStringLiteral("0.0.0"));
+ return "0.0.0"_L1;
}
//---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/ifc/xml/vdomdocument.h b/src/libs/ifc/xml/vdomdocument.h
index 690e347fc..730569778 100644
--- a/src/libs/ifc/xml/vdomdocument.h
+++ b/src/libs/ifc/xml/vdomdocument.h
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -201,6 +202,13 @@ inline void VDomDocument::SetAttribute(QDomElement &domElement, c
domElement.setAttribute(name, value);
}
+//---------------------------------------------------------------------------------------------------------------------
+template <>
+inline void VDomDocument::SetAttribute(QDomElement &domElement, const QString &name, const QUuid &value) const
+{
+ domElement.setAttribute(name, value.toString());
+}
+
//---------------------------------------------------------------------------------------------------------------------
template <>
inline void VDomDocument::SetAttribute(QDomElement &domElement, const QString &name, const QChar &value) const
diff --git a/src/libs/ifc/xml/vknownmeasurementsconverter.cpp b/src/libs/ifc/xml/vknownmeasurementsconverter.cpp
new file mode 100644
index 000000000..4051ceb39
--- /dev/null
+++ b/src/libs/ifc/xml/vknownmeasurementsconverter.cpp
@@ -0,0 +1,137 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurementsconverter.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 26 10, 2023
+ **
+ ** @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) 2023 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 "vknownmeasurementsconverter.h"
+
+#include
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+#include "../vmisc/compatibility.h"
+#endif
+
+using namespace Qt::Literals::StringLiterals;
+
+/*
+ * Version rules:
+ * 1. Version have three parts "major.minor.patch";
+ * 2. major part only for stable releases;
+ * 3. minor - 10 or more patch changes, or one big change;
+ * 4. patch - little change.
+ */
+
+const QString VKnownMeasurementsConverter::KnownMeasurementsMinVerStr = QStringLiteral("1.0.0");
+const QString VKnownMeasurementsConverter::KnownMeasurementsMaxVerStr = QStringLiteral("1.0.0");
+const QString VKnownMeasurementsConverter::CurrentSchema = QStringLiteral("://schema/known_measurements/v1.0.0.xsd");
+
+// VKnownMeasurementsConverter::KnownMeasurementsMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
+// VKnownMeasurementsConverter::KnownMeasurementsMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
+
+//---------------------------------------------------------------------------------------------------------------------
+VKnownMeasurementsConverter::VKnownMeasurementsConverter(const QString &fileName)
+ : VAbstractConverter(fileName)
+{
+ m_ver = GetFormatVersion(VKnownMeasurementsConverter::GetFormatVersionStr());
+ ValidateInputFile(CurrentSchema);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::GetFormatVersionStr() const -> QString
+{
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ const QDomElement layoutElement = root.toElement();
+ if (not layoutElement.isNull())
+ {
+ return GetParametrString(layoutElement, AttrKMVersion, "0.0.0"_L1);
+ }
+ }
+ return "0.0.0"_L1;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::XSDSchemas() -> QHash
+{
+ static auto schemas = QHash{std::make_pair(FormatVersion(1, 0, 0), CurrentSchema)};
+
+ return schemas;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::MinVer() const -> unsigned int
+{
+ return KnownMeasurementsMinVer;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::MaxVer() const -> unsigned int
+{
+ return KnownMeasurementsMaxVer;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::MinVerStr() const -> QString
+{
+ return KnownMeasurementsMinVerStr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::MaxVerStr() const -> QString
+{
+ return KnownMeasurementsMaxVerStr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsConverter::ApplyPatches()
+{
+ switch (m_ver)
+ {
+ case (FormatVersion(1, 0, 0)):
+ break;
+ default:
+ InvalidVersion(m_ver);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsConverter::DowngradeToCurrentMaxVersion()
+{
+ SetVersion(KnownMeasurementsMaxVerStr);
+ Save();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::IsReadOnly() const -> bool
+{
+ return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsConverter::Schemas() const -> QHash
+{
+ return XSDSchemas();
+}
diff --git a/src/libs/ifc/xml/vknownmeasurementsconverter.h b/src/libs/ifc/xml/vknownmeasurementsconverter.h
new file mode 100644
index 000000000..4687b0096
--- /dev/null
+++ b/src/libs/ifc/xml/vknownmeasurementsconverter.h
@@ -0,0 +1,70 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurementsconverter.h
+ ** @author Roman Telezhynskyi
+ ** @date 26 10, 2023
+ **
+ ** @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) 2023 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 VKNOWNMEASUREMENTSCONVERTER_H
+#define VKNOWNMEASUREMENTSCONVERTER_H
+
+#include "../vmisc/projectversion.h"
+#include "vabstractconverter.h"
+
+class VKnownMeasurementsConverter : public VAbstractConverter
+{
+ Q_OBJECT // NOLINT
+
+public:
+ explicit VKnownMeasurementsConverter(const QString &fileName);
+ ~VKnownMeasurementsConverter() override = default;
+
+ auto GetFormatVersionStr() const -> QString override;
+
+ static const QString KnownMeasurementsMaxVerStr;
+ static const QString CurrentSchema;
+ static Q_DECL_CONSTEXPR const unsigned KnownMeasurementsMinVer = FormatVersion(1, 0, 0);
+ static Q_DECL_CONSTEXPR const unsigned KnownMeasurementsMaxVer = FormatVersion(1, 0, 0);
+
+ static auto XSDSchemas() -> QHash;
+
+protected:
+ auto MinVer() const -> unsigned override;
+ auto MaxVer() const -> unsigned override;
+
+ auto MinVerStr() const -> QString override;
+ auto MaxVerStr() const -> QString override;
+
+ void ApplyPatches() override;
+ void DowngradeToCurrentMaxVersion() override;
+
+ auto IsReadOnly() const -> bool override;
+
+ auto Schemas() const -> QHash override;
+
+private:
+ Q_DISABLE_COPY_MOVE(VKnownMeasurementsConverter) // NOLINT
+ static const QString KnownMeasurementsMinVerStr;
+};
+
+#endif // VKNOWNMEASUREMENTSCONVERTER_H
diff --git a/src/libs/ifc/xml/vlayoutconverter.cpp b/src/libs/ifc/xml/vlayoutconverter.cpp
index 594824846..6df412ce0 100644
--- a/src/libs/ifc/xml/vlayoutconverter.cpp
+++ b/src/libs/ifc/xml/vlayoutconverter.cpp
@@ -132,10 +132,10 @@ auto VLayoutConverter::GetFormatVersionStr() const -> QString
const QDomElement layoutElement = root.toElement();
if (not layoutElement.isNull())
{
- return GetParametrString(layoutElement, AttrLayoutVersion, QStringLiteral("0.0.0"));
+ return GetParametrString(layoutElement, AttrLayoutVersion, "0.0.0"_L1);
}
}
- return QStringLiteral("0.0.0");
+ return "0.0.0"_L1;
}
//---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/ifc/xml/vpatternimage.cpp b/src/libs/ifc/xml/vpatternimage.cpp
index 2318f719c..86c50fef8 100644
--- a/src/libs/ifc/xml/vpatternimage.cpp
+++ b/src/libs/ifc/xml/vpatternimage.cpp
@@ -209,3 +209,15 @@ auto VPatternImage::Size() const -> QSize
return QImageReader(&buffer).size();
}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VPatternImage::Title() const -> QString
+{
+ return m_title;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPatternImage::SetTitle(const QString &newTitle)
+{
+ m_title = newTitle;
+}
diff --git a/src/libs/ifc/xml/vpatternimage.h b/src/libs/ifc/xml/vpatternimage.h
index 6d37a19b2..c8d3ca79e 100644
--- a/src/libs/ifc/xml/vpatternimage.h
+++ b/src/libs/ifc/xml/vpatternimage.h
@@ -60,10 +60,14 @@ public:
auto Size() const -> QSize;
+ auto Title() const -> QString;
+ void SetTitle(const QString &newTitle);
+
private:
QString m_contentType{};
QByteArray m_contentData{};
mutable QString m_errorString{};
+ QString m_title{};
};
#endif // VPATTERNIMAGE_H
diff --git a/src/libs/ifc/xml/xml.pri b/src/libs/ifc/xml/xml.pri
index 0b78e5809..5073a365d 100644
--- a/src/libs/ifc/xml/xml.pri
+++ b/src/libs/ifc/xml/xml.pri
@@ -16,7 +16,8 @@ HEADERS += \
$$PWD//vabstractmconverter.h \
$$PWD/vlabeltemplateconverter.h \
$$PWD/vwatermarkconverter.h \
- $$PWD/vparsererrorhandler.h
+ $$PWD/vparsererrorhandler.h \
+ $$PWD/vknownmeasurementsconverter.h
SOURCES += \
$$PWD/utils.cpp \
@@ -33,4 +34,6 @@ SOURCES += \
$$PWD//vabstractmconverter.cpp \
$$PWD/vlabeltemplateconverter.cpp \
$$PWD/vwatermarkconverter.cpp \
- $$PWD/vparsererrorhandler.cpp
+ $$PWD/vparsererrorhandler.cpp \
+ $$PWD/vknownmeasurementsconverter.cpp
+
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurement.h b/src/libs/vformat/knownmeasurements/vknownmeasurement.h
new file mode 100644
index 000000000..6c6ae7202
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurement.h
@@ -0,0 +1,45 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurement.h
+ ** @author Roman Telezhynskyi
+ ** @date 27 10, 2023
+ **
+ ** @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) 2023 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 VKNOWNMEASUREMENT_H
+#define VKNOWNMEASUREMENT_H
+
+#include
+#include
+
+struct VKnownMeasurement
+{
+ QString name{};
+ QString fullName{};
+ QString description{};
+ QString formula{};
+ bool specialUnits{false};
+ QUuid diagram{};
+ int index{0};
+};
+
+#endif // VKNOWNMEASUREMENT_H
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurements.cpp b/src/libs/vformat/knownmeasurements/vknownmeasurements.cpp
new file mode 100644
index 000000000..e9498de83
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurements.cpp
@@ -0,0 +1,162 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurements.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 27 10, 2023
+ **
+ ** @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) 2023 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 "vknownmeasurements.h"
+#include "../vmisc/def.h"
+#include "vknownmeasurements_p.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VKnownMeasurements::VKnownMeasurements()
+ : d(new VKnownMeasurementsData)
+{
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VKnownMeasurements::~VKnownMeasurements()
+{
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+COPY_CONSTRUCTOR_IMPL(VKnownMeasurements)
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::operator=(const VKnownMeasurements &measurements) -> VKnownMeasurements &
+{
+ if (&measurements == this)
+ {
+ return *this;
+ }
+ d = measurements.d;
+ return *this;
+}
+
+#ifdef Q_COMPILER_RVALUE_REFS
+//---------------------------------------------------------------------------------------------------------------------
+VKnownMeasurements::VKnownMeasurements(VKnownMeasurements &&paper) noexcept
+ : d(std::move(paper.d))
+{
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::operator=(VKnownMeasurements &&paper) noexcept -> VKnownMeasurements &
+{
+ std::swap(d, paper.d);
+ return *this;
+}
+#endif
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::IsValid() const -> bool
+{
+ return !d->m_uid.isNull();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::GetUId() const -> QUuid
+{
+ return d->m_uid;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurements::SetUId(const QUuid &id)
+{
+ d->m_uid = id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::Name() const -> QString
+{
+ return d->m_name;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurements::SetName(const QString &name)
+{
+ d->m_name = name;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::Description() const -> QString
+{
+ return d->m_description;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurements::SetDescription(const QString &desc)
+{
+ d->m_description = desc;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::IsReadOnly() const -> bool
+{
+ return d->m_readOnly;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurements::SetReadOnly(bool ro)
+{
+ d->m_readOnly = ro;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::Measurments() const -> QHash
+{
+ return d->m_measurements;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::OrderedMeasurments() const -> QMap
+{
+ QMap ordered;
+ auto i = d->m_measurements.constBegin();
+ while (i != d->m_measurements.constEnd())
+ {
+ ordered.insert(i.value().index, i.value());
+ ++i;
+ }
+
+ return ordered;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurements::Images() const -> QHash
+{
+ return d->m_images;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurements::AddMeasurement(const VKnownMeasurement &m)
+{
+ d->m_measurements.insert(m.name, m);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurements::AddImage(const QUuid &id, const VPatternImage &image)
+{
+ d->m_images.insert(id, image);
+}
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurements.h b/src/libs/vformat/knownmeasurements/vknownmeasurements.h
new file mode 100644
index 000000000..c94e5b9e3
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurements.h
@@ -0,0 +1,80 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurements.h
+ ** @author Roman Telezhynskyi
+ ** @date 27 10, 2023
+ **
+ ** @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) 2023 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 VKNOWNMEASUREMENTS_H
+#define VKNOWNMEASUREMENTS_H
+
+#include "xml/vpatternimage.h"
+#include
+#include
+
+class VKnownMeasurementsData;
+class QUuid;
+struct VKnownMeasurement;
+
+class VKnownMeasurements
+{
+public:
+ VKnownMeasurements();
+ ~VKnownMeasurements();
+
+ VKnownMeasurements(const VKnownMeasurements &measurements);
+
+ auto operator=(const VKnownMeasurements &paper) -> VKnownMeasurements &;
+#ifdef Q_COMPILER_RVALUE_REFS
+ VKnownMeasurements(VKnownMeasurements &&paper) noexcept;
+ auto operator=(VKnownMeasurements &&paper) noexcept -> VKnownMeasurements &;
+#endif
+
+ auto IsValid() const -> bool;
+
+ auto GetUId() const -> QUuid;
+ void SetUId(const QUuid &id);
+
+ auto Name() const -> QString;
+ void SetName(const QString &name);
+
+ auto Description() const -> QString;
+ void SetDescription(const QString &desc);
+
+ auto IsReadOnly() const -> bool;
+ void SetReadOnly(bool ro);
+
+ auto Measurments() const -> QHash;
+ auto OrderedMeasurments() const -> QMap;
+ auto Images() const -> QHash;
+
+ void AddMeasurement(const VKnownMeasurement &m);
+ void AddImage(const QUuid &id, const VPatternImage &image);
+
+private:
+ QSharedDataPointer d;
+};
+
+Q_DECLARE_TYPEINFO(VKnownMeasurements, Q_MOVABLE_TYPE); // NOLINT
+
+#endif // VKNOWNMEASUREMENTS_H
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurements_p.h b/src/libs/vformat/knownmeasurements/vknownmeasurements_p.h
new file mode 100644
index 000000000..35d384fb8
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurements_p.h
@@ -0,0 +1,62 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurements_p.h
+ ** @author Roman Telezhynskyi
+ ** @date 27 10, 2023
+ **
+ ** @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) 2023 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 VKNOWNMEASUREMENTS_P_H
+#define VKNOWNMEASUREMENTS_P_H
+
+#include "../ifc/xml/vpatternimage.h"
+#include "../vmisc/defglobal.h"
+#include "vknownmeasurement.h"
+#include
+#include
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Weffc++")
+QT_WARNING_DISABLE_GCC("-Wnon-virtual-dtor")
+
+class VKnownMeasurementsData : public QSharedData
+{
+public:
+ VKnownMeasurementsData() = default;
+ VKnownMeasurementsData(const VKnownMeasurementsData &measurements) = default;
+ ~VKnownMeasurementsData() = default;
+
+ QUuid m_uid{}; // NOLINT (misc-non-private-member-variables-in-classes)
+ QString m_name{}; // NOLINT (misc-non-private-member-variables-in-classes)
+ QString m_description{}; // NOLINT (misc-non-private-member-variables-in-classes)
+ bool m_readOnly{false}; // NOLINT (misc-non-private-member-variables-in-classes)
+
+ QHash m_images{}; // NOLINT (misc-non-private-member-variables-in-classes)
+ QHash m_measurements{}; // NOLINT (misc-non-private-member-variables-in-classes)
+
+private:
+ Q_DISABLE_ASSIGN_MOVE(VKnownMeasurementsData) // NOLINT
+};
+
+QT_WARNING_POP
+
+#endif // VKNOWNMEASUREMENTS_P_H
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurementsdatabase.cpp b/src/libs/vformat/knownmeasurements/vknownmeasurementsdatabase.cpp
new file mode 100644
index 000000000..d76f70604
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurementsdatabase.cpp
@@ -0,0 +1,156 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurementsdatabase.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 26 10, 2023
+ **
+ ** @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) 2023 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 "vknownmeasurementsdatabase.h"
+#include "../ifc/exception/vexception.h"
+#include "../ifc/xml/vknownmeasurementsconverter.h"
+#include "../vformat/knownmeasurements/vknownmeasurements.h"
+#include "../vformat/knownmeasurements/vknownmeasurementsdocument.h"
+#include "../vmisc/vabstractapplication.h"
+#include "../vmisc/vcommonsettings.h"
+
+#include
+#include
+#include
+#include
+
+namespace
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wunused-member-function")
+
+Q_GLOBAL_STATIC(QMutex, knownMeasurementsDatabaseMutex) // NOLINT
+
+QT_WARNING_POP
+} // namespace
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDatabase::PopulateMeasurementsDatabase()
+{
+ QMutexLocker locker(knownMeasurementsDatabaseMutex());
+
+ m_measurementsCache.clear();
+
+ VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
+
+ m_measurementsDB.clear();
+ m_populated = false;
+
+ ParseDirectory(settings->GetPathKnownMeasurements());
+
+ UpdateIndexes();
+ m_populated = true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsDatabase::IsPopulated() const -> bool
+{
+ QMutexLocker locker(knownMeasurementsDatabaseMutex());
+ return m_populated;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsDatabase::AllKnownMeasurements() const -> QHash
+{
+ return m_measurementsDB;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsDatabase::KnownMeasurements(const QUuid &id) const -> VKnownMeasurements
+{
+ if (m_measurementsCache.contains(id))
+ {
+ return {*m_measurementsCache.object(id)};
+ }
+
+ QString measurementsFilePath = m_indexMeasurementsPath.value(id);
+ if (measurementsFilePath.isEmpty())
+ {
+ return {};
+ }
+
+ try
+ {
+ VKnownMeasurementsConverter converter(measurementsFilePath);
+ VKnownMeasurementsDocument measurements;
+ measurements.setXMLContent(converter.Convert());
+
+ VKnownMeasurements known = measurements.KnownMeasurements();
+ m_measurementsCache.insert(id, new VKnownMeasurements(known));
+ return known;
+ }
+ catch (VException &e)
+ {
+ qDebug("%s\n\n%s\n\n%s", qUtf8Printable("File error."), qUtf8Printable(e.ErrorMessage()),
+ qUtf8Printable(e.DetailedInformation()));
+ }
+
+ return {};
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDatabase::UpdateIndexes()
+{
+ m_indexMeasurementsPath.clear();
+
+ auto i = m_measurementsDB.constBegin();
+ while (i != m_measurementsDB.constEnd())
+ {
+ m_indexMeasurementsPath.insert(i.key(), i.value().path);
+ ++i;
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDatabase::ParseDirectory(const QString &path)
+{
+ QDirIterator it(path, {"*.vkm"}, QDir::Files, QDirIterator::Subdirectories);
+ while (it.hasNext())
+ {
+ QString measurementsFilePath = it.next();
+
+ try
+ {
+ VKnownMeasurementsConverter converter(measurementsFilePath);
+ VKnownMeasurementsDocument measurements;
+ measurements.setXMLContent(converter.Convert());
+
+ VKnownMeasurementsHeader header;
+ header.uid = measurements.GetUId();
+ header.name = measurements.Name();
+ header.description = measurements.Description();
+ header.path = measurementsFilePath;
+
+ m_measurementsDB.insert(header.uid, header);
+ }
+ catch (VException &e)
+ {
+ qDebug("%s\n\n%s\n\n%s", qUtf8Printable("File error."), qUtf8Printable(e.ErrorMessage()),
+ qUtf8Printable(e.DetailedInformation()));
+ }
+ }
+}
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurementsdatabase.h b/src/libs/vformat/knownmeasurements/vknownmeasurementsdatabase.h
new file mode 100644
index 000000000..b226ec89d
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurementsdatabase.h
@@ -0,0 +1,70 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurementsdatabase.h
+ ** @author Roman Telezhynskyi
+ ** @date 26 10, 2023
+ **
+ ** @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) 2023 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 VKNOWNMEASUREMENTSDATABASE_H
+#define VKNOWNMEASUREMENTSDATABASE_H
+
+#include
+#include
+#include
+#include
+
+class VKnownMeasurements;
+
+struct VKnownMeasurementsHeader
+{
+ QUuid uid{};
+ QString name{};
+ QString description{};
+ QString path{};
+};
+
+class VKnownMeasurementsDatabase
+{
+public:
+ VKnownMeasurementsDatabase() = default;
+
+ void PopulateMeasurementsDatabase();
+
+ auto IsPopulated() const -> bool;
+
+ auto AllKnownMeasurements() const -> QHash;
+
+ auto KnownMeasurements(const QUuid &id) const -> VKnownMeasurements;
+
+private:
+ bool m_populated{false};
+ QHash m_measurementsDB{};
+ QHash m_indexMeasurementsPath{};
+ mutable QCache m_measurementsCache{15};
+
+ void UpdateIndexes();
+
+ void ParseDirectory(const QString &path);
+};
+
+#endif // VKNOWNMEASUREMENTSDATABASE_H
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurementsdocument.cpp b/src/libs/vformat/knownmeasurements/vknownmeasurementsdocument.cpp
new file mode 100644
index 000000000..f53310537
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurementsdocument.cpp
@@ -0,0 +1,601 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurementsdocument.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 27 10, 2023
+ **
+ ** @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) 2023 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 "vknownmeasurementsdocument.h"
+#include "../ifc/xml/vknownmeasurementsconverter.h"
+#include "../ifc/xml/vpatternimage.h"
+#include "../vmisc/projectversion.h"
+#include "ifcdef.h"
+#include "literals.h"
+#include "quuid.h"
+#include "vformat/knownmeasurements/vknownmeasurement.h"
+#include "vknownmeasurements.h"
+
+#include
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+#include "../vmisc/compatibility.h"
+#endif
+
+using namespace Qt::Literals::StringLiterals;
+
+namespace
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wunused-member-function")
+
+// The list of all string we use for conversion
+// Better to use global variables because repeating QStringLiteral blows up code size
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagKnownMeasurements, ("known-measurements"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagMeasurements, ("measurements"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagMeasurement, ("m"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagDiagrams, ("diagrams"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagImage, ("tagImage"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagName, ("name"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagDescription, ("description"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, tagInfo, ("info"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrFormula, ("formula"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrSpecialUnits, ("specialUnits"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrName, ("name"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrContentType, ("contentType"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrUId, ("uid"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrTitle, ("title"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrReadOnly, ("read-only"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrDescription, ("description"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrFullName, ("full_name"_L1)) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, attrDiagram, ("diagram"_L1)) // NOLINT
+
+QT_WARNING_POP
+
+//---------------------------------------------------------------------------------------------------------------------
+auto FileComment() -> QString
+{
+ return u"Known measurements created with Valentina v%1 (https://smart-pattern.com.ua/)."_s.arg(AppVersionStr());
+}
+} // namespace
+
+//---------------------------------------------------------------------------------------------------------------------
+VKnownMeasurementsDocument::VKnownMeasurementsDocument(QObject *parent)
+ : VDomDocument(parent)
+{
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsDocument::SaveDocument(const QString &fileName, QString &error) -> bool
+{
+ // Update comment with Valentina version
+ QDomNode commentNode = documentElement().firstChild();
+ if (commentNode.isComment())
+ {
+ QDomComment comment = commentNode.toComment();
+ comment.setData(FileComment());
+ }
+
+ return VDomDocument::SaveDocument(fileName, error);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::CreateEmptyFile()
+{
+ clear();
+ QDomElement kmElement = this->createElement(*tagKnownMeasurements);
+
+ kmElement.appendChild(createComment(FileComment()));
+ kmElement.setAttribute(AttrKMVersion, VKnownMeasurementsConverter::KnownMeasurementsMaxVerStr);
+ kmElement.setAttribute(*attrUId, QUuid::createUuid().toString());
+
+ QDomElement info = createElement(*tagInfo);
+ info.appendChild(createElement(*tagName));
+ info.appendChild(createElement(*tagDescription));
+ kmElement.appendChild(info);
+
+ kmElement.appendChild(createElement(*tagDiagrams));
+ kmElement.appendChild(createElement(*tagMeasurements));
+
+ appendChild(kmElement);
+ insertBefore(
+ createProcessingInstruction(QStringLiteral("xml"), QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")),
+ firstChild());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::AddEmptyMeasurement(const QString &name)
+{
+ const QDomElement element = MakeEmptyMeasurement(name);
+
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).appendChild(element);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::AddEmptyMeasurementAfter(const QString &after, const QString &name)
+{
+ const QDomElement element = MakeEmptyMeasurement(name);
+ const QDomElement sibling = FindM(after);
+
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+
+ if (sibling.isNull())
+ {
+ list.at(0).appendChild(element);
+ }
+ else
+ {
+ list.at(0).insertAfter(element, sibling);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::AddImage(const VPatternImage &image)
+{
+ const QDomElement element = MakeEmptyImage(image);
+
+ const QDomNodeList list = elementsByTagName(*tagDiagrams);
+ list.at(0).appendChild(element);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::RemoveMeasurement(const QString &name)
+{
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).removeChild(FindM(name));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::RemoveImage(const QUuid &id)
+{
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).removeChild(FindImage(id));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::MoveTop(const QString &name)
+{
+ const QDomElement node = FindM(name);
+ if (node.isNull())
+ {
+ return;
+ }
+
+ const QDomNodeList mList = elementsByTagName(*tagMeasurement);
+ if (mList.size() >= 2)
+ {
+ const QDomNode top = mList.at(0);
+ if (not top.isNull())
+ {
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).insertBefore(node, top);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::MoveUp(const QString &name)
+{
+ const QDomElement node = FindM(name);
+ if (node.isNull())
+ {
+ return;
+ }
+
+ const QDomElement prSibling = node.previousSiblingElement(*tagMeasurement);
+ if (not prSibling.isNull())
+ {
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).insertBefore(node, prSibling);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::MoveDown(const QString &name)
+{
+ const QDomElement node = FindM(name);
+ if (node.isNull())
+ {
+ return;
+ }
+
+ const QDomElement nextSibling = node.nextSiblingElement(*tagMeasurement);
+ if (not nextSibling.isNull())
+ {
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).insertAfter(node, nextSibling);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::MoveBottom(const QString &name)
+{
+ const QDomElement node = FindM(name);
+ if (node.isNull())
+ {
+ return;
+ }
+
+ const QDomNodeList mList = elementsByTagName(*tagMeasurement);
+ if (mList.size() >= 2)
+ {
+ const QDomNode bottom = mList.at(mList.size() - 1);
+ if (not bottom.isNull())
+ {
+ const QDomNodeList list = elementsByTagName(*tagMeasurements);
+ list.at(0).insertAfter(node, bottom);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QUuid VKnownMeasurementsDocument::GetUId() const
+{
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ const QDomElement rootElement = root.toElement();
+ if (not rootElement.isNull())
+ {
+ return QUuid(GetParametrEmptyString(rootElement, AttrKMVersion));
+ }
+ }
+ return {};
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetUId(const QUuid &id)
+{
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ QDomElement rootElement = root.toElement();
+ if (not rootElement.isNull())
+ {
+ SetAttribute(rootElement, *attrUId, id.toString());
+ }
+ }
+ else
+ {
+ qDebug() << "Can't save known measurements uid " << Q_FUNC_INFO;
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VKnownMeasurementsDocument::Name() const
+{
+ return UniqueTagText(*tagName, QString());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetName(const QString &name)
+{
+ setTagText(*tagName, name);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VKnownMeasurementsDocument::Description() const
+{
+ return UniqueTagText(*tagDescription, QString());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetDescription(const QString &desc)
+{
+ setTagText(*tagDescription, desc);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VKnownMeasurementsDocument::IsReadOnly() const
+{
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ const QDomElement rootElement = root.toElement();
+ if (not rootElement.isNull())
+ {
+ return GetParametrBool(rootElement, *attrReadOnly, falseStr);
+ }
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetReadOnly(bool ro)
+{
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ QDomElement rootElement = root.toElement();
+ if (not rootElement.isNull())
+ {
+ SetAttributeOrRemoveIf(rootElement, *attrReadOnly, ro, [](bool ro) noexcept { return not ro; });
+ }
+ }
+ else
+ {
+ qDebug() << "Can't save known measurements read only status " << Q_FUNC_INFO;
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsDocument::KnownMeasurements() const -> VKnownMeasurements
+{
+ VKnownMeasurements known;
+
+ known.SetUId(GetUId());
+ known.SetName(Name());
+ known.SetDescription(Description());
+ known.SetReadOnly(IsReadOnly());
+
+ ReadImages(known);
+ ReadMeasurements(known);
+
+ return known;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetMName(const QString &name, const QString &text)
+{
+ QDomElement node = FindM(name);
+ if (not node.isNull())
+ {
+ SetAttribute(node, *attrName, text);
+ }
+ else
+ {
+ qWarning() << tr("Can't find measurement '%1'").arg(name);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetMFormula(const QString &name, const QString &text)
+{
+ QDomElement node = FindM(name);
+ if (not node.isNull())
+ {
+ SetAttribute(node, *attrFormula, text);
+ }
+ else
+ {
+ qWarning() << tr("Can't find measurement '%1'").arg(name);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetMSpecialUnits(const QString &name, bool special)
+{
+ QDomElement node = FindM(name);
+ if (not node.isNull())
+ {
+ SetAttributeOrRemoveIf(node, *attrSpecialUnits, special,
+ [](bool special) noexcept { return not special; });
+ }
+ else
+ {
+ qWarning() << tr("Can't find measurement '%1'").arg(name);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetMDescription(const QString &name, const QString &text)
+{
+ QDomElement node = FindM(name);
+ if (not node.isNull())
+ {
+ SetAttributeOrRemoveIf(node, *attrDescription, text,
+ [](const QString &text) noexcept { return text.isEmpty(); });
+ }
+ else
+ {
+ qWarning() << tr("Can't find measurement '%1'").arg(name);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetMFullName(const QString &name, const QString &text)
+{
+ QDomElement node = FindM(name);
+ if (not node.isNull())
+ {
+ SetAttribute(node, *attrFullName, text);
+ }
+ else
+ {
+ qWarning() << tr("Can't find measurement '%1'").arg(name);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetMImage(const QString &name, const QUuid &imageId)
+{
+ QDomElement node = FindM(name);
+ if (not node.isNull())
+ {
+ SetAttributeOrRemoveIf(node, *attrDiagram, imageId,
+ [](const QUuid &imageId) noexcept { return imageId.isNull(); });
+ }
+ else
+ {
+ qWarning() << tr("Can't find measurement '%1'").arg(name);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetImageContent(const QUuid &id, const VPatternImage &image)
+{
+ QDomElement node = FindImage(id);
+ if (not node.isNull())
+ {
+ setTagText(node, image.ContentData());
+ node.setAttribute(*attrContentType, image.ContentType());
+ }
+ else
+ {
+ qWarning() << tr("Can't find image by id '%1'").arg(id.toString());
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::SetImageTitle(const QUuid &id, const QString &text)
+{
+ QDomElement node = FindImage(id);
+ if (not node.isNull())
+ {
+ SetAttributeOrRemoveIf(node, *attrTitle, text,
+ [](const QString &text) noexcept { return text.isEmpty(); });
+ }
+ else
+ {
+ qWarning() << tr("Can't find image by id '%1'").arg(id.toString());
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement VKnownMeasurementsDocument::MakeEmptyMeasurement(const QString &name)
+{
+ QDomElement element = createElement(*tagMeasurement);
+ SetAttribute(element, *attrName, name);
+ return element;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VKnownMeasurementsDocument::FindM(const QString &name) const -> QDomElement
+{
+ if (name.isEmpty())
+ {
+ qWarning() << tr("The measurement name is empty!");
+ return {};
+ }
+
+ QDomNodeList list = elementsByTagName(*tagMeasurement);
+
+ for (int i = 0; i < list.size(); ++i)
+ {
+ const QDomElement domElement = list.at(i).toElement();
+ if (domElement.isNull())
+ {
+ continue;
+ }
+
+ const QString parameter = domElement.attribute(*attrName);
+ if (parameter == name)
+ {
+ return domElement;
+ }
+ }
+
+ return {};
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement VKnownMeasurementsDocument::MakeEmptyImage(const VPatternImage &image)
+{
+ QDomElement element = createElement(*tagImage);
+
+ SetAttribute(element, *attrContentType, image.ContentType());
+ SetAttribute(element, *attrUId, QUuid::createUuid().toString());
+ SetAttributeOrRemoveIf(element, *attrTitle, image.Title(),
+ [](const QString &text) noexcept { return text.isEmpty(); });
+ setTagText(element, image.ContentData());
+
+ return element;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement VKnownMeasurementsDocument::FindImage(const QUuid &id) const
+{
+ if (id.isNull())
+ {
+ qWarning() << tr("The image id is empty!");
+ return {};
+ }
+
+ QDomNodeList list = elementsByTagName(*tagImage);
+
+ QString idString = id.toString();
+
+ for (int i = 0; i < list.size(); ++i)
+ {
+ const QDomElement domElement = list.at(i).toElement();
+ if (domElement.isNull())
+ {
+ continue;
+ }
+
+ const QString parameter = domElement.attribute(*attrUId);
+ if (parameter == idString)
+ {
+ return domElement;
+ }
+ }
+
+ return {};
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::ReadImages(VKnownMeasurements &known) const
+{
+ QDomNodeList list = elementsByTagName(*tagImage);
+
+ for (int i = 0; i < list.size(); ++i)
+ {
+ const QDomElement domElement = list.at(i).toElement();
+ if (domElement.isNull())
+ {
+ continue;
+ }
+
+ VPatternImage image;
+ image.SetContentData(domElement.text().toLatin1(), domElement.attribute(*attrContentType));
+ image.SetTitle(domElement.attribute(*attrTitle));
+
+ known.AddImage(QUuid(domElement.attribute(*attrUId)), image);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VKnownMeasurementsDocument::ReadMeasurements(VKnownMeasurements &known) const
+{
+ QDomNodeList list = elementsByTagName(*tagMeasurement);
+
+ for (int i = 0; i < list.size(); ++i)
+ {
+ const QDomElement domElement = list.at(i).toElement();
+ if (domElement.isNull())
+ {
+ continue;
+ }
+
+ VKnownMeasurement m;
+ m.name = domElement.attribute(*attrName);
+ m.fullName = domElement.attribute(*attrFullName);
+ m.description = domElement.attribute(*attrDescription);
+ m.formula = domElement.attribute(*attrFormula);
+ m.specialUnits = GetParametrBool(domElement, *attrSpecialUnits, falseStr);
+ m.diagram = QUuid(GetParametrEmptyString(domElement, *attrDiagram));
+ m.index = i;
+
+ known.AddMeasurement(m);
+ }
+}
diff --git a/src/libs/vformat/knownmeasurements/vknownmeasurementsdocument.h b/src/libs/vformat/knownmeasurements/vknownmeasurementsdocument.h
new file mode 100644
index 000000000..1f42fda4e
--- /dev/null
+++ b/src/libs/vformat/knownmeasurements/vknownmeasurementsdocument.h
@@ -0,0 +1,98 @@
+/************************************************************************
+ **
+ ** @file vknownmeasurementsdocument.h
+ ** @author Roman Telezhynskyi
+ ** @date 27 10, 2023
+ **
+ ** @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) 2023 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 VKNOWNMEASUREMENTSDOCUMENT_H
+#define VKNOWNMEASUREMENTSDOCUMENT_H
+
+#include "../ifc/xml/vdomdocument.h"
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif
+
+class VKnownMeasurements;
+class VPatternImage;
+
+class VKnownMeasurementsDocument : public VDomDocument
+{
+ Q_OBJECT // NOLINT
+
+public:
+ explicit VKnownMeasurementsDocument(QObject *parent = nullptr);
+ ~VKnownMeasurementsDocument() override = default;
+
+ auto SaveDocument(const QString &fileName, QString &error) -> bool override;
+
+ void CreateEmptyFile();
+
+ void AddEmptyMeasurement(const QString &name);
+ void AddEmptyMeasurementAfter(const QString &after, const QString &name);
+ void AddImage(const VPatternImage &image);
+ void RemoveMeasurement(const QString &name);
+ void RemoveImage(const QUuid &id);
+ void MoveTop(const QString &name);
+ void MoveUp(const QString &name);
+ void MoveDown(const QString &name);
+ void MoveBottom(const QString &name);
+
+ auto GetUId() const -> QUuid;
+ void SetUId(const QUuid &id);
+
+ auto Name() const -> QString;
+ void SetName(const QString &name);
+
+ auto Description() const -> QString;
+ void SetDescription(const QString &desc);
+
+ auto IsReadOnly() const -> bool;
+ void SetReadOnly(bool ro);
+
+ auto KnownMeasurements() const -> VKnownMeasurements;
+
+ void SetMName(const QString &name, const QString &text);
+ void SetMFormula(const QString &name, const QString &text);
+ void SetMSpecialUnits(const QString &name, bool special);
+ void SetMDescription(const QString &name, const QString &text);
+ void SetMFullName(const QString &name, const QString &text);
+ void SetMImage(const QString &name, const QUuid &imageId);
+
+ void SetImageContent(const QUuid &id, const VPatternImage &image);
+ void SetImageTitle(const QUuid &id, const QString &text);
+
+private:
+ Q_DISABLE_COPY_MOVE(VKnownMeasurementsDocument) // NOLINT
+
+ auto MakeEmptyMeasurement(const QString &name) -> QDomElement;
+ auto FindM(const QString &name) const -> QDomElement;
+ auto MakeEmptyImage(const VPatternImage &image) -> QDomElement;
+ auto FindImage(const QUuid &id) const -> QDomElement;
+
+ void ReadImages(VKnownMeasurements &known) const;
+ void ReadMeasurements(VKnownMeasurements &known) const;
+};
+
+#endif // VKNOWNMEASUREMENTSDOCUMENT_H
diff --git a/src/libs/vformat/vformat.pri b/src/libs/vformat/vformat.pri
index 65077449f..3f9ec6036 100644
--- a/src/libs/vformat/vformat.pri
+++ b/src/libs/vformat/vformat.pri
@@ -7,7 +7,12 @@ SOURCES += \
$$PWD/vlabeltemplate.cpp \
$$PWD/vpatternrecipe.cpp \
$$PWD/vsinglelineoutlinechar.cpp \
- $$PWD/vwatermark.cpp
+ $$PWD/vwatermark.cpp \
+ $$PWD/knownmeasurements/vknownmeasurements.cpp \
+ $$PWD/knownmeasurements/vknownmeasurementsdocument.cpp \
+ $$PWD/knownmeasurements/vknownmeasurementsdatabase.cpp
+
+
*msvc*:SOURCES += $$PWD/stable.cpp
@@ -18,4 +23,9 @@ HEADERS += \
$$PWD/vlabeltemplate.h \
$$PWD/vpatternrecipe.h \
$$PWD/vsinglelineoutlinechar.h \
- $$PWD/vwatermark.h
+ $$PWD/vwatermark.h \
+ $$PWD/knownmeasurements/vknownmeasurement.h \
+ $$PWD/knownmeasurements/vknownmeasurements.h \
+ $$PWD/knownmeasurements/vknownmeasurements_p.h \
+ $$PWD/knownmeasurements/vknownmeasurementsdocument.h \
+ $$PWD/knownmeasurements/vknownmeasurementsdatabase.h
diff --git a/src/libs/vformat/vformat.qbs b/src/libs/vformat/vformat.qbs
index ddfb3315e..f163341c1 100644
--- a/src/libs/vformat/vformat.qbs
+++ b/src/libs/vformat/vformat.qbs
@@ -4,7 +4,15 @@ VLib {
name: "VFormatLib"
files: [
+ "knownmeasurements/vknownmeasurement.h",
+ "knownmeasurements/vknownmeasurements.cpp",
+ "knownmeasurements/vknownmeasurements.h",
+ "knownmeasurements/vknownmeasurements_p.h",
+ "knownmeasurements/vknownmeasurementsdocument.cpp",
+ "knownmeasurements/vknownmeasurementsdocument.h",
"vdimensions.cpp",
+ "knownmeasurements/vknownmeasurementsdatabase.cpp",
+ "knownmeasurements/vknownmeasurementsdatabase.h",
"vmeasurements.cpp",
"vlabeltemplate.cpp",
"vpatternrecipe.cpp",
diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp
index b462d5662..80914e52d 100644
--- a/src/libs/vformat/vmeasurements.cpp
+++ b/src/libs/vformat/vmeasurements.cpp
@@ -132,13 +132,18 @@ auto FileComment() -> QString
} // namespace
//---------------------------------------------------------------------------------------------------------------------
-VMeasurements::VMeasurements(VContainer *data)
- : data(data),
- type(MeasurementsType::Unknown){SCASSERT(data != nullptr)}
+VMeasurements::VMeasurements(VContainer *data, QObject *parent)
+ : VDomDocument(parent),
+ data(data),
+ type(MeasurementsType::Unknown)
+{
+ SCASSERT(data != nullptr);
+}
- //---------------------------------------------------------------------------------------------------------------------
- VMeasurements::VMeasurements(Unit unit, VContainer * data)
- : data(data),
+//---------------------------------------------------------------------------------------------------------------------
+VMeasurements::VMeasurements(Unit unit, VContainer *data, QObject *parent)
+ : VDomDocument(parent),
+ data(data),
type(MeasurementsType::Individual)
{
SCASSERT(data != nullptr)
@@ -147,8 +152,10 @@ VMeasurements::VMeasurements(VContainer *data)
}
//---------------------------------------------------------------------------------------------------------------------
-VMeasurements::VMeasurements(Unit unit, const QVector &dimensions, VContainer *data)
- : data(data),
+VMeasurements::VMeasurements(Unit unit, const QVector &dimensions, VContainer *data,
+ QObject *parent)
+ : VDomDocument(parent),
+ data(data),
type(MeasurementsType::Multisize)
{
SCASSERT(data != nullptr)
@@ -249,17 +256,19 @@ void VMeasurements::Remove(const QString &name)
void VMeasurements::MoveTop(const QString &name)
{
const QDomElement node = FindM(name);
- if (not node.isNull())
+ if (node.isNull())
{
- const QDomNodeList mList = elementsByTagName(TagMeasurement);
- if (mList.size() >= 2)
+ return;
+ }
+
+ const QDomNodeList mList = elementsByTagName(TagMeasurement);
+ if (mList.size() >= 2)
+ {
+ const QDomNode top = mList.at(0);
+ if (not top.isNull())
{
- const QDomNode top = mList.at(0);
- if (not top.isNull())
- {
- const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
- list.at(0).insertBefore(node, top);
- }
+ const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
+ list.at(0).insertBefore(node, top);
}
}
}
@@ -268,14 +277,16 @@ void VMeasurements::MoveTop(const QString &name)
void VMeasurements::MoveUp(const QString &name)
{
const QDomElement node = FindM(name);
- if (not node.isNull())
+ if (node.isNull())
{
- const QDomElement prSibling = node.previousSiblingElement(TagMeasurement);
- if (not prSibling.isNull())
- {
- const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
- list.at(0).insertBefore(node, prSibling);
- }
+ return;
+ }
+
+ const QDomElement prSibling = node.previousSiblingElement(TagMeasurement);
+ if (not prSibling.isNull())
+ {
+ const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
+ list.at(0).insertBefore(node, prSibling);
}
}
@@ -283,14 +294,16 @@ void VMeasurements::MoveUp(const QString &name)
void VMeasurements::MoveDown(const QString &name)
{
const QDomElement node = FindM(name);
- if (not node.isNull())
+ if (node.isNull())
{
- const QDomElement nextSibling = node.nextSiblingElement(TagMeasurement);
- if (not nextSibling.isNull())
- {
- const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
- list.at(0).insertAfter(node, nextSibling);
- }
+ return;
+ }
+
+ const QDomElement nextSibling = node.nextSiblingElement(TagMeasurement);
+ if (not nextSibling.isNull())
+ {
+ const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
+ list.at(0).insertAfter(node, nextSibling);
}
}
@@ -298,17 +311,19 @@ void VMeasurements::MoveDown(const QString &name)
void VMeasurements::MoveBottom(const QString &name)
{
const QDomElement node = FindM(name);
- if (not node.isNull())
+ if (node.isNull())
{
- const QDomNodeList mList = elementsByTagName(TagMeasurement);
- if (mList.size() >= 2)
+ return;
+ }
+
+ const QDomNodeList mList = elementsByTagName(TagMeasurement);
+ if (mList.size() >= 2)
+ {
+ const QDomNode bottom = mList.at(mList.size() - 1);
+ if (not bottom.isNull())
{
- const QDomNode bottom = mList.at(mList.size() - 1);
- if (not bottom.isNull())
- {
- const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
- list.at(0).insertAfter(node, bottom);
- }
+ const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
+ list.at(0).insertAfter(node, bottom);
}
}
}
@@ -771,7 +786,8 @@ void VMeasurements::SetMDescription(const QString &name, const QString &text)
QDomElement node = FindM(name);
if (not node.isNull())
{
- SetAttribute(node, AttrDescription, text);
+ SetAttributeOrRemoveIf(node, AttrDescription, text,
+ [](const QString &text) noexcept { return text.isEmpty(); });
}
else
{
@@ -1276,7 +1292,7 @@ auto VMeasurements::FindM(const QString &name) const -> QDomElement
if (name.isEmpty())
{
qWarning() << tr("The measurement name is empty!");
- return QDomElement();
+ return {};
}
QDomNodeList list = elementsByTagName(TagMeasurement);
@@ -1284,17 +1300,19 @@ auto VMeasurements::FindM(const QString &name) const -> QDomElement
for (int i = 0; i < list.size(); ++i)
{
const QDomElement domElement = list.at(i).toElement();
- if (domElement.isNull() == false)
+ if (domElement.isNull())
{
- const QString parameter = domElement.attribute(AttrName);
- if (parameter == name)
- {
- return domElement;
- }
+ continue;
+ }
+
+ const QString parameter = domElement.attribute(AttrName);
+ if (parameter == name)
+ {
+ return domElement;
}
}
- return QDomElement();
+ return {};
}
//---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h
index 2f27603e7..1cca94b98 100644
--- a/src/libs/vformat/vmeasurements.h
+++ b/src/libs/vformat/vmeasurements.h
@@ -39,6 +39,10 @@
#include "../vmisc/def.h"
#include "vdimensions.h"
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif
+
class VContainer;
class VPatternImage;
class VMeasurement;
@@ -57,9 +61,10 @@ class VMeasurements : public VDomDocument
Q_OBJECT // NOLINT
public:
- explicit VMeasurements(VContainer *data);
- VMeasurements(Unit unit, VContainer *data);
- VMeasurements(Unit unit, const QVector &dimensions, VContainer *data);
+ explicit VMeasurements(VContainer *data, QObject *parent = nullptr);
+ VMeasurements(Unit unit, VContainer *data, QObject *parent = nullptr);
+ VMeasurements(Unit unit, const QVector &dimensions, VContainer *data,
+ QObject *parent = nullptr);
~VMeasurements() override = default;
void setXMLContent(const QString &fileName) override;