Known measurements database.

This commit is contained in:
Roman Telezhynskyi 2023-10-28 08:56:05 +03:00
parent 45999c10c1
commit b145a25abf
25 changed files with 1691 additions and 62 deletions

View File

@ -86,6 +86,8 @@ VLib {
"vabstractmconverter.cpp", "vabstractmconverter.cpp",
"vlabeltemplateconverter.cpp", "vlabeltemplateconverter.cpp",
"vwatermarkconverter.cpp", "vwatermarkconverter.cpp",
"vknownmeasurementsconverter.cpp",
"vknownmeasurementsconverter.h",
] ]
} }

View File

@ -148,6 +148,7 @@ const QString AttrCurve1Alias2 = QStringLiteral("curve1Alias2");
const QString AttrCurve2Alias1 = QStringLiteral("curve2Alias1"); const QString AttrCurve2Alias1 = QStringLiteral("curve2Alias1");
const QString AttrCurve2Alias2 = QStringLiteral("curve2Alias2"); const QString AttrCurve2Alias2 = QStringLiteral("curve2Alias2");
const QString AttrLayoutVersion = QStringLiteral("version"); const QString AttrLayoutVersion = QStringLiteral("version");
const QString AttrKMVersion = QStringLiteral("version");
const QString TypeLineDefault = QStringLiteral("default"); const QString TypeLineDefault = QStringLiteral("default");
const QString TypeLineNone = QStringLiteral("none"); const QString TypeLineNone = QStringLiteral("none");

View File

@ -165,6 +165,7 @@ extern const QString AttrCurve1Alias2;
extern const QString AttrCurve2Alias1; extern const QString AttrCurve2Alias1;
extern const QString AttrCurve2Alias2; extern const QString AttrCurve2Alias2;
extern const QString AttrLayoutVersion; extern const QString AttrLayoutVersion;
extern const QString AttrKMVersion;
extern const QString TypeLineDefault; extern const QString TypeLineDefault;
extern const QString TypeLineNone; extern const QString TypeLineNone;

View File

@ -101,5 +101,6 @@
<file>schema/layout/v0.1.4.xsd</file> <file>schema/layout/v0.1.4.xsd</file>
<file>schema/layout/v0.1.5.xsd</file> <file>schema/layout/v0.1.5.xsd</file>
<file>schema/layout/v0.1.6.xsd</file> <file>schema/layout/v0.1.6.xsd</file>
<file>schema/known_measurements/v1.0.0.xsd</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,75 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="known-measurements">
<xs:complexType>
<xs:sequence>
<xs:element name="info">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:string" name="description"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="diagrams">
<xs:complexType>
<xs:sequence>
<xs:element name="image" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="contentType" name="contentType" use="optional"/>
<xs:attribute type="uuid" name="uid" use="required"/>
<xs:attribute type="xs:string" name="title" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="measurements">
<xs:complexType>
<xs:sequence>
<xs:element name="m" maxOccurs="unbounded" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="description" use="optional"/>
<xs:attribute type="xs:string" name="full_name" use="optional"/>
<xs:attribute type="shortName" name="name" use="required"/>
<xs:attribute type="xs:string" name="formula" use="optional"/>
<xs:attribute type="uid" name="diagram" use="optional"/>
<xs:attribute name="specialUnits" type="xs:boolean" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="formatVersion" name="version" use="required"/>
<xs:attribute type="xs:boolean" name="read-only" use="optional"/>
<xs:attribute type="uuid" name="uid" use="required"/>
</xs:complexType>
<xs:unique name="measurementName">
<xs:selector xpath="measurements/m"/>
<xs:field xpath="@name"/>
</xs:unique>
</xs:element>
<xs:simpleType name="shortName">
<xs:restriction base="xs:string">
<xs:pattern value="([^@\p{Nd}\p{Zs}*\\/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;'\\&quot;]){1,1}([^\p{Zs}*\\/&amp;|!&lt;&gt;^&#10;\()\-+.,٫, ٬.=?:;\\&quot;]){0,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="formatVersion">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="contentType">
<xs:restriction base="xs:string">
<xs:pattern value="image/[-\w]+(\.[-\w]+)*([+][-\w]+)?"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -832,7 +832,7 @@ auto VDomDocument::SaveDocument(const QString &fileName, QString &error) -> bool
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction
auto VDomDocument::Major() const -> QString 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); QStringList v = version.split('.'_L1);
return v.at(0); return v.at(0);
} }
@ -841,7 +841,7 @@ auto VDomDocument::Major() const -> QString
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction
auto VDomDocument::Minor() const -> QString 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); QStringList v = version.split('.'_L1);
return v.at(1); return v.at(1);
} }
@ -850,7 +850,7 @@ auto VDomDocument::Minor() const -> QString
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction
auto VDomDocument::Patch() const -> QString 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); QStringList v = version.split('.'_L1);
return v.at(2); return v.at(2);
} }
@ -880,7 +880,7 @@ auto VDomDocument::GetFormatVersionStr() const -> QString
return domElement.text(); return domElement.text();
} }
} }
return QString(QStringLiteral("0.0.0")); return "0.0.0"_L1;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -38,6 +38,7 @@
#include <QLocale> #include <QLocale>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QString> #include <QString>
#include <QUuid>
#include <QtCore/qcontainerfwd.h> #include <QtCore/qcontainerfwd.h>
#include <QtGlobal> #include <QtGlobal>
#include <functional> #include <functional>
@ -201,6 +202,13 @@ inline void VDomDocument::SetAttribute<QLatin1String>(QDomElement &domElement, c
domElement.setAttribute(name, value); domElement.setAttribute(name, value);
} }
//---------------------------------------------------------------------------------------------------------------------
template <>
inline void VDomDocument::SetAttribute<QUuid>(QDomElement &domElement, const QString &name, const QUuid &value) const
{
domElement.setAttribute(name, value.toString());
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
template <> template <>
inline void VDomDocument::SetAttribute<QChar>(QDomElement &domElement, const QString &name, const QChar &value) const inline void VDomDocument::SetAttribute<QChar>(QDomElement &domElement, const QString &name, const QChar &value) const

View File

@ -0,0 +1,137 @@
/************************************************************************
**
** @file vknownmeasurementsconverter.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vknownmeasurementsconverter.h"
#include <QtGlobal>
#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<unsigned int, QString>
{
static auto schemas = QHash<unsigned, QString>{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<unsigned int, QString>
{
return XSDSchemas();
}

View File

@ -0,0 +1,70 @@
/************************************************************************
**
** @file vknownmeasurementsconverter.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef 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<unsigned, QString>;
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<unsigned, QString> override;
private:
Q_DISABLE_COPY_MOVE(VKnownMeasurementsConverter) // NOLINT
static const QString KnownMeasurementsMinVerStr;
};
#endif // VKNOWNMEASUREMENTSCONVERTER_H

View File

@ -132,10 +132,10 @@ auto VLayoutConverter::GetFormatVersionStr() const -> QString
const QDomElement layoutElement = root.toElement(); const QDomElement layoutElement = root.toElement();
if (not layoutElement.isNull()) 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;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -209,3 +209,15 @@ auto VPatternImage::Size() const -> QSize
return QImageReader(&buffer).size(); return QImageReader(&buffer).size();
} }
//---------------------------------------------------------------------------------------------------------------------
auto VPatternImage::Title() const -> QString
{
return m_title;
}
//---------------------------------------------------------------------------------------------------------------------
void VPatternImage::SetTitle(const QString &newTitle)
{
m_title = newTitle;
}

View File

@ -60,10 +60,14 @@ public:
auto Size() const -> QSize; auto Size() const -> QSize;
auto Title() const -> QString;
void SetTitle(const QString &newTitle);
private: private:
QString m_contentType{}; QString m_contentType{};
QByteArray m_contentData{}; QByteArray m_contentData{};
mutable QString m_errorString{}; mutable QString m_errorString{};
QString m_title{};
}; };
#endif // VPATTERNIMAGE_H #endif // VPATTERNIMAGE_H

View File

@ -16,7 +16,8 @@ HEADERS += \
$$PWD//vabstractmconverter.h \ $$PWD//vabstractmconverter.h \
$$PWD/vlabeltemplateconverter.h \ $$PWD/vlabeltemplateconverter.h \
$$PWD/vwatermarkconverter.h \ $$PWD/vwatermarkconverter.h \
$$PWD/vparsererrorhandler.h $$PWD/vparsererrorhandler.h \
$$PWD/vknownmeasurementsconverter.h
SOURCES += \ SOURCES += \
$$PWD/utils.cpp \ $$PWD/utils.cpp \
@ -33,4 +34,6 @@ SOURCES += \
$$PWD//vabstractmconverter.cpp \ $$PWD//vabstractmconverter.cpp \
$$PWD/vlabeltemplateconverter.cpp \ $$PWD/vlabeltemplateconverter.cpp \
$$PWD/vwatermarkconverter.cpp \ $$PWD/vwatermarkconverter.cpp \
$$PWD/vparsererrorhandler.cpp $$PWD/vparsererrorhandler.cpp \
$$PWD/vknownmeasurementsconverter.cpp

View File

@ -0,0 +1,45 @@
/************************************************************************
**
** @file vknownmeasurement.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VKNOWNMEASUREMENT_H
#define VKNOWNMEASUREMENT_H
#include <QString>
#include <QUuid>
struct VKnownMeasurement
{
QString name{};
QString fullName{};
QString description{};
QString formula{};
bool specialUnits{false};
QUuid diagram{};
int index{0};
};
#endif // VKNOWNMEASUREMENT_H

View File

@ -0,0 +1,162 @@
/************************************************************************
**
** @file vknownmeasurements.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "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<QString, VKnownMeasurement>
{
return d->m_measurements;
}
//---------------------------------------------------------------------------------------------------------------------
auto VKnownMeasurements::OrderedMeasurments() const -> QMap<int, VKnownMeasurement>
{
QMap<int, VKnownMeasurement> 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<QUuid, VPatternImage>
{
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);
}

View File

@ -0,0 +1,80 @@
/************************************************************************
**
** @file vknownmeasurements.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VKNOWNMEASUREMENTS_H
#define VKNOWNMEASUREMENTS_H
#include "xml/vpatternimage.h"
#include <QSharedDataPointer>
#include <QTypeInfo>
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<QString, VKnownMeasurement>;
auto OrderedMeasurments() const -> QMap<int, VKnownMeasurement>;
auto Images() const -> QHash<QUuid, VPatternImage>;
void AddMeasurement(const VKnownMeasurement &m);
void AddImage(const QUuid &id, const VPatternImage &image);
private:
QSharedDataPointer<VKnownMeasurementsData> d;
};
Q_DECLARE_TYPEINFO(VKnownMeasurements, Q_MOVABLE_TYPE); // NOLINT
#endif // VKNOWNMEASUREMENTS_H

View File

@ -0,0 +1,62 @@
/************************************************************************
**
** @file vknownmeasurements_p.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VKNOWNMEASUREMENTS_P_H
#define VKNOWNMEASUREMENTS_P_H
#include "../ifc/xml/vpatternimage.h"
#include "../vmisc/defglobal.h"
#include "vknownmeasurement.h"
#include <QSharedData>
#include <QUuid>
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<QUuid, VPatternImage> m_images{}; // NOLINT (misc-non-private-member-variables-in-classes)
QHash<QString, VKnownMeasurement> m_measurements{}; // NOLINT (misc-non-private-member-variables-in-classes)
private:
Q_DISABLE_ASSIGN_MOVE(VKnownMeasurementsData) // NOLINT
};
QT_WARNING_POP
#endif // VKNOWNMEASUREMENTS_P_H

View File

@ -0,0 +1,156 @@
/************************************************************************
**
** @file vknownmeasurementsdatabase.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "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 <QDir>
#include <QDirIterator>
#include <QFileInfo>
#include <QMutex>
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<QUuid, VKnownMeasurementsHeader>
{
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()));
}
}
}

View File

@ -0,0 +1,70 @@
/************************************************************************
**
** @file vknownmeasurementsdatabase.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VKNOWNMEASUREMENTSDATABASE_H
#define VKNOWNMEASUREMENTSDATABASE_H
#include <QCache>
#include <QHash>
#include <QString>
#include <QUuid>
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<QUuid, VKnownMeasurementsHeader>;
auto KnownMeasurements(const QUuid &id) const -> VKnownMeasurements;
private:
bool m_populated{false};
QHash<QUuid, VKnownMeasurementsHeader> m_measurementsDB{};
QHash<QUuid, QString> m_indexMeasurementsPath{};
mutable QCache<QUuid, VKnownMeasurements> m_measurementsCache{15};
void UpdateIndexes();
void ParseDirectory(const QString &path);
};
#endif // VKNOWNMEASUREMENTSDATABASE_H

View File

@ -0,0 +1,601 @@
/************************************************************************
**
** @file vknownmeasurementsdocument.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "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 <QUuid>
#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<bool>(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<bool>(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<QString>(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<QUuid>(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<QString>(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<QString>(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);
}
}

View File

@ -0,0 +1,98 @@
/************************************************************************
**
** @file vknownmeasurementsdocument.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef 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

View File

@ -7,7 +7,12 @@ SOURCES += \
$$PWD/vlabeltemplate.cpp \ $$PWD/vlabeltemplate.cpp \
$$PWD/vpatternrecipe.cpp \ $$PWD/vpatternrecipe.cpp \
$$PWD/vsinglelineoutlinechar.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 *msvc*:SOURCES += $$PWD/stable.cpp
@ -18,4 +23,9 @@ HEADERS += \
$$PWD/vlabeltemplate.h \ $$PWD/vlabeltemplate.h \
$$PWD/vpatternrecipe.h \ $$PWD/vpatternrecipe.h \
$$PWD/vsinglelineoutlinechar.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

View File

@ -4,7 +4,15 @@ VLib {
name: "VFormatLib" name: "VFormatLib"
files: [ files: [
"knownmeasurements/vknownmeasurement.h",
"knownmeasurements/vknownmeasurements.cpp",
"knownmeasurements/vknownmeasurements.h",
"knownmeasurements/vknownmeasurements_p.h",
"knownmeasurements/vknownmeasurementsdocument.cpp",
"knownmeasurements/vknownmeasurementsdocument.h",
"vdimensions.cpp", "vdimensions.cpp",
"knownmeasurements/vknownmeasurementsdatabase.cpp",
"knownmeasurements/vknownmeasurementsdatabase.h",
"vmeasurements.cpp", "vmeasurements.cpp",
"vlabeltemplate.cpp", "vlabeltemplate.cpp",
"vpatternrecipe.cpp", "vpatternrecipe.cpp",

View File

@ -132,13 +132,18 @@ auto FileComment() -> QString
} // namespace } // namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VMeasurements::VMeasurements(VContainer *data) VMeasurements::VMeasurements(VContainer *data, QObject *parent)
: data(data), : VDomDocument(parent),
type(MeasurementsType::Unknown){SCASSERT(data != nullptr)} data(data),
type(MeasurementsType::Unknown)
{
SCASSERT(data != nullptr);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VMeasurements::VMeasurements(Unit unit, VContainer * data) VMeasurements::VMeasurements(Unit unit, VContainer *data, QObject *parent)
: data(data), : VDomDocument(parent),
data(data),
type(MeasurementsType::Individual) type(MeasurementsType::Individual)
{ {
SCASSERT(data != nullptr) SCASSERT(data != nullptr)
@ -147,8 +152,10 @@ VMeasurements::VMeasurements(VContainer *data)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VMeasurements::VMeasurements(Unit unit, const QVector<MeasurementDimension_p> &dimensions, VContainer *data) VMeasurements::VMeasurements(Unit unit, const QVector<MeasurementDimension_p> &dimensions, VContainer *data,
: data(data), QObject *parent)
: VDomDocument(parent),
data(data),
type(MeasurementsType::Multisize) type(MeasurementsType::Multisize)
{ {
SCASSERT(data != nullptr) SCASSERT(data != nullptr)
@ -249,17 +256,19 @@ void VMeasurements::Remove(const QString &name)
void VMeasurements::MoveTop(const QString &name) void VMeasurements::MoveTop(const QString &name)
{ {
const QDomElement node = FindM(name); const QDomElement node = FindM(name);
if (not node.isNull()) if (node.isNull())
{ {
const QDomNodeList mList = elementsByTagName(TagMeasurement); return;
if (mList.size() >= 2) }
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); const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
if (not top.isNull()) 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) void VMeasurements::MoveUp(const QString &name)
{ {
const QDomElement node = FindM(name); const QDomElement node = FindM(name);
if (not node.isNull()) if (node.isNull())
{ {
const QDomElement prSibling = node.previousSiblingElement(TagMeasurement); return;
if (not prSibling.isNull()) }
{
const QDomNodeList list = elementsByTagName(TagBodyMeasurements); const QDomElement prSibling = node.previousSiblingElement(TagMeasurement);
list.at(0).insertBefore(node, prSibling); 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) void VMeasurements::MoveDown(const QString &name)
{ {
const QDomElement node = FindM(name); const QDomElement node = FindM(name);
if (not node.isNull()) if (node.isNull())
{ {
const QDomElement nextSibling = node.nextSiblingElement(TagMeasurement); return;
if (not nextSibling.isNull()) }
{
const QDomNodeList list = elementsByTagName(TagBodyMeasurements); const QDomElement nextSibling = node.nextSiblingElement(TagMeasurement);
list.at(0).insertAfter(node, nextSibling); 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) void VMeasurements::MoveBottom(const QString &name)
{ {
const QDomElement node = FindM(name); const QDomElement node = FindM(name);
if (not node.isNull()) if (node.isNull())
{ {
const QDomNodeList mList = elementsByTagName(TagMeasurement); return;
if (mList.size() >= 2) }
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); const QDomNodeList list = elementsByTagName(TagBodyMeasurements);
if (not bottom.isNull()) 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); QDomElement node = FindM(name);
if (not node.isNull()) if (not node.isNull())
{ {
SetAttribute(node, AttrDescription, text); SetAttributeOrRemoveIf<QString>(node, AttrDescription, text,
[](const QString &text) noexcept { return text.isEmpty(); });
} }
else else
{ {
@ -1276,7 +1292,7 @@ auto VMeasurements::FindM(const QString &name) const -> QDomElement
if (name.isEmpty()) if (name.isEmpty())
{ {
qWarning() << tr("The measurement name is empty!"); qWarning() << tr("The measurement name is empty!");
return QDomElement(); return {};
} }
QDomNodeList list = elementsByTagName(TagMeasurement); QDomNodeList list = elementsByTagName(TagMeasurement);
@ -1284,17 +1300,19 @@ auto VMeasurements::FindM(const QString &name) const -> QDomElement
for (int i = 0; i < list.size(); ++i) for (int i = 0; i < list.size(); ++i)
{ {
const QDomElement domElement = list.at(i).toElement(); const QDomElement domElement = list.at(i).toElement();
if (domElement.isNull() == false) if (domElement.isNull())
{ {
const QString parameter = domElement.attribute(AttrName); continue;
if (parameter == name) }
{
return domElement; const QString parameter = domElement.attribute(AttrName);
} if (parameter == name)
{
return domElement;
} }
} }
return QDomElement(); return {};
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -39,6 +39,10 @@
#include "../vmisc/def.h" #include "../vmisc/def.h"
#include "vdimensions.h" #include "vdimensions.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
#include "../vmisc/defglobal.h"
#endif
class VContainer; class VContainer;
class VPatternImage; class VPatternImage;
class VMeasurement; class VMeasurement;
@ -57,9 +61,10 @@ class VMeasurements : public VDomDocument
Q_OBJECT // NOLINT Q_OBJECT // NOLINT
public: public:
explicit VMeasurements(VContainer *data); explicit VMeasurements(VContainer *data, QObject *parent = nullptr);
VMeasurements(Unit unit, VContainer *data); VMeasurements(Unit unit, VContainer *data, QObject *parent = nullptr);
VMeasurements(Unit unit, const QVector<MeasurementDimension_p> &dimensions, VContainer *data); VMeasurements(Unit unit, const QVector<MeasurementDimension_p> &dimensions, VContainer *data,
QObject *parent = nullptr);
~VMeasurements() override = default; ~VMeasurements() override = default;
void setXMLContent(const QString &fileName) override; void setXMLContent(const QString &fileName) override;