From 715442508d8764faefea96f6ac04d67248a4f9da Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <dismine@gmail.com>
Date: Mon, 14 Feb 2022 13:26:24 +0200
Subject: [PATCH] Dimension custom name.

---
 ChangeLog.txt                                 |   1 +
 .../dialogs/dialogdimensioncustomnames.cpp    | 107 ++++++
 .../tape/dialogs/dialogdimensioncustomnames.h |  62 ++++
 .../dialogs/dialogdimensioncustomnames.ui     |  90 +++++
 .../tape/dialogs/dialogdimensionlabels.cpp    |   7 +-
 .../dialogs/dialogmeasurementscsvcolumns.cpp  |  20 +-
 .../tape/dialogs/dialogrestrictdimension.cpp  |  12 +-
 src/app/tape/dialogs/dialogsetupmultisize.cpp | 198 +++++++++--
 src/app/tape/dialogs/dialogsetupmultisize.h   |  19 +-
 src/app/tape/dialogs/dialogsetupmultisize.ui  | 164 ++++++++-
 src/app/tape/tape.pri                         |   3 +
 src/app/tape/tmainwindow.cpp                  |  50 ++-
 src/app/tape/tmainwindow.h                    |   1 +
 src/app/tape/tmainwindow.ui                   |  12 +
 src/app/valentina/mainwindow.cpp              |  37 ++-
 src/libs/ifc/schema.qrc                       |   1 +
 .../schema/multisize_measurements/v0.5.3.xsd  | 145 ++++++++
 src/libs/ifc/xml/vvstconverter.cpp            |  34 +-
 src/libs/ifc/xml/vvstconverter.h              |   3 +-
 src/libs/vformat/vdimensions.cpp              | 314 ++++++------------
 src/libs/vformat/vdimensions.h                | 153 ++++++---
 src/libs/vformat/vmeasurements.cpp            |  67 ++--
 src/libs/vformat/vmeasurements.h              |   2 +
 23 files changed, 1118 insertions(+), 384 deletions(-)
 create mode 100644 src/app/tape/dialogs/dialogdimensioncustomnames.cpp
 create mode 100644 src/app/tape/dialogs/dialogdimensioncustomnames.h
 create mode 100644 src/app/tape/dialogs/dialogdimensioncustomnames.ui
 create mode 100644 src/libs/ifc/schema/multisize_measurements/v0.5.3.xsd

diff --git a/ChangeLog.txt b/ChangeLog.txt
index 4fedd3662..16797ae67 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -37,6 +37,7 @@
 - Improve creation by mouse for tool Spline.
 - Fix incorrect translation of known measurements.
 - Adjust combobox to fit a dimension label length.
+- Dimension custom name.
 
 # Valentina 0.7.49 July 1, 2021
 - Fix crash.
diff --git a/src/app/tape/dialogs/dialogdimensioncustomnames.cpp b/src/app/tape/dialogs/dialogdimensioncustomnames.cpp
new file mode 100644
index 000000000..ea7c4e03b
--- /dev/null
+++ b/src/app/tape/dialogs/dialogdimensioncustomnames.cpp
@@ -0,0 +1,107 @@
+/************************************************************************
+ **
+ **  @file   dialogdimensioncustomnames.cpp
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   14 2, 2022
+ **
+ **  @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) 2022 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 "dialogdimensioncustomnames.h"
+#include "qstringliteral.h"
+#include "ui_dialogdimensioncustomnames.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+DialogDimensionCustomNames::DialogDimensionCustomNames(
+        const QMap<MeasurementDimension, MeasurementDimension_p> &dimensions, QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::DialogDimensionCustomNames)
+{
+    ui->setupUi(this);
+
+    InitTable(dimensions);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+DialogDimensionCustomNames::~DialogDimensionCustomNames()
+{
+    delete ui;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QMap<MeasurementDimension, QString> DialogDimensionCustomNames::CustomNames() const
+{
+    QMap<MeasurementDimension, QString> names;
+
+    const int rows = ui->tableWidget->rowCount();
+    for (int row = 0; row < rows; ++row)
+    {
+        QTableWidgetItem *item = ui->tableWidget->item(row, 1);
+        if (item != nullptr)
+        {
+            names.insert(static_cast<MeasurementDimension>(item->data(Qt::UserRole).toInt()), item->text());
+        }
+    }
+
+    return names;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogDimensionCustomNames::InitTable(const QMap<MeasurementDimension, MeasurementDimension_p> &dimensions)
+{
+    ui->tableWidget->blockSignals(true);
+    ui->tableWidget->clearContents();
+
+    ui->tableWidget->setRowCount(dimensions.size());
+
+    int row = 0;
+    QMap<MeasurementDimension, MeasurementDimension_p>::const_iterator i = dimensions.constBegin();
+    while (i != dimensions.constEnd())
+    {
+        {
+            QString name = QStringLiteral("%1 (%2)")
+                    .arg(VAbstartMeasurementDimension::DimensionName(i.value()->Type()), i.value()->Axis());
+            auto *itemValue = new QTableWidgetItem(name);
+            itemValue->setTextAlignment(Qt::AlignHCenter | Qt::AlignCenter);
+
+            // set the item non-editable (view only), and non-selectable
+            Qt::ItemFlags flags = itemValue->flags();
+            flags &= ~(Qt::ItemIsEditable); // reset/clear the flag
+            itemValue->setFlags(flags);
+
+            ui->tableWidget->setItem(row, 0, itemValue);
+        }
+
+        {
+            auto *itemLabel = new QTableWidgetItem(i.value()->CustomName());
+            itemLabel->setData(Qt::UserRole, static_cast<int>(i.value()->Type()));
+            itemLabel->setTextAlignment(Qt::AlignHCenter | Qt::AlignCenter);
+
+            ui->tableWidget->setItem(row, 1, itemLabel);
+        }
+
+        ++row;
+        ++i;
+    }
+
+    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+    ui->tableWidget->blockSignals(false);
+}
diff --git a/src/app/tape/dialogs/dialogdimensioncustomnames.h b/src/app/tape/dialogs/dialogdimensioncustomnames.h
new file mode 100644
index 000000000..9af71c537
--- /dev/null
+++ b/src/app/tape/dialogs/dialogdimensioncustomnames.h
@@ -0,0 +1,62 @@
+/************************************************************************
+ **
+ **  @file   dialogdimensioncustomnames.h
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   14 2, 2022
+ **
+ **  @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) 2022 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 DIALOGDIMENSIONCUSTOMNAMES_H
+#define DIALOGDIMENSIONCUSTOMNAMES_H
+
+#include <QDialog>
+
+#include "../vformat/vdimensions.h"
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif // QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+
+namespace Ui
+{
+class DialogDimensionCustomNames;
+}
+
+class DialogDimensionCustomNames : public QDialog
+{
+    Q_OBJECT // NOLINT
+
+public:
+    explicit DialogDimensionCustomNames(const QMap<MeasurementDimension, MeasurementDimension_p > &dimensions,
+                                        QWidget *parent = nullptr);
+    ~DialogDimensionCustomNames() override;
+
+    auto CustomNames() const -> QMap<MeasurementDimension, QString>;
+
+private:
+    Q_DISABLE_COPY_MOVE(DialogDimensionCustomNames) // NOLINT
+    Ui::DialogDimensionCustomNames *ui;
+
+    void InitTable(const QMap<MeasurementDimension, MeasurementDimension_p> &dimensions);
+};
+
+#endif // DIALOGDIMENSIONCUSTOMNAMES_H
diff --git a/src/app/tape/dialogs/dialogdimensioncustomnames.ui b/src/app/tape/dialogs/dialogdimensioncustomnames.ui
new file mode 100644
index 000000000..20da7cfc2
--- /dev/null
+++ b/src/app/tape/dialogs/dialogdimensioncustomnames.ui
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogDimensionCustomNames</class>
+ <widget class="QDialog" name="DialogDimensionCustomNames">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>418</width>
+    <height>444</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dimension custom names</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../share/resources/tapeicon.qrc">
+    <normaloff>:/tapeicon/64x64/logo.png</normaloff>:/tapeicon/64x64/logo.png</iconset>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTableWidget" name="tableWidget">
+     <attribute name="horizontalHeaderStretchLastSection">
+      <bool>true</bool>
+     </attribute>
+     <attribute name="verticalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Custom Name</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../share/resources/tapeicon.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>DialogDimensionCustomNames</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>DialogDimensionCustomNames</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/app/tape/dialogs/dialogdimensionlabels.cpp b/src/app/tape/dialogs/dialogdimensionlabels.cpp
index ecfbcba89..a984be32a 100644
--- a/src/app/tape/dialogs/dialogdimensionlabels.cpp
+++ b/src/app/tape/dialogs/dialogdimensionlabels.cpp
@@ -29,8 +29,8 @@
 #include "ui_dialogdimensionlabels.h"
 
 //---------------------------------------------------------------------------------------------------------------------
-DialogDimensionLabels::DialogDimensionLabels(const QMap<MeasurementDimension, MeasurementDimension_p> &dimensions, bool fullCircumference,
-                                             QWidget *parent)
+DialogDimensionLabels::DialogDimensionLabels(const QMap<MeasurementDimension, MeasurementDimension_p> &dimensions,
+                                             bool fullCircumference, QWidget *parent)
     : QDialog(parent),
       ui(new Ui::DialogDimensionLabels),
       m_dimensions(dimensions),
@@ -130,8 +130,7 @@ void DialogDimensionLabels::InitDimensions()
 
     for(auto &dimension : m_dimensions)
     {
-        ui->comboBoxDimensionLabels->addItem(VAbstartMeasurementDimension::DimensionName(dimension->Type()),
-                                             static_cast<int>(dimension->Type()));
+        ui->comboBoxDimensionLabels->addItem(dimension->Name(), static_cast<int>(dimension->Type()));
     }
 
     ui->comboBoxDimensionLabels->blockSignals(false);
diff --git a/src/app/tape/dialogs/dialogmeasurementscsvcolumns.cpp b/src/app/tape/dialogs/dialogmeasurementscsvcolumns.cpp
index c3c1280ad..66e4609e9 100644
--- a/src/app/tape/dialogs/dialogmeasurementscsvcolumns.cpp
+++ b/src/app/tape/dialogs/dialogmeasurementscsvcolumns.cpp
@@ -255,8 +255,7 @@ QString DialogMeasurementsCSVColumns::ColumnHeader(int column) const
                 if (m_dimensions.size() > 0)
                 {
                     MeasurementDimension_p dimension = m_dimensions.at(0);
-                    return tr("Shift (%1):", "measurement column")
-                        .arg(VAbstartMeasurementDimension::DimensionName(dimension->Type()));
+                    return tr("Shift (%1):", "measurement column").arg(dimension->Name());
                 }
                 else
                 {
@@ -266,8 +265,7 @@ QString DialogMeasurementsCSVColumns::ColumnHeader(int column) const
                 if (m_dimensions.size() > 1)
                 {
                     MeasurementDimension_p dimension = m_dimensions.at(1);
-                    return tr("Shift (%1):", "measurement column")
-                        .arg(VAbstartMeasurementDimension::DimensionName(dimension->Type()));
+                    return tr("Shift (%1):", "measurement column").arg(dimension->Name());
                 }
                 else
                 {
@@ -277,8 +275,7 @@ QString DialogMeasurementsCSVColumns::ColumnHeader(int column) const
                 if (m_dimensions.size() > 2)
                 {
                     MeasurementDimension_p dimension = m_dimensions.at(2);
-                    return tr("Shift (%1):", "measurement column")
-                        .arg(VAbstartMeasurementDimension::DimensionName(dimension->Type()));
+                    return tr("Shift (%1):", "measurement column").arg(dimension->Name());
                 }
                 else
                 {
@@ -289,7 +286,7 @@ QString DialogMeasurementsCSVColumns::ColumnHeader(int column) const
             case MultisizeMeasurementsColumns::Description:
                 return tr("Description", "measurement column");
             default:
-                return QString();
+            return {};
         }
     }
 }
@@ -741,22 +738,19 @@ void DialogMeasurementsCSVColumns::RetranslateLabels()
         if (m_dimensions.size() > 0)
         {
             MeasurementDimension_p dimension = m_dimensions.at(0);
-            ui->labelShiftA->setText(tr("Shift (%1)*:")
-                                         .arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
+            ui->labelShiftA->setText(tr("Shift (%1)*:").arg(dimension->Name()));
         }
 
         if (m_dimensions.size() > 1)
         {
             MeasurementDimension_p dimension = m_dimensions.at(1);
-            ui->labelShiftB->setText(tr("Shift (%1)*:")
-                                         .arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
+            ui->labelShiftB->setText(tr("Shift (%1)*:").arg(dimension->Name()));
         }
 
         if (m_dimensions.size() > 2)
         {
             MeasurementDimension_p dimension = m_dimensions.at(2);
-            ui->labelShiftC->setText(tr("Shift (%1)*:")
-                                         .arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
+            ui->labelShiftC->setText(tr("Shift (%1)*:").arg(dimension->Name()));
         }
     }
 }
diff --git a/src/app/tape/dialogs/dialogrestrictdimension.cpp b/src/app/tape/dialogs/dialogrestrictdimension.cpp
index ce4e8a8aa..2d3cda383 100644
--- a/src/app/tape/dialogs/dialogrestrictdimension.cpp
+++ b/src/app/tape/dialogs/dialogrestrictdimension.cpp
@@ -135,10 +135,8 @@ void DialogRestrictDimension::changeEvent(QEvent *event)
             {
                 MeasurementDimension_p dimension = m_dimensions.at(index);
 
-                name->setText(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
-                name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension->Type(),
-                                                                                dimension->IsCircumference(),
-                                                                                m_fullCircumference));
+                name->setText(dimension->Name()+QChar(':'));
+                name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension, m_fullCircumference));
 
                 InitDimensionGradation(dimension, control);
             }
@@ -412,10 +410,8 @@ void DialogRestrictDimension::InitDimensionsBaseValues()
         if (m_dimensions.size() > index)
         {
             MeasurementDimension_p dimension = m_dimensions.at(index);
-            name->setText(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
-            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension->Type(),
-                                                                            dimension->IsCircumference(),
-                                                                            m_fullCircumference));
+            name->setText(dimension->Name()+QChar(':'));
+            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension, m_fullCircumference));
 
             InitDimensionGradation(dimension, control);
         }
diff --git a/src/app/tape/dialogs/dialogsetupmultisize.cpp b/src/app/tape/dialogs/dialogsetupmultisize.cpp
index c4296976b..a9e134eff 100644
--- a/src/app/tape/dialogs/dialogsetupmultisize.cpp
+++ b/src/app/tape/dialogs/dialogsetupmultisize.cpp
@@ -34,6 +34,15 @@
 #include "../mapplication.h"
 #include "../vmisc/backport/qoverload.h"
 
+namespace
+{
+void InitDimensionTitle(QGroupBox *group, const MeasurementDimension_p &dimension)
+{
+    SCASSERT(group != nullptr)
+    group->setTitle(QStringLiteral("%1 (%2)").arg(dimension->Name(), dimension->Axis()));
+}
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 DialogSetupMultisize::DialogSetupMultisize(Unit unit, QWidget *parent) :
     QDialog(parent),
@@ -46,7 +55,6 @@ DialogSetupMultisize::DialogSetupMultisize(Unit unit, QWidget *parent) :
     ui->setupUi(this);
 
     ui->labelError->clear();
-    ui->checkBoxYDimensionCircumference->setChecked(m_yDimension->IsCircumference());
 
     InitXDimension();
     InitYDimension();
@@ -157,8 +165,47 @@ DialogSetupMultisize::DialogSetupMultisize(Unit unit, QWidget *parent) :
 
     connect(ui->checkBoxFullCircumference, &QCheckBox::stateChanged,
             this, &DialogSetupMultisize::ShowFullCircumference);
+
+    connect(ui->checkBoxXDimensionCircumference, &QCheckBox::stateChanged,
+            this, &DialogSetupMultisize::XDimensionCircumferenceChanged);
     connect(ui->checkBoxYDimensionCircumference, &QCheckBox::stateChanged,
             this, &DialogSetupMultisize::YDimensionCircumferenceChanged);
+    connect(ui->checkBoxWDimensionCircumference, &QCheckBox::stateChanged,
+            this, &DialogSetupMultisize::WDimensionCircumferenceChanged);
+    connect(ui->checkBoxZDimensionCircumference, &QCheckBox::stateChanged,
+            this, &DialogSetupMultisize::ZDimensionCircumferenceChanged);
+
+    connect(ui->lineEditCustomXDimensionName, &QLineEdit::textChanged, this, [this](const QString &text)
+    {
+        m_xDimension->SetCustomName(text);
+        InitDimensionTitle(ui->groupBoxXDimension, m_xDimension);
+
+        CheckState();
+    });
+
+    connect(ui->lineEditCustomYDimensionName, &QLineEdit::textChanged, this, [this](const QString &text)
+    {
+        m_yDimension->SetCustomName(text);
+        InitDimensionTitle(ui->groupBoxYDimension, m_yDimension);
+
+        CheckState();
+    });
+
+    connect(ui->lineEditCustomWDimensionName, &QLineEdit::textChanged, this, [this](const QString &text)
+    {
+        m_wDimension->SetCustomName(text);
+        InitDimensionTitle(ui->groupBoxWDimension, m_wDimension);
+
+        CheckState();
+    });
+
+    connect(ui->lineEditCustomZDimensionName, &QLineEdit::textChanged, this, [this](const QString &text)
+    {
+        m_zDimension->SetCustomName(text);
+        InitDimensionTitle(ui->groupBoxZDimension, m_zDimension);
+
+        CheckState();
+    });
 
     CheckState();
 }
@@ -176,21 +223,37 @@ auto DialogSetupMultisize::Dimensions() const -> QVector<MeasurementDimension_p>
 
     if (ui->groupBoxXDimension->isChecked())
     {
+        if (not ui->groupBoxCustomXDimensionName->isChecked())
+        {
+            m_xDimension->SetCustomName(QString());
+        }
         dimensions.append(m_xDimension);
     }
 
     if (ui->groupBoxYDimension->isChecked())
     {
+        if (not ui->groupBoxCustomYDimensionName->isChecked())
+        {
+            m_yDimension->SetCustomName(QString());
+        }
         dimensions.append(m_yDimension);
     }
 
     if (ui->groupBoxWDimension->isChecked())
     {
+        if (not ui->groupBoxCustomWDimensionName->isChecked())
+        {
+            m_wDimension->SetCustomName(QString());
+        }
         dimensions.append(m_wDimension);
     }
 
     if (ui->groupBoxZDimension->isChecked())
     {
+        if (not ui->groupBoxCustomZDimensionName->isChecked())
+        {
+            m_zDimension->SetCustomName(QString());
+        }
         dimensions.append(m_zDimension);
     }
 
@@ -203,19 +266,6 @@ auto DialogSetupMultisize::FullCircumference() const -> bool
     return ui->checkBoxFullCircumference->isChecked();
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void DialogSetupMultisize::changeEvent(QEvent *event)
-{
-    if (event->type() == QEvent::LanguageChange)
-    {
-        // retranslate designer form (single inheritance approach)
-        ui->retranslateUi(this);
-    }
-
-    // remember to call base class implementation
-    QDialog::changeEvent(event);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::showEvent(QShowEvent *event)
 {
@@ -257,6 +307,8 @@ void DialogSetupMultisize::ShowFullCircumference()
         comboBoxBase->blockSignals(false);
     };
 
+    ShowDimensionFullCircumference(ui->doubleSpinBoxXDimensionMinValue, ui->doubleSpinBoxXDimensionMaxValue,
+                                   ui->comboBoxXDimensionStep, ui->comboBoxXDimensionBase, m_xDimension);
     ShowDimensionFullCircumference(ui->doubleSpinBoxYDimensionMinValue, ui->doubleSpinBoxYDimensionMaxValue,
                                    ui->comboBoxYDimensionStep, ui->comboBoxYDimensionBase, m_yDimension);
     ShowDimensionFullCircumference(ui->doubleSpinBoxWDimensionMinValue, ui->doubleSpinBoxWDimensionMaxValue,
@@ -267,6 +319,34 @@ void DialogSetupMultisize::ShowFullCircumference()
     CheckState();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSetupMultisize::XDimensionCircumferenceChanged()
+{
+    bool checked = ui->checkBoxXDimensionCircumference->isChecked();
+    m_xDimension->SetCircumference(checked);
+
+    const bool c = m_xDimension->IsCircumference();
+    const QString unitStr = c ? " " + UnitsToStr(m_xDimension->Units()) : QString();
+
+    ui->doubleSpinBoxXDimensionMinValue->setSuffix(unitStr);
+    ui->doubleSpinBoxXDimensionMaxValue->setSuffix(unitStr);
+
+    InitDimension(ui->doubleSpinBoxXDimensionMinValue, ui->doubleSpinBoxXDimensionMaxValue, ui->comboBoxXDimensionStep,
+                  m_xDimension);
+
+    UpdateBase(ui->comboBoxXDimensionBase, m_xDimension);
+
+    ui->comboBoxXDimensionBase->blockSignals(true);
+    ui->comboBoxXDimensionBase->setCurrentIndex(-1);
+    ui->comboBoxXDimensionBase->blockSignals(false);
+
+    bool ok = false;
+    const qreal base = ui->comboBoxXDimensionBase->currentData().toDouble(&ok);
+    m_xDimension->SetBaseValue(ok ? base : -1);
+
+    CheckState();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::YDimensionCircumferenceChanged()
 {
@@ -295,6 +375,62 @@ void DialogSetupMultisize::YDimensionCircumferenceChanged()
     CheckState();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSetupMultisize::WDimensionCircumferenceChanged()
+{
+    bool checked = ui->checkBoxWDimensionCircumference->isChecked();
+    m_wDimension->SetCircumference(checked);
+
+    const bool c = m_wDimension->IsCircumference();
+    const QString unitStr = c ? " " + UnitsToStr(m_wDimension->Units()) : QString();
+
+    ui->doubleSpinBoxWDimensionMinValue->setSuffix(unitStr);
+    ui->doubleSpinBoxWDimensionMaxValue->setSuffix(unitStr);
+
+    InitDimension(ui->doubleSpinBoxWDimensionMinValue, ui->doubleSpinBoxWDimensionMaxValue, ui->comboBoxWDimensionStep,
+                  m_wDimension);
+
+    UpdateBase(ui->comboBoxWDimensionBase, m_wDimension);
+
+    ui->comboBoxWDimensionBase->blockSignals(true);
+    ui->comboBoxWDimensionBase->setCurrentIndex(-1);
+    ui->comboBoxWDimensionBase->blockSignals(false);
+
+    bool ok = false;
+    const qreal base = ui->comboBoxWDimensionBase->currentData().toDouble(&ok);
+    m_wDimension->SetBaseValue(ok ? base : -1);
+
+    CheckState();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSetupMultisize::ZDimensionCircumferenceChanged()
+{
+    bool checked = ui->checkBoxZDimensionCircumference->isChecked();
+    m_zDimension->SetCircumference(checked);
+
+    const bool c = m_zDimension->IsCircumference();
+    const QString unitStr = c ? " " + UnitsToStr(m_zDimension->Units()) : QString();
+
+    ui->doubleSpinBoxZDimensionMinValue->setSuffix(unitStr);
+    ui->doubleSpinBoxZDimensionMaxValue->setSuffix(unitStr);
+
+    InitDimension(ui->doubleSpinBoxZDimensionMinValue, ui->doubleSpinBoxZDimensionMaxValue, ui->comboBoxZDimensionStep,
+                  m_zDimension);
+
+    UpdateBase(ui->comboBoxZDimensionBase, m_zDimension);
+
+    ui->comboBoxZDimensionBase->blockSignals(true);
+    ui->comboBoxZDimensionBase->setCurrentIndex(-1);
+    ui->comboBoxZDimensionBase->blockSignals(false);
+
+    bool ok = false;
+    const qreal base = ui->comboBoxZDimensionBase->currentData().toDouble(&ok);
+    m_zDimension->SetBaseValue(ok ? base : -1);
+
+    CheckState();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::CheckState()
 {
@@ -307,10 +443,12 @@ void DialogSetupMultisize::CheckState()
 
     int dimensions = 0;
 
-    auto CheckDimension = [this](QGroupBox *group, bool &dimensionValid, int &dimensions,
-                                 const MeasurementDimension_p &dimension)
+    auto CheckDimension = [this](QGroupBox *group, QGroupBox *nameGroup, QLineEdit *lineEdit, bool &dimensionValid,
+            int &dimensions, const MeasurementDimension_p &dimension)
     {
         SCASSERT(group != nullptr)
+        SCASSERT(nameGroup != nullptr)
+        SCASSERT(lineEdit != nullptr)
 
         if (group->isChecked())
         {
@@ -319,15 +457,29 @@ void DialogSetupMultisize::CheckState()
 
             if (ui->labelError->text().isEmpty() && not dimensionValid)
             {
-                ui->labelError->setText(tr("Please, provide correct data for dimensions"));
+                ui->labelError->setText(tr("Please, provide correct data for dimension %1").arg(dimension->Axis()));
+                return;
+            }
+
+            if (nameGroup->isChecked() && lineEdit->text().isEmpty())
+            {
+                if (ui->labelError->text().isEmpty())
+                {
+                    ui->labelError->setText(tr("Please, provide custom name for dimension %1").arg(dimension->Axis()));
+                    return;
+                }
             }
         }
     };
 
-    CheckDimension(ui->groupBoxXDimension, xDimensionValid, dimensions, m_xDimension);
-    CheckDimension(ui->groupBoxYDimension, yDimensionValid, dimensions, m_yDimension);
-    CheckDimension(ui->groupBoxWDimension, wDimensionValid, dimensions, m_wDimension);
-    CheckDimension(ui->groupBoxZDimension, zDimensionValid, dimensions, m_zDimension);
+    CheckDimension(ui->groupBoxXDimension, ui->groupBoxCustomXDimensionName, ui->lineEditCustomXDimensionName,
+                   xDimensionValid, dimensions, m_xDimension);
+    CheckDimension(ui->groupBoxYDimension, ui->groupBoxCustomYDimensionName, ui->lineEditCustomYDimensionName,
+                   yDimensionValid, dimensions, m_yDimension);
+    CheckDimension(ui->groupBoxWDimension, ui->groupBoxCustomWDimensionName, ui->lineEditCustomWDimensionName,
+                   wDimensionValid, dimensions, m_wDimension);
+    CheckDimension(ui->groupBoxZDimension, ui->groupBoxCustomZDimensionName, ui->lineEditCustomZDimensionName,
+                   zDimensionValid, dimensions, m_zDimension);
 
     if (ui->labelError->text().isEmpty() && dimensions == 0)
     {
@@ -431,6 +583,7 @@ void DialogSetupMultisize::InitDimension(QDoubleSpinBox *doubleSpinBoxMinValue,
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::InitXDimension()
 {
+    InitDimensionTitle(ui->groupBoxXDimension, m_xDimension);
     InitDimension(ui->doubleSpinBoxXDimensionMinValue, ui->doubleSpinBoxXDimensionMaxValue, ui->comboBoxXDimensionStep,
                   m_xDimension);
 }
@@ -438,6 +591,7 @@ void DialogSetupMultisize::InitXDimension()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::InitYDimension()
 {
+    InitDimensionTitle(ui->groupBoxYDimension,  m_yDimension);
     InitDimension(ui->doubleSpinBoxYDimensionMinValue, ui->doubleSpinBoxYDimensionMaxValue, ui->comboBoxYDimensionStep,
                   m_yDimension);
 }
@@ -445,6 +599,7 @@ void DialogSetupMultisize::InitYDimension()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::InitWDimension()
 {
+    InitDimensionTitle(ui->groupBoxWDimension, m_wDimension);
     InitDimension(ui->doubleSpinBoxWDimensionMinValue, ui->doubleSpinBoxWDimensionMaxValue, ui->comboBoxWDimensionStep,
                   m_wDimension);
 }
@@ -452,6 +607,7 @@ void DialogSetupMultisize::InitWDimension()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSetupMultisize::InitZDimension()
 {
+    InitDimensionTitle(ui->groupBoxZDimension, m_zDimension);
     InitDimension(ui->doubleSpinBoxZDimensionMinValue, ui->doubleSpinBoxZDimensionMaxValue, ui->comboBoxZDimensionStep,
                   m_zDimension);
 }
diff --git a/src/app/tape/dialogs/dialogsetupmultisize.h b/src/app/tape/dialogs/dialogsetupmultisize.h
index 311656165..98295ccdc 100644
--- a/src/app/tape/dialogs/dialogsetupmultisize.h
+++ b/src/app/tape/dialogs/dialogsetupmultisize.h
@@ -33,6 +33,10 @@
 #include "../vformat/vdimensions.h"
 #include "../vmisc/def.h"
 
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif // QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+
 class QDoubleSpinBox;
 
 namespace Ui
@@ -42,26 +46,29 @@ class DialogSetupMultisize;
 
 class DialogSetupMultisize : public QDialog
 {
-    Q_OBJECT
+    Q_OBJECT // NOLINT
 
 public:
     explicit DialogSetupMultisize(Unit unit, QWidget *parent = nullptr);
-    ~DialogSetupMultisize();
+    ~DialogSetupMultisize() override;
 
     auto Dimensions() const -> QVector<MeasurementDimension_p>;
 
     auto FullCircumference() const -> bool;
 
 protected:
-    virtual void changeEvent(QEvent* event) override;
-    virtual void showEvent(QShowEvent *event) override;
+    void showEvent(QShowEvent *event) override;
 
 private slots:
     void ShowFullCircumference();
+
+    void XDimensionCircumferenceChanged();
     void YDimensionCircumferenceChanged();
+    void WDimensionCircumferenceChanged();
+    void ZDimensionCircumferenceChanged();
 
 private:
-    Q_DISABLE_COPY(DialogSetupMultisize)
+    Q_DISABLE_COPY_MOVE(DialogSetupMultisize)
     Ui::DialogSetupMultisize *ui;
     bool m_isInitialized{false};
     QSharedPointer<VXMeasurementDimension> m_xDimension;
@@ -73,7 +80,7 @@ private:
 
     void InitDimensionMinMax(QDoubleSpinBox *doubleSpinBoxMinValue, QDoubleSpinBox *doubleSpinBoxMaxValue,
                              const MeasurementDimension_p &dimension);
-    void InitDimensionStep(QComboBox *comboBoxStep,const MeasurementDimension_p &dimension);
+    void InitDimensionStep(QComboBox *comboBoxStep, const MeasurementDimension_p &dimension);
 
     void InitDimension(QDoubleSpinBox *doubleSpinBoxMinValue, QDoubleSpinBox *doubleSpinBoxMaxValue,
                        QComboBox *comboBoxStep, const MeasurementDimension_p &dimension);
diff --git a/src/app/tape/dialogs/dialogsetupmultisize.ui b/src/app/tape/dialogs/dialogsetupmultisize.ui
index b8438cb15..18c2c393f 100644
--- a/src/app/tape/dialogs/dialogsetupmultisize.ui
+++ b/src/app/tape/dialogs/dialogsetupmultisize.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>734</width>
-    <height>289</height>
+    <width>802</width>
+    <height>373</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -30,12 +30,41 @@
      <item>
       <widget class="QGroupBox" name="groupBoxXDimension">
        <property name="title">
-        <string comment="dimension">Height</string>
+        <string notr="true" comment="dimension">X</string>
        </property>
        <property name="checkable">
         <bool>true</bool>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <widget class="QGroupBox" name="groupBoxCustomXDimensionName">
+          <property name="title">
+           <string>Custom name</string>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+          <property name="checked">
+           <bool>false</bool>
+          </property>
+          <layout class="QHBoxLayout" name="horizontalLayout_2">
+           <item>
+            <widget class="QLabel" name="label_17">
+             <property name="text">
+              <string>Name:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="lineEditCustomXDimensionName">
+             <property name="clearButtonEnabled">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
         <item>
          <layout class="QFormLayout" name="formLayout_2">
           <property name="fieldGrowthPolicy">
@@ -117,13 +146,23 @@
           </item>
          </layout>
         </item>
+        <item>
+         <widget class="QCheckBox" name="checkBoxXDimensionCircumference">
+          <property name="text">
+           <string>Circumference</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBoxYDimension">
        <property name="title">
-        <string comment="dimension">Size</string>
+        <string notr="true" comment="dimension">Y</string>
        </property>
        <property name="checkable">
         <bool>true</bool>
@@ -132,6 +171,35 @@
         <bool>true</bool>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout">
+        <item>
+         <widget class="QGroupBox" name="groupBoxCustomYDimensionName">
+          <property name="title">
+           <string>Custom name</string>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+          <property name="checked">
+           <bool>false</bool>
+          </property>
+          <layout class="QHBoxLayout" name="horizontalLayout_3">
+           <item>
+            <widget class="QLabel" name="label_18">
+             <property name="text">
+              <string>Name:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="lineEditCustomYDimensionName">
+             <property name="clearButtonEnabled">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
         <item>
          <layout class="QFormLayout" name="formLayout_3">
           <property name="fieldGrowthPolicy">
@@ -229,7 +297,7 @@
      <item>
       <widget class="QGroupBox" name="groupBoxWDimension">
        <property name="title">
-        <string comment="dimension">Waist</string>
+        <string notr="true" comment="dimension">W</string>
        </property>
        <property name="checkable">
         <bool>true</bool>
@@ -238,6 +306,35 @@
         <bool>false</bool>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_4">
+        <item>
+         <widget class="QGroupBox" name="groupBoxCustomWDimensionName">
+          <property name="title">
+           <string>Custom name</string>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+          <property name="checked">
+           <bool>false</bool>
+          </property>
+          <layout class="QHBoxLayout" name="horizontalLayout_4">
+           <item>
+            <widget class="QLabel" name="label_19">
+             <property name="text">
+              <string>Name:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="lineEditCustomWDimensionName">
+             <property name="clearButtonEnabled">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
         <item>
          <layout class="QFormLayout" name="formLayout_5">
           <property name="fieldGrowthPolicy">
@@ -319,13 +416,23 @@
           </item>
          </layout>
         </item>
+        <item>
+         <widget class="QCheckBox" name="checkBoxWDimensionCircumference">
+          <property name="text">
+           <string>Circumference</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBoxZDimension">
        <property name="title">
-        <string comment="dimension">Hip</string>
+        <string notr="true" comment="dimension">Z</string>
        </property>
        <property name="checkable">
         <bool>true</bool>
@@ -334,6 +441,35 @@
         <bool>false</bool>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_3">
+        <item>
+         <widget class="QGroupBox" name="groupBoxCustomZDimensionName">
+          <property name="title">
+           <string>Custom name</string>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+          <property name="checked">
+           <bool>false</bool>
+          </property>
+          <layout class="QHBoxLayout" name="horizontalLayout_5">
+           <item>
+            <widget class="QLabel" name="label_20">
+             <property name="text">
+              <string>Name:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="lineEditCustomZDimensionName">
+             <property name="clearButtonEnabled">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
         <item>
          <layout class="QFormLayout" name="formLayout_4">
           <property name="fieldGrowthPolicy">
@@ -415,6 +551,16 @@
           </item>
          </layout>
         </item>
+        <item>
+         <widget class="QCheckBox" name="checkBoxZDimensionCircumference">
+          <property name="text">
+           <string>Circumference</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
        </layout>
       </widget>
      </item>
@@ -422,6 +568,12 @@
    </item>
    <item>
     <widget class="QLabel" name="labelError">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
      <property name="text">
       <string notr="true">_</string>
      </property>
diff --git a/src/app/tape/tape.pri b/src/app/tape/tape.pri
index fd2e7443e..c970bf799 100644
--- a/src/app/tape/tape.pri
+++ b/src/app/tape/tape.pri
@@ -2,6 +2,7 @@
 # This need for corect working file translations.pro
 
 SOURCES  += \
+    $$PWD/dialogs/dialogdimensioncustomnames.cpp \
     $$PWD/dialogs/dialogdimensionlabels.cpp \
     $$PWD/dialogs/dialogmeasurementscsvcolumns.cpp \
     $$PWD/dialogs/dialogrestrictdimension.cpp \
@@ -21,6 +22,7 @@ SOURCES  += \
 *msvc*:SOURCES += $$PWD/stable.cpp
 
 HEADERS  += \
+    $$PWD/dialogs/dialogdimensioncustomnames.h \
     $$PWD/dialogs/dialogdimensionlabels.h \
     $$PWD/dialogs/dialogmeasurementscsvcolumns.h \
     $$PWD/dialogs/dialogrestrictdimension.h \
@@ -39,6 +41,7 @@ HEADERS  += \
     $$PWD/dialogs/dialogsetupmultisize.h
 
 FORMS    += \
+    $$PWD/dialogs/dialogdimensioncustomnames.ui \
     $$PWD/dialogs/dialogdimensionlabels.ui \
     $$PWD/dialogs/dialogmeasurementscsvcolumns.ui \
     $$PWD/dialogs/dialogrestrictdimension.ui \
diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp
index f4ec7226b..f7d7ff10d 100644
--- a/src/app/tape/tmainwindow.cpp
+++ b/src/app/tape/tmainwindow.cpp
@@ -36,6 +36,7 @@
 #include "dialogs/dialogrestrictdimension.h"
 #include "dialogs/dialogdimensionlabels.h"
 #include "dialogs/dialogmeasurementscsvcolumns.h"
+#include "dialogs/dialogdimensioncustomnames.h"
 #include "../vpatterndb/vcontainer.h"
 #include "../vpatterndb/calculator.h"
 #include "../vpatterndb/pmsystems.h"
@@ -2390,6 +2391,23 @@ void TMainWindow::EditDimensionLabels()
     InitDimensionControls();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void TMainWindow::DimensionCustomNames()
+{
+    const QMap<MeasurementDimension, MeasurementDimension_p > dimensions = m->Dimensions();
+
+    DialogDimensionCustomNames dialog(dimensions, this);
+    if (dialog.exec() == QDialog::Rejected)
+    {
+        return;
+    }
+
+    m->SetDimensionCustomNames(dialog.CustomNames());
+
+    MeasurementsWereSaved(false);
+    InitDimensionControls();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void TMainWindow::SetDefaultGUILanguage()
 {
@@ -2716,6 +2734,10 @@ void TMainWindow::InitMenu()
         ui->actionDimensionLabels->setEnabled(true);
         connect(ui->actionDimensionLabels, &QAction::triggered, this, &TMainWindow::EditDimensionLabels);
 
+        ui->actionDimensionCustomNames->setVisible(true);
+        ui->actionDimensionCustomNames->setEnabled(true);
+        connect(ui->actionDimensionCustomNames, &QAction::triggered, this, &TMainWindow::DimensionCustomNames);
+
         // File
         ui->actionExportToIndividual->setVisible(true);
         ui->actionExportToIndividual->setEnabled(true);
@@ -2738,10 +2760,8 @@ void TMainWindow::InitDimensionsBaseValue()
         if (dimensions.size() > index)
         {
             MeasurementDimension_p dimension = dimensions.at(index);
-            name->setText(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
-            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension->Type(),
-                                                                            dimension->IsCircumference(),
-                                                                            m->IsFullCircumference()));
+            name->setText(dimension->Name()+QChar(':'));
+            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension, m->IsFullCircumference()));
 
             DimesionLabels labels = dimension->Labels();
 
@@ -2872,19 +2892,17 @@ void TMainWindow::InitDimensionControls()
     {
         if (dimensions.size() > index)
         {
-            MeasurementDimension_p dimension = dimensions.at(index);
+            const MeasurementDimension_p& dimension = dimensions.at(index);
 
             if (name == nullptr)
             {
-                name = new QLabel(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
+                name = new QLabel(dimension->Name()+QChar(':'));
             }
             else
             {
-                name->setText(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
+                name->setText(dimension->Name()+QChar(':'));
             }
-            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension->Type(),
-                                                                            dimension->IsCircumference(),
-                                                                            m->IsFullCircumference()));
+            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension, m->IsFullCircumference()));
 
             if (control == nullptr)
             {
@@ -2912,10 +2930,8 @@ void TMainWindow::InitDimesionShifts()
         {
             MeasurementDimension_p dimension = dimensions.at(index);
 
-            name->setText(tr("Shift (%1):").arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
-            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension->Type(),
-                                                                            dimension->IsCircumference(),
-                                                                            m->IsFullCircumference()));
+            name->setText(tr("Shift (%1):").arg(dimension->Name()));
+            name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension, m->IsFullCircumference()));
         }
     };
 
@@ -4649,7 +4665,7 @@ void TMainWindow::RetranslateTableHeaders()
         {
             const MeasurementDimension_p& dimension = dimensions.at(0);
             ui->tableWidget->horizontalHeaderItem(ColumnShiftA)->setText(
-                tr("%1 shift").arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
+                tr("%1 shift").arg(dimension->Name()));
         }
 
         if (dimensions.size() < 2)
@@ -4660,7 +4676,7 @@ void TMainWindow::RetranslateTableHeaders()
         {
             const MeasurementDimension_p &dimension = dimensions.at(1);
             ui->tableWidget->horizontalHeaderItem(ColumnShiftB)->setText(
-                tr("%1 shift").arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
+                tr("%1 shift").arg(dimension->Name()));
         }
 
         if (dimensions.size() < 3)
@@ -4671,7 +4687,7 @@ void TMainWindow::RetranslateTableHeaders()
         {
             const MeasurementDimension_p &dimension = dimensions.at(2);
             ui->tableWidget->horizontalHeaderItem(ColumnShiftC)->setText(
-                tr("%1 shift").arg(VAbstartMeasurementDimension::DimensionName(dimension->Type())));
+                tr("%1 shift").arg(dimension->Name()));
         }
     }
 }
diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h
index a7d11fc7c..ae3a66aa2 100644
--- a/src/app/tape/tmainwindow.h
+++ b/src/app/tape/tmainwindow.h
@@ -145,6 +145,7 @@ private slots:
     void RestrictThirdDimesion();
 
     void EditDimensionLabels();
+    void DimensionCustomNames();
 
     void SetDefaultGUILanguage();
 
diff --git a/src/app/tape/tmainwindow.ui b/src/app/tape/tmainwindow.ui
index b3aa525f8..d80584beb 100644
--- a/src/app/tape/tmainwindow.ui
+++ b/src/app/tape/tmainwindow.ui
@@ -1189,6 +1189,7 @@
     <addaction name="actionRestrictSecondDimension"/>
     <addaction name="actionRestrictThirdDimension"/>
     <addaction name="actionDimensionLabels"/>
+    <addaction name="actionDimensionCustomNames"/>
    </widget>
    <addaction name="menuFile"/>
    <addaction name="menuMeasurements"/>
@@ -1627,6 +1628,17 @@
     <string>Add separator</string>
    </property>
   </action>
+  <action name="actionDimensionCustomNames">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Dimension custom names</string>
+   </property>
+   <property name="visible">
+    <bool>false</bool>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <customwidgets>
diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index b264f16cc..89fcb029c 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -2140,6 +2140,30 @@ void MainWindow::StoreMultisizeMDimensions()
 
     QList<MeasurementDimension_p> dimensions = m->Dimensions().values();
 
+    if (dimensions.size() > 0)
+    {
+        if (not dimensionALabel.isNull())
+        {
+            dimensionALabel->setText(dimensions.at(0)->Name()+QChar(':'));
+        }
+    }
+
+    if (dimensions.size() > 1)
+    {
+        if (not dimensionBLabel.isNull())
+        {
+            dimensionBLabel->setText(dimensions.at(1)->Name()+QChar(':'));
+        }
+    }
+
+    if (dimensions.size() > 2)
+    {
+        if (not dimensionCLabel.isNull())
+        {
+            dimensionCLabel->setText(dimensions.at(2)->Name()+QChar(':'));
+        }
+    }
+
     auto StoreDimension = [this, dimensions](int index, qreal currentBase)
     {
         if (dimensions.size() > index)
@@ -4483,23 +4507,22 @@ void MainWindow::InitDimensionControls()
         {
             if (dimensions.size() > index)
             {
-                MeasurementDimension_p dimension = dimensions.at(index);
+                const MeasurementDimension_p& dimension = dimensions.at(index);
 
                 if (name.isNull())
                 {
-                    name = new QLabel(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
+                    name = new QLabel(dimension->Name()+QChar(':'));
                 }
                 else
                 {
-                    name->setText(VAbstartMeasurementDimension::DimensionName(dimension->Type())+QChar(':'));
+                    name->setText(dimension->Name()+QChar(':'));
                 }
-                name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension->Type(),
-                                                                                dimension->IsCircumference(),
-                                                                                m->IsFullCircumference()));
+                name->setToolTip(VAbstartMeasurementDimension::DimensionToolTip(dimension, m->IsFullCircumference()));
 
                 if (control.isNull())
                 {
                     control = new QComboBox;
+                    control->setSizeAdjustPolicy(QComboBox::AdjustToContents);
                 }
 
                 InitDimensionGradation(index, dimension, control);
@@ -7140,7 +7163,7 @@ void MainWindow::PrintPatternMessage(QEvent *event)
 void MainWindow::OpenWatermark(const QString &path)
 {
     QList<QPointer<WatermarkWindow>>::const_iterator i;
-    for (i = m_watermarkEditors.begin(); i != m_watermarkEditors.end(); ++i)
+    for (i = m_watermarkEditors.cbegin(); i != m_watermarkEditors.cend(); ++i)
     {
         if (not (*i).isNull() && not (*i)->CurrentFile().isEmpty()
                 && (*i)->CurrentFile() == AbsoluteMPath(VAbstractValApplication::VApp()->GetPatternPath(), path))
diff --git a/src/libs/ifc/schema.qrc b/src/libs/ifc/schema.qrc
index 86389c39b..fec6becc2 100644
--- a/src/libs/ifc/schema.qrc
+++ b/src/libs/ifc/schema.qrc
@@ -75,6 +75,7 @@
         <file>schema/multisize_measurements/v0.5.0.xsd</file>
         <file>schema/multisize_measurements/v0.5.1.xsd</file>
         <file>schema/multisize_measurements/v0.5.2.xsd</file>
+        <file>schema/multisize_measurements/v0.5.3.xsd</file>
         <file>schema/individual_measurements/v0.2.0.xsd</file>
         <file>schema/individual_measurements/v0.3.0.xsd</file>
         <file>schema/individual_measurements/v0.3.1.xsd</file>
diff --git a/src/libs/ifc/schema/multisize_measurements/v0.5.3.xsd b/src/libs/ifc/schema/multisize_measurements/v0.5.3.xsd
new file mode 100644
index 000000000..7b5878642
--- /dev/null
+++ b/src/libs/ifc/schema/multisize_measurements/v0.5.3.xsd
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+  <xs:element name="vst">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="version" type="formatVersion"/>
+        <xs:element name="read-only" type="xs:boolean"/>
+        <xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="unit" type="units"/>
+        <xs:element name="pm_system" type="psCode"/>
+        <xs:element name="dimensions">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="dimension" minOccurs="1" maxOccurs="3">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="labels" minOccurs="0" maxOccurs="1">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="label" minOccurs="0" maxOccurs="unbounded">
+                            <xs:complexType>
+                              <xs:attribute name="value" type="dimesionValue" use="required"/>
+                              <xs:attribute name="label" type="xs:string" use="required"/>
+                            </xs:complexType>
+                          </xs:element>
+                        </xs:sequence>
+                      </xs:complexType>
+                    </xs:element>
+                  </xs:sequence>
+                  <xs:attribute name="type" type="dimensionType" use="required"/>
+                  <xs:attribute name="base" type="dimesionValue" use="required"/>
+                  <xs:attribute name="min" type="dimesionValue" use="required"/>
+                  <xs:attribute name="max" type="dimesionValue" use="required"/>
+                  <xs:attribute name="step" type="dimensionStep" use="required"/>
+                  <xs:attribute name="circumference" type="xs:boolean"/>
+                  <xs:attribute name="customName" type="xs:string"/> 
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+            <xs:attribute name="fullCircumference" type="xs:boolean"/>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="restrictions">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="restriction" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:attribute name="coordinates" type="xs:string" use="required"/>
+                  <xs:attribute name="min" type="dimesionValue"/>
+                  <xs:attribute name="max" type="dimesionValue"/>
+                  <xs:attribute name="exclude" type="xs:string"/>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="body-measurements">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="m" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="corrections" minOccurs="0" maxOccurs="1">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="correction" minOccurs="0" maxOccurs="unbounded">
+                            <xs:complexType>
+                              <xs:attribute name="coordinates" type="xs:string" use="required"/>
+                              <xs:attribute name="correction" type="xs:double" use="required"/> 
+                            </xs:complexType>
+                          </xs:element>
+                        </xs:sequence>
+                      </xs:complexType>
+                    </xs:element>
+                  </xs:sequence>
+                  <xs:attribute name="name" type="shortName" use="required"/>
+                  <xs:attribute name="base" type="xs:double"/>
+                  <xs:attribute name="shiftA" type="xs:double"/>
+                  <xs:attribute name="shiftB" type="xs:double"/>
+                  <xs:attribute name="shiftC" type="xs:double"/>
+                  <xs:attribute name="full_name" type="xs:string"/>
+                  <xs:attribute name="description" type="xs:string"/>
+                  <xs:attribute name="specialUnits" type="xs:boolean"/>
+                  <xs:attribute name="type" type="measurementType"/>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+    </xs:complexType>
+    <xs:unique name="measurementName">
+      <xs:selector xpath="body-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="units">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="mm"/>
+      <xs:enumeration value="cm"/>
+      <xs:enumeration value="inch"/>
+    </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="psCode">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="(([0-9]|[1-4][0-9]|5[0-4])|998)"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="dimensionType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="x"/>
+      <xs:enumeration value="y"/>
+      <xs:enumeration value="w"/>
+      <xs:enumeration value="z"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="dimesionValue">
+    <xs:restriction base="xs:double">
+      <xs:minInclusive value="1"/>
+      <xs:maxInclusive value="2720"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="dimensionStep">
+    <xs:restriction base="xs:double">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="80"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="measurementType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="measurement"/>
+      <xs:enumeration value="separator"/>
+    </xs:restriction>
+  </xs:simpleType>
+</xs:schema>
diff --git a/src/libs/ifc/xml/vvstconverter.cpp b/src/libs/ifc/xml/vvstconverter.cpp
index b63f3add9..b6b2d303b 100644
--- a/src/libs/ifc/xml/vvstconverter.cpp
+++ b/src/libs/ifc/xml/vvstconverter.cpp
@@ -54,8 +54,8 @@
  */
 
 const QString VVSTConverter::MeasurementMinVerStr = QStringLiteral("0.3.0");
-const QString VVSTConverter::MeasurementMaxVerStr = QStringLiteral("0.5.2");
-const QString VVSTConverter::CurrentSchema        = QStringLiteral("://schema/multisize_measurements/v0.5.2.xsd");
+const QString VVSTConverter::MeasurementMaxVerStr = QStringLiteral("0.5.3");
+const QString VVSTConverter::CurrentSchema        = QStringLiteral("://schema/multisize_measurements/v0.5.3.xsd");
 
 //VVSTConverter::MeasurementMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
 //VVSTConverter::MeasurementMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@@ -73,7 +73,7 @@ VVSTConverter::VVSTConverter(const QString &fileName)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QString VVSTConverter::XSDSchema(unsigned ver) const
+auto VVSTConverter::XSDSchema(unsigned ver) const -> QString
 {
     QHash <unsigned, QString> schemas =
     {
@@ -85,17 +85,16 @@ QString VVSTConverter::XSDSchema(unsigned ver) const
         std::make_pair(FormatVersion(0, 4, 4), QStringLiteral("://schema/multisize_measurements/v0.4.4.xsd")),
         std::make_pair(FormatVersion(0, 5, 0), QStringLiteral("://schema/multisize_measurements/v0.5.0.xsd")),
         std::make_pair(FormatVersion(0, 5, 1), QStringLiteral("://schema/multisize_measurements/v0.5.1.xsd")),
-        std::make_pair(FormatVersion(0, 5, 2), CurrentSchema),
+        std::make_pair(FormatVersion(0, 5, 2), QStringLiteral("://schema/multisize_measurements/v0.5.2.xsd")),
+        std::make_pair(FormatVersion(0, 5, 3), CurrentSchema),
     };
 
     if (schemas.contains(ver))
     {
         return schemas.value(ver);
     }
-    else
-    {
-        InvalidVersion(ver);
-    }
+
+    InvalidVersion(ver);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -136,6 +135,10 @@ void VVSTConverter::ApplyPatches()
             ValidateXML(XSDSchema(FormatVersion(0, 5, 2)));
             Q_FALLTHROUGH();
         case (FormatVersion(0, 5, 2)):
+            ToV0_5_3();
+            ValidateXML(XSDSchema(FormatVersion(0, 5, 3)));
+            Q_FALLTHROUGH();
+        case (FormatVersion(0, 5, 3)):
             break;
         default:
             InvalidVersion(m_ver);
@@ -151,10 +154,10 @@ void VVSTConverter::DowngradeToCurrentMaxVersion()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VVSTConverter::IsReadOnly() const
+auto VVSTConverter::IsReadOnly() const -> bool
 {
     // Check if attribute read-only was not changed in file format
-    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMaxVer == FormatVersion(0, 5, 2),
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMaxVer == FormatVersion(0, 5, 3),
                       "Check attribute read-only.");
 
     // Possibly in future attribute read-only will change position etc.
@@ -524,3 +527,14 @@ void VVSTConverter::ToV0_5_2()
     SetVersion(QStringLiteral("0.5.2"));
     Save();
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VVSTConverter::ToV0_5_3()
+{
+    // TODO. Delete if minimal supported version is 0.5.3
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < FormatVersion(0, 5, 3),
+                      "Time to refactor the code.");
+
+    SetVersion(QStringLiteral("0.5.3"));
+    Save();
+}
diff --git a/src/libs/ifc/xml/vvstconverter.h b/src/libs/ifc/xml/vvstconverter.h
index f1db82a47..db9d99299 100644
--- a/src/libs/ifc/xml/vvstconverter.h
+++ b/src/libs/ifc/xml/vvstconverter.h
@@ -49,7 +49,7 @@ public:
     static const QString MeasurementMaxVerStr;
     static const QString CurrentSchema;
     static Q_DECL_CONSTEXPR const unsigned MeasurementMinVer = FormatVersion(0, 3, 0);
-    static Q_DECL_CONSTEXPR const unsigned MeasurementMaxVer = FormatVersion(0, 5, 2);
+    static Q_DECL_CONSTEXPR const unsigned MeasurementMaxVer = FormatVersion(0, 5, 3);
 
 protected:
     virtual unsigned MinVer() const override;
@@ -86,6 +86,7 @@ private:
     void ToV0_5_0();
     void ToV0_5_1();
     void ToV0_5_2();
+    void ToV0_5_3();
 };
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vformat/vdimensions.cpp b/src/libs/vformat/vdimensions.cpp
index 548cbce79..a4a1c8e96 100644
--- a/src/libs/vformat/vdimensions.cpp
+++ b/src/libs/vformat/vdimensions.cpp
@@ -51,6 +51,62 @@ auto VAbstartMeasurementDimension::IsValid() -> bool
     return IsUnitsValid() && IsRangeValid() && IsStepValid() && IsBaseValid();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+auto VAbstartMeasurementDimension::RangeMin() const -> int
+{
+    if (m_circumference)
+    {
+        const int rangeMinCm = 20;
+        const int rangeMinMm = 200;
+        const int rangeMinInch = 8;
+
+        switch(Units())
+        {
+            case Unit::Cm:
+                return rangeMinCm;
+            case Unit::Mm:
+                return rangeMinMm;
+            case Unit::Inch:
+                return rangeMinInch;
+            default:
+                return 0;
+        }
+    }
+
+    return 1;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VAbstartMeasurementDimension::RangeMax() const -> int
+{
+    if (m_circumference)
+    {
+        const int rangeMaxCm = 272;
+        const int rangeMaxMm = 2720;
+        const int rangeMaxInch = 107;
+
+        switch(Units())
+        {
+            case Unit::Cm:
+                return rangeMaxCm;
+            case Unit::Mm:
+                return rangeMaxMm;
+            case Unit::Inch:
+                return rangeMaxInch;
+            default:
+                return 0;
+        }
+    }
+
+    return 100;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+auto VAbstartMeasurementDimension::Name() const -> QString
+{
+    return m_customName.isEmpty() ? DimensionName(Type()) : m_customName;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 auto VAbstartMeasurementDimension::ValidSteps() const -> QVector<qreal>
 {
@@ -205,33 +261,41 @@ auto VAbstartMeasurementDimension::DimensionName(MeasurementDimension type) -> Q
         case MeasurementDimension::Z:
             return tr("Hip", "dimension");
         default:
-            return QString();
+            return {};
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-auto VAbstartMeasurementDimension::DimensionToolTip(MeasurementDimension type, bool circumference, bool fc) -> QString
+auto VAbstartMeasurementDimension::DimensionToolTip(const MeasurementDimension_p &dimension, bool fc) -> QString
 {
-    switch(type)
+    if (dimension.isNull())
     {
-    case MeasurementDimension::X:
-        return tr("Height", "dimension");
-    case MeasurementDimension::Y:
-        if (circumference)
-        {
-            return fc ? tr("Chest full circumference", "dimension") : tr("Chest half circumference", "dimension");
-        }
-        else
-        {
-            return tr("Size");
-        }
-        return circumference ? tr("Chest circumference", "dimension") : tr("Size", "dimension");
-    case MeasurementDimension::W:
-        return fc ? tr("Waist full circumference", "dimension") : tr("Waist half circumference", "dimension");
-    case MeasurementDimension::Z:
-        return fc ? tr("Hip full circumference", "dimension") : tr("Hip half circumference", "dimension");
-    default:
-        return QString();
+        return {};
+    }
+
+    switch(dimension->Type())
+    {
+        case MeasurementDimension::Y:
+            if (dimension->CustomName().isEmpty() && dimension->IsCircumference())
+            {
+                return fc ? tr("Chest full circumference", "dimension") : tr("Chest half circumference", "dimension");
+            }
+            return {};
+        case MeasurementDimension::W:
+            if (dimension->CustomName().isEmpty() && dimension->IsCircumference())
+            {
+                return fc ? tr("Waist full circumference", "dimension") : tr("Waist half circumference", "dimension");
+            }
+            return {};
+        case MeasurementDimension::Z:
+            if (dimension->CustomName().isEmpty() && dimension->IsCircumference())
+            {
+                return fc ? tr("Hip full circumference", "dimension") : tr("Hip half circumference", "dimension");
+            }
+            return {};
+        case MeasurementDimension::X:
+        default:
+            return {};
     }
 }
 
@@ -246,52 +310,6 @@ VXMeasurementDimension::VXMeasurementDimension(Unit units, qreal min, qreal max,
     : VAbstartMeasurementDimension(units, min, max, step)
 {}
 
-//---------------------------------------------------------------------------------------------------------------------
-auto VXMeasurementDimension::Type() const -> MeasurementDimension
-{
-    return MeasurementDimension::X;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VXMeasurementDimension::RangeMin() const -> int
-{
-    const int rangeMinCm = 50;
-    const int rangeMinMm = 500;
-    const int rangeMinInch = 19;
-
-    switch(m_units)
-    {
-        case Unit::Cm:
-            return rangeMinCm;
-        case Unit::Mm:
-            return rangeMinMm;
-        case Unit::Inch:
-            return rangeMinInch;
-        default:
-            return 0;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VXMeasurementDimension::RangeMax() const -> int
-{
-    const int rangeMaxCm = 272;
-    const int rangeMaxMm = 2720;
-    const int rangeMaxInch = 107;
-
-    switch(m_units)
-    {
-        case Unit::Cm:
-            return rangeMaxCm;
-        case Unit::Mm:
-            return rangeMaxMm;
-        case Unit::Inch:
-            return rangeMaxInch;
-        default:
-            return 0;
-    }
-}
-
 // VYMeasurementDimension
 //---------------------------------------------------------------------------------------------------------------------
 VYMeasurementDimension::VYMeasurementDimension(Unit units)
@@ -303,68 +321,6 @@ VYMeasurementDimension::VYMeasurementDimension(Unit units, qreal min, qreal max,
     : VAbstartMeasurementDimension(units, min, max, step)
 {}
 
-//---------------------------------------------------------------------------------------------------------------------
-auto VYMeasurementDimension::Type() const -> MeasurementDimension
-{
-    return MeasurementDimension::Y;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VYMeasurementDimension::RangeMin() const -> int
-{
-    if (m_circumference)
-    {
-        const int rangeMinCm = 22;
-        const int rangeMinMm = 220;
-        const int rangeMinInch = 8;
-
-        switch(m_units)
-        {
-            case Unit::Cm:
-                return rangeMinCm;
-            case Unit::Mm:
-                return rangeMinMm;
-            case Unit::Inch:
-                return rangeMinInch;
-            default:
-                return 0;
-        }
-    }
-    else
-    {
-        const int rangeMinCir = 1;
-        return rangeMinCir;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VYMeasurementDimension::RangeMax() const -> int
-{
-    if (m_circumference)
-    {
-        const int rangeMaxCm = 72;
-        const int rangeMaxMm = 720;
-        const int rangeMaxInch = 29;
-
-        switch(m_units)
-        {
-            case Unit::Cm:
-                return rangeMaxCm;
-            case Unit::Mm:
-                return rangeMaxMm;
-            case Unit::Inch:
-                return rangeMaxInch;
-            default:
-                return 0;
-        }
-    }
-    else
-    {
-        const int rangeMaxCir = 100;
-        return rangeMaxCir;
-    }
-}
-
 // VWMeasurementDimension
 //---------------------------------------------------------------------------------------------------------------------
 VWMeasurementDimension::VWMeasurementDimension(Unit units)
@@ -376,52 +332,6 @@ VWMeasurementDimension::VWMeasurementDimension(Unit units, qreal min, qreal max,
     : VAbstartMeasurementDimension(units, min, max, step)
 {}
 
-//---------------------------------------------------------------------------------------------------------------------
-auto VWMeasurementDimension::Type() const -> MeasurementDimension
-{
-    return MeasurementDimension::W;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VWMeasurementDimension::RangeMin() const -> int
-{
-    const int rangeMinCm = 20;
-    const int rangeMinMm = 200;
-    const int rangeMinInch = 8;
-
-    switch(m_units)
-    {
-        case Unit::Cm:
-            return rangeMinCm;
-        case Unit::Mm:
-            return rangeMinMm;
-        case Unit::Inch:
-            return rangeMinInch;
-        default:
-            return 0;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VWMeasurementDimension::RangeMax() const -> int
-{
-    const int rangeMaxCm = 65;
-    const int rangeMaxMm = 650;
-    const int rangeMaxInch = 26;
-
-    switch(m_units)
-    {
-        case Unit::Cm:
-            return rangeMaxCm;
-        case Unit::Mm:
-            return rangeMaxMm;
-        case Unit::Inch:
-            return rangeMaxInch;
-        default:
-            return 0;
-    }
-}
-
 // VZMeasurementDimension
 //---------------------------------------------------------------------------------------------------------------------
 VZMeasurementDimension::VZMeasurementDimension(Unit units)
@@ -433,53 +343,15 @@ VZMeasurementDimension::VZMeasurementDimension(Unit units, qreal min, qreal max,
     : VAbstartMeasurementDimension(units, min, max, step)
 {}
 
-//---------------------------------------------------------------------------------------------------------------------
-auto VZMeasurementDimension::Type() const -> MeasurementDimension
-{
-    return MeasurementDimension::Z;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VZMeasurementDimension::RangeMin() const -> int
-{
-    const int rangeMinCm = 20;
-    const int rangeMinMm = 200;
-    const int rangeMinInch = 8;
-
-    switch(m_units)
-    {
-        case Unit::Cm:
-            return rangeMinCm;
-        case Unit::Mm:
-            return rangeMinMm;
-        case Unit::Inch:
-            return rangeMinInch;
-        default:
-            return 0;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-auto VZMeasurementDimension::RangeMax() const -> int
-{
-    const int rangeMaxCm = 75;
-    const int rangeMaxMm = 750;
-    const int rangeMaxInch = 30;
-
-    switch(m_units)
-    {
-        case Unit::Cm:
-            return rangeMaxCm;
-        case Unit::Mm:
-            return rangeMaxMm;
-        case Unit::Inch:
-            return rangeMaxInch;
-        default:
-            return 0;
-    }
-}
-
 // VDimensionRestriction
+//---------------------------------------------------------------------------------------------------------------------
+VDimensionRestriction::VDimensionRestriction(qreal min, qreal max, const QString &exclude) :
+    m_min(min),
+    m_max(max)
+{
+    SetExcludeString(exclude);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VDimensionRestriction::SetExcludeString(const QString &exclude)
 {
diff --git a/src/libs/vformat/vdimensions.h b/src/libs/vformat/vdimensions.h
index 4ac4bc0c3..10f3bd82f 100644
--- a/src/libs/vformat/vdimensions.h
+++ b/src/libs/vformat/vdimensions.h
@@ -33,6 +33,11 @@
 #include <QSet>
 
 #include "../vmisc/def.h"
+#include "qglobal.h"
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif // QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
 
 enum class MeasurementDimension: qint8
 {
@@ -50,16 +55,16 @@ using DimesionLabels = QMap<qreal, QString>;
 
 class VAbstartMeasurementDimension
 {
-    Q_DECLARE_TR_FUNCTIONS(VAbstartMeasurementDimension)
+    Q_DECLARE_TR_FUNCTIONS(VAbstartMeasurementDimension) // NOLINT
 public:
     VAbstartMeasurementDimension() =default;
     explicit VAbstartMeasurementDimension(Unit units);
     VAbstartMeasurementDimension(Unit units, qreal min, qreal max, qreal step);
     virtual ~VAbstartMeasurementDimension() =default;
 
-    virtual MeasurementDimension Type() const =0;
+    virtual auto Type() const -> MeasurementDimension =0;
 
-    virtual bool IsValid();
+    auto IsValid() -> bool;
 
     auto MinValue() const -> qreal;
     void SetMinValue(qreal minValue);
@@ -77,10 +82,15 @@ public:
 
     auto Units() const -> Unit;
 
-    virtual auto IsCircumference() const -> bool;
+    auto IsCircumference() const -> bool;
+    void SetCircumference(bool circumference);
 
-    virtual auto RangeMin() const -> int =0;
-    virtual auto RangeMax() const -> int =0;
+    auto RangeMin() const -> int;
+    auto RangeMax() const -> int;
+
+    virtual auto Axis() const -> QChar =0;
+
+    auto Name() const -> QString;
 
     auto ValidSteps() const -> QVector<qreal>;
     auto ValidBases() const -> QVector<qreal>;
@@ -88,12 +98,23 @@ public:
 
     static auto ValidBases(qreal min, qreal max, qreal step, const QSet<qreal> &exclude) -> QVector<qreal>;
     static auto DimensionName(MeasurementDimension type) -> QString;
-    static auto DimensionToolTip(MeasurementDimension type, bool circumference, bool fc) -> QString;
+    static auto DimensionToolTip(const MeasurementDimension_p &dimension, bool fc) -> QString;
 
     auto Labels() const -> DimesionLabels;
     void SetLabels(const DimesionLabels &labels);
 
+    auto CustomName() const -> const QString &;
+    void SetCustomName(const QString &newCustomName);
+
 protected:
+    auto IsRangeValid() -> bool;
+    auto IsStepValid() -> bool;
+    auto IsBaseValid() -> bool;
+    auto IsUnitsValid() const -> bool;
+
+private:
+    Q_DISABLE_COPY_MOVE(VAbstartMeasurementDimension) // NOLINT
+
     Unit           m_units{Unit::Cm};
     qreal          m_minValue{0};
     qreal          m_maxValue{0};
@@ -101,11 +122,8 @@ protected:
     qreal          m_baseValue{0};
     QString        m_error{};
     DimesionLabels m_labels{};
-
-    auto IsRangeValid() -> bool;
-    auto IsStepValid() -> bool;
-    auto IsBaseValid() -> bool;
-    auto IsUnitsValid() const -> bool;
+    bool           m_circumference{true};
+    QString        m_customName{};
 };
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -171,7 +189,13 @@ inline auto VAbstartMeasurementDimension::Units() const -> Unit
 //---------------------------------------------------------------------------------------------------------------------
 inline auto VAbstartMeasurementDimension::IsCircumference() const -> bool
 {
-    return true;
+    return m_circumference;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline void VAbstartMeasurementDimension::SetCircumference(bool circumference)
+{
+    m_circumference = circumference;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -186,6 +210,18 @@ inline void VAbstartMeasurementDimension::SetLabels(const DimesionLabels &labels
     m_labels = labels;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+inline auto VAbstartMeasurementDimension::CustomName() const -> const QString &
+{
+    return m_customName;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline void VAbstartMeasurementDimension::SetCustomName(const QString &newCustomName)
+{
+    m_customName = newCustomName;
+}
+
 // VXMeasurementDimension
 //---------------------------------------------------------------------------------------------------------------------
 class VXMeasurementDimension : public VAbstartMeasurementDimension
@@ -194,19 +230,26 @@ public:
     VXMeasurementDimension() =default;
     explicit VXMeasurementDimension(Unit units);
     VXMeasurementDimension(Unit units, qreal min, qreal max, qreal step);
+    ~VXMeasurementDimension() override =default;
 
-    virtual auto Type() const -> MeasurementDimension override;
+    auto Type() const -> MeasurementDimension override;
 
-    virtual auto RangeMin() const -> int override;
-    virtual auto RangeMax() const -> int override;
+    auto Axis() const -> QChar override;
 
-    virtual bool IsCircumference() const override;
+private:
+    Q_DISABLE_COPY_MOVE(VXMeasurementDimension) // NOLINT
 };
 
 //---------------------------------------------------------------------------------------------------------------------
-inline auto VXMeasurementDimension::IsCircumference() const -> bool
+inline auto VXMeasurementDimension::Type() const -> MeasurementDimension
 {
-    return false;
+    return MeasurementDimension::X;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline auto VXMeasurementDimension::Axis() const -> QChar
+{
+    return QChar('X');
 }
 
 // VYMeasurementDimension
@@ -217,29 +260,28 @@ public:
     VYMeasurementDimension() =default;
     explicit VYMeasurementDimension(Unit units);
     VYMeasurementDimension(Unit units, qreal min, qreal max, qreal step);
+    ~VYMeasurementDimension() override =default;
 
-    virtual auto Type() const -> MeasurementDimension override;
+    auto Type() const -> MeasurementDimension override;
 
-    virtual auto RangeMin() const -> int override;
-    virtual auto RangeMax() const -> int override;
-
-    virtual auto IsCircumference() const -> bool override;
-    void SetCircumference(bool circumference);
+    auto Axis() const -> QChar override;
 
 private:
+    Q_DISABLE_COPY_MOVE(VYMeasurementDimension) // NOLINT
+
     bool m_circumference{true};
 };
 
 //---------------------------------------------------------------------------------------------------------------------
-inline bool VYMeasurementDimension::IsCircumference() const
+inline auto VYMeasurementDimension::Type() const -> MeasurementDimension
 {
-    return m_circumference;
+    return MeasurementDimension::Y;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-inline void VYMeasurementDimension::SetCircumference(bool circumference)
+inline auto VYMeasurementDimension::Axis() const -> QChar
 {
-    m_circumference = circumference;
+    return QChar('Y');
 }
 
 // VWMeasurementDimension
@@ -250,13 +292,28 @@ public:
     VWMeasurementDimension() =default;
     explicit VWMeasurementDimension(Unit units);
     VWMeasurementDimension(Unit units, qreal min, qreal max, qreal step);
+    ~VWMeasurementDimension() override =default;
 
-    virtual auto Type() const -> MeasurementDimension override;
+    auto Type() const -> MeasurementDimension override;
 
-    virtual auto RangeMin() const -> int override;
-    virtual auto RangeMax() const -> int override;
+    auto Axis() const -> QChar override;
+
+private:
+    Q_DISABLE_COPY_MOVE(VWMeasurementDimension) // NOLINT
 };
 
+//---------------------------------------------------------------------------------------------------------------------
+inline auto VWMeasurementDimension::Type() const -> MeasurementDimension
+{
+    return MeasurementDimension::W;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline auto VWMeasurementDimension::Axis() const -> QChar
+{
+    return QChar('W');
+}
+
 // VZMeasurementDimension
 //---------------------------------------------------------------------------------------------------------------------
 class VZMeasurementDimension : public VAbstartMeasurementDimension
@@ -265,25 +322,33 @@ public:
     VZMeasurementDimension() =default;
     explicit VZMeasurementDimension(Unit units);
     VZMeasurementDimension(Unit units, qreal min, qreal max, qreal step);
+    ~VZMeasurementDimension() override =default;
 
-    virtual auto Type() const -> MeasurementDimension override;
+    auto Type() const -> MeasurementDimension override;
 
-    virtual auto RangeMin() const -> int override;
-    virtual auto RangeMax() const -> int override;
+    auto Axis() const -> QChar override;
+
+private:
+    Q_DISABLE_COPY_MOVE(VZMeasurementDimension) // NOLINT
 };
 
+//---------------------------------------------------------------------------------------------------------------------
+inline auto VZMeasurementDimension::Type() const -> MeasurementDimension
+{
+    return MeasurementDimension::Z;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline auto VZMeasurementDimension::Axis() const -> QChar
+{
+    return QChar('Z');
+}
+
 class VDimensionRestriction
 {
 public:
-    VDimensionRestriction()
-    {}
-
-    VDimensionRestriction(qreal min, qreal max, const QString &exclude = QString()) :
-        m_min(min),
-        m_max(max)
-    {
-        SetExcludeString(exclude);
-    }
+    VDimensionRestriction() = default;
+    VDimensionRestriction(qreal min, qreal max, const QString &exclude = QString());
 
     void SetMin(qreal min);
     auto GetMin() const -> qreal;
diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp
index b47b1fc2b..2457cf1b7 100644
--- a/src/libs/vformat/vmeasurements.cpp
+++ b/src/libs/vformat/vmeasurements.cpp
@@ -97,6 +97,7 @@ const QString VMeasurements::AttrCircumference     = QStringLiteral("circumferen
 const QString VMeasurements::AttrFullCircumference = QStringLiteral("fullCircumference");
 const QString VMeasurements::AttrLabel             = QStringLiteral("label");
 const QString VMeasurements::AttrDimension         = QStringLiteral("dimension");
+const QString VMeasurements::AttrCustomName        = QStringLiteral("customName");
 
 const QString VMeasurements::GenderMale    = QStringLiteral("male");
 const QString VMeasurements::GenderFemale  = QStringLiteral("female");
@@ -885,7 +886,7 @@ QString VMeasurements::MeasurementForDimension(IMD type) const
             }
         }
     }
-    return QString();
+    return {};
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -972,6 +973,25 @@ void VMeasurements::SetDimensionLabels(const QMap<MeasurementDimension, Dimesion
     m_dimensions = ReadDimensions(); // Refresh cache
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VMeasurements::SetDimensionCustomNames(const QMap<MeasurementDimension, QString> &names)
+{
+    const QDomNodeList list = elementsByTagName(TagDimension);
+    for (int i=0; i < list.size(); ++i)
+    {
+        QDomElement dom = list.at(i).toElement();
+        const MeasurementDimension type = StrToDimensionType(GetParametrString(dom, AttrType));
+
+        if (names.contains(type))
+        {
+            SetAttributeOrRemoveIf<QString>(dom, AttrCustomName, names.value(type),
+                                            [](const QString &name) noexcept {return name.isEmpty();});
+        }
+    }
+
+    m_dimensions = ReadDimensions(); // Refresh cache
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QString VMeasurements::GenderToStr(const GenderType &sex)
 {
@@ -1223,7 +1243,7 @@ QDomElement VMeasurements::CreateDimensions(const QVector<MeasurementDimension_p
 {
     QDomElement dimensionsTag = createElement(TagDimensions);
 
-    for(auto &dimension : dimensions)
+    for(const auto &dimension : dimensions)
     {
         QDomElement dimensionTag = createElement(TagDimension);
 
@@ -1232,11 +1252,10 @@ QDomElement VMeasurements::CreateDimensions(const QVector<MeasurementDimension_p
         SetAttribute(dimensionTag, AttrMin, dimension->MinValue());
         SetAttribute(dimensionTag, AttrMax, dimension->MaxValue());
         SetAttribute(dimensionTag, AttrStep, dimension->Step());
-
-        if (dimension->Type() == MeasurementDimension::Y)
-        {
-            SetAttribute(dimensionTag, AttrCircumference, dimension->IsCircumference());
-        }
+        SetAttributeOrRemoveIf<bool>(dimensionTag, AttrCircumference, dimension->IsCircumference(),
+                                     [](bool c) noexcept {return c;});
+        SetAttributeOrRemoveIf<QString>(dimensionTag, AttrCustomName, dimension->CustomName(),
+                                     [](const QString &name) noexcept {return name.isEmpty();});
 
         dimensionsTag.appendChild(dimensionTag);
     }
@@ -1372,39 +1391,35 @@ auto VMeasurements::ReadDimensions() const -> VDimensions
         const qreal min = GetParametrDouble(dom, AttrMin, QChar('0'));
         const qreal max = GetParametrDouble(dom, AttrMax, QChar('0'));
         const qreal step = GetParametrDouble(dom, AttrStep, QStringLiteral("-1"));
-        const qreal base = GetParametrDouble(dom, AttrBase, QChar('0'));
 
-        const DimesionLabels labels = ReadDimensionLabels(dom);
+        MeasurementDimension_p dimension;
 
         if (type == MeasurementDimension::X)
         {
-            auto dimension = QSharedPointer<VXMeasurementDimension>::create(units, min, max, step);
-            dimension->SetBaseValue(base);
-            dimension->SetLabels(labels);
-            dimensions.insert(type, dimension);
+            dimension = QSharedPointer<VXMeasurementDimension>::create(units, min, max, step);
         }
         else if (type == MeasurementDimension::Y)
         {
-            auto dimension = QSharedPointer<VYMeasurementDimension>::create(units, min, max, step);
-            dimension->SetBaseValue(base);
-            dimension->SetCircumference(GetParametrBool(dom, AttrCircumference, trueStr));
-            dimension->SetLabels(labels);
-            dimensions.insert(type, dimension);
+            dimension = QSharedPointer<VYMeasurementDimension>::create(units, min, max, step);
         }
         else if (type == MeasurementDimension::W)
         {
-            auto dimension = QSharedPointer<VWMeasurementDimension>::create(units, min, max, step);
-            dimension->SetBaseValue(base);
-            dimension->SetLabels(labels);
-            dimensions.insert(type, dimension);
+            dimension = QSharedPointer<VWMeasurementDimension>::create(units, min, max, step);
         }
         else if (type == MeasurementDimension::Z)
         {
-            auto dimension = QSharedPointer<VZMeasurementDimension>::create(units, min, max, step);
-            dimension->SetBaseValue(base);
-            dimension->SetLabels(labels);
-            dimensions.insert(type, dimension);
+            dimension = QSharedPointer<VZMeasurementDimension>::create(units, min, max, step);
         }
+        else
+        {
+            continue;
+        }
+
+        dimension->SetBaseValue(GetParametrDouble(dom, AttrBase, QChar('0')));
+        dimension->SetCircumference(GetParametrBool(dom, AttrCircumference, trueStr));
+        dimension->SetCustomName(GetParametrEmptyString(dom, AttrCustomName));
+        dimension->SetLabels(ReadDimensionLabels(dom));
+        dimensions.insert(type, dimension);
     }
 
     return dimensions;
diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h
index 38e5c1b58..792f855b0 100644
--- a/src/libs/vformat/vmeasurements.h
+++ b/src/libs/vformat/vmeasurements.h
@@ -130,6 +130,7 @@ public:
     auto Restriction(qreal base, qreal base2=0) const -> VDimensionRestriction;
 
     void SetDimensionLabels(const QMap<MeasurementDimension, DimesionLabels> &labels);
+    void SetDimensionCustomNames(const QMap<MeasurementDimension, QString> &names);
 
     static const QString TagVST;
     static const QString TagVIT;
@@ -171,6 +172,7 @@ public:
     static const QString AttrFullCircumference;
     static const QString AttrLabel;
     static const QString AttrDimension;
+    static const QString AttrCustomName;
 
     static const QString GenderMale;
     static const QString GenderFemale;