From 4646b6c1fb3dfce31e5d31e5749faf837bcfd72c Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Sat, 21 Aug 2021 16:13:56 +0300 Subject: [PATCH] Default layout settings. --- src/app/puzzle/carousel/vpmimedatapiece.h | 3 +- .../puzzlepreferencesconfigurationpage.cpp | 67 +- .../puzzlepreferencesconfigurationpage.ui | 432 +++++++++--- .../puzzlepreferenceslayoutpage.cpp | 657 ++++++++++++++++++ .../configpages/puzzlepreferenceslayoutpage.h | 102 +++ .../puzzlepreferenceslayoutpage.ui | 653 +++++++++++++++++ .../dialogs/dialogpuzzlepreferences.cpp | 6 +- .../puzzle/dialogs/dialogpuzzlepreferences.h | 2 + .../puzzle/dialogs/dialogpuzzlepreferences.ui | 14 +- src/app/puzzle/layout/layoutdef.h | 4 +- src/app/puzzle/layout/vplayout.cpp | 27 + src/app/puzzle/layout/vplayoutsettings.cpp | 39 +- src/app/puzzle/layout/vplayoutsettings.h | 120 ++-- src/app/puzzle/puzzle.pri | 3 + src/app/puzzle/vpapplication.cpp | 12 + src/app/puzzle/vpapplication.h | 9 +- src/app/puzzle/vpmainwindow.cpp | 70 +- src/app/puzzle/vpmainwindow.h | 4 + src/app/puzzle/vpmainwindow.ui | 4 +- src/app/puzzle/vpsettings.cpp | 218 +++++- src/app/puzzle/vpsettings.h | 53 +- .../preferencesconfigurationpage.cpp | 20 +- .../preferencesconfigurationpage.ui | 4 +- .../vlayout/dialogs/vabstractlayoutdialog.h | 4 +- src/libs/vmisc/def.h | 4 +- src/libs/vmisc/share/resources/icon.qrc | 1 + .../vmisc/share/resources/icon/layout.png | Bin 0 -> 19880 bytes src/libs/vmisc/vcommonsettings.cpp | 1 + 28 files changed, 2308 insertions(+), 225 deletions(-) create mode 100644 src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp create mode 100644 src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.h create mode 100644 src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui create mode 100644 src/libs/vmisc/share/resources/icon/layout.png diff --git a/src/app/puzzle/carousel/vpmimedatapiece.h b/src/app/puzzle/carousel/vpmimedatapiece.h index 9ad6e6338..68e794b1a 100644 --- a/src/app/puzzle/carousel/vpmimedatapiece.h +++ b/src/app/puzzle/carousel/vpmimedatapiece.h @@ -30,6 +30,7 @@ #define VPMIMEDATAPIECE_H #include +#include #include "../layout/layoutdef.h" @@ -62,7 +63,7 @@ public: private: Q_DISABLE_COPY(VPMimeDataPiece) - VPPiecePtr m_piece{}; + VPPieceWeakPtr m_piece{}; }; #endif // VPMIMEDATAPIECE_H diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp index f5c06d700..094f64011 100644 --- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp @@ -43,14 +43,44 @@ PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget * m_langChanged = true; }); + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + // Theme - ui->darkModeCheck->setChecked(VPApplication::VApp()->PuzzleSettings()->GetDarkMode()); + ui->darkModeCheck->setChecked(settings->GetDarkMode()); // Native dialogs - ui->checkBoxDontUseNativeDialog->setChecked(VPApplication::VApp()->PuzzleSettings()->IsDontUseNativeDialog()); + ui->checkBoxDontUseNativeDialog->setChecked(settings->IsDontUseNativeDialog()); //----------------------- Toolbar - ui->toolBarStyleCheck->setChecked(VPApplication::VApp()->PuzzleSettings()->GetToolBarStyle()); + ui->toolBarStyleCheck->setChecked(settings->GetToolBarStyle()); + + // Undo + ui->undoCount->setValue(settings->GetUndoCount()); + + //Graphical output + ui->graphOutputCheck->setChecked(settings->GetGraphicalOutput()); + ui->checkBoxOpenGLRender->setChecked(settings->IsOpenGLRender()); + + // Tab Scrolling + ui->spinBoxDuration->setMinimum(VCommonSettings::scrollingDurationMin); + ui->spinBoxDuration->setMaximum(VCommonSettings::scrollingDurationMax); + ui->spinBoxDuration->setValue(settings->GetScrollingDuration()); + + ui->spinBoxUpdateInterval->setMinimum(VCommonSettings::scrollingUpdateIntervalMin); + ui->spinBoxUpdateInterval->setMaximum(VCommonSettings::scrollingUpdateIntervalMax); + ui->spinBoxUpdateInterval->setValue(settings->GetScrollingUpdateInterval()); + + ui->doubleSpinBoxSensor->setMinimum(VCommonSettings::sensorMouseScaleMin); + ui->doubleSpinBoxSensor->setMaximum(VCommonSettings::sensorMouseScaleMax); + ui->doubleSpinBoxSensor->setValue(settings->GetSensorMouseScale()); + + ui->doubleSpinBoxWheel->setMinimum(VCommonSettings::wheelMouseScaleMin); + ui->doubleSpinBoxWheel->setMaximum(VCommonSettings::wheelMouseScaleMax); + ui->doubleSpinBoxWheel->setValue(settings->GetWheelMouseScale()); + + ui->doubleSpinBoxAcceleration->setMinimum(VCommonSettings::scrollingAccelerationMin); + ui->doubleSpinBoxAcceleration->setMaximum(VCommonSettings::scrollingAccelerationMax); + ui->doubleSpinBoxAcceleration->setValue(settings->GetScrollingAcceleration()); } //--------------------------------------------------------------------------------------------------------------------- @@ -60,7 +90,7 @@ PuzzlePreferencesConfigurationPage::~PuzzlePreferencesConfigurationPage() } //--------------------------------------------------------------------------------------------------------------------- -QStringList PuzzlePreferencesConfigurationPage::Apply() +auto PuzzlePreferencesConfigurationPage::Apply() -> QStringList { QStringList preferences; VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); @@ -88,6 +118,35 @@ QStringList PuzzlePreferencesConfigurationPage::Apply() qApp->processEvents();// force to call changeEvent } + /* Maximum number of commands in undo stack may only be set when the undo stack is empty, since setting it on a + * non-empty stack might delete the command at the current index. Calling setUndoLimit() on a non-empty stack + * prints a warning and does nothing.*/ + if (settings->GetUndoCount() != ui->undoCount->value()) + { + preferences.append(tr("undo limit")); + settings->SetUndoCount(ui->undoCount->value()); + } + + // Scene antialiasing + if (settings->GetGraphicalOutput() != ui->graphOutputCheck->isChecked()) + { + preferences.append(tr("antialiasing")); + settings->SetGraphicalOutput(ui->graphOutputCheck->isChecked()); + } + + if (settings->IsOpenGLRender() != ui->checkBoxOpenGLRender->isChecked()) + { + preferences.append(tr("scene render")); + settings->SetOpenGLRender(ui->checkBoxOpenGLRender->isChecked()); + } + + // Tab Scrolling + settings->SetScrollingDuration(ui->spinBoxDuration->value()); + settings->SetScrollingUpdateInterval(ui->spinBoxUpdateInterval->value()); + settings->SetSensorMouseScale(ui->doubleSpinBoxSensor->value()); + settings->SetWheelMouseScale(ui->doubleSpinBoxWheel->value()); + settings->SetScrollingAcceleration(ui->doubleSpinBoxAcceleration->value()); + return preferences; } diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui index 7f10c762d..35b7e19a7 100644 --- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui @@ -6,8 +6,8 @@ 0 0 - 505 - 548 + 702 + 741 @@ -15,97 +15,365 @@ - - - true + + + 0 - - - - 0 - 0 - 494 - 514 - - + + + General + - - - Language + + + true - - - QFormLayout::ExpandingFieldsGrow + + + + 0 + 0 + 660 + 672 + - - - - GUI language: - - - - - - - + + + + + Language + + + + QFormLayout::ExpandingFieldsGrow + + + + + GUI language: + + + + + + + + + + + + + Toolbar + + + + + + The text appears under the icon (recommended for beginners). + + + true + + + + + + + + + + User Interface + + + + + + Activate dark mode + + + + + + + Don't use the native file dialog + + + + + + + + + + Graphical output + + + + + + Use antialiasing + + + + + + + Use OpenGL to render a scene. +This option will take an affect after restart. + + + Use OpenGL render + + + false + + + + + + + + + + Undo + + + + QFormLayout::ExpandingFieldsGrow + + + + + Count steps (0 - no limit): + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Scrolling + + - - - Toolbar + + + true - - - - - The text appears under the icon (recommended for beginners). - - - true - - - - + + + + 0 + 0 + 660 + 672 + + + + + + + Animation + + + + QFormLayout::ExpandingFieldsGrow + + + + + Duration: + + + + + + + Scrolling animation duration + + + ms + + + 100 + + + 1000 + + + 300 + + + + + + + Update interval: + + + + + + + Time in milliseconds between each animation update + + + ms + + + 10 + + + 100 + + + 30 + + + + + + + + + + Mouse scale + + + + QFormLayout::ExpandingFieldsGrow + + + + + Sensor: + + + + + + + Scale scrolling sensitivity for mouse with sensor + + + 1.000000000000000 + + + 10.000000000000000 + + + 0.100000000000000 + + + 2.000000000000000 + + + + + + + Wheel: + + + + + + + Scale scrolling sensitivity for mouse with wheel + + + 1.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + 45.000000000000000 + + + + + + + + + + Scrolling + + + + QFormLayout::ExpandingFieldsGrow + + + + + Acceleration: + + + + + + + 1.000000000000000 + + + 10.000000000000000 + + + 0.100000000000000 + + + 1.300000000000000 + + + + + + + + + + Qt::Vertical + + + + 20 + 359 + + + + + + - - - - User Interface - - - - - - Activate dark mode - - - - - - - Don't use the native file dialog - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp new file mode 100644 index 000000000..4695a6848 --- /dev/null +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp @@ -0,0 +1,657 @@ +/************************************************************************ + ** + ** @file puzzlepreferenceslayoutpage.cpp + ** @author Roman Telezhynskyi + ** @date 20 8, 2021 + ** + ** @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) 2021 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "puzzlepreferenceslayoutpage.h" +#include "ui_puzzlepreferenceslayoutpage.h" +#include "vpapplication.h" + +//--------------------------------------------------------------------------------------------------------------------- +PuzzlePreferencesLayoutPage::PuzzlePreferencesLayoutPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::PuzzlePreferencesLayoutPage) +{ + ui->setupUi(this); + + VPApplication::VApp()->PuzzleSettings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c()); + + InitLayoutUnits(); + VAbstractLayoutDialog::InitTemplates(ui->comboBoxSheetTemplates); + VAbstractLayoutDialog::InitTemplates(ui->comboBoxTileTemplates); + MinimumSheetPaperSize(); + MinimumTilePaperSize(); + + ReadSettings(); + + connect(ui->comboBoxLayoutUnit, QOverload::of(&QComboBox::currentIndexChanged), + this, &PuzzlePreferencesLayoutPage::ConvertPaperSize); + + connect(ui->comboBoxSheetTemplates, QOverload::of(&QComboBox::currentIndexChanged), + this, [this]{SheetSize(SheetTemplate());}); + connect(ui->comboBoxTileTemplates, QOverload::of(&QComboBox::currentIndexChanged), + this, [this]{TileSize(TileTemplate());}); + + connect(ui->doubleSpinBoxSheetPaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::SheetPaperSizeChanged); + connect(ui->doubleSpinBoxSheetPaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::SheetPaperSizeChanged); + connect(ui->doubleSpinBoxTilePaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::TilePaperSizeChanged); + connect(ui->doubleSpinBoxTilePaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::TilePaperSizeChanged); + + connect(ui->doubleSpinBoxSheetPaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::FindSheetTemplate); + connect(ui->doubleSpinBoxSheetPaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::FindSheetTemplate); + connect(ui->doubleSpinBoxTilePaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::FindTileTemplate); + connect(ui->doubleSpinBoxTilePaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::FindTileTemplate); + + connect(ui->doubleSpinBoxSheetPaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins); + connect(ui->doubleSpinBoxSheetPaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins); + connect(ui->doubleSpinBoxTilePaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins); + connect(ui->doubleSpinBoxTilePaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins); + + connect(ui->checkBoxLayoutIgnoreFileds, &QCheckBox::stateChanged, this, + &PuzzlePreferencesLayoutPage::LayoutSheetIgnoreMargins); + connect(ui->checkBoxTileIgnoreFileds, &QCheckBox::stateChanged, this, + &PuzzlePreferencesLayoutPage::LayoutTileIgnoreMargins); + + connect(ui->toolButtonSheetPortraitOritation, &QToolButton::toggled, this, + &PuzzlePreferencesLayoutPage::SwapSheetOrientation); + connect(ui->toolButtonSheetLandscapeOrientation, &QToolButton::toggled, this, + &PuzzlePreferencesLayoutPage::SwapSheetOrientation); + connect(ui->toolButtonTilePortraitOrientation, &QToolButton::toggled, this, + &PuzzlePreferencesLayoutPage::SwapTileOrientation); + connect(ui->toolButtonTileLandscapeOrientation, &QToolButton::toggled, this, + &PuzzlePreferencesLayoutPage::SwapTileOrientation); +} + +//--------------------------------------------------------------------------------------------------------------------- +PuzzlePreferencesLayoutPage::~PuzzlePreferencesLayoutPage() +{ + delete ui; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PuzzlePreferencesLayoutPage::Apply() -> QStringList +{ + QStringList preferences; + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + + settings->SetLayoutUnit(LayoutUnit()); + + settings->SetLayoutSheetPaperHeight( + UnitConvertor(ui->doubleSpinBoxSheetPaperHeight->value(), m_oldLayoutUnit, Unit::Px)); + settings->SetLayoutSheetPaperWidth( + UnitConvertor(ui->doubleSpinBoxSheetPaperWidth->value(), m_oldLayoutUnit, Unit::Px)); + + settings->SetLayoutSheetIgnoreMargins(ui->checkBoxLayoutIgnoreFileds->isChecked()); + settings->SetLayoutSheetMargins(GetSheetMargins()); + + settings->SetLayoutTileShowTiles(ui->checkBoxTileShowTiles->isChecked()); + + settings->SetLayoutTilePaperHeight( + UnitConvertor(ui->doubleSpinBoxTilePaperHeight->value(), m_oldLayoutUnit, Unit::Px)); + settings->SetLayoutTilePaperWidth( + UnitConvertor(ui->doubleSpinBoxTilePaperWidth->value(), m_oldLayoutUnit, Unit::Px)); + + settings->SetLayoutTileIgnoreMargins(ui->checkBoxTileIgnoreFileds->isChecked()); + settings->SetLayoutTileMargins(GetTileMargins()); + + settings->SetLayoutPieceGap(UnitConvertor(ui->doubleSpinBoxPiecesGap->value(), m_oldLayoutUnit, Unit::Px)); + + settings->SetLayoutWarningPiecesSuperposition(ui->checkBoxWarningPiecesSuperposition->isChecked()); + settings->SetLayoutStickyEdges(ui->checkBoxStickyEdges->isChecked()); + settings->SetLayoutWarningPiecesOutOfBound(ui->checkBoxWarningPiecesOutOfBound->isChecked()); + settings->SetLayoutFollowGrainline(ui->checkBoxFollowGrainline->isChecked()); + + preferences.append(tr("default layout settings")); + return preferences; +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) + { + // retranslate designer form (single inheritance approach) + ui->retranslateUi(this); + } + // remember to call base class implementation + QWidget::changeEvent(event); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::ConvertPaperSize() +{ + const Unit layoutUnit = LayoutUnit(); + + const qreal sheetWidth = ui->doubleSpinBoxSheetPaperWidth->value(); + const qreal sheetHeight = ui->doubleSpinBoxSheetPaperHeight->value(); + + const qreal sheetLeftMargin = ui->doubleSpinBoxSheetMarginLeft->value(); + const qreal sheetRightMargin = ui->doubleSpinBoxSheetMarginRight->value(); + const qreal sheetTopMargin = ui->doubleSpinBoxSheetMarginTop->value(); + const qreal sheetBottomMargin = ui->doubleSpinBoxSheetMarginBottom->value(); + + ui->doubleSpinBoxSheetPaperWidth->blockSignals(true); + ui->doubleSpinBoxSheetPaperHeight->blockSignals(true); + ui->doubleSpinBoxSheetPaperWidth->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit)); + ui->doubleSpinBoxSheetPaperHeight->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit)); + ui->doubleSpinBoxSheetPaperWidth->blockSignals(false); + ui->doubleSpinBoxSheetPaperHeight->blockSignals(false); + + const qreal newSheetWidth = UnitConvertor(sheetWidth, m_oldLayoutUnit, layoutUnit); + const qreal newSheetHeight = UnitConvertor(sheetHeight, m_oldLayoutUnit, layoutUnit); + + const qreal newSheetLeftMargin = UnitConvertor(sheetLeftMargin, m_oldLayoutUnit, layoutUnit); + const qreal newSheetRightMargin = UnitConvertor(sheetRightMargin, m_oldLayoutUnit, layoutUnit); + const qreal newSheetTopMargin = UnitConvertor(sheetTopMargin, m_oldLayoutUnit, layoutUnit); + const qreal newSheetBottomMargin = UnitConvertor(sheetBottomMargin, m_oldLayoutUnit, layoutUnit); + + const qreal tileWidth = ui->doubleSpinBoxTilePaperWidth->value(); + const qreal tileHeight = ui->doubleSpinBoxTilePaperHeight->value(); + + const qreal tileLeftMargin = ui->doubleSpinBoxTileMarginLeft->value(); + const qreal tileRightMargin = ui->doubleSpinBoxTileMarginRight->value(); + const qreal tileTopMargin = ui->doubleSpinBoxTileMarginTop->value(); + const qreal tileBottomMargin = ui->doubleSpinBoxTileMarginBottom->value(); + + ui->doubleSpinBoxTilePaperWidth->blockSignals(true); + ui->doubleSpinBoxTilePaperHeight->blockSignals(true); + ui->doubleSpinBoxTilePaperWidth->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit)); + ui->doubleSpinBoxTilePaperHeight->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit)); + ui->doubleSpinBoxTilePaperWidth->blockSignals(false); + ui->doubleSpinBoxTilePaperHeight->blockSignals(false); + + const qreal newTileWidth = UnitConvertor(tileWidth, m_oldLayoutUnit, layoutUnit); + const qreal newTileHeight = UnitConvertor(tileHeight, m_oldLayoutUnit, layoutUnit); + + const qreal newTileLeftMargin = UnitConvertor(tileLeftMargin, m_oldLayoutUnit, layoutUnit); + const qreal newTileRightMargin = UnitConvertor(tileRightMargin, m_oldLayoutUnit, layoutUnit); + const qreal newTileTopMargin = UnitConvertor(tileTopMargin, m_oldLayoutUnit, layoutUnit); + const qreal newTileBottomMargin = UnitConvertor(tileBottomMargin, m_oldLayoutUnit, layoutUnit); + + qreal newGap = UnitConvertor(ui->doubleSpinBoxPiecesGap->value(), m_oldLayoutUnit, layoutUnit); + + m_oldLayoutUnit = layoutUnit; + CorrectPaperDecimals(); + MinimumSheetPaperSize(); + MinimumTilePaperSize(); + + ui->doubleSpinBoxSheetPaperWidth->setValue(newSheetWidth); + ui->doubleSpinBoxSheetPaperHeight->setValue(newSheetHeight); + + ui->doubleSpinBoxSheetMarginLeft->setValue(newSheetLeftMargin); + ui->doubleSpinBoxSheetMarginRight->setValue(newSheetRightMargin); + ui->doubleSpinBoxSheetMarginTop->setValue(newSheetTopMargin); + ui->doubleSpinBoxSheetMarginBottom->setValue(newSheetBottomMargin); + + ui->doubleSpinBoxTilePaperWidth->setValue(newTileWidth); + ui->doubleSpinBoxTilePaperHeight->setValue(newTileHeight); + + ui->doubleSpinBoxTileMarginLeft->setValue(newTileLeftMargin); + ui->doubleSpinBoxTileMarginRight->setValue(newTileRightMargin); + ui->doubleSpinBoxTileMarginTop->setValue(newTileTopMargin); + ui->doubleSpinBoxTileMarginBottom->setValue(newTileBottomMargin); + + ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(50, Unit::Cm, layoutUnit)); + ui->doubleSpinBoxPiecesGap->setValue(newGap); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::LayoutSheetIgnoreMargins(int state) +{ + ui->doubleSpinBoxSheetMarginLeft->setDisabled(state != 0); + ui->doubleSpinBoxSheetMarginRight->setDisabled(state != 0); + ui->doubleSpinBoxSheetMarginTop->setDisabled(state != 0); + ui->doubleSpinBoxSheetMarginBottom->setDisabled(state != 0); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::LayoutTileIgnoreMargins(int state) +{ + ui->doubleSpinBoxTileMarginLeft->setDisabled(state != 0); + ui->doubleSpinBoxTileMarginRight->setDisabled(state != 0); + ui->doubleSpinBoxTileMarginTop->setDisabled(state != 0); + ui->doubleSpinBoxTileMarginBottom->setDisabled(state != 0); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::FindSheetTemplate() +{ + const qreal width = ui->doubleSpinBoxSheetPaperWidth->value(); + const qreal height = ui->doubleSpinBoxSheetPaperHeight->value(); + FindTemplate(ui->comboBoxSheetTemplates, width, height); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::FindTileTemplate() +{ + const qreal width = ui->doubleSpinBoxTilePaperWidth->value(); + const qreal height = ui->doubleSpinBoxTilePaperHeight->value(); + FindTemplate(ui->comboBoxTileTemplates, width, height); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::CorrectMaxMargins() +{ + const qreal sheetWidth = ui->doubleSpinBoxSheetPaperWidth->value(); + const qreal sheetHeight = ui->doubleSpinBoxSheetPaperHeight->value(); + + // 80%/2 of paper size for each field + const qreal sheetWidthMargin = (sheetWidth*80.0/100.0)/2.0; + const qreal sheetHeightMargin = (sheetHeight*80.0/100.0)/2.0; + + ui->doubleSpinBoxSheetMarginLeft->setMaximum(sheetWidthMargin); + ui->doubleSpinBoxSheetMarginRight->setMaximum(sheetWidthMargin); + ui->doubleSpinBoxSheetMarginTop->setMaximum(sheetHeightMargin); + ui->doubleSpinBoxSheetMarginBottom->setMaximum(sheetHeightMargin); + + const qreal tileWidth = ui->doubleSpinBoxTilePaperWidth->value(); + const qreal tileHeight = ui->doubleSpinBoxTilePaperHeight->value(); + + // 80%/2 of paper size for each field + const qreal tileWidthMargin = (tileWidth*80.0/100.0)/2.0; + const qreal tileHeightMargin = (tileHeight*80.0/100.0)/2.0; + + ui->doubleSpinBoxTileMarginLeft->setMaximum(tileWidthMargin); + ui->doubleSpinBoxTileMarginRight->setMaximum(tileWidthMargin); + ui->doubleSpinBoxTileMarginTop->setMaximum(tileHeightMargin); + ui->doubleSpinBoxTileMarginBottom->setMaximum(tileHeightMargin); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SwapSheetOrientation(bool checked) +{ + if (checked) + { + const qreal width = ui->doubleSpinBoxSheetPaperWidth->value(); + const qreal height = ui->doubleSpinBoxSheetPaperHeight->value(); + + ui->doubleSpinBoxSheetPaperWidth->blockSignals(true); + ui->doubleSpinBoxSheetPaperWidth->setValue(height); + ui->doubleSpinBoxSheetPaperWidth->blockSignals(false); + + ui->doubleSpinBoxSheetPaperHeight->blockSignals(true); + ui->doubleSpinBoxSheetPaperHeight->setValue(width); + ui->doubleSpinBoxSheetPaperHeight->blockSignals(false); + + SheetPaperSizeChanged(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SwapTileOrientation(bool checked) +{ + if (checked) + { + const qreal width = ui->doubleSpinBoxTilePaperWidth->value(); + const qreal height = ui->doubleSpinBoxTilePaperHeight->value(); + + ui->doubleSpinBoxTilePaperWidth->blockSignals(true); + ui->doubleSpinBoxTilePaperWidth->setValue(height); + ui->doubleSpinBoxTilePaperWidth->blockSignals(false); + + ui->doubleSpinBoxTilePaperHeight->blockSignals(true); + ui->doubleSpinBoxTilePaperHeight->setValue(width); + ui->doubleSpinBoxTilePaperHeight->blockSignals(false); + + TilePaperSizeChanged(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::InitLayoutUnits() +{ + ui->comboBoxLayoutUnit->addItem(tr("Millimiters"), QVariant(UnitsToStr(Unit::Mm))); + ui->comboBoxLayoutUnit->addItem(tr("Centimeters"), QVariant(UnitsToStr(Unit::Cm))); + ui->comboBoxLayoutUnit->addItem(tr("Inches"), QVariant(UnitsToStr(Unit::Inch))); + ui->comboBoxLayoutUnit->addItem(tr("Pixels"), QVariant(UnitsToStr(Unit::Px))); + + // set default unit + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + m_oldLayoutUnit = StrToUnits(settings->GetUnit()); + const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(settings->GetUnit()); + if (indexUnit != -1) + { + ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QSizeF PuzzlePreferencesLayoutPage::Template(VAbstractLayoutDialog::PaperSizeTemplate t) const +{ + const Unit layoutUnit = LayoutUnit(); + + switch (t) + { + case VAbstractLayoutDialog::PaperSizeTemplate::A0: + case VAbstractLayoutDialog::PaperSizeTemplate::A1: + case VAbstractLayoutDialog::PaperSizeTemplate::A2: + case VAbstractLayoutDialog::PaperSizeTemplate::A3: + case VAbstractLayoutDialog::PaperSizeTemplate::A4: + case VAbstractLayoutDialog::PaperSizeTemplate::Letter: + case VAbstractLayoutDialog::PaperSizeTemplate::Legal: + case VAbstractLayoutDialog::PaperSizeTemplate::Tabloid: + return VAbstractLayoutDialog::GetTemplateSize(t, layoutUnit); + case VAbstractLayoutDialog::PaperSizeTemplate::Roll24in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll30in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll36in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll42in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll44in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll48in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll62in: + case VAbstractLayoutDialog::PaperSizeTemplate::Roll72in: + return VAbstractLayoutDialog::GetTemplateSize(t, layoutUnit); + case VAbstractLayoutDialog::PaperSizeTemplate::Custom: + return VAbstractLayoutDialog::GetTemplateSize(t, layoutUnit); + default: + break; + } + return QSizeF(); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PuzzlePreferencesLayoutPage::SheetTemplate() const -> QSizeF +{ + auto t = static_cast(ui->comboBoxSheetTemplates->currentData().toInt()); + return Template(t); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PuzzlePreferencesLayoutPage::TileTemplate() const -> QSizeF +{ + auto t = static_cast(ui->comboBoxTileTemplates->currentData().toInt()); + return Template(t); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::MinimumSheetPaperSize() +{ + const qreal value = UnitConvertor(1, Unit::Px, m_oldLayoutUnit); + ui->doubleSpinBoxSheetPaperWidth->setMinimum(value); + ui->doubleSpinBoxSheetPaperHeight->setMinimum(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::MinimumTilePaperSize() +{ + const qreal value = UnitConvertor(1, Unit::Px, m_oldLayoutUnit); + ui->doubleSpinBoxTilePaperWidth->setMinimum(value); + ui->doubleSpinBoxTilePaperHeight->setMinimum(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PuzzlePreferencesLayoutPage::LayoutUnit() const -> Unit +{ + return StrToUnits(ui->comboBoxLayoutUnit->currentData().toString()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SetLayoutUnit(Unit unit) +{ + const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(UnitsToStr(unit)); + if (indexUnit != -1) + { + ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SheetSize(const QSizeF &size) +{ + m_oldLayoutUnit = LayoutUnit(); + ui->doubleSpinBoxSheetPaperWidth->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit)); + ui->doubleSpinBoxSheetPaperHeight->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit)); + + ui->doubleSpinBoxSheetPaperWidth->setValue(size.width()); + ui->doubleSpinBoxSheetPaperHeight->setValue(size.height()); + + CorrectPaperDecimals(); + SheetPaperSizeChanged(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::TileSize(const QSizeF &size) +{ + m_oldLayoutUnit = LayoutUnit(); + ui->doubleSpinBoxTilePaperWidth->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit)); + ui->doubleSpinBoxTilePaperHeight->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit)); + + ui->doubleSpinBoxTilePaperWidth->setValue(size.width()); + ui->doubleSpinBoxTilePaperHeight->setValue(size.height()); + + CorrectPaperDecimals(); + TilePaperSizeChanged(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::CorrectPaperDecimals() +{ + switch (m_oldLayoutUnit) + { + case Unit::Cm: + case Unit::Mm: + case Unit::Px: + ui->doubleSpinBoxSheetPaperWidth->setDecimals(2); + ui->doubleSpinBoxSheetPaperHeight->setDecimals(2); + + ui->doubleSpinBoxTilePaperWidth->setDecimals(2); + ui->doubleSpinBoxTilePaperHeight->setDecimals(2); + + ui->doubleSpinBoxSheetMarginLeft->setDecimals(4); + ui->doubleSpinBoxSheetMarginRight->setDecimals(4); + ui->doubleSpinBoxSheetMarginTop->setDecimals(4); + ui->doubleSpinBoxSheetMarginBottom->setDecimals(4); + + ui->doubleSpinBoxTileMarginLeft->setDecimals(4); + ui->doubleSpinBoxTileMarginRight->setDecimals(4); + ui->doubleSpinBoxTileMarginTop->setDecimals(4); + ui->doubleSpinBoxTileMarginBottom->setDecimals(4); + + ui->doubleSpinBoxPiecesGap->setDecimals(2); + break; + case Unit::Inch: + ui->doubleSpinBoxSheetPaperWidth->setDecimals(5); + ui->doubleSpinBoxSheetPaperHeight->setDecimals(5); + + ui->doubleSpinBoxTilePaperWidth->setDecimals(5); + ui->doubleSpinBoxTilePaperHeight->setDecimals(5); + + ui->doubleSpinBoxSheetMarginLeft->setDecimals(5); + ui->doubleSpinBoxSheetMarginRight->setDecimals(5); + ui->doubleSpinBoxSheetMarginTop->setDecimals(5); + ui->doubleSpinBoxSheetMarginBottom->setDecimals(5); + + ui->doubleSpinBoxTileMarginLeft->setDecimals(5); + ui->doubleSpinBoxTileMarginRight->setDecimals(5); + ui->doubleSpinBoxTileMarginTop->setDecimals(5); + ui->doubleSpinBoxTileMarginBottom->setDecimals(5); + + ui->doubleSpinBoxPiecesGap->setDecimals(5); + break; + default: + break; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SheetPaperSizeChanged() +{ + bool portrait = ui->doubleSpinBoxSheetPaperHeight->value() > ui->doubleSpinBoxSheetPaperWidth->value(); + + ui->toolButtonSheetPortraitOritation->blockSignals(true); + ui->toolButtonSheetPortraitOritation->setChecked(portrait); + ui->toolButtonSheetPortraitOritation->blockSignals(false); + + ui->toolButtonSheetLandscapeOrientation->blockSignals(true); + ui->toolButtonSheetLandscapeOrientation->setChecked(not portrait); + ui->toolButtonSheetLandscapeOrientation->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::TilePaperSizeChanged() +{ + bool portrait = ui->doubleSpinBoxTilePaperHeight->value() > ui->doubleSpinBoxTilePaperWidth->value(); + + ui->toolButtonTilePortraitOrientation->blockSignals(true); + ui->toolButtonTilePortraitOrientation->setChecked(portrait); + ui->toolButtonTilePortraitOrientation->blockSignals(false); + + ui->toolButtonTileLandscapeOrientation->blockSignals(true); + ui->toolButtonTileLandscapeOrientation->setChecked(not portrait); + ui->toolButtonTileLandscapeOrientation->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PuzzlePreferencesLayoutPage::GetSheetMargins() const -> QMarginsF +{ + QMarginsF fields; + fields.setLeft(UnitConvertor(ui->doubleSpinBoxSheetMarginLeft->value(), m_oldLayoutUnit, Unit::Px)); + fields.setRight(UnitConvertor(ui->doubleSpinBoxSheetMarginRight->value(), m_oldLayoutUnit, Unit::Px)); + fields.setTop(UnitConvertor(ui->doubleSpinBoxSheetMarginTop->value(), m_oldLayoutUnit, Unit::Px)); + fields.setBottom(UnitConvertor(ui->doubleSpinBoxSheetMarginBottom->value(), m_oldLayoutUnit, Unit::Px)); + return fields; +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SetSheetMargins(const QMarginsF &value) +{ + ui->doubleSpinBoxSheetMarginLeft->setValue(UnitConvertor(value.left(), Unit::Px, LayoutUnit())); + ui->doubleSpinBoxSheetMarginRight->setValue(UnitConvertor(value.right(), Unit::Px, LayoutUnit())); + ui->doubleSpinBoxSheetMarginTop->setValue(UnitConvertor(value.top(), Unit::Px, LayoutUnit())); + ui->doubleSpinBoxSheetMarginBottom->setValue(UnitConvertor(value.bottom(), Unit::Px, LayoutUnit())); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PuzzlePreferencesLayoutPage::GetTileMargins() const -> QMarginsF +{ + QMarginsF fields; + fields.setLeft(UnitConvertor(ui->doubleSpinBoxTileMarginLeft->value(), m_oldLayoutUnit, Unit::Px)); + fields.setRight(UnitConvertor(ui->doubleSpinBoxTileMarginRight->value(), m_oldLayoutUnit, Unit::Px)); + fields.setTop(UnitConvertor(ui->doubleSpinBoxTileMarginTop->value(), m_oldLayoutUnit, Unit::Px)); + fields.setBottom(UnitConvertor(ui->doubleSpinBoxTileMarginBottom->value(), m_oldLayoutUnit, Unit::Px)); + return fields; +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SetTileMargins(const QMarginsF &value) +{ + ui->doubleSpinBoxTileMarginLeft->setValue(UnitConvertor(value.left(), Unit::Px, LayoutUnit())); + ui->doubleSpinBoxTileMarginRight->setValue(UnitConvertor(value.right(), Unit::Px, LayoutUnit())); + ui->doubleSpinBoxTileMarginTop->setValue(UnitConvertor(value.top(), Unit::Px, LayoutUnit())); + ui->doubleSpinBoxTileMarginBottom->setValue(UnitConvertor(value.bottom(), Unit::Px, LayoutUnit())); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::SetPieceGap(qreal gap) +{ + qreal value = UnitConvertor(gap, Unit::Px, LayoutUnit()); + ui->doubleSpinBoxPiecesGap->setValue(value); + CorrectPaperDecimals(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::ReadSettings() +{ + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + + SetLayoutUnit(settings->LayoutUnit()); + m_oldLayoutUnit = LayoutUnit(); + + const qreal sheetWidth = UnitConvertor(settings->GetLayoutSheetPaperWidth(), Unit::Px, LayoutUnit()); + const qreal sheetHeight = UnitConvertor(settings->GetLayoutSheetPaperHeight(), Unit::Px, LayoutUnit()); + SheetSize(QSizeF(sheetWidth, sheetHeight)); + + ui->checkBoxLayoutIgnoreFileds->setChecked(settings->GetLayoutSheetIgnoreMargins()); + SetSheetMargins(settings->GetLayoutSheetMargins()); + + const qreal tileWidth = UnitConvertor(settings->GetLayoutTilePaperWidth(), Unit::Px, LayoutUnit()); + const qreal tileHeight = UnitConvertor(settings->GetLayoutTilePaperHeight(), Unit::Px, LayoutUnit()); + TileSize(QSizeF(tileWidth, tileHeight)); + + ui->checkBoxTileShowTiles->setChecked(settings->GetLayoutTileShowTiles()); + ui->checkBoxTileIgnoreFileds->setChecked(settings->GetLayoutTileIgnoreMargins()); + SetTileMargins(settings->GetLayoutSheetMargins()); + + ui->checkBoxWarningPiecesSuperposition->setChecked(settings->GetLayoutWarningPiecesSuperposition()); + ui->checkBoxStickyEdges->setChecked(settings->GetLayoutStickyEdges()); + ui->checkBoxWarningPiecesOutOfBound->setChecked(settings->GetLayoutWarningPiecesOutOfBound()); + ui->checkBoxFollowGrainline->setChecked(settings->GetLayoutFollowGrainline()); + + ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(50, Unit::Cm, LayoutUnit())); + SetPieceGap(settings->GetLayoutPieceGap()); + + FindSheetTemplate(); + FindTileTemplate(); + + SheetPaperSizeChanged(); + TilePaperSizeChanged(); + + LayoutSheetIgnoreMargins(static_cast(ui->checkBoxLayoutIgnoreFileds->isChecked())); + LayoutTileIgnoreMargins(static_cast(ui->checkBoxTileIgnoreFileds->isChecked())); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesLayoutPage::FindTemplate(QComboBox *box, qreal width, qreal height) +{ + SCASSERT(box != nullptr) + const Unit paperUnit = LayoutUnit(); + + const int max = static_cast(VAbstractLayoutDialog::PaperSizeTemplate::Custom); + for (int i=0; i < max; ++i) + { + const QSizeF tmplSize = VAbstractLayoutDialog::GetTemplateSize( + static_cast(i), paperUnit); + if (QSizeF(width, height) == tmplSize || QSizeF(height, width) == tmplSize) + { + box->blockSignals(true); + const int index = ui->comboBoxTileTemplates->findData(i); + if (index != -1) + { + box->setCurrentIndex(index); + } + box->blockSignals(false); + return; + } + } + + box->blockSignals(true); + const int index = box->findData(max); + if (index != -1) + { + box->setCurrentIndex(index); + } + box->blockSignals(false); +} diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.h b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.h new file mode 100644 index 000000000..eefc4246b --- /dev/null +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.h @@ -0,0 +1,102 @@ +/************************************************************************ + ** + ** @file puzzlepreferenceslayoutpage.h + ** @author Roman Telezhynskyi + ** @date 20 8, 2021 + ** + ** @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) 2021 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef PUZZLEPREFERENCESLAYOUTPAGE_H +#define PUZZLEPREFERENCESLAYOUTPAGE_H + +#include + +#include "../vmisc/def.h" +#include "../vlayout/dialogs/vabstractlayoutdialog.h" + +namespace Ui +{ + class PuzzlePreferencesLayoutPage; +} + +class PuzzlePreferencesLayoutPage : public QWidget +{ + Q_OBJECT + +public: + explicit PuzzlePreferencesLayoutPage(QWidget *parent = nullptr); + ~PuzzlePreferencesLayoutPage(); + + QStringList Apply(); + +protected: + virtual void changeEvent(QEvent* event) override; + +private slots: + void ConvertPaperSize(); + void LayoutSheetIgnoreMargins(int state); + void LayoutTileIgnoreMargins(int state); + void FindSheetTemplate(); + void FindTileTemplate(); + void CorrectMaxMargins(); + void SwapSheetOrientation(bool checked); + void SwapTileOrientation(bool checked); + +private: + Q_DISABLE_COPY(PuzzlePreferencesLayoutPage) + Ui::PuzzlePreferencesLayoutPage *ui; + Unit m_oldLayoutUnit{Unit::Mm}; + + void InitLayoutUnits(); + + QSizeF Template(VAbstractLayoutDialog::PaperSizeTemplate t) const; + QSizeF SheetTemplate() const; + QSizeF TileTemplate() const; + + void MinimumSheetPaperSize(); + void MinimumTilePaperSize(); + + Unit LayoutUnit() const; + void SetLayoutUnit(Unit unit); + + void SheetSize(const QSizeF &size); + void TileSize(const QSizeF &size); + + void CorrectPaperDecimals(); + + void SheetPaperSizeChanged(); + void TilePaperSizeChanged(); + + QMarginsF GetSheetMargins() const; + void SetSheetMargins(const QMarginsF &value); + + QMarginsF GetTileMargins() const; + void SetTileMargins(const QMarginsF &value); + + void SetPieceGap(qreal gap); + + void ReadSettings(); + + void FindTemplate(QComboBox *box, qreal width, qreal height); +}; + +#endif // PUZZLEPREFERENCESLAYOUTPAGE_H diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui new file mode 100644 index 000000000..02593bac5 --- /dev/null +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui @@ -0,0 +1,653 @@ + + + PuzzlePreferencesLayoutPage + + + + 0 + 0 + 616 + 668 + + + + Form + + + + + + + + Sheet + + + + + + false + + + Format + + + false + + + false + + + false + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + Unit: + + + + + + + + + + + 0 + 0 + + + + Templates: + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + ... + + + + :/icon/16x16/portrait.png:/icon/16x16/portrait.png + + + true + + + true + + + true + + + + + + + ... + + + + :/icon/16x16/landscape.png:/icon/16x16/landscape.png + + + true + + + false + + + true + + + + + + + + + + 0 + 0 + + + + Width: + + + + + + + + 0 + 0 + + + + Height: + + + + + + + + 94 + 0 + + + + 2 + + + 99999.000000000000000 + + + + + + + + 94 + 0 + + + + 2 + + + 99999.990000000005239 + + + + + + + + + + + + Margins + + + + + + + + Right: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0.100000000000000 + + + + + + + Top: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.100000000000000 + + + + + + + 0.100000000000000 + + + + + + + Left: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Bottom: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.100000000000000 + + + + + + + + + + 0 + 0 + + + + Ignore margins + + + + + + + + + + + + + Control + + + + + + Warning superposition of pieces + + + + + + + Warning pieces out of bound + + + + + + + Sticky edges + + + + + + + Follow grainline + + + + + + + + + Pieces gap + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Tiles + + + false + + + false + + + + + + Show Tiles on sheet + + + + + + + false + + + Format + + + false + + + false + + + false + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + + 0 + 0 + + + + Templates: + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + ... + + + + :/icon/16x16/portrait.png:/icon/16x16/portrait.png + + + true + + + true + + + true + + + + + + + ... + + + + :/icon/16x16/landscape.png:/icon/16x16/landscape.png + + + true + + + false + + + true + + + + + + + + + + 0 + 0 + + + + Width: + + + + + + + + 0 + 0 + + + + Height: + + + + + + + + 94 + 0 + + + + 2 + + + 99999.000000000000000 + + + + + + + + 94 + 0 + + + + 2 + + + 99999.990000000005239 + + + + + + + + + + + + Margins + + + + + + + + Right: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0.100000000000000 + + + + + + + Top: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.100000000000000 + + + + + + + 0.100000000000000 + + + + + + + Left: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Bottom: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.100000000000000 + + + + + + + + + + 0 + 0 + + + + Ignore margins + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + diff --git a/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp b/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp index 1691fbab3..deb8c4a5f 100644 --- a/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp +++ b/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp @@ -31,6 +31,7 @@ #include "../vpapplication.h" #include "configpages/puzzlepreferencesconfigurationpage.h" #include "configpages/puzzlepreferencespathpage.h" +#include "configpages/puzzlepreferenceslayoutpage.h" #include #include @@ -41,6 +42,7 @@ DialogPuzzlePreferences::DialogPuzzlePreferences(QWidget *parent) : QDialog(parent), ui(new Ui::DialogPuzzlePreferences), m_configurationPage(new PuzzlePreferencesConfigurationPage), + m_layoutPage(new PuzzlePreferencesLayoutPage), m_pathPage(new PuzzlePreferencesPathPage) { ui->setupUi(this); @@ -60,7 +62,8 @@ DialogPuzzlePreferences::DialogPuzzlePreferences(QWidget *parent) : connect(bApply, &QPushButton::clicked, this, &DialogPuzzlePreferences::Apply); ui->pagesWidget->insertWidget(0, m_configurationPage); - ui->pagesWidget->insertWidget(1, m_pathPage); + ui->pagesWidget->insertWidget(1, m_layoutPage); + ui->pagesWidget->insertWidget(2, m_pathPage); connect(ui->contentsWidget, &QListWidget::currentItemChanged, this, &DialogPuzzlePreferences::PageChanged); ui->pagesWidget->setCurrentIndex(0); @@ -127,6 +130,7 @@ void DialogPuzzlePreferences::Apply() QStringList preferences; preferences += m_configurationPage->Apply(); + preferences += m_layoutPage->Apply(); m_pathPage->Apply(); if (not preferences.isEmpty()) diff --git a/src/app/puzzle/dialogs/dialogpuzzlepreferences.h b/src/app/puzzle/dialogs/dialogpuzzlepreferences.h index 487a558cc..c84390bf1 100644 --- a/src/app/puzzle/dialogs/dialogpuzzlepreferences.h +++ b/src/app/puzzle/dialogs/dialogpuzzlepreferences.h @@ -38,6 +38,7 @@ namespace Ui class PuzzlePreferencesConfigurationPage; class PuzzlePreferencesPathPage; class QListWidgetItem; +class PuzzlePreferencesLayoutPage; class DialogPuzzlePreferences : public QDialog { @@ -65,6 +66,7 @@ private: Ui::DialogPuzzlePreferences *ui; bool m_isInitialized{false}; PuzzlePreferencesConfigurationPage *m_configurationPage; + PuzzlePreferencesLayoutPage *m_layoutPage; PuzzlePreferencesPathPage *m_pathPage; }; diff --git a/src/app/puzzle/dialogs/dialogpuzzlepreferences.ui b/src/app/puzzle/dialogs/dialogpuzzlepreferences.ui index 632f93440..7d3869348 100644 --- a/src/app/puzzle/dialogs/dialogpuzzlepreferences.ui +++ b/src/app/puzzle/dialogs/dialogpuzzlepreferences.ui @@ -53,7 +53,7 @@ QListView::IconMode - 0 + -1 @@ -70,6 +70,18 @@ ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled + + + Layout + + + AlignCenter + + + + :/icon/layout.png:/icon/layout.png + + Paths diff --git a/src/app/puzzle/layout/layoutdef.h b/src/app/puzzle/layout/layoutdef.h index fa3db8f46..d23aac007 100644 --- a/src/app/puzzle/layout/layoutdef.h +++ b/src/app/puzzle/layout/layoutdef.h @@ -29,7 +29,9 @@ #define LAYOUTDEF_H #include -#include + +template class QSharedPointer; +template class QWeakPointer; class VPLayout; using VPLayoutPtr = QSharedPointer; diff --git a/src/app/puzzle/layout/vplayout.cpp b/src/app/puzzle/layout/vplayout.cpp index 165f07fe7..2e574dee1 100644 --- a/src/app/puzzle/layout/vplayout.cpp +++ b/src/app/puzzle/layout/vplayout.cpp @@ -29,6 +29,7 @@ #include "vplayout.h" #include "vppiece.h" #include "vpsheet.h" +#include "../vpapplication.h" #include #include @@ -56,6 +57,32 @@ auto VPLayout::CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr layout->AddSheet(sheet); layout->SetFocusedSheet(sheet); + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + + layout->LayoutSettings().SetUnit(settings->LayoutUnit()); + + layout->LayoutSettings().SetShowTiles(settings->GetLayoutTileShowTiles()); + layout->LayoutSettings().SetTilesSize(QSizeF(settings->GetLayoutTilePaperWidth(), + settings->GetLayoutTilePaperHeight())); + layout->LayoutSettings().SetIgnoreTilesMargins(settings->GetLayoutTileIgnoreMargins()); + layout->LayoutSettings().SetTilesMargins(settings->GetLayoutTileMargins()); + + layout->LayoutSettings().SetIgnoreMargins(settings->GetLayoutSheetIgnoreMargins()); + layout->LayoutSettings().SetSheetMargins(settings->GetLayoutSheetMargins()); + layout->LayoutSettings().SetSheetSize(QSizeF(settings->GetLayoutSheetPaperWidth(), + settings->GetLayoutSheetPaperHeight())); + + layout->LayoutSettings().SetWarningSuperpositionOfPieces(settings->GetLayoutWarningPiecesSuperposition()); + layout->LayoutSettings().SetWarningPiecesOutOfBound(settings->GetLayoutWarningPiecesOutOfBound()); + layout->LayoutSettings().SetFollowGrainline(settings->GetLayoutFollowGrainline()); + layout->LayoutSettings().SetStickyEdges(settings->GetLayoutStickyEdges()); + layout->LayoutSettings().SetPiecesGap(settings->GetLayoutPieceGap()); + + // ----- for test purposes, to be removed------------------ + layout->LayoutSettings().SetTitle(QString("My Test Layout")); + layout->LayoutSettings().SetDescription(QString("Description of my Layout")); + // -------------------------------------------------------- + return layout; } diff --git a/src/app/puzzle/layout/vplayoutsettings.cpp b/src/app/puzzle/layout/vplayoutsettings.cpp index 16b891ddb..619a62c33 100644 --- a/src/app/puzzle/layout/vplayoutsettings.cpp +++ b/src/app/puzzle/layout/vplayoutsettings.cpp @@ -145,16 +145,7 @@ auto VPLayoutSettings::GetTilesSizeConverted() const -> QSizeF //--------------------------------------------------------------------------------------------------------------------- auto VPLayoutSettings::GetTilesOrientation() -> PageOrientation { - return m_tilesOrientation; -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPLayoutSettings::SetTilesOrientation(PageOrientation orientation) -{ - if(orientation != m_tilesOrientation) - { - m_tilesOrientation = orientation; - } + return m_tilesSize.height() >= m_tilesSize.width() ? PageOrientation::Portrait : PageOrientation::Landscape; } //--------------------------------------------------------------------------------------------------------------------- @@ -563,13 +554,13 @@ auto VPLayoutSettings::GetSheetMarginsConverted() const -> QMarginsF } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutSettings::SetFollowGrainline(FollowGrainline state) +void VPLayoutSettings::SetFollowGrainline(bool state) { m_followGrainLine = state; } //--------------------------------------------------------------------------------------------------------------------- -auto VPLayoutSettings::GetFollowGrainline() const -> FollowGrainline +auto VPLayoutSettings::GetFollowGrainline() const -> bool { return m_followGrainLine; } @@ -670,3 +661,27 @@ void VPLayoutSettings::SetGridRowHeightConverted(qreal value) { m_gridRowHeight = UnitConvertor(value, m_unit, Unit::Px); } + +//--------------------------------------------------------------------------------------------------------------------- +auto VPLayoutSettings::IgnoreTilesMargins() const -> bool +{ + return m_ignoreTilesMargins; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPLayoutSettings::SetIgnoreTilesMargins(bool newIgnoreTilesMargins) +{ + m_ignoreTilesMargins = newIgnoreTilesMargins; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPLayoutSettings::IgnoreMargins() const -> bool +{ + return m_ignoreMargins; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPLayoutSettings::SetIgnoreMargins(bool newIgnoreMargins) +{ + m_ignoreMargins = newIgnoreMargins; +} diff --git a/src/app/puzzle/layout/vplayoutsettings.h b/src/app/puzzle/layout/vplayoutsettings.h index bfe0c6f84..4fc95bb22 100644 --- a/src/app/puzzle/layout/vplayoutsettings.h +++ b/src/app/puzzle/layout/vplayoutsettings.h @@ -35,12 +35,6 @@ #include "def.h" -enum class FollowGrainline : qint8 { - No = 0, - Follow90 = 1, - Follow180 = 2 -}; - enum class PaperSizeTemplate : qint8 { A0 = 0, A1, @@ -67,6 +61,8 @@ class VPLayoutSettings public: VPLayoutSettings() = default; + // Layout + /** * @brief SetUnit Sets the unit of the layout to the given unit * @param unit the new unit @@ -79,12 +75,6 @@ public: */ auto GetUnit() const -> Unit; - void SetWarningSuperpositionOfPieces(bool state); - auto GetWarningSuperpositionOfPieces() const -> bool; - - void SetWarningPiecesOutOfBound(bool state); - auto GetWarningPiecesOutOfBound() const -> bool; - /** * @brief SetTitle Sets the title of the layout to the given value * @param title the title of the layout @@ -109,6 +99,55 @@ public: */ auto GetDescription() const -> QString; + void SetStickyEdges(bool state); + auto GetStickyEdges() const -> bool; + + // Piece + + void SetWarningSuperpositionOfPieces(bool state); + auto GetWarningSuperpositionOfPieces() const -> bool; + + void SetWarningPiecesOutOfBound(bool state); + auto GetWarningPiecesOutOfBound() const -> bool; + + /** + * @brief SetFollowGrainline Sets the type of grainline for the pieces to follow + * @param state the type of grainline + */ + void SetFollowGrainline(bool state); + + /** + * @brief GetFollowGrainline Returns if the sheet's pieces follow a grainline or not + * @return wether the pieces follow a grainline and if so, which grainline + */ + auto GetFollowGrainline() const -> bool; + + /** + * @brief SetPiecesGap sets the pieces gap to the given value, the unit has to be in Unit::Px + * @param value pieces gap + */ + void SetPiecesGap(qreal value); + + /** + * @brief SetPiecesGapConverted sets the pieces gap to the given value, the unit has to be in the layout's unit + * @param value pieces gap + */ + void SetPiecesGapConverted(qreal value); + + /** + * @brief GetPiecesGap returns the pieces gap in Unit::Px + * @return the pieces gap in Unit::Px + */ + auto GetPiecesGap() const -> qreal; + + /** + * @brief GetPiecesGapConverted returns the pieces gap in the layout's unit + * @return the pieces gap in the layout's unit + */ + auto GetPiecesGapConverted() const -> qreal; + + // Tiles + /** * @brief SetTilesSize sets the size of the tiles, the values have to be in Unit::Px * @param width tiles width @@ -158,12 +197,6 @@ public: */ auto GetTilesOrientation() -> PageOrientation; - /** - * @brief SetOrientation Sets the orientation of the tiles to the given value - * @param orientation the new tiles orientation - */ - void SetTilesOrientation(PageOrientation orientation); - /** * @brief SetTilesMargins, set the margins of the tiles, the values have to be in Unit::Px * @param left in Unit::Px @@ -260,6 +293,8 @@ public: */ static auto isRollTemplate(PaperSizeTemplate tmpl) -> bool; + // Sheet + /** * @brief SetSheetSize sets the size of the sheet, the values have to be in Unit::Px * @param width sheet width @@ -351,42 +386,6 @@ public: */ auto GetSheetMarginsConverted() const -> QMarginsF; - /** - * @brief SetFollowGrainline Sets the type of grainline for the pieces to follow - * @param state the type of grainline - */ - void SetFollowGrainline(FollowGrainline state); - - /** - * @brief GetFollowGrainline Returns if the sheet's pieces follow a grainline or not - * @return wether the pieces follow a grainline and if so, which grainline - */ - auto GetFollowGrainline() const -> FollowGrainline; - - /** - * @brief SetPiecesGap sets the pieces gap to the given value, the unit has to be in Unit::Px - * @param value pieces gap - */ - void SetPiecesGap(qreal value); - - /** - * @brief SetPiecesGapConverted sets the pieces gap to the given value, the unit has to be in the layout's unit - * @param value pieces gap - */ - void SetPiecesGapConverted(qreal value); - - /** - * @brief GetPiecesGap returns the pieces gap in Unit::Px - * @return the pieces gap in Unit::Px - */ - auto GetPiecesGap() const -> qreal; - - /** - * @brief GetPiecesGapConverted returns the pieces gap in the layout's unit - * @return the pieces gap in the layout's unit - */ - auto GetPiecesGapConverted() const -> qreal; - /** * @brief GetShowGrid Returns true if the placement grid has to be shown on the current sheet * @return true if the placement grid has to be shown on the current sheet @@ -449,8 +448,11 @@ public: */ void SetGridRowHeightConverted(qreal value); - void SetStickyEdges(bool state); - auto GetStickyEdges() const -> bool; + auto IgnoreTilesMargins() const -> bool; + void SetIgnoreTilesMargins(bool newIgnoreTilesMargins); + + auto IgnoreMargins() const -> bool; + void SetIgnoreMargins(bool newIgnoreMargins); private: Unit m_unit{Unit::Cm}; @@ -477,6 +479,8 @@ private: */ QMarginsF m_tilesMargins{}; + bool m_ignoreTilesMargins{false}; + bool m_showTiles{false}; /** @@ -495,8 +499,10 @@ private: */ QMarginsF m_margins{}; + bool m_ignoreMargins{false}; + // control - FollowGrainline m_followGrainLine{FollowGrainline::No}; + bool m_followGrainLine{false}; /** * @brief m_piecesGap the pieces gap in Unit::Px diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri index 2f605734f..d2a4b800d 100644 --- a/src/app/puzzle/puzzle.pri +++ b/src/app/puzzle/puzzle.pri @@ -4,6 +4,7 @@ SOURCES += \ $$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp \ $$PWD/dialogs/configpages/puzzlepreferencespathpage.cpp \ + $$PWD/dialogs/configpages/puzzlepreferenceslayoutpage.cpp \ $$PWD/dialogs/dialogpuzzlepreferences.cpp \ $$PWD/dialogs/vpdialogabout.cpp \ $$PWD/main.cpp \ @@ -43,6 +44,7 @@ SOURCES += \ HEADERS += \ $$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.h \ $$PWD/dialogs/configpages/puzzlepreferencespathpage.h \ + $$PWD/dialogs/configpages/puzzlepreferenceslayoutpage.h \ $$PWD/dialogs/dialogpuzzlepreferences.h \ $$PWD/dialogs/vpdialogabout.h \ $$PWD/layout/layoutdef.h \ @@ -82,6 +84,7 @@ HEADERS += \ FORMS += \ $$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.ui \ $$PWD/dialogs/configpages/puzzlepreferencespathpage.ui \ + $$PWD/dialogs/configpages/puzzlepreferenceslayoutpage.ui \ $$PWD/dialogs/dialogpuzzlepreferences.ui \ $$PWD/dialogs/vpdialogabout.ui \ $$PWD/carousel/vpcarrousel.ui \ diff --git a/src/app/puzzle/vpapplication.cpp b/src/app/puzzle/vpapplication.cpp index ddb7dfdd1..0b349b0c4 100644 --- a/src/app/puzzle/vpapplication.cpp +++ b/src/app/puzzle/vpapplication.cpp @@ -638,6 +638,18 @@ void VPApplication::NewLocalSocketConnection() MainWindow()->activateWindow(); } +//--------------------------------------------------------------------------------------------------------------------- +auto VPApplication::PreferencesDialog() const -> QSharedPointer +{ + return m_preferencesDialog; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPApplication::SetPreferencesDialog(const QSharedPointer &newPreferencesDialog) +{ + m_preferencesDialog = newPreferencesDialog; +} + //--------------------------------------------------------------------------------------------------------------------- void VPApplication::Clean() { diff --git a/src/app/puzzle/vpapplication.h b/src/app/puzzle/vpapplication.h index e66e98003..7cc36ecba 100644 --- a/src/app/puzzle/vpapplication.h +++ b/src/app/puzzle/vpapplication.h @@ -33,10 +33,10 @@ #include "../vmisc/vabstractapplication.h" #include "vpcommandline.h" -#include - +template class QWeakPointer; class VPMainWindow; class QLocalServer; +class DialogPuzzlePreferences; enum class SocketConnection : bool {Client = false, Server = true}; @@ -68,6 +68,10 @@ public: static VPCommandLinePtr CommandLine(); static VPApplication *VApp(); + + auto PreferencesDialog() const -> QSharedPointer; + void SetPreferencesDialog(const QSharedPointer &newPreferencesDialog); + public slots: void ProcessCMD(); @@ -85,6 +89,7 @@ private: Q_DISABLE_COPY(VPApplication) QList > mainWindows{}; QLocalServer *localServer{nullptr}; + QWeakPointer m_preferencesDialog{}; void Clean(); }; diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index 8b437f0dc..b65acc6df 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -78,23 +78,6 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : { ui->setupUi(this); - // ----- for test purposes, to be removed------------------ - m_layout->LayoutSettings().SetUnit(Unit::Cm); - m_layout->LayoutSettings().SetWarningSuperpositionOfPieces(true); - m_layout->LayoutSettings().SetTitle(QString("My Test Layout")); - m_layout->LayoutSettings().SetDescription(QString("Description of my Layout")); - - m_layout->LayoutSettings().SetTilesSizeConverted(21, 29.7); - m_layout->LayoutSettings().SetTilesOrientation(PageOrientation::Portrait); - m_layout->LayoutSettings().SetTilesMarginsConverted(1, 1, 1, 1); - m_layout->LayoutSettings().SetShowTiles(true); - - m_layout->LayoutSettings().SetSheetMarginsConverted(1, 1, 1, 1); - m_layout->LayoutSettings().SetSheetSizeConverted(84.1, 118.9); - m_layout->LayoutSettings().SetPiecesGapConverted(1); - - // -------------------------------------------------------- - // init the tile factory m_tileFactory = new VPTileFactory(m_layout, VPApplication::VApp()->Settings()); m_tileFactory->refreshTileInfos(); @@ -228,6 +211,7 @@ auto VPMainWindow::LoadFile(QString path) -> bool m_carrousel->Refresh(); m_graphicsView->RefreshLayout(); m_graphicsView->RefreshPieces(); + m_tileFactory->refreshTileInfos(); return true; } @@ -940,7 +924,7 @@ void VPMainWindow::ReadSettings() m_graphicsView->SetAntialiasing(settings->GetGraphicalOutput()); // Stack limit -// qApp->getUndoStack()->setUndoLimit(settings->GetUndoCount()); + m_undoStack->setUndoLimit(settings->GetUndoCount()); } else { @@ -1148,6 +1132,14 @@ auto VPMainWindow::IsLayoutReadOnly() const -> bool return not fileWritable; } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ConnectToPreferences(const QSharedPointer &preferences) +{ + // Must be first + connect(preferences.get(), &DialogPuzzlePreferences::UpdateProperties, this, &VPMainWindow::WindowsLocale); + connect(preferences.get(), &DialogPuzzlePreferences::UpdateProperties, this, &VPMainWindow::ToolBarStyles); +} + //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_actionNew_triggered() { @@ -1612,14 +1604,6 @@ void VPMainWindow::on_TilesSizeChanged(bool changedViaSizeCombobox) void VPMainWindow::on_TilesOrientationChanged() { // Updates the orientation - if(ui->radioButtonTilesPortrait->isChecked()) - { - m_layout->LayoutSettings().SetTilesOrientation(PageOrientation::Portrait); - } - else - { - m_layout->LayoutSettings().SetTilesOrientation(PageOrientation::Landscape); - } m_tileFactory->refreshTileInfos(); // TODO Undo / Redo @@ -1909,19 +1893,33 @@ void VPMainWindow::ShowWindow() const void VPMainWindow::on_actionPreferences_triggered() { // Calling constructor of the dialog take some time. Because of this user have time to call the dialog twice. - static QPointer guard;// Prevent any second run - if (guard.isNull()) + QSharedPointer preferences = VPApplication::VApp()->PreferencesDialog(); + if (preferences.isNull()) { + auto CleanAfterDialog = qScopeGuard([&preferences]() + { + preferences.clear(); + }); + QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - auto *preferences = new DialogPuzzlePreferences(this); - // QScopedPointer needs to be sure any exception will never block guard - QScopedPointer dlg(preferences); - guard = preferences; - // Must be first - connect(dlg.data(), &DialogPuzzlePreferences::UpdateProperties, this, &VPMainWindow::WindowsLocale); - connect(dlg.data(), &DialogPuzzlePreferences::UpdateProperties, this, &VPMainWindow::ToolBarStyles); + + preferences.reset(new DialogPuzzlePreferences()); + preferences->setWindowModality(Qt::ApplicationModal); + VPApplication::VApp()->SetPreferencesDialog(preferences); + + const QList windows = VPApplication::VApp()->MainWindows(); + for (auto *window : windows) + { + window->ConnectToPreferences(preferences); + } + QGuiApplication::restoreOverrideCursor(); - dlg->exec(); + + preferences->exec(); + } + else + { + preferences->show(); } } diff --git a/src/app/puzzle/vpmainwindow.h b/src/app/puzzle/vpmainwindow.h index 81d45aa17..227f939e5 100644 --- a/src/app/puzzle/vpmainwindow.h +++ b/src/app/puzzle/vpmainwindow.h @@ -52,6 +52,8 @@ namespace Ui } class QFileSystemWatcher; +template class QSharedPointer; +class DialogPuzzlePreferences; class VPMainWindow : public VAbstractMainWindow { @@ -563,6 +565,8 @@ private: void CreateWindowMenu(QMenu *menu); auto IsLayoutReadOnly() const -> bool; + + void ConnectToPreferences(const QSharedPointer &preferences); }; #endif // VPMAINWINDOW_H diff --git a/src/app/puzzle/vpmainwindow.ui b/src/app/puzzle/vpmainwindow.ui index e0b469fc4..46f18ca67 100644 --- a/src/app/puzzle/vpmainwindow.ui +++ b/src/app/puzzle/vpmainwindow.ui @@ -195,7 +195,7 @@ QTabWidget::Rounded - 1 + 2 @@ -669,7 +669,7 @@ 0 - 0 + -170 342 870 diff --git a/src/app/puzzle/vpsettings.cpp b/src/app/puzzle/vpsettings.cpp index 4d7360762..e93947ccf 100644 --- a/src/app/puzzle/vpsettings.cpp +++ b/src/app/puzzle/vpsettings.cpp @@ -27,31 +27,56 @@ *************************************************************************/ #include "vpsettings.h" +#include + namespace { Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingDockWidgetPropertiesActive, (QLatin1String("dockWidget/properties"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingDockPropertiesContentsActive, (QLatin1String("dockWidget/contents"))) -} +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutUnit, (QLatin1String("layout/unit"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutSheetPaperWidth, (QLatin1String("layout/sheetPaperWidth"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutSheetPaperHeight, (QLatin1String("layout/sheetPaperHeight"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTilePaperWidth, (QLatin1String("layout/tilePaperWidth"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTilePaperHeight, (QLatin1String("layout/tilePaperHeight"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutSheetMargins, (QLatin1String("layout/sheetMargins"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTileMargins, (QLatin1String("layout/tileMargins"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutSheetIgnoreMargins, (QLatin1String("layout/sheetIgnoreMargins"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTileIgnoreMargins, (QLatin1String("layout/tileIgnoreMargins"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTileShowTiles, (QLatin1String("layout/tileShowTiles"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesSuperposition, + (QLatin1String("layout/warningPiecesSuperposition"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutStickyEdges, (QLatin1String("layout/stickyEdges"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesOutOfBound, + (QLatin1String("layout/warningPiecesOutOfBound"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutFollowGrainline, (QLatin1String("layout/followGrainline"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutPieceGap, (QLatin1String("layout/pieceGap"))) +} // namespace + +Q_DECLARE_METATYPE(QMarginsF) //--------------------------------------------------------------------------------------------------------------------- VPSettings::VPSettings(Format format, Scope scope, const QString &organization, const QString &application, QObject *parent) : VCommonSettings(format, scope, organization, application, parent) -{} +{ + qRegisterMetaTypeStreamOperators("QMarginsF"); +} //--------------------------------------------------------------------------------------------------------------------- VPSettings::VPSettings(const QString &fileName, QSettings::Format format, QObject *parent) : VCommonSettings(fileName, format, parent) -{} +{ + qRegisterMetaTypeStreamOperators("QMarginsF"); +} //--------------------------------------------------------------------------------------------------------------------- -bool VPSettings::IsDockWidgetPropertiesActive() const +auto VPSettings::IsDockWidgetPropertiesActive() const -> bool { return value(*settingDockWidgetPropertiesActive, GetDefDockWidgetPropertiesActive()).toBool(); } //--------------------------------------------------------------------------------------------------------------------- -bool VPSettings::GetDefDockWidgetPropertiesActive() +auto VPSettings::GetDefDockWidgetPropertiesActive() -> bool { return true; } @@ -63,13 +88,13 @@ void VPSettings::SetDockWidgetPropertiesActive(bool value) } //--------------------------------------------------------------------------------------------------------------------- -bool VPSettings::IsDockWidgetPropertiesContentsActive() const +auto VPSettings::IsDockWidgetPropertiesContentsActive() const -> bool { return value(*settingDockWidgetPropertiesActive, GetDefDockWidgetPropertiesActive()).toBool(); } //--------------------------------------------------------------------------------------------------------------------- -bool VPSettings::GetDefDockWidgetPropertiesContentsActive() +auto VPSettings::GetDefDockWidgetPropertiesContentsActive() -> bool { return true; } @@ -79,3 +104,182 @@ void VPSettings::SetDockWidgetPropertiesContentsActive(bool value) { setValue(*settingDockPropertiesContentsActive, value); } + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutUnit(Unit unit) +{ + setValue(*settingLayoutUnit, UnitsToStr(unit)); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::LayoutUnit() const -> Unit +{ + return StrToUnits(value(*settingLayoutUnit, QString()).toString()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutSheetPaperWidth(qreal width) +{ + setValue(*settingLayoutSheetPaperWidth, width); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutSheetPaperWidth() const -> qreal +{ + return ValueOrDef(*this, *settingLayoutSheetPaperWidth, UnitConvertor(841/*A0*/, Unit::Mm, Unit::Px)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutSheetPaperHeight(qreal height) +{ + setValue(*settingLayoutSheetPaperHeight, height); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutSheetPaperHeight() const -> qreal +{ + return ValueOrDef(*this, *settingLayoutSheetPaperHeight, UnitConvertor(1189/*A0*/, Unit::Mm, Unit::Px)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutTilePaperWidth(qreal width) +{ + setValue(*settingLayoutTilePaperWidth, width); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutTilePaperWidth() const -> qreal +{ + return ValueOrDef(*this, *settingLayoutTilePaperWidth, UnitConvertor(210/*A4*/, Unit::Mm, Unit::Px)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutTilePaperHeight(qreal height) +{ + setValue(*settingLayoutTilePaperHeight, height); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutTilePaperHeight() const -> qreal +{ + return ValueOrDef(*this, *settingLayoutTilePaperHeight, UnitConvertor(297/*A4*/, Unit::Mm, Unit::Px)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutSheetMargins(const QMarginsF &margins) +{ + setValue(*settingLayoutSheetMargins, QVariant::fromValue(margins)); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutSheetMargins() const -> QMarginsF +{ + return ValueOrDef(*this, *settingLayoutSheetMargins, QMarginsF()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutTileMargins(const QMarginsF &margins) +{ + setValue(*settingLayoutTileMargins, QVariant::fromValue(margins)); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutTileMargins() const -> QMarginsF +{ + return ValueOrDef(*this, *settingLayoutTileMargins, QMarginsF()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutSheetIgnoreMargins(bool value) +{ + setValue(*settingLayoutSheetIgnoreMargins, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutSheetIgnoreMargins() const -> bool +{ + return value(*settingLayoutSheetIgnoreMargins, false).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutTileIgnoreMargins(bool value) +{ + setValue(*settingLayoutTileIgnoreMargins, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutTileIgnoreMargins() const -> bool +{ + return value(*settingLayoutTileIgnoreMargins, false).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutTileShowTiles(bool value) +{ + setValue(*settingLayoutTileShowTiles, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutTileShowTiles() const -> bool +{ + return value(*settingLayoutTileShowTiles, true).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutWarningPiecesSuperposition(bool value) +{ + setValue(*settingLayoutWarningPiecesSuperposition, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutWarningPiecesSuperposition() const -> bool +{ + return value(*settingLayoutWarningPiecesSuperposition, true).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutStickyEdges(bool value) +{ + setValue(*settingLayoutStickyEdges, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutStickyEdges() const -> bool +{ + return value(*settingLayoutStickyEdges, true).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutWarningPiecesOutOfBound(bool value) +{ + setValue(*settingLayoutWarningPiecesOutOfBound, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutWarningPiecesOutOfBound() const -> bool +{ + return value(*settingLayoutWarningPiecesOutOfBound, true).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutFollowGrainline(bool value) +{ + setValue(*settingLayoutFollowGrainline, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutFollowGrainline() const -> bool +{ + return value(*settingLayoutFollowGrainline, false).toBool(); +} + +void VPSettings::SetLayoutPieceGap(qreal value) +{ + setValue(*settingLayoutPieceGap, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSettings::GetLayoutPieceGap() const -> qreal +{ + return ValueOrDef(*this, *settingLayoutPieceGap, UnitConvertor(5, Unit::Mm, Unit::Px)); +} diff --git a/src/app/puzzle/vpsettings.h b/src/app/puzzle/vpsettings.h index 6d822042d..74d26178c 100644 --- a/src/app/puzzle/vpsettings.h +++ b/src/app/puzzle/vpsettings.h @@ -40,14 +40,59 @@ public: QObject *parent = nullptr); VPSettings(const QString &fileName, Format format, QObject *parent = nullptr); - bool IsDockWidgetPropertiesActive() const; - static bool GetDefDockWidgetPropertiesActive(); + auto IsDockWidgetPropertiesActive() const -> bool; + static auto GetDefDockWidgetPropertiesActive() -> bool; void SetDockWidgetPropertiesActive(bool value); - bool IsDockWidgetPropertiesContentsActive() const; - static bool GetDefDockWidgetPropertiesContentsActive(); + auto IsDockWidgetPropertiesContentsActive() const -> bool; + static auto GetDefDockWidgetPropertiesContentsActive() -> bool; void SetDockWidgetPropertiesContentsActive(bool value); + void SetLayoutUnit(Unit unit); + auto LayoutUnit() const -> Unit; + + void SetLayoutSheetPaperWidth(qreal width); + auto GetLayoutSheetPaperWidth() const -> qreal; + + void SetLayoutSheetPaperHeight(qreal height); + auto GetLayoutSheetPaperHeight() const -> qreal; + + void SetLayoutTilePaperWidth(qreal width); + auto GetLayoutTilePaperWidth() const -> qreal; + + void SetLayoutTilePaperHeight(qreal height); + auto GetLayoutTilePaperHeight() const -> qreal; + + void SetLayoutSheetMargins(const QMarginsF &margins); + auto GetLayoutSheetMargins() const -> QMarginsF; + + void SetLayoutTileMargins(const QMarginsF &margins); + auto GetLayoutTileMargins() const -> QMarginsF; + + void SetLayoutSheetIgnoreMargins(bool value); + auto GetLayoutSheetIgnoreMargins() const -> bool; + + void SetLayoutTileIgnoreMargins(bool value); + auto GetLayoutTileIgnoreMargins() const -> bool; + + void SetLayoutTileShowTiles(bool value); + auto GetLayoutTileShowTiles() const -> bool; + + void SetLayoutWarningPiecesSuperposition(bool value); + auto GetLayoutWarningPiecesSuperposition() const -> bool; + + void SetLayoutStickyEdges(bool value); + auto GetLayoutStickyEdges() const -> bool; + + void SetLayoutWarningPiecesOutOfBound(bool value); + auto GetLayoutWarningPiecesOutOfBound() const -> bool; + + void SetLayoutFollowGrainline(bool value); + auto GetLayoutFollowGrainline() const -> bool; + + void SetLayoutPieceGap(qreal value); + auto GetLayoutPieceGap() const -> qreal; + private: Q_DISABLE_COPY(VPSettings) }; diff --git a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp index 364ff0f0a..22737dad9 100644 --- a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp +++ b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp @@ -136,24 +136,24 @@ PreferencesConfigurationPage::PreferencesConfigurationPage(QWidget *parent) ui->checkBoxDontUseNativeDialog->setChecked(settings->IsDontUseNativeDialog()); // Tab Scrolling - ui->spinBoxDuration->setMinimum(VValentinaSettings::scrollingDurationMin); - ui->spinBoxDuration->setMaximum(VValentinaSettings::scrollingDurationMax); + ui->spinBoxDuration->setMinimum(VCommonSettings::scrollingDurationMin); + ui->spinBoxDuration->setMaximum(VCommonSettings::scrollingDurationMax); ui->spinBoxDuration->setValue(settings->GetScrollingDuration()); - ui->spinBoxUpdateInterval->setMinimum(VValentinaSettings::scrollingUpdateIntervalMin); - ui->spinBoxUpdateInterval->setMaximum(VValentinaSettings::scrollingUpdateIntervalMax); + ui->spinBoxUpdateInterval->setMinimum(VCommonSettings::scrollingUpdateIntervalMin); + ui->spinBoxUpdateInterval->setMaximum(VCommonSettings::scrollingUpdateIntervalMax); ui->spinBoxUpdateInterval->setValue(settings->GetScrollingUpdateInterval()); - ui->doubleSpinBoxSensor->setMinimum(VValentinaSettings::sensorMouseScaleMin); - ui->doubleSpinBoxSensor->setMaximum(VValentinaSettings::sensorMouseScaleMax); + ui->doubleSpinBoxSensor->setMinimum(VCommonSettings::sensorMouseScaleMin); + ui->doubleSpinBoxSensor->setMaximum(VCommonSettings::sensorMouseScaleMax); ui->doubleSpinBoxSensor->setValue(settings->GetSensorMouseScale()); - ui->doubleSpinBoxWheel->setMinimum(VValentinaSettings::wheelMouseScaleMin); - ui->doubleSpinBoxWheel->setMaximum(VValentinaSettings::wheelMouseScaleMax); + ui->doubleSpinBoxWheel->setMinimum(VCommonSettings::wheelMouseScaleMin); + ui->doubleSpinBoxWheel->setMaximum(VCommonSettings::wheelMouseScaleMax); ui->doubleSpinBoxWheel->setValue(settings->GetWheelMouseScale()); - ui->doubleSpinBoxAcceleration->setMinimum(VValentinaSettings::scrollingAccelerationMin); - ui->doubleSpinBoxAcceleration->setMaximum(VValentinaSettings::scrollingAccelerationMax); + ui->doubleSpinBoxAcceleration->setMinimum(VCommonSettings::scrollingAccelerationMin); + ui->doubleSpinBoxAcceleration->setMaximum(VCommonSettings::scrollingAccelerationMax); ui->doubleSpinBoxAcceleration->setValue(settings->GetScrollingAcceleration()); } diff --git a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui index 5004dcd15..17f6b00c3 100644 --- a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui +++ b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui @@ -33,9 +33,9 @@ 0 - -189 + 0 624 - 745 + 765 diff --git a/src/libs/vlayout/dialogs/vabstractlayoutdialog.h b/src/libs/vlayout/dialogs/vabstractlayoutdialog.h index 811f9a10a..07323945f 100644 --- a/src/libs/vlayout/dialogs/vabstractlayoutdialog.h +++ b/src/libs/vlayout/dialogs/vabstractlayoutdialog.h @@ -61,6 +61,8 @@ public: static auto GetTemplateSize(PaperSizeTemplate tmpl, Unit unit) -> QSizeF; + static void InitTemplates(QComboBox *comboBoxTemplates); + protected: typedef QStringList FormatsVector; const static FormatsVector pageFormatNames; @@ -68,7 +70,7 @@ protected: static auto RoundTemplateSize(qreal width, qreal height, Unit unit) -> QSizeF; - static void InitTemplates(QComboBox *comboBoxTemplates); + private: Q_DISABLE_COPY(VAbstractLayoutDialog) }; diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h index 816379595..8e7bf8cf4 100644 --- a/src/libs/vmisc/def.h +++ b/src/libs/vmisc/def.h @@ -525,7 +525,7 @@ Q_DECL_RELAXED_CONSTEXPR inline qreal UnitConvertor(qreal value, const Unit &fro case Unit::Cm: return value / 10.0; case Unit::Inch: - return value / 25.4; + return value / 10.0 / 2.54; case Unit::Px: return (value / 25.4) * PrintDPI; default: @@ -551,7 +551,7 @@ Q_DECL_RELAXED_CONSTEXPR inline qreal UnitConvertor(qreal value, const Unit &fro switch (to) { case Unit::Mm: - return value * 25.4; + return value * 2.54 * 10.0; case Unit::Cm: return value * 2.54; case Unit::Inch: diff --git a/src/libs/vmisc/share/resources/icon.qrc b/src/libs/vmisc/share/resources/icon.qrc index 72ed1fe0f..7e62554aa 100644 --- a/src/libs/vmisc/share/resources/icon.qrc +++ b/src/libs/vmisc/share/resources/icon.qrc @@ -93,5 +93,6 @@ icon/24x24/star@2x.png icon/24x24/close.png icon/24x24/close@2x.png + icon/layout.png diff --git a/src/libs/vmisc/share/resources/icon/layout.png b/src/libs/vmisc/share/resources/icon/layout.png new file mode 100644 index 0000000000000000000000000000000000000000..3f4159168b6a6eb07ef0de06b0a0b2083fe35605 GIT binary patch literal 19880 zcmXtA18}5Wu$^RL+u2wf+qR93ZQItywl;RMv9a;S-q^OCy!qd&H&s*L%+#&9x9``t z`}8?o-%lk4Nklk2H~;{EC@m$X0sw%4K7s*YpguE6W!A3&fq$bBT|z?*-TMH_xM;c}Uo zdnBOPesx8kAcTm{1e*bl02L0_9VACg=m^j#z~urX0DA7mq6jzr!1-_g#>i zgT{$rrlY?02YjBP8%l8rXaz&S-oMc7xB*yZz}9i&kkg5Su#AflBf)J^+bq6cD{g!B zp#;5ANdW?x=b*&0&H_A-K0N}SI_TQT7n{9QqQbg9A@48K6|K#Y<)r`m>uXA4*H~n6 z`E`ZARapIj`xa^o`So9`>*|EdjQ`m5h< zDfQW7cjhIPSt>DR3qA^3THKX-9*8?NY|W-C3AyZ$9OT=fJdxYrC|ZbxgX?GMJ&N-M zUfdhnCttFNN0)QoT9-P^AM3V6eN6BvilCS*|0qGs_SThEbtgAF_)cVL3Kkc&Z>+U; zL#{_PNG1>qYaP2IZ7Uvp$#8NV3=!)Rocg#mdo=9Fe;IxBYVM@1Z+0C}^?il?tA>CT zDATbM>hAusb4l0nCJL4P<0Pn>^mB(*LY2p!37XSCynDX(DJ`=PYTI)(RyHBf-W^Vf zkxL))F!Ze_gbHyF`szI@SXkU!UVQsXNc*@(CV{xe0zk@yfdkgW@3Y+uE#%3jGOVSN zj4K$x62W;@*4!grWko4tc^k3wn@-q+Qr`k#*5__0STBPTnuYw;@mvA3CMM(k9r^R& zZU6D2X8B&&&=5yXW@hr|2(A#1Oxs2M-RGpE={VT$>Fu8V2gb-4bqi@31>>1PBj49e z?{x<0noO`!uupt}aWq%S-B~cc$fUV9%&ciP=7ZG)htIR5v|M3lZMe7Pi&<+93{Ol; z#CUbs4zimT2$aCODm~kB9&`!Src9?hf~fIV8+K;!Ereul*bbVTLx6cf`I9Gkr(zvb zR$(kL9G&kyR=0U8YCu2{gtA!IM_cVu2iHku#ZJQjEtCR*%-8RbrmTCg!trAWC-E-s z!0|-}EfspXHkQ}nxqEy!lOzVj2twEns+)a4loH1jAIoi$la@Dm#4N!T4!Z@Pd334v zzjMcxq=Gk8MI^(Vr6Hqv$*^&xd?}gVN<0c~Yv6_mH(uJw#BeYcJoPa9g^@;~;FB*O zeK)gJf7l)WC?VOeSGjZJnz=Nx_+o{HA{8*qNjyt`pNYOEpZ=lTQ&w*p7CsKP4$cQD zMh-{CO&>PVRV}r?N_z|aIBV0uL*O17gx=R0M1k5epz~T-&Y`E^X)(^;SJapNt4Enj zV1d35U(E6vxEZ=Bkz(1(7?}dND*F8cU%dF2SjrUDyX*mY3iBRw0ewd3YX~g0;%8(M zL0ERcQF7KS*&JnPa{05oXa9guFU;CCuSnN9OfztlBv|p&MQrc#>qV^7kHip1=A_xu z+_V@`=qGRt=>SpW0#LXcPauyPn8&0uQEXNsxftYaN#gx99^XXMG12}6SGvUqEqu(u z5}T-RaE5yE2pOjIwF(z#-5iZxmnBi*PS>?nY+lOzTxe8W9P#~}m~BBrO||)oOQG`$ zZpR*1yJpp{rKdZmv{E~MS;pJk<>?=dz}7N4VlLsk*&SXDB{JAFNQy~+0?KR$062_jeu~&gY9+FeXrL|SZ}rRI z%1v6S>a|gwtL;@)9XcU9YZ#G?4fwr#n55m)e_WfqwG!_Zqi`9_5-N2PUw2qtv^$!v znVn0i~L1s@BjBcGf^L)~uzEGf4f>8dLA3J6|;1cAm0?sslUpgfzu~LbLXC>_ZfRV%C z&dWe07|-zy_rOx{ab-OREe**+Bg}UYxR4VF1t%CWXJyoM>)3<)<59YF86nBIQN|Z% zCASr;vAXddN^u23kQ@vr?mc9!i@T2IWd;e_u(w$sOVJIN!`LI@!9phx7st>akC*#S zx>|reQzarJej*m|=%GRetw|`t6>;y7>;TY0bD*gv7i?6bRM44KdPmNJt}NNxjIUu{ zA0}Xvxp&C^cZd}Qu!|eD4eMDIXQDj;x6j5>Y)CtX@^fq9ImKKKv=F16k;X%xMt^^p zXXu@1rCcB#B%OBbx2|L3+j-J%5m?0kRzr7xmN_7rY~ekBZ;!E9pmf*|Pp$fiJToRk zcczEa^d4zR{@-k|og)f6yZ-tV0h7?~V4C55F~)|>*U+x_-{+E(UOwK>m?Lj^<#wNv zDI$5qgts}<8HYokj-`5hq&co-w*mTGSRvH6`&~9C$+N65t#SHjNTB#G zttfLi6y`D08L{k*uL-^uq~4eN?5=Amw6gDmDxUaEB^0%p4Y7^wQfurzCPZY9nJvaf z$R+$#%*3CZUe}rYhTSb;*SWkn&B*=c{EI7;zR#!tuH-O~(2RczA1Ac%#DiHt#s?Q7 zk!U(=ntedx?Y1R@0%Vm~s6W4p=iOo5O<(8Nu2hJk*;;I$xP^i6kS){gpc#C-@65HK z2VpaL8UU75!rmJ1tK&xh5cwObl`6H=^nU8u)ul!Vk%)l{1LAYus`!tz#2f}w)47H@ z)WK)z#ux~DTpnA4_b=9i)N}o=EWN8b<2PQS-*+3S3q-s>_wVVH7p>2B_ijVz1ll6x zQ!&-p7L(IVNvPOe-QXvn$XuY2$T*v!c`Iq1q*O*PONLWLC2r5vTW2^~pBIaC^*Bsp zr(Mh2^B&l<)VI#5%P?z%EF5d1>nXQiKzq+(ImaYnz!Rk0IAWxr0QcMKW`tY1zN1LJ z+W*l_;rt&_ia*uU#k2`4gNagP7}IIZ1z)>8&^&xhPCR$esbTLif}=>= zzHwlRMf*ywFBWi{hQ7CH_H)uA{yAc2rwbUx9{w& zEX|%mQm?%Uf72weh~8r;pr4dBme7<8#wb}`WFqPfkEJM|=n=Ck6=4YbxK9JOiXb?+ z{rp_Yd&ATUVga1^@>r~Qz3mCyPg9a?q26nx9KT!KuN%jSN*bHVil4^n$?tafw2X&IL_!&##k!#@&)@wT;i!P%Azb zbyY6TeJ+ZhS&vwtoW*nQzTO}gH6|CeB3HM-#zHr%?4Udi*2H~Ir~AlbhvdU#&q<_p zIgbD5hHC>rM-J1xqS3Y;sqVYlEsvkxaAX6$bH`VKEnfvfCmRn+2P`N*EgR3Hy#C zpoSVBlTZj<34WnSis?nSWyH#(elJ9EjA5c=I-y6HolS#VPkAybJ*|=x1p=X6JQ9~X z(u)7VV2nSZb5*^wk>?!b3KG-%|0+8$VDAY4Lek!f=GdvmC}ItCW2QPPQmj-)>AGC& z0))}_P#Ukd;f~_qEx_K#>nncc`)zX|XF-ba+z`EV*JDxdt}_>UYFJ>}ynNPja;a`u z#X{?hhUU;WTl_86ZvC}QnXhWy{8zaG1t)FFEy6o>t3f;){5SkFEmgmqSoT!c4!)~9 z*ud&y@nJVKKxhV0Jrj| zoOzmW?;%l|Eeu?i8Xt#MnV{dOo3o9AvyShPK>aN);$IWBBPaIFxm6!_07A@B_f{^2iVxoF)e3D{MF}hd^ZCFt~}`A2tY}I1&C3t zj#+u!-adVbq)(|b2?u-jQ%6nEd_V9pDZP1UfJNY|gDTp0G?yW~fPV7bv(P6@6|VvU zD4`z9^EbW+2UEuNnkzi_dN3SlMFb3e|W>hFqbjC!9W58i$R6y`8kIFccuL&U9} z$R+b+xsU0`TxpH`&gUa-DwxS(fTU%hlv17$LYZeY0`UriSJ- zMP;_riZbsj>+0muG}C?@-*F)a6@q3v-zu0K{i>R#87LficqHRF8x4e^2;VP`AMUxG zIMB8;9s&bQh^`!{@$XNb8T7?(1(04ALMjqgnvTEW|Ld_uw?ov2xAaw@ChQB_FD+$u zaKzO_CLBsw7yBkjP6zR;I z&e7GK#ToGEktX={ZRCkyX!FFNDWlyMFL-R^TqYg;C}>h(t7`tlQ1OChbF(uyejM4* zjfYxpx;UcU$K1mk9U4W&)Js38{fS7Rf}aIOT>eCMg!4BW5HPekWEshG_`tYL6&--j zVFy;WF$UTYwtRaL=Z@pVT!r4ml47&BGBN|dwy1am{l9SsI*!mg5o8%jQr$03*W54S z!>>!pqj7!lZwSGoW+CA&ThA5#({NdxJS#pOS;JFEV#?&bk~~GX(NZiDujD$}kyC)c zp%LVpH$8mYT!k`7M<5ZH0nnQG5p>`TFw8U;KLR5Rd}DsiON1{(4xf6b2|h9KrUgU| zJRS(v6T{sT@khQOGnkHIT+LaGw-WB}rKdR?4p@u|^O>;5=Y@IgBlK>bJ=+q-ZP)~x zM+4;Oar>5s6-_{pt8TOLVgWX9t0C>8?0YZT_iS4hmzRPaUzfQdj8bR0&V_mARaA^gF&{d5u&LQ7l`(O4EvYnEE61573Vg4}&n=bqE3TyR0afkr!&QkE zhD{+=dEh`*8&gf0#xSi{05vPiGkDC`5#TG1F zgTWM^C}R|Tb*(ie!>7!}y!h16kAu4i0AhIY!xa;CY!_#=-i>EaMZp=gDHCgnBPp{x3sWh(pg8)S5!>bw!h96#sIJm;_xk;0Q9T_wcqPBZK)3tHaxSPw6RC+{Jf` z^MhnZZav@Yb5eb;cW&$W*P7H|LlzS{ycnxvv7})GiMfmwoVQe?W4)M+yjYaMWR!kG zF}dmCnNA#&UY3agN|SR=aAsEQenXK4S^$17ofw{M$qJesi{AauKieDKXU!S zzEe!$=(ETL)1f2U7;c}W`T^UD+EDN-xZ=nu0>F@`Ug2VQy^enS^lB5MDf@-@dAbag z3+de^o0iz$9{l@LLVtTwhxdpwA3i~grq~8bGw3#tBvvBrR`LX%TiE-65}@~kl*JbA z7a^J0vK(;|YoLX@!|ua?Pg9mIK@}@Nsd%_2R>n+I7$w8E#$F*&6T;*=q|n0fiOgba zrZb~>wy|EW9na*3Y4F}QveetHFcM_%Z%d{_l4O+m#zaEBQH?EQtZD^lx4h+Qf!`p5 zY_Ys8B%+fT|Y}mQcDB@9i69Sw27V{YL1oZJ!vLS4)-(va$E4E(cw-u3A!=uVoBiek z0&t@KS_Kx3Pfe^HK{cTsUuhI%awwPh>3z3;!FL6Mb`piB2WOT>Igk`C4% zhbOE9O}0ofpyD7+*X7HAJn~Ft2lFm-m|EVLd*xLkODi6c;h93@761ulQxiK1H$9DJ z$|WriKv-Y1H8zzVe{2(7U9^%vY(CW2I&Z4pQ!z#i#eh?O#q9KX1 z@LGR76htzvNk2diC=oJV!Uax5aWVPhG(l|Iep)KOC))D% z+dYPscm#z8C-ljuyWz)U&QR!9WeHr|1v1eO$vnAkn9TMQxKCun7;_GZIBHGDeoeo( zaBD~}A*CwBxTq}2{klS_s05;Y2d}=h1feFoqt2ug*%VY!0lHr=ZqQ`20G2l}#$NggW z`zFHY^cvnIxq)|CQf&G<5CWB%7I~ba)iBeEUqmHJ@o|VOm;!Qqh|@6B4c*usERs~j z8F_-NG@0*>W3oR0$sspz<6!rN9!!1bCwH~N>-N+oDTSHD0T0yQ}ZA6C`{M&Lg{Zk%XHwnGSn{DkV#|4~TCvDfg5}MS{ z)l~4yXACo=h$8a)V9pZKihb+@Zl7T@e4+4tMcy_jsd05I1aSEye%84r;k@_kN=ZvT zvK)_PXZCS-2VaVqbsi=ic~lb?^q9T61tESy_>;hc$6;K> zJImv8o5p0;tdzF!2Xe*Y6b{)Jbri{0jqPZ;18~d9fnXR2=X?oqus|g+J%(;E1vUA!vcATf zYzKlg)Rt*`j+;G^0-Js9|8psSoN_N{-n~mDo#CuU)CGcx;AH$JcgRqZl8?8Bd z#m|`rr`SvA8gs6Jm70)Msxj8Jlm+xhk*w{|4Syw0u|s+#8snY(qE0dizDDZ41R9V# zi`%R95N7po#G>I^el|}zh6qjK zh{$b?JC@+@fl6dVIz`q5*DTk=5DSvld`k!CF?GgG#-1{~>#XD<>*J=n<{5Lj4798j z-cECDUD&g?QPZzM9Oa;Gn1@n0I%37`w}eWD?Kc&cQV^G$7M7dV(9diqmYBA1EiE=~ z@bK5qQF52nNB+c@h%qr%?p4ahamw534AZb}}a5|w+MUYU>J@0K;HN|1x9UOF2R2-fe5|)!#KW_6q{xH;r z&?hc7H#`+YGx3D@}^3E=VfCpNG0lQ@e1m0hYu#CDc_*g|xP9*)LIZ1{O zdK#BnH%PG@lUGG(I51o!E#HCs@avU}hP%NP6K!S+eVi;AF)`h~Xb~J2^GjFBx>1Mz zVtJ7)waJq84%#s$M>547-)CTg5b+dvRrD~Y2G$a+<4CkrP*@va%g|FG!DbJ{QgmGj zHlvmZN~=9c81;Oh$57`qVKjLhBj)=>^XYa{+_#bYLi&zGf_~RSpafY2I#{#ID99S^ zJh6X-D2_JBMaOxTWi0Z(hZv+esb7x#_Tay4RP2``S6O*t>2< zJXjq6pmdw--}N^}|LavyRZcCAu7x>c`?sMbx||iT$Jd0pQu_T4!`(C+Q}aMrm;C^z z;TH7|iX|C-49-O^jvSV4GiK!lDBrTMB)>f(x69|jJRlSlHvf!RW>{4D;Fg4T#Jr|p zM4d!3#H%OBC|q`2e;?ER7>yO~bQ&1r`FsgEa*{o5UjQX3|Mc}+%oU@7-ydY>`3&&d z!f{H(9xZ!(9q=nlLBBK&>Quad!YO7GX&A+E=DLKZjm>@*)@{a8xVTtba|0p5BcZ4<|BUTzD@XhgT`U<`h4213URI!EXi<8)- z-56QQr5?)aYka7lblFb;YrEie}eIqE%vYtXY4XumEP8)ELR-F3_Uf-=xI z(OL&?+@5U~Dx=d=;u>3?xMA&eq-kJ3N&EA~YW(xKdTZ!JnqxyzZMfjY%0v)lU3%a& z@SAL?WHb;Z=tm!apS-7)riMQUa`!V=np%7b*!%9xp%-DBhI2PM$8vEt5vVGTPEP0DE$jpijfYr5$8B_;(R++vDc;J6u5yXAidcO z?<;#@+(sCPTasshrG$V0R$3VP@Jb$)zQP+FVekr;*&UKy(t59WWvS1(pBkz^EbDBf z(+i`S`pCSmi2^~5i)1!$c+GXKX~@Pd>XnKRaRQ%;`zMjG-XmlerK?8&+}&jBhFN8R zhHkzVQJR7*eJohI!I%a|NOKWvk}puuPM`1rsgJV#*p~nujmvJBC+`AFGR{j zLU&u6O)(zTlaFjUa~ytn%Bc|7E%gL9W}O1t%3Euj&>EsYm+ag3m%eN2UI`3uXIkc) zF@{LBr@vED?!A1vi#_Nh+JsoYg-;=2A>iURy`Ak$Qf?>na$Zk|@P2sx@eu+4g!Y7prTXFq z$rBLUqQu)?9b?9aS(5g<;Y1rjG&Ik`go_bXo=+YQm7GjCAc$x(>iT9Dp@;iEd5Ux_ zi-8=5-vd8D`6jrC455m4PaEu{5Ma==;V*d_8h?%iIQ=&1+h6&rif1;6?R;VAPJPsH+F=+N=0x%}e9m zPHp}l9Ceyd7?Qq!D~?BssU{MH#q(74c3Poz2mK3<2HT!0vXW$$rcC~xrh*ptqUHl4 zfw!g%DMIZmDKr5Qb%bK$%-cugC0aP_J_Pd)S@K`MSHTJUjo0R4+t^F3N|R8dY6D;# z&)4=h>;q;E+dfeb5CpYPHn1;Wal7uIxxBO*E2?gZr#`Zo5tn1{=EOS;6@}$w`c=3R zYLg@QT0J^{xO*}_#lfel3L-lw%K7e*U-SHZ@mD7%6ki96gi73`ctOZuN+C&(V6|P9 zni$*Bo442N629xO%BXyH6q0(NayoxB9_Fwl(ETXTR6UP0kq*l4MZV&PKHz1~UiGLE zIbY3Gp< zIGf*`8@Lv0x4~O1G2(mt|GfZo&rreK^@g?Zgn`U8REIet1mCH?OX5vAmVdH|I*Yb8 zL9h*sb(?;V@|2W9gCqS8o0gc3JNsV|>z7;h)%TmEz0Tz5yJ^)FPm?1+_hIrM-un>> zqT^)9-#KyM%4(EJy5gHg-rLPJA;r^dk4JfQSO*0Sj%*-$sO7cjxivTxWb3~9TZ4S% zGNcRIa8J)zw2#|XI9|@d>dvs~LBD+bcVU6wQM1+OI>)vMJn^<87h#q0SoV9GghDF% zf|D5`W)Y91kQPywE0j7o_qgE2I=q2@yD^*C%c(%6IuiV6hfdmWyC0<=rc7BWRsnn% z$j!xl?8r6&@teL>Jf2x#Fi>P^z7K5M-Zs2%3ebn1O^$9a`gsEDt~St)&+{Ky%ZMbN zubm3#%K@vC?TBiBqejTP-~QOz{l@YTMXZ(4qvw5iiq30oOuCg}+iHC&w!cB>O|W%e zUrqHY3bwxhAlYen0D{M2m<9jAHL%3_oi%4;AciwH2K#PN8=l)zuqp#bENnjVA-8Gr&ca6!NXvz!Y7qA|%(`!fK6o_pLCjb^t!H4e)CIs5V$*(!@Z6xl>)gj94) zcuc#8rGMFFnzwFQ-1A~{)*6Z!P#SL}rqf1o?!ZhXxiyVTd)2Ws82bcArlST}{?AFP zk+@vgld%5RklNiGAQaHsnhX&K7!^rG$VI<`a3X`n$4Jm`z3daD5OsC=kzJjyjX4}Km})y! zBr$)NZli!5yA*2R6~VkB!XiBdX!HEi(DB}~K&t&r8S3?9Aa4G8ZveP7F%TJ$E1N7tXzT?($EvHyp zkub(`l1Wl2(TokA8XSIsY!@roLUJ z6|S=Z1|xw^Lt)nQa1=yers$;_OluyA53STAOw}#{-ETU~XI&c5IgQt*bJi^DdL}k9 z#7=>izi}{l5jM4rJqp7^bIT86%T|7l5T9|wl7U`c%f2QHnAZ3v>} z%BXpTF;G?JL{$)*8;7?!0dgl#JI}*&{v`bMve~hp_li0wm#i4#=jnX!n7ZSG zFyQcq1QTuWo)CAohSDoT+Oy@kxbYU%1eDAd#|wt`CkGZ$)*vnVw(4;+CoLDWd!(fv*Ob zvj;y~A(vn6{@z&Boqw z_SjHmKoW>xz6J@?3LMksV<|Mw{9+IL%2W1=9gNy2{z|XU;MvfG92x5UHn)JmSoRq* z*5jvGST#70ya9Y8rJ{UL;X7HGWq)qT6WjR1&pj;%RS-4DX%7&NIHTm7Xa*AA=6!oX z#4?@$=3V58@Fd*A2dXCFWe-iidIURTH16gE!1v!%qFFU&XZ^ReJ=K{0Fw@7M`MsL! zbYQi4ywn9x;|kCqQNi(CADuiJV=zYdqQes`WgyC{NuYDK_zZxc5TW=ZkWjK^-pNx( zD1@ls>K`Onw_q0Nz%hAieRC;=tUb8mdba8lOkgx(G90B>>D5=A<&OsvavU^P86Gcc zw$gRXMsUHc92DPqZXfi)|20omXCvMAFAM`64uIm9DZ^MAK$D$;YA%ylJ&HTpJP~ya zQW9L1HA))EVR=1gk#>S~ltqGwpsewQ%{ef;U%~|r-Qhz|$WIL4=>Q;sa55yA*8vwo zQqSJiS-~NNMT6t|eW5|K%v6i7!9YiMzI+dWfRtSdwH?OgmxTTHJ=oH4^&_CjB7X<$ z0o`se6$ofM`MX2+HbQUubT2qNyn$m1ouC?-kX5@`a0_@Y@JGLEV(*82c<4>Y3d%^X zTM3iid!9j`TJp|c%~w>h#!B~p;(wLz*t`-bOl<>oQ>IT+m%JxOy!3OH%~2VcY*!Go zTN5e1#1MlR50#G&x`8F+5T9vF^E2ngN};}$D;Ym53r8N5=1>j(ZR^?czttkv8YE=3 zzA0zz$REt#_oKh2z1w$%+# zK|@Iye^KPES6K_=jT8hD4nQ2rDIz(x?=##h_!INrC{6aNkI2k+oVRjl*Plu7A;>I7 zfCimEwH#;Q-iU25CQ05nUS0EcgaA;xD0wGATd)8;3RAlLvc2;y)449;{+k3CucmOx zYZ81P->vZ^dn;%UkJfnbDihfuL~kReZ`-Fm3$u9xKeLu8a*3)1ab&~K(uoWnpmHkU zUc1SLGi44~tqezL2FnxCja>gRJtsaFX`*!*dOFJX58-XBg300h5b|ey$Z^qJ6gDM_ z&vr$Hpi8cu+0=9A-s$eOEd4u-z(L#fhJEoG87!1E>;ZCi$|~;zDt6PcFnJTK^qkr3 z9REGPOU}IGC8Rz>ls2y*Z`1ViCbBT%ACeO^eQZi)G7-WAl|8W<80W$T>(e4dLaDm zb#4pM-C(#Vx$|-4$Cylr*hb-b#cif23M63{Z6s}^ZfCN}*|C{*lX=@LQFVBz+A`d6 zUpcW>)f9t+?sp9!WrEBAHPT3cDff2sn0tO3fIevWiab(MK9QriJmk69@DW6rz@lTV zEjlaG6goT6=t0N&z^(N{iP^N;7bi#;#eF~EZC?9HnufbfW{CkUeQNn|rZl*?S?%?n z{(~##d=~`#2>=WcsjLwKrI**%r?gA6`kHYB!%-4>FyTOIsBaMVkPFj`g&Dk9ar@A{ zdL`Z)UWTmFs&z=Oeu(Yj8IlIUARh1{{D60-W~=`p-V$p*2F_OFd75Z@0d=EP+Qi&s zRQ+o#gLlmj>4iT+|MV)bqV;95PLPdYZS=Q1qjIAMGlP#SY(G>31P)9W7y;xrG6`tG zzMAC}D{~Yc#q);>r4q)B@lrz&574_aHgG+iFaC7Wmnq|UV4;ub4-&#agin=$$3Nzm zA6)ZxSA!aQwcdIti1+!<(FT5RA`hGKKVB9P1YYJT)a(MtPN4*!j{tK)g5YmKIxvP< ziKcOJh#7_NuJ##qBzNS}T#sSj%{2R1KC}_KqaU(4a>F$PYI78Njb?6MsFMeD~v~lh%q4)$!ph z;S&7q6mSUe33349@o2unfX5J3ce0v+lm^_;z<4xf86O6ir3qc*P)@)&%484nXWyG(rqHCo14Rik0Z=51sy7KOhomc;Nqhh4 zw7-nEs-oQXab3tgWV`~m5)UT0KN6&4s$4K%rQz2g*4xCA)+~17$QjkLt*=0xVfWAV z3P*diKN@R%8%y5|Do{pQu(i9BJ~dy3HUIz>f*oggpE5n&D?CzHsFx`aE>5mOq7+{JsEQ z6(rwBQUGTO&J$Rl$}{H-fZFa2Ts|_Gr^L8<&>3;MI1rVRj=K!19UeK0XMT!XW?$1X z*NymHOgES|%Jt+h++&mKo)d@%MTU{`9qE@Ph(-<8-=5{JuKBy#b6QWTsj+8aUQC_D z=8jZqg#D}HdavHZO7n-e*Uy?m>YC1`<&AXyM=(gUMqtPEiz~-+{dqd;iRHDn*b?kJ zz8Ot7QlzK63qABTsbeo^t{k4;XtH3|K+I2NqUR&b<@GO)tAOfn;*?q{((SLpp~W-# zW3vBCHbbwRe$_r7X{iv?BGXkEDtwZb_AOPUd~f}cnjB8NPYhFm3o@h5YYI84OH;*% zH8@=sRij$GqFHPm!&4 z>$^xI2=}pB@*Og#TS`0!sVqva+#sK`HeYK0l&=~NWd0e}yCSd6cyX?1@VvjW#@%xu zxXD%{^kdoqVRbSjvP^tMDaEbVeEp;^iB6-(pI1|t1%+hFb-sZm`Q+TW!6@6i*~mkd z-`L$q$!uT&1wkUl56bwQ6{eycYbCzx*%6ff$p24I7N3!BU|#L4Z)%0=sCoTL&y z{QC5tH*#ZoPC6>*E)w`RSnaD)>q{J?0oD*xbqk2=K6COxbwx)S%3wM^SNPS za{KXt_H->aKP=A09!H|;edu!G@MP5BscgLt&y#KQ<31#jtJ9T}&OnHpJNi_v7JlQN z@EGBJz4-V2gKv{o>#|z@9Csyj= zlr>e!7$ljgabTLv5_j>FaOkZ0F5NHxS*awXN}g+EDra4&aS%A1+zx=H5TyLOY-6Ag zo)Pq>if|0tB?=fFp*W z4v>D^{*75Q=MMl0JMeBsnp|E#u-*1_1w8K+DCa7xwWrcA%@6*&u|2%w zcJe;klh8PDB_)>1z2Ttw>XiKrg@T!3m-l_su?N@&-KJObiyE%$Z8tUs4@!&1Z817Ej7e7S#aJzu#h-co%L03Hvru3zkD|1~}qhxC?4Q>7cck51r z*p2Nd{f>Rb$i`B6mo|QaorY-{Vou!jqBBGhuADhUG9(E%CNn=YGrx|P+2N_i$>N{& z#h@`{8V85O4YWy}w4M9HyuE_VCzglJqmK^7wUZ(`Z(oQ8ca#P7KD1tYkfU=4Rs>pi z=qPBw9pv+gnR_RYju)n2p2a(5DxjcHhx8tWdVv@R23ferly5s5(2-zbW8x~3_=Vx* zn)L~K3R$i6Pk&)2-gZXz5p#F$_}xFBEY7{YU~4F4gCGSw2#lsatgjZV?{j^qhCV>j z@j?F5Neg$tbqLy@thu?s*>CI3cITufm$p>x%_MXoL_$ni$J|EWO6fk%=QgfB{vLgr zt;i2aY(Ni8`(1Lup(vY!Rp!xxLc}lLJp=9sSHFnM(yg$NFM{ATc@;_cv=(y+no31K zk*I!qs`hq$)LWRl&(>Cj?fV_Xf2)2~80%^exP*vVB6RtHHNR6f8I&NBz|&Uu$#s&A z-IHE74@CP|@4M1!zW9(YUjzl-v6_dB8atRE`<@|`!u>yUo1h+>6~>26!<#VlQB^y# zPKs07CSU}^{(XP5x4iyM#Q?Pk1jCZGU50GMfT%}}8o>M$RS9z#TRbQe z8~l(4tpM)}LI|X_ap~Z{AO9FOZA_ZeRaEh5 zoF1Ytf)q|;Ug?yww;P;W#b^%MT3Hp!R?v2gx4mlAph(wq_#k4#Opqc5uf$}5P7fED zrO?jcYl$z_`nhIRW;U)Om>U>8You8^G5L_e%ln?zg+v8a7D8@=PebpP!K+=gYHncz z{IAPn$*}=c&UQoT@4MwMg@2b1QWolbl}a&zP*W$3x^2#nx(THi8%4Z}uz~{1bpg*z zt{qHC+*9vuSc`4;g$B_@B)qmb^Da_^TxrGnLm3@B3F1J8Mo1bOSeox}0i!qsNHIvf zP-XPCJ~)r8RP||BeJe|$mMsaoY#9qdd#GYpyR==n?|=_Vz4-p~kLsmgL{CJSVll)< z5Nh+qbKYVD$Sl6^_q?p0He>#_?hgs-204Lr?UpMo1S4Lj-BW2i+AV&OC58a2filu8 z`V3nQIZ#6bF>&TZTP)?e1Z&dlzPh`f(5QWk0#)I@m@5~Go$Z%jvnWvPo+o~LVMzj+ zUC)D<9T#0ckUT*Wfk_p&%w9)p@BIL_DQ?j~Tzex>RtLR8-U4*YT!fW zQbkTfO%@?4&!W{MGkCa8V#auy}ar!Fk`zXP4Exa8)N9 z1l1cUc}3($o6};=J%&a0w8g^Fg(VK#!vkjG z%>n+`>DOkmK?#*^%>!uWzKf=OH;CUA)xIS5K2#t&X|}~@a;1>4hnI2)HfMO96+v9_DVW$$YV!J3i%w-U3EsyJ z@&cN3-sxIZ*A5X?nFVQS8=9-#26stfalU7>PgQI~A=)Fyr>W}n>uI8%$-{eJ-GOxM z{->Wb3;vJh8&9DRIUIF>Q0HPRHBUt&;oHfcYu>;3g%zmaKoV|55*aoa)7H?UPx4$$ zAImpedXNta)Z9!bCS^*R_bc&a18KeSCi;1n}}MrKicV}Bp$E7Xv8BQ8;JXG#HuO-xx~;cr)lUdIq*M8U!FJ^jEXQQ+q9MkO!C>xR6;b#$?}sn3@7Jw8 z7cUcCrU$+umGJd`oO9a zWGtflmlq>P2b?QVX916pZ*>%epRsQXnzRg8LwgYD#*AO6B%Rvt2TZTJo!A^cUwD$} z4Fm?J{>mMuRsGFisf{EX!K+wGAbNsYIS@Ow?4Q*Nsp-g>LiYjnogJQoe-*)+WyX=M zS#G>A|3}nYRtuk63L}XK2-$zZ%5{D@#B`iSkUxyR&auxL7Ji9y8rf8p-3%&h^dL~e z&tC;3{z@0Xsn^Rxi8a@*M4t1t&euj~{fh(lW$zT2;{q57iU7n5&y}6=;s{Wu?}RuH zm}{}II!ig&8*n8px${cKaqf2Yp+*+=HNpD5yd}dwPx&P?;VmqmmJIQ?f2I8fZF4B= z1EHE4qz3t&iz(++={!tuB)5*i_i^;4BHrI=SNH9B^;ltK3}&Z(j7*o|1_`ywm9i*^ z7_sfaT_mja92zu>9*qCw*eFX>cpf;+{m$fX!!6SqVQ`X5pfR&IXRKMidFJBCA_{!X zUXx$@HHU+uj@iZ9H%0hPc8<*#XV~>kae(34zefVropB1n= za~y9_UEF=RdGSUklvbg0^Y`d)KiCQ}9(AT8{eOHXh~M#lFtTwd*!kz)p{+=UCs%xU zPtod13T2|w2a<;9I=!wUOe|;9Ain@@NjN;HTwj`rKmy<#A3GiW<=AX9a>P(MgpyxJ z?(){!xXsn2+15@+;OpP^eGY`N9`Wjqi`<1eU;2VKb1bAH*VCF5h4!!ox{L4qzx!qp zzl=YkpHA4{zFoWGOu)in3t;&pz1Nk6vod}+pVZ0P?S~Z^toFSJ9fN$1;5MB*|(&Hsm9SCu>tv3K59j z24%*9@}PSRU{Mmmhi9;T-rTa^Kb2J<3PB46lTKP`=*&{bk8gAyU>4X=j~%E8ILDHK zCdQk*|DG%6ze0h5kS%V1A{NS(C~zls5v2Hh&6$3}-dIQnDFE9p47O`!#0CD$`?nM- z@ZoozBKPYW(bP9gfkrgXkmmWZj+)f2`y~b}zw#aq#4sTBw*bTt^G(^!Z7ZDQ!Zsci z7_Fy2{NDJ%0FD%I{4dyU@y|UgA8$q`FltdJ@R#0?$Mv5u)i70Nu&&bb%*+ml0Q)v$ zt$$Y=4!dsmxT~J`1E41lApZAU0Iwgd`0oJhjTZzfJSrTE-+(WP734^5Gr}6JxsN`i z0zI5hR%pG)v!6TFWe~8zVcZlUKahLl`it@XXaMmA#qiTe?MD9FZcOb=`(y4o^mkxe z9^q)ADG3mkLleRprlSnF<3q?jrx*SsD25a=1v6&POqU|Dis3N8FI#LGe=qz|J$i;sUd9zjP`!h887qAwME!y!k?QiChc}1S< zi~kd044(5$x%J0<|Q_tRB@6O9^31@Si zW(43hzurmDKB_fkx)nz^{ELk*e;v2JexMq)DABm>Kojs8@E0I-b=A)j@Z|CJKVJ91 z9p72>SGNy2-^msuZ~W<6u9=%SRtyHR3`LWlq55=q1Zq=y=5y0C$3w4J979xpwt}_K z--X>8v{~|(v0^HHG%+jjaD{p506CskU8I=pe!o)v?4}&?@~%8UPs;0 zPXpF7I7?4pAfTCt94NtX;Wy)_k?%ZzeN>8$T05Pr-&Vz%%_rEj<0OYF8fj=!Pk%KS z1d0nYDI1*2%!^8xHMy8kL-WG=fNW~%V&KeYX=(|rl5(oZ z%m2Xc_x=yb5%Ax_4Wy$47KMah{6w=+HZ^=c5PtEAE22hp)a{n}c*8MX{qJYIx8g9J zU4f;%mh{Qw_Jt$3^V*RN?3bngh9L0anj>6!-`hwUWzGXZ5Di@Vz4s{`acM~Uk0-26 zr`YkI|K-@GH<1I&rYr=4GNtfDFk&{lfTO@dd^}ZHFlP|sM);Si8Z2BcH~)HfFSq`` zcX{UJE$ls9_m%Wse`sm5v2JS>&%U;uy@%=;*e{FxUZItcA5fgZ;CvIy)}O>B1-GP^ z(VW7Jum6L-V;2Oq-+0BGoKErht0@?H3vNlG{mfz9l3$sXPZPrGL%|B#-VeNwk_eH3 zN}YiViL?V)z3Bv3-uo6Wy|qhoiXRBF3K7lyQCNks6}FFt?ksq9m@G z*_ZOFHjY&X=XX<3Hk(=BdW-yFGlSA!cS0~`(R;`|244Iy8TrEz5U{nML2`P%JP4@+ z2-PaJ5Eu(g22?egBDDl)>#+0C|19TU@9quzy))91c(A6g+u8(b^%#MBZ6;hH=(l) zE<7ESWjAd#`)H}&!>Qf>rS`ybtu8{k1kkR!=s(qGUpvrn0FhwlzFKa2cu~ZHlv>;E z-2a26EdS&vFF(0JH;Bh4Xx7Oo*+thB?t~- zs;=%gp_&0i9e;m&HxK-9sqa$U&;qPO$&x$*)S(>9m{CqX`k=&mPXfl_!@kOa@_MG< z@K08}c3W^x3W6ZknIOm{96;px*SmYU{|8HPdw)FEfg+XuDzFJf_uU&ZP)UxN_ZNFR_&b4L0wpNblGfw> z;0Hw!_7z|jil)LcZ{BpWwvD;BzfNnrez8kcTn=!@bgBBd!;9Lb5ht!4!10qU-1_Zz zy;ax!02qd%i5QFm58F{>p{@c>=`}u7(ZC&#yyt%zJzL20MiTgd4Rm&?t~ z5C7Mj&{!9WlIxX(roP(}U<{zU)w^Wn5&rPWc@7ZaC&X}r25!c8vbhZ0cA~7Pw zr30v{Y2{acUa!~84$KD@h2A1S*-Q8)@SIj7yF=oUUw9$ED7&Gn4Xn*X|5j7?KyoR8 zKduqwwo^-xARyw#0en`jo8uo%Yyb0cqc{PN9I0%j zQ#+<1K?1*t=rQ2>ou`9#wEg}X-7x-5!MRgN*oY#p{uLy*%#*KtMnP^$P;OLRrye|H zYpdnhrk8?pp9?Vl zR(@EUIYj6FL~s!VN~b))=9Eh|L;lyc=ZUrNkJv^0`bvT7GhC)WD9e@lx8sdBCaUA$_gl+JK@6nBB0nxs; zc37JuZ2~A`C#1iLaO?rR3EYAgx_Cjx4J<{eu^tufT!)WPRD+I1+K_NyZSbIX5JgxU zBf2kp3guW>HB3BMgewl z$RB=17|rpXuGSj88Ok$+ZdPeUBQiADggX!@Y#%JfsXzOQWlo^{m_0iDhKhAC=lfwb z$XgmJbminW5hpXX?s5#6ApE$|*nDlM*oey!oswp?`*j7JH-^KGaFB2S2||gg=Az4C zrRKBu!)c3GNKPBI`!(yiR1h5}TR|b=01|`}O?l%`GQDfL>qA@{T7)#>bsEKi9;>v~bA3#Ek2@tnNSQ=TF5{QCEBm#nhw7dzlE+%S1 zXf4>@PMh;3UG+@voyDBa^v*peB_sieREhx4;spe|ZWFaoTl2z-BN#cJSYLm_+Pg|O z&H7uiM5Y_UEX2CukIiCe6nDWcJiCvoomC7r-A?ZIN=Abnta}G%9=Jr7{QLi#Bmj|W zA)prU#R{1G*h9JR9L~HFb+d}2ptO#iHU7Ebx2+vSqhZYcj?I`2U$aW8>j4M>;05{t zN34MS5-+E2y|zpea5|!mtpQg8J=!vx+yMv`rhy{hc&vbxg=xMI^-xjYgzj*wo7o2J zhSuH|a6U}yBovW50HI1g&)Ly4u;zU&Z@Kwo(8fCAXJ$J zu3@eW#1tOy=hdTQOb)8=+iKIb8T*=XSoy$dB#!_>rO%iN;B>s8)s=ZhdfQl$-mkO|#D1 zND4^;5b5H=yc0OT*#kArMsD$5@^{qWF08=eDnQe0tS-;8vKV4^;sfDt1Bn*(90F=K zI|m`e|I>k|n6KQW>y!PZe}%BPE5ID-NdWx{&QA#O54Auy>Jvb-f^!o>BtQc$17Aq} zg}(&cRdZTGh|Ms7tH67bf8qZC9$*%z6+&2C1Mmd1RQ6Uc`Y>jR?TbKi+AL=YSq2oD zWFKaq2Os9rT_xZF@-Qo0hkzN(ipm2(5VJ7p8(>-ebgl0f3WmFb(6i%{00000NkvXX Hu0mjfa^+Or literal 0 HcmV?d00001 diff --git a/src/libs/vmisc/vcommonsettings.cpp b/src/libs/vmisc/vcommonsettings.cpp index 1aa73dc8d..3d2e54a0f 100644 --- a/src/libs/vmisc/vcommonsettings.cpp +++ b/src/libs/vmisc/vcommonsettings.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include "../vmisc/def.h" #include "../vmisc/vmath.h"