From a569a207560d567dedffe26ba8b8257ee455b93e Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 19 Jan 2021 21:13:17 +0200 Subject: [PATCH] Improve multisize measurements format. Allow excluding combinations inside min/max range. --- ChangeLog.txt | 1 + .../tape/dialogs/dialogrestrictdimension.cpp | 380 +++++++++++++----- .../tape/dialogs/dialogrestrictdimension.h | 20 +- src/app/tape/tmainwindow.cpp | 80 ++-- src/app/tape/tmainwindow.h | 1 + src/app/tape/tmainwindow.ui | 29 +- src/app/valentina/mainwindow.cpp | 11 +- .../schema/multisize_measurements/v0.5.1.xsd | 1 + src/libs/vformat/vdimensions.cpp | 54 ++- src/libs/vformat/vdimensions.h | 69 +++- src/libs/vformat/vmeasurements.cpp | 22 +- src/libs/vformat/vmeasurements.h | 7 +- 12 files changed, 523 insertions(+), 152 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index f8dc94429..ef45fb7f7 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,7 @@ - Improve the layout option "Auto crop unused width". - Improve multisize measurements format. Allow decimal step 0.5. - Improve restrict dimension dialog. Disable not available combinations. +- Improve multisize measurements format. Allow excluding combinations inside min/max range. # Version 0.7.41 Dec 4, 2020 - Bug fixes. diff --git a/src/app/tape/dialogs/dialogrestrictdimension.cpp b/src/app/tape/dialogs/dialogrestrictdimension.cpp index 84401cd70..7e75e17a2 100644 --- a/src/app/tape/dialogs/dialogrestrictdimension.cpp +++ b/src/app/tape/dialogs/dialogrestrictdimension.cpp @@ -28,6 +28,7 @@ #include "dialogrestrictdimension.h" #include "ui_dialogrestrictdimension.h" +#include #include #include "../vpatterndb/variables/vmeasurement.h" @@ -79,12 +80,12 @@ auto FilterByMaximum(const QVector &base, qreal restriction) -> QVector &dimensions, - const QMap> &restrictions, - bool oneDimesionRestriction, bool fullCircumference, + const QMap &restrictions, + RestrictDimension restrictionType, bool fullCircumference, QWidget *parent) : QDialog(parent), ui(new Ui::DialogRestrictDimension), - m_oneDimesionRestriction(oneDimesionRestriction), + m_restrictionType(restrictionType), m_fullCircumference(fullCircumference), m_dimensions(dimensions), m_restrictions(restrictions) @@ -93,8 +94,11 @@ DialogRestrictDimension::DialogRestrictDimension(const QListtableWidget->setItemDelegate( new VDecorationAligningDelegate(Qt::AlignHCenter | Qt::AlignCenter, ui->tableWidget)); + ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->tableWidget, &QTableWidget::itemSelectionChanged, this, &DialogRestrictDimension::RowSelected); + connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, + &DialogRestrictDimension::CellContextMenu); connect(ui->comboBoxDimensionA, QOverload::of(&QComboBox::currentIndexChanged), this, &DialogRestrictDimension::DimensionAChanged); @@ -140,7 +144,7 @@ void DialogRestrictDimension::changeEvent(QEvent *event) } }; - if (not m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::Third) { RetranslateControls(0, ui->labelDimensionA, ui->comboBoxDimensionA); } @@ -163,7 +167,7 @@ void DialogRestrictDimension::RowSelected() qreal base2 = 0; MeasurementDimension_p dimension; - if (m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::Second) { base1 = item->data(Qt::UserRole).toDouble(); @@ -183,8 +187,7 @@ void DialogRestrictDimension::RowSelected() } } - QPair restriction = m_restrictions.value(VMeasurement::CorrectionHash(base1, base2), - QPair(0, 0)); + VDimensionRestriction restriction = m_restrictions.value(VMeasurement::CorrectionHash(base1, base2)); if (dimension.isNull()) { @@ -195,17 +198,17 @@ void DialogRestrictDimension::RowSelected() ui->comboBoxMin->blockSignals(true); ui->comboBoxMin->clear(); - QVector filtered = FilterByMaximum(bases, restriction.second); + QVector filtered = FilterByMaximum(bases, restriction.GetMax()); FillBases(filtered, dimension, ui->comboBoxMin); - int index = ui->comboBoxMin->findData(restriction.first); + int index = ui->comboBoxMin->findData(restriction.GetMin()); ui->comboBoxMin->setCurrentIndex(index != -1 ? index : 0); ui->comboBoxMin->blockSignals(false); ui->comboBoxMax->blockSignals(true); ui->comboBoxMax->clear(); - filtered = FilterByMinimum(bases, restriction.first); - FillBases(FilterByMinimum(bases, restriction.first), dimension, ui->comboBoxMax); - index = ui->comboBoxMax->findData(restriction.second); + filtered = FilterByMinimum(bases, restriction.GetMin()); + FillBases(FilterByMinimum(bases, restriction.GetMin()), dimension, ui->comboBoxMax); + index = ui->comboBoxMax->findData(restriction.GetMax()); ui->comboBoxMax->setCurrentIndex(index != -1 ? index : ui->comboBoxMax->count() - 1); ui->comboBoxMax->blockSignals(false); @@ -229,7 +232,7 @@ void DialogRestrictDimension::MinRestrictionChanged() qreal base1 = 0; qreal base2 = 0; - if (m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::Second) { base1 = item->data(Qt::UserRole).toDouble(); } @@ -240,9 +243,9 @@ void DialogRestrictDimension::MinRestrictionChanged() } const QString coordinates = VMeasurement::CorrectionHash(base1, base2); - QPair restriction = m_restrictions.value(coordinates, QPair(0, 0)); + VDimensionRestriction restriction = m_restrictions.value(coordinates); - restriction.first = ui->comboBoxMin->currentData().toDouble(); + restriction.SetMin(ui->comboBoxMin->currentData().toDouble()); m_restrictions.insert(coordinates, restriction); const int currentRow = ui->tableWidget->currentRow(); @@ -266,7 +269,7 @@ void DialogRestrictDimension::MaxRestrictionChanged() qreal base1 = 0; qreal base2 = 0; - if (m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::Second) { base1 = item->data(Qt::UserRole).toDouble(); } @@ -277,9 +280,9 @@ void DialogRestrictDimension::MaxRestrictionChanged() } const QString coordinates = VMeasurement::CorrectionHash(base1, base2); - QPair restriction = m_restrictions.value(coordinates, QPair(0, 0)); + VDimensionRestriction restriction = m_restrictions.value(coordinates); - restriction.second = ui->comboBoxMax->currentData().toDouble(); + restriction.SetMax(ui->comboBoxMax->currentData().toDouble()); m_restrictions.insert(coordinates, restriction); const int currentRow = ui->tableWidget->currentRow(); @@ -293,6 +296,111 @@ void DialogRestrictDimension::MaxRestrictionChanged() } } +//--------------------------------------------------------------------------------------------------------------------- +void DialogRestrictDimension::CellContextMenu(QPoint pos) +{ + QTableWidgetItem *item = ui->tableWidget->itemAt(pos); + if (item != nullptr && (item->flags() & Qt::ItemIsEnabled) != 0U) + { + qreal columnValue = 0; + QString coordinates; + MeasurementDimension_p dimension; + + if (m_restrictionType == RestrictDimension::First) + { + if (not m_dimensions.empty()) + { + columnValue = m_dimensions.at(0)->ValidBases().at(item->column()); + coordinates = QChar('0'); + } + else + { + return; + } + } + else if (m_restrictionType == RestrictDimension::Second) + { + if (m_dimensions.size() >= 2) + { + dimension = m_dimensions.at(1); + columnValue = dimension->ValidBases().at(item->column()); + qreal base1 = m_dimensions.at(0)->ValidBases().at(item->row()); + coordinates = VMeasurement::CorrectionHash(base1); + } + else + { + return; + } + } + else if (m_restrictionType == RestrictDimension::Third) + { + if (m_dimensions.size() >= 3) + { + dimension = m_dimensions.at(2); + columnValue = dimension->ValidBases().at(item->column()); + qreal base1 = ui->comboBoxDimensionA->currentData().toDouble(); + qreal base2 = m_dimensions.at(1)->ValidBases().at(item->row()); + coordinates = VMeasurement::CorrectionHash(base1, base2); + } + else + { + return; + } + } + else + { + return; + } + + VDimensionRestriction restriction = m_restrictions.value(coordinates); + bool exclude = not restriction.GetExcludeValues().contains(columnValue); + QScopedPointer menu(new QMenu()); + QAction *actionExclude = menu->addAction(exclude ? tr("Exclude") : tr("Include")); + + if (m_restrictionType == RestrictDimension::Second || m_restrictionType == RestrictDimension::Third) + { + if (dimension != nullptr) + { + qreal min = restriction.GetMin(); + if (qFuzzyIsNull(min)) + { + min = dimension->MinValue(); + } + + qreal max = restriction.GetMax(); + if (qFuzzyIsNull(max)) + { + max = dimension->MaxValue(); + } + + actionExclude->setEnabled(columnValue >= min && columnValue <= max); + } + else + { + return; + } + } + + QAction *selectedAction = menu->exec(ui->tableWidget->viewport()->mapToGlobal(pos)); + if (selectedAction == actionExclude) + { + QSet list = restriction.GetExcludeValues(); + if (exclude) + { + list.insert(columnValue); + item->setIcon(QIcon(QStringLiteral("://icon/24x24/close.png"))); + } + else + { + list.remove(columnValue); + item->setIcon(QIcon(QStringLiteral("://icon/24x24/star.png"))); + } + restriction.SetExcludeValues(list); + m_restrictions[coordinates] = restriction; + } + } +} + //--------------------------------------------------------------------------------------------------------------------- void DialogRestrictDimension::InitDimensionsBaseValues() { @@ -313,7 +421,18 @@ void DialogRestrictDimension::InitDimensionsBaseValues() } }; - if (not m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::First) + { + ui->labelDimensionA->setVisible(false); + ui->comboBoxDimensionA->setVisible(false); + ui->groupBoxRestriction->setVisible(false); + } + else if (m_restrictionType == RestrictDimension::Second) + { + ui->labelDimensionA->setVisible(false); + ui->comboBoxDimensionA->setVisible(false); + } + else if (m_restrictionType == RestrictDimension::Third) { if (not m_dimensions.empty()) { @@ -325,11 +444,6 @@ void DialogRestrictDimension::InitDimensionsBaseValues() ui->comboBoxDimensionA->setVisible(false); } } - else - { - ui->labelDimensionA->setVisible(false); - ui->comboBoxDimensionA->setVisible(false); - } } //--------------------------------------------------------------------------------------------------------------------- @@ -346,7 +460,7 @@ void DialogRestrictDimension::InitDimensionGradation(const MeasurementDimension_ control->blockSignals(true); control->clear(); - FillBases(dimension->ValidBases(), dimension, control); + FillBases(DimensionRestrictedValues(dimension), dimension, control); int i = control->findData(current); if (i != -1) @@ -367,23 +481,44 @@ void DialogRestrictDimension::InitTable() ui->tableWidget->blockSignals(true); ui->tableWidget->clear(); - auto InitHeaders = [this](int index) + auto InitVerticalHeaderForDimension = [this](int index) { if (m_dimensions.size() > index) { - MeasurementDimension_p dimensionA = m_dimensions.at(index-1); - const QVector basesA = dimensionA->ValidBases(); - ui->tableWidget->setRowCount(basesA.size()); - ui->tableWidget->setVerticalHeaderLabels(DimensionLabels(basesA, dimensionA)); - - MeasurementDimension_p dimensionB = m_dimensions.at(index); - const QVector basesB = dimensionB->ValidBases(); - ui->tableWidget->setColumnCount(basesB.size()); - ui->tableWidget->setHorizontalHeaderLabels(DimensionLabels(basesB, dimensionB)); + MeasurementDimension_p dimension = m_dimensions.at(index); + const QVector bases = dimension->ValidBases(); + ui->tableWidget->setRowCount(bases.size()); + ui->tableWidget->setVerticalHeaderLabels(DimensionLabels(bases, dimension)); } }; - InitHeaders(m_oneDimesionRestriction ? 1 : 2); + auto InitHorizontalHeaderForDimension = [this](int index) + { + if (m_dimensions.size() > index) + { + MeasurementDimension_p dimension = m_dimensions.at(index); + const QVector bases = dimension->ValidBases(); + ui->tableWidget->setColumnCount(bases.size()); + ui->tableWidget->setHorizontalHeaderLabels(DimensionLabels(bases, dimension)); + } + }; + + if (m_restrictionType == RestrictDimension::First) + { + InitHorizontalHeaderForDimension(0); + ui->tableWidget->setRowCount(1); + } + else if (m_restrictionType == RestrictDimension::Second) + { + InitVerticalHeaderForDimension(0); + InitHorizontalHeaderForDimension(1); + } + else if (m_restrictionType == RestrictDimension::Third) + { + InitVerticalHeaderForDimension(1); + InitHorizontalHeaderForDimension(2); + } + ui->tableWidget->blockSignals(false); RefreshTable(); @@ -396,7 +531,19 @@ void DialogRestrictDimension::RefreshTable() QVector basesRow; QVector basesColumn; - if (m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::First) + { + if (not m_dimensions.empty()) + { + MeasurementDimension_p dimensionA = m_dimensions.at(0); + basesColumn = dimensionA->ValidBases(); + } + else + { + return; + } + } + else if (m_restrictionType == RestrictDimension::Second) { if (m_dimensions.size() >= 2) { @@ -411,7 +558,7 @@ void DialogRestrictDimension::RefreshTable() return; } } - else + else if (m_restrictionType == RestrictDimension::Third) { if (m_dimensions.size() >= 3) { @@ -430,16 +577,30 @@ void DialogRestrictDimension::RefreshTable() ui->tableWidget->blockSignals(true); ui->tableWidget->clearContents(); - for(int row=0; row < basesRow.size(); ++row) + if (m_restrictionType == RestrictDimension::First) { for(int column=0; column < basesColumn.size(); ++column) { - AddCell(row, column, basesRow.at(row), basesColumn.at(column)); + AddCell(0, column, 0, basesColumn.at(column)); + } + } + else + { + for(int row=0; row < basesRow.size(); ++row) + { + for(int column=0; column < basesColumn.size(); ++column) + { + AddCell(row, column, basesRow.at(row), basesColumn.at(column)); + } } } ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + if (m_restrictionType != RestrictDimension::First) + { + ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); + } ui->tableWidget->blockSignals(false); } @@ -450,74 +611,95 @@ void DialogRestrictDimension::AddCell(int row, int column, qreal rowValue, qreal auto *item = new QTableWidgetItem(); item->setData(Qt::UserRole, rowValue); - qreal base1 = 0; - qreal base2 = 0; - MeasurementDimension_p dimension; - QVector bases; - QVector validRows; - - if (m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::First) { - base1 = rowValue; - - if (m_dimensions.size() >= 2) + VDimensionRestriction restriction = m_restrictions.value(QChar('0')); + if (restriction.GetExcludeValues().contains(columnValue)) { - validRows = m_dimensions.at(0)->ValidBases(); - dimension = m_dimensions.at(1); - bases = dimension->ValidBases(); + item->setIcon(QIcon(QStringLiteral("://icon/24x24/close.png"))); + } + else + { + item->setIcon(QIcon(QStringLiteral("://icon/24x24/star.png"))); } } else { - base1 = ui->comboBoxDimensionA->currentData().toDouble(); - base2 = rowValue; + qreal base1 = 0; + qreal base2 = 0; + MeasurementDimension_p dimension; + QVector bases; + QVector validRows; - if (m_dimensions.size() >= 3) + if (m_restrictionType == RestrictDimension::Second) { - validRows = DimensionRestrictedValues(m_dimensions.at(1)); - dimension = m_dimensions.at(2); - bases = dimension->ValidBases(); + base1 = rowValue; + + if (m_dimensions.size() >= 2) + { + validRows = m_dimensions.at(0)->ValidBases(); + dimension = m_dimensions.at(1); + bases = dimension->ValidBases(); + } } - } - - QPair restriction = m_restrictions.value(VMeasurement::CorrectionHash(base1, base2), - QPair(0, 0)); - qreal min = INT32_MIN; - qreal max = INT32_MAX; - - if (not dimension.isNull()) - { - min = bases.indexOf(restriction.first) != -1 ? restriction.first : dimension->MinValue(); - max = bases.indexOf(restriction.second) != -1 ? restriction.second : dimension->MaxValue(); - - if (max < min) + else if (m_restrictionType == RestrictDimension::Third) { - min = dimension->MinValue(); - max = dimension->MaxValue(); + base1 = ui->comboBoxDimensionA->currentData().toDouble(); + base2 = rowValue; + + if (m_dimensions.size() >= 3) + { + validRows = DimensionRestrictedValues(m_dimensions.at(1)); + dimension = m_dimensions.at(2); + bases = dimension->ValidBases(); + } } - } - if (validRows.contains(rowValue)) - { - const bool leftRestriction = columnValue >= min; - const bool rightRestriction = columnValue <= max; + VDimensionRestriction restriction = m_restrictions.value(VMeasurement::CorrectionHash(base1, base2)); + qreal min = INT32_MIN; + qreal max = INT32_MAX; - if (leftRestriction && rightRestriction) + if (not dimension.isNull()) { - item->setIcon(QIcon(QStringLiteral("://icon/24x24/star.png"))); + min = bases.indexOf(restriction.GetMin()) != -1 ? restriction.GetMin() : dimension->MinValue(); + max = bases.indexOf(restriction.GetMax()) != -1 ? restriction.GetMax() : dimension->MaxValue(); + + if (max < min) + { + min = dimension->MinValue(); + max = dimension->MaxValue(); + } + } + + if (validRows.contains(rowValue)) + { + const bool leftRestriction = columnValue >= min; + const bool rightRestriction = columnValue <= max; + + if (leftRestriction && rightRestriction) + { + if (restriction.GetExcludeValues().contains(columnValue)) + { + item->setIcon(QIcon(QStringLiteral("://icon/24x24/close.png"))); + } + else + { + item->setIcon(QIcon(QStringLiteral("://icon/24x24/star.png"))); + } + } + else + { + item->setIcon(QIcon(QStringLiteral("://icon/24x24/close.png"))); + } } else { item->setIcon(QIcon(QStringLiteral("://icon/24x24/close.png"))); - } - } - else - { - item->setIcon(QIcon(QStringLiteral("://icon/24x24/close.png"))); - Qt::ItemFlags flags = item->flags(); - flags &= ~(Qt::ItemIsEnabled); - item->setFlags(flags); + Qt::ItemFlags flags = item->flags(); + flags &= ~(Qt::ItemIsEnabled); + item->setFlags(flags); + } } // set the item non-editable (view only), and non-selectable @@ -671,18 +853,22 @@ auto DialogRestrictDimension::DimensionLabels(const QVector &bases, //--------------------------------------------------------------------------------------------------------------------- auto DialogRestrictDimension::DimensionRestrictedValues(const MeasurementDimension_p &dimension) const -> QVector { - QPair restriction; + VDimensionRestriction restriction; - if (not m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::First) + { + restriction = m_restrictions.value(QChar('0')); + } + else if (m_restrictionType == RestrictDimension::Third) { qreal base1 = ui->comboBoxDimensionA->currentData().toDouble(); - restriction = m_restrictions.value(VMeasurement::CorrectionHash(base1), QPair(0, 0)); + restriction = m_restrictions.value(VMeasurement::CorrectionHash(base1)); } const QVector bases = dimension->ValidBases(); - qreal min = bases.indexOf(restriction.first) != -1 ? restriction.first : dimension->MinValue(); - qreal max = bases.indexOf(restriction.second) != -1 ? restriction.second : dimension->MaxValue(); + qreal min = bases.indexOf(restriction.GetMin()) != -1 ? restriction.GetMin() : dimension->MinValue(); + qreal max = bases.indexOf(restriction.GetMax()) != -1 ? restriction.GetMax() : dimension->MaxValue(); if (min > max) { @@ -690,13 +876,13 @@ auto DialogRestrictDimension::DimensionRestrictedValues(const MeasurementDimensi max = dimension->MaxValue(); } - return VAbstartMeasurementDimension::ValidBases(min, max, dimension->Step()); + return VAbstartMeasurementDimension::ValidBases(min, max, dimension->Step(), restriction.GetExcludeValues()); } //--------------------------------------------------------------------------------------------------------------------- auto DialogRestrictDimension::StartRow() const -> int { - if (m_oneDimesionRestriction) + if (m_restrictionType == RestrictDimension::Second) { return 0; } diff --git a/src/app/tape/dialogs/dialogrestrictdimension.h b/src/app/tape/dialogs/dialogrestrictdimension.h index cb7614a10..39741c22e 100644 --- a/src/app/tape/dialogs/dialogrestrictdimension.h +++ b/src/app/tape/dialogs/dialogrestrictdimension.h @@ -40,6 +40,13 @@ class DialogRestrictDimension; class QTableWidgetItem; +enum class RestrictDimension: qint8 +{ + First = 0, + Second = 1, + Third = 2 +}; + class DialogRestrictDimension : public QDialog { @@ -47,11 +54,11 @@ class DialogRestrictDimension : public QDialog public: DialogRestrictDimension(const QList &dimensions, - const QMap> &restrictions, bool oneDimesionRestriction, + const QMap &restrictions, RestrictDimension restrictionType, bool fullCircumference, QWidget *parent = nullptr); virtual ~DialogRestrictDimension(); - auto Restrictions() const -> QMap >; + auto Restrictions() const -> QMap; protected: virtual void changeEvent(QEvent* event) override; @@ -62,14 +69,17 @@ protected slots: void MinRestrictionChanged(); void MaxRestrictionChanged(); +private slots: + void CellContextMenu(QPoint pos); + private: Q_DISABLE_COPY(DialogRestrictDimension) Ui::DialogRestrictDimension *ui; - bool m_oneDimesionRestriction; + RestrictDimension m_restrictionType; bool m_fullCircumference; QList m_dimensions; - QMap> m_restrictions; + QMap m_restrictions; void InitDimensionsBaseValues(); void InitDimensionGradation(const MeasurementDimension_p &dimension, QComboBox *control); @@ -89,7 +99,7 @@ private: }; //--------------------------------------------------------------------------------------------------------------------- -inline auto DialogRestrictDimension::Restrictions() const -> QMap > +inline auto DialogRestrictDimension::Restrictions() const -> QMap { return m_restrictions; } diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index 0ae3fde7e..6425a66d7 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -2245,16 +2245,36 @@ void TMainWindow::ExportToIndividual() } } +//--------------------------------------------------------------------------------------------------------------------- +void TMainWindow::RestrictFirstDimesion() +{ + const QList dimensions = m->Dimensions().values(); + const QMap restrictions = m->GetRestrictions(); + bool fullCircumference = m->IsFullCircumference(); + + DialogRestrictDimension dialog(dimensions, restrictions, RestrictDimension::First, fullCircumference, this); + if (dialog.exec() == QDialog::Rejected) + { + return; + } + + m->SetRestrictions(dialog.Restrictions()); + MeasurementsWereSaved(false); + + if (not dimensions.isEmpty()) + { + InitDimensionGradation(0, dimensions.at(0), gradationDimensionA); + } +} + //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::RestrictSecondDimesion() { const QList dimensions = m->Dimensions().values(); - const QMap> restrictions = m->GetRestrictions(); - - bool oneDimesionRestriction = true; + const QMap restrictions = m->GetRestrictions(); bool fullCircumference = m->IsFullCircumference(); - DialogRestrictDimension dialog(dimensions, restrictions, oneDimesionRestriction, fullCircumference, this); + DialogRestrictDimension dialog(dimensions, restrictions, RestrictDimension::Second, fullCircumference, this); if (dialog.exec() == QDialog::Rejected) { return; @@ -2269,12 +2289,10 @@ void TMainWindow::RestrictSecondDimesion() void TMainWindow::RestrictThirdDimesion() { const QList dimensions = m->Dimensions().values(); - const QMap> restrictions = m->GetRestrictions(); - - bool oneDimesionRestriction = false; + const QMap restrictions = m->GetRestrictions(); bool fullCircumference = m->IsFullCircumference(); - DialogRestrictDimension dialog(dimensions, restrictions, oneDimesionRestriction, fullCircumference, this); + DialogRestrictDimension dialog(dimensions, restrictions, RestrictDimension::Third, fullCircumference, this); if (dialog.exec() == QDialog::Rejected) { return; @@ -2591,18 +2609,26 @@ void TMainWindow::InitMenu() ui->menuMeasurements->insertAction(ui->actionUseFullCircumference, separator); const QList dimensions = m->Dimensions().values(); - if (dimensions.size() > 1) + if (dimensions.size() > 0) { - ui->actionRestrictSecondDimension->setVisible(true); - ui->actionRestrictSecondDimension->setEnabled(true); - connect(ui->actionRestrictSecondDimension, &QAction::triggered, this, &TMainWindow::RestrictSecondDimesion); + ui->actionRestrictFirstDimension->setVisible(true); + ui->actionRestrictFirstDimension->setEnabled(true); + connect(ui->actionRestrictFirstDimension, &QAction::triggered, this, &TMainWindow::RestrictFirstDimesion); - if (dimensions.size() > 2) + if (dimensions.size() > 1) { - ui->actionRestrictThirdDimension->setVisible(true); - ui->actionRestrictThirdDimension->setEnabled(true); - connect(ui->actionRestrictThirdDimension, &QAction::triggered, this, - &TMainWindow::RestrictThirdDimesion); + ui->actionRestrictSecondDimension->setVisible(true); + ui->actionRestrictSecondDimension->setEnabled(true); + connect(ui->actionRestrictSecondDimension, &QAction::triggered, this, + &TMainWindow::RestrictSecondDimesion); + + if (dimensions.size() > 2) + { + ui->actionRestrictThirdDimension->setVisible(true); + ui->actionRestrictThirdDimension->setEnabled(true); + connect(ui->actionRestrictThirdDimension, &QAction::triggered, this, + &TMainWindow::RestrictThirdDimesion); + } } } @@ -4176,18 +4202,24 @@ void TMainWindow::SetCurrentDimensionValues() //--------------------------------------------------------------------------------------------------------------------- QVector TMainWindow::DimensionRestrictedValues(int index, const MeasurementDimension_p &dimension) { + VDimensionRestriction restriction; if (index == 0) { - return dimension->ValidBases(); + restriction = m->Restriction(0); + } + else if (index == 1) + { + restriction = m->Restriction(currentDimensionA); + } + else + { + restriction = m->Restriction(currentDimensionA, currentDimensionB); } - - QPair restriction = index == 1 ? m->Restriction(currentDimensionA) - : m->Restriction(currentDimensionA, currentDimensionB); const QVector bases = dimension->ValidBases(); - qreal min = bases.indexOf(restriction.first) != -1 ? restriction.first : dimension->MinValue(); - qreal max = bases.indexOf(restriction.second) != -1 ? restriction.second : dimension->MaxValue(); + qreal min = bases.indexOf(restriction.GetMin()) != -1 ? restriction.GetMin() : dimension->MinValue(); + qreal max = bases.indexOf(restriction.GetMax()) != -1 ? restriction.GetMax() : dimension->MaxValue(); if (min > max) { @@ -4195,7 +4227,7 @@ QVector TMainWindow::DimensionRestrictedValues(int index, const Measureme max = dimension->MaxValue(); } - return VAbstartMeasurementDimension::ValidBases(min, max, dimension->Step()); + return VAbstartMeasurementDimension::ValidBases(min, max, dimension->Step(), restriction.GetExcludeValues()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h index 987ac794f..389c0fb54 100644 --- a/src/app/tape/tmainwindow.h +++ b/src/app/tape/tmainwindow.h @@ -140,6 +140,7 @@ private slots: void ExportToIndividual(); + void RestrictFirstDimesion(); void RestrictSecondDimesion(); void RestrictThirdDimesion(); diff --git a/src/app/tape/tmainwindow.ui b/src/app/tape/tmainwindow.ui index 21814521a..b31ae4f4a 100644 --- a/src/app/tape/tmainwindow.ui +++ b/src/app/tape/tmainwindow.ui @@ -1016,6 +1016,7 @@ + @@ -1401,6 +1402,9 @@ false + + QAction::ApplicationSpecificRole + @@ -1412,6 +1416,9 @@ false + + QAction::ApplicationSpecificRole + @@ -1424,6 +1431,20 @@ false + + + false + + + Restrict first dimension + + + false + + + QAction::ApplicationSpecificRole + + @@ -1448,8 +1469,8 @@ -1 - 764 - 377 + 1187 + 457 @@ -1460,8 +1481,8 @@ setChecked(bool) - 734 - 384 + 1187 + 464 -1 diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index 76f42daf7..5aecfe66b 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -2148,11 +2148,10 @@ void MainWindow::StoreIndividualMDimensions() //--------------------------------------------------------------------------------------------------------------------- QVector MainWindow::DimensionRestrictedValues(int index, const MeasurementDimension_p &dimension) { - QPair restriction; - + VDimensionRestriction restriction; if (index == 0) { - return dimension->ValidBases(); + restriction = m->Restriction(0); } else if (index == 1) { @@ -2165,8 +2164,8 @@ QVector MainWindow::DimensionRestrictedValues(int index, const Measuremen const QVector bases = dimension->ValidBases(); - qreal min = bases.indexOf(restriction.first) != -1 ? restriction.first : dimension->MinValue(); - qreal max = bases.indexOf(restriction.second) != -1 ? restriction.second : dimension->MaxValue(); + qreal min = bases.indexOf(restriction.GetMin()) != -1 ? restriction.GetMin() : dimension->MinValue(); + qreal max = bases.indexOf(restriction.GetMax()) != -1 ? restriction.GetMax() : dimension->MaxValue(); if (min > max) { @@ -2174,7 +2173,7 @@ QVector MainWindow::DimensionRestrictedValues(int index, const Measuremen max = dimension->MaxValue(); } - return VAbstartMeasurementDimension::ValidBases(min, max, dimension->Step()); + return VAbstartMeasurementDimension::ValidBases(min, max, dimension->Step(), restriction.GetExcludeValues()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/ifc/schema/multisize_measurements/v0.5.1.xsd b/src/libs/ifc/schema/multisize_measurements/v0.5.1.xsd index 7833fa111..b4ebbc349 100644 --- a/src/libs/ifc/schema/multisize_measurements/v0.5.1.xsd +++ b/src/libs/ifc/schema/multisize_measurements/v0.5.1.xsd @@ -47,6 +47,7 @@ + diff --git a/src/libs/vformat/vdimensions.cpp b/src/libs/vformat/vdimensions.cpp index 43454d720..d49e61f8c 100644 --- a/src/libs/vformat/vdimensions.cpp +++ b/src/libs/vformat/vdimensions.cpp @@ -87,7 +87,7 @@ auto VAbstartMeasurementDimension::ValidSteps() const -> QVector //--------------------------------------------------------------------------------------------------------------------- auto VAbstartMeasurementDimension::ValidBases() const -> QVector { - return VAbstartMeasurementDimension::ValidBases(m_minValue, m_maxValue, m_step); + return VAbstartMeasurementDimension::ValidBases(m_minValue, m_maxValue, m_step, QSet()); } //--------------------------------------------------------------------------------------------------------------------- @@ -105,7 +105,8 @@ auto VAbstartMeasurementDimension::ValidBasesList() const -> QStringList } //--------------------------------------------------------------------------------------------------------------------- -auto VAbstartMeasurementDimension::ValidBases(qreal min, qreal max, qreal step) -> QVector +auto VAbstartMeasurementDimension::ValidBases(qreal min, qreal max, qreal step, + const QSet &exclude) -> QVector { QVector validBases; @@ -124,11 +125,25 @@ auto VAbstartMeasurementDimension::ValidBases(qreal min, qreal max, qreal step) qreal value = min; do { - validBases.append(value); + if (not exclude.contains(value)) + { + validBases.append(value); + } value += step; } while(value < max + step); + if (validBases.isEmpty()) + { + value = min; + do + { + validBases.append(value); + value += step; + } + while(value < max + step); + } + return validBases; } @@ -463,3 +478,36 @@ auto VZMeasurementDimension::RangeMax() const -> int return 0; } } + +// VDimensionRestriction +//--------------------------------------------------------------------------------------------------------------------- +void VDimensionRestriction::SetExcludeString(const QString &exclude) +{ + m_exclude.clear(); + + QStringList values = exclude.split(';'); + for(auto &value : values) + { + bool ok = false; + qreal val = value.toDouble(&ok); + + if (ok) + { + m_exclude.insert(val); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VDimensionRestriction::GetExcludeString() const -> QString +{ + QList list = m_exclude.values(); + QStringList excludeList; + + for(auto &value : list) + { + excludeList.append(QString::number(value)); + } + + return excludeList.join(';'); +} diff --git a/src/libs/vformat/vdimensions.h b/src/libs/vformat/vdimensions.h index 913ad36a6..4ac4bc0c3 100644 --- a/src/libs/vformat/vdimensions.h +++ b/src/libs/vformat/vdimensions.h @@ -30,6 +30,7 @@ #include #include +#include #include "../vmisc/def.h" @@ -85,7 +86,7 @@ public: auto ValidBases() const -> QVector; auto ValidBasesList() const -> QStringList; - static auto ValidBases(qreal min, qreal max, qreal step) -> QVector; + static auto ValidBases(qreal min, qreal max, qreal step, const QSet &exclude) -> QVector; static auto DimensionName(MeasurementDimension type) -> QString; static auto DimensionToolTip(MeasurementDimension type, bool circumference, bool fc) -> QString; @@ -271,4 +272,70 @@ public: virtual auto RangeMax() const -> int override; }; +class VDimensionRestriction +{ +public: + VDimensionRestriction() + {} + + VDimensionRestriction(qreal min, qreal max, const QString &exclude = QString()) : + m_min(min), + m_max(max) + { + SetExcludeString(exclude); + } + + void SetMin(qreal min); + auto GetMin() const -> qreal; + + void SetMax(qreal max); + auto GetMax() const -> qreal; + + void SetExcludeString(const QString &exclude); + auto GetExcludeString() const -> QString; + + void SetExcludeValues(const QSet &exclude); + auto GetExcludeValues() const -> QSet; +private: + qreal m_min{0}; + qreal m_max{0}; + QSet m_exclude{}; +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline void VDimensionRestriction::SetMin(qreal min) +{ + m_min = min; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VDimensionRestriction::GetMin() const -> qreal +{ + return m_min; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VDimensionRestriction::SetMax(qreal max) +{ + m_max = max; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VDimensionRestriction::GetMax() const -> qreal +{ + return m_max; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VDimensionRestriction::SetExcludeValues(const QSet &exclude) +{ + m_exclude = exclude; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VDimensionRestriction::GetExcludeValues() const -> QSet +{ + return m_exclude; +} + #endif // VDIMENSIONS_H diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp index 23ef04726..eca655d69 100644 --- a/src/libs/vformat/vmeasurements.cpp +++ b/src/libs/vformat/vmeasurements.cpp @@ -84,6 +84,7 @@ const QString VMeasurements::AttrShiftB = QStringLiteral("shiftB"); const QString VMeasurements::AttrShiftC = QStringLiteral("shiftC"); const QString VMeasurements::AttrCorrection = QStringLiteral("correction"); const QString VMeasurements::AttrCoordinates = QStringLiteral("coordinates"); +const QString VMeasurements::AttrExclude = QStringLiteral("exclude"); const QString VMeasurements::AttrSpecialUnits = QStringLiteral("specialUnits"); const QString VMeasurements::AttrDescription = QStringLiteral("description"); const QString VMeasurements::AttrName = QStringLiteral("name"); @@ -903,9 +904,9 @@ auto VMeasurements::Dimensions() const -> QMap QMap > +auto VMeasurements::GetRestrictions() const -> QMap { - QMap > restrictions; + QMap restrictions; const QDomNodeList list = elementsByTagName(TagRestriction); for (int i=0; i < list.size(); ++i) @@ -915,15 +916,16 @@ auto VMeasurements::GetRestrictions() const -> QMap QString coordinates = GetParametrString(res, AttrCoordinates); const qreal min = GetParametrDouble(res, AttrMin, QChar('0')); const qreal max = GetParametrDouble(res, AttrMax, QChar('0')); + const QString exclude = GetParametrEmptyString(res, AttrExclude); - restrictions.insert(coordinates, qMakePair(min, max)); + restrictions.insert(coordinates, VDimensionRestriction(min, max, exclude)); } return restrictions; } //--------------------------------------------------------------------------------------------------------------------- -void VMeasurements::SetRestrictions(const QMap > &restrictions) +void VMeasurements::SetRestrictions(const QMap &restrictions) { QDomElement root = documentElement(); QDomElement restrictionsTag = root.firstChildElement(TagRestrictions); @@ -941,8 +943,10 @@ void VMeasurements::SetRestrictions(const QMap > &r QDomElement restrictionTag = createElement(TagRestriction); SetAttribute(restrictionTag, AttrCoordinates, i.key()); - SetAttributeOrRemoveIf(restrictionTag, AttrMin, i.value().first, qFuzzyIsNull(i.value().first)); - SetAttributeOrRemoveIf(restrictionTag, AttrMax, i.value().second, qFuzzyIsNull(i.value().second)); + SetAttributeOrRemoveIf(restrictionTag, AttrMin, i.value().GetMin(), qFuzzyIsNull(i.value().GetMin())); + SetAttributeOrRemoveIf(restrictionTag, AttrMax, i.value().GetMax(), qFuzzyIsNull(i.value().GetMax())); + SetAttributeOrRemoveIf(restrictionTag, AttrExclude, i.value().GetExcludeString(), + i.value().GetExcludeString().isEmpty()); restrictionsTag.appendChild(restrictionTag); ++i; @@ -950,11 +954,11 @@ void VMeasurements::SetRestrictions(const QMap > &r } //--------------------------------------------------------------------------------------------------------------------- -auto VMeasurements::Restriction(qreal base, qreal base2) const -> QPair +auto VMeasurements::Restriction(qreal base, qreal base2) const -> VDimensionRestriction { - const QMap > restrictions = GetRestrictions(); + const QMap restrictions = GetRestrictions(); const QString hash = VMeasurement::CorrectionHash(base, base2, 0); - return restrictions.value(hash, QPair(0, 0)); + return restrictions.value(hash); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h index fb267bdcf..22f17f906 100644 --- a/src/libs/vformat/vmeasurements.h +++ b/src/libs/vformat/vmeasurements.h @@ -119,9 +119,9 @@ public: auto Dimensions() const -> QMap; - auto GetRestrictions() const -> QMap >; - void SetRestrictions(const QMap > &restrictions); - auto Restriction(qreal base, qreal base2=0) const -> QPair; + auto GetRestrictions() const -> QMap; + void SetRestrictions(const QMap &restrictions); + auto Restriction(qreal base, qreal base2=0) const -> VDimensionRestriction; void SetDimensionLabels(const QMap &labels); @@ -153,6 +153,7 @@ public: static const QString AttrShiftC; static const QString AttrCorrection; static const QString AttrCoordinates; + static const QString AttrExclude; static const QString AttrSpecialUnits; static const QString AttrDescription; static const QString AttrName;