From d32bbfcfd40c0800fe763f89f312b74596a18c4b Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Wed, 25 Aug 2021 16:58:50 +0300 Subject: [PATCH] Layout properties. --- .../puzzle/carousel/vpcarrouselpiecelist.cpp | 6 + .../puzzlepreferenceslayoutpage.cpp | 8 +- src/app/puzzle/layout/vplayout.h | 2 + src/app/puzzle/layout/vplayoutsettings.cpp | 25 +- src/app/puzzle/layout/vplayoutsettings.h | 23 - src/app/puzzle/layout/vpsheet.cpp | 28 +- src/app/puzzle/layout/vpsheet.h | 2 + src/app/puzzle/scene/vpgraphicspiece.cpp | 86 +- src/app/puzzle/scene/vpgraphicspiece.h | 1 - .../puzzle/scene/vpgraphicspiececontrols.cpp | 47 +- .../puzzle/scene/vpgraphicspiececontrols.h | 6 +- src/app/puzzle/scene/vpgraphicssheet.cpp | 16 +- src/app/puzzle/scene/vpgraphicstilegrid.cpp | 8 +- src/app/puzzle/scene/vpgraphicstilegrid.h | 2 +- src/app/puzzle/scene/vpmaingraphicsview.cpp | 91 +- src/app/puzzle/scene/vpmaingraphicsview.h | 1 + src/app/puzzle/share/resources/puzzleicon.qrc | 8 - .../64x64/iconGrainlineHorizontal.png | Bin 979 -> 0 bytes .../64x64/iconGrainlineHorizontal@2x.png | Bin 1498 -> 0 bytes .../64x64/iconGrainlineVertical.png | Bin 984 -> 0 bytes .../64x64/iconGrainlineVertical@2x.png | Bin 1516 -> 0 bytes .../puzzleicon/64x64/iconLandscape.png | Bin 1042 -> 0 bytes .../puzzleicon/64x64/iconLandscape@2x.png | Bin 1491 -> 0 bytes .../puzzleicon/64x64/iconPortrait.png | Bin 980 -> 0 bytes .../puzzleicon/64x64/iconPortrait@2x.png | Bin 1505 -> 0 bytes .../64x64/iconRotate90Anticlockwise.png | Bin 1847 -> 0 bytes .../64x64/iconRotate90Clockwise.png | Bin 1831 -> 0 bytes .../64x64/iconRotateGrainlineHorizontal.png | Bin 1224 -> 0 bytes .../iconRotateGrainlineHorizontal@2x.png | Bin 2389 -> 0 bytes .../64x64/iconRotateGrainlineVertical.png | Bin 1249 -> 0 bytes .../64x64/iconRotateGrainlineVertical@2x.png | Bin 2641 -> 0 bytes .../undocommands/vpundomovepieceonsheet.cpp | 6 +- .../puzzle/undocommands/vpundooriginmove.cpp | 10 +- .../puzzle/undocommands/vpundopiecemove.cpp | 24 +- src/app/puzzle/undocommands/vpundopiecemove.h | 4 +- .../puzzle/undocommands/vpundopiecerotate.cpp | 24 +- .../puzzle/undocommands/vpundopiecerotate.h | 6 +- src/app/puzzle/vpexporter.cpp | 4 - src/app/puzzle/vpmainwindow.cpp | 1958 ++++++++++++----- src/app/puzzle/vpmainwindow.h | 181 +- src/app/puzzle/vpmainwindow.ui | 1393 ++++++------ src/app/puzzle/vpsettings.cpp | 7 + src/app/puzzle/vpsettings.h | 1 + src/app/puzzle/vptilefactory.cpp | 45 +- src/app/puzzle/xml/vplayoutfilewriter.cpp | 2 - .../valentina/dialogs/dialogsavelayout.cpp | 16 +- src/app/valentina/dialogs/dialogsavelayout.h | 1 - .../vlayout/dialogs/vabstractlayoutdialog.cpp | 17 + .../vlayout/dialogs/vabstractlayoutdialog.h | 1 + .../16x16/actions/object-rotate-right.png | Bin 0 -> 1246 bytes .../24x24/actions/object-rotate-right.png | Bin 0 -> 10415 bytes .../32x32/actions/object-rotate-right.png | Bin 0 -> 2077 bytes src/libs/vmisc/share/resources/theme.qrc | 3 + 53 files changed, 2438 insertions(+), 1625 deletions(-) delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineHorizontal.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineHorizontal@2x.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineVertical.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineVertical@2x.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconLandscape.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconLandscape@2x.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconPortrait.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconPortrait@2x.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconRotate90Anticlockwise.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconRotate90Clockwise.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconRotateGrainlineHorizontal.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconRotateGrainlineHorizontal@2x.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconRotateGrainlineVertical.png delete mode 100644 src/app/puzzle/share/resources/puzzleicon/64x64/iconRotateGrainlineVertical@2x.png create mode 100644 src/libs/vmisc/share/resources/icons/win.icon.theme/16x16/actions/object-rotate-right.png create mode 100644 src/libs/vmisc/share/resources/icons/win.icon.theme/24x24/actions/object-rotate-right.png create mode 100644 src/libs/vmisc/share/resources/icons/win.icon.theme/32x32/actions/object-rotate-right.png diff --git a/src/app/puzzle/carousel/vpcarrouselpiecelist.cpp b/src/app/puzzle/carousel/vpcarrouselpiecelist.cpp index 3f5889162..c39fa26cc 100644 --- a/src/app/puzzle/carousel/vpcarrouselpiecelist.cpp +++ b/src/app/puzzle/carousel/vpcarrouselpiecelist.cpp @@ -151,6 +151,12 @@ void VPCarrouselPieceList::startDrag(Qt::DropActions supportedActions) { m_carrousel->Refresh(); piece->SetSelected(true); + + VPLayoutPtr layout = piece->Layout(); + if (not layout.isNull()) + { + emit layout->PieceSelectionChanged(piece); + } } } } diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp index 4695a6848..42544049d 100644 --- a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.cpp @@ -40,7 +40,7 @@ PuzzlePreferencesLayoutPage::PuzzlePreferencesLayoutPage(QWidget *parent) : InitLayoutUnits(); VAbstractLayoutDialog::InitTemplates(ui->comboBoxSheetTemplates); - VAbstractLayoutDialog::InitTemplates(ui->comboBoxTileTemplates); + VAbstractLayoutDialog::InitTileTemplates(ui->comboBoxTileTemplates); MinimumSheetPaperSize(); MinimumTilePaperSize(); @@ -225,7 +225,7 @@ void PuzzlePreferencesLayoutPage::ConvertPaperSize() ui->doubleSpinBoxTileMarginTop->setValue(newTileTopMargin); ui->doubleSpinBoxTileMarginBottom->setValue(newTileBottomMargin); - ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(50, Unit::Cm, layoutUnit)); + ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Cm, layoutUnit)); ui->doubleSpinBoxPiecesGap->setValue(newGap); } @@ -610,7 +610,7 @@ void PuzzlePreferencesLayoutPage::ReadSettings() ui->checkBoxWarningPiecesOutOfBound->setChecked(settings->GetLayoutWarningPiecesOutOfBound()); ui->checkBoxFollowGrainline->setChecked(settings->GetLayoutFollowGrainline()); - ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(50, Unit::Cm, LayoutUnit())); + ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, LayoutUnit())); SetPieceGap(settings->GetLayoutPieceGap()); FindSheetTemplate(); @@ -637,7 +637,7 @@ void PuzzlePreferencesLayoutPage::FindTemplate(QComboBox *box, qreal width, qrea if (QSizeF(width, height) == tmplSize || QSizeF(height, width) == tmplSize) { box->blockSignals(true); - const int index = ui->comboBoxTileTemplates->findData(i); + const int index = box->findData(i); if (index != -1) { box->setCurrentIndex(index); diff --git a/src/app/puzzle/layout/vplayout.h b/src/app/puzzle/layout/vplayout.h index d565e54a5..fb120725e 100644 --- a/src/app/puzzle/layout/vplayout.h +++ b/src/app/puzzle/layout/vplayout.h @@ -90,6 +90,8 @@ signals: void PieceTransformationChanged(const VPPiecePtr &piece); void TransformationOriginChanged(); void SheetListChanged(); + void PieceSelectionChanged(const VPPiecePtr &piece); + void LayoutChanged(); protected: explicit VPLayout(QUndoStack *undoStack); diff --git a/src/app/puzzle/layout/vplayoutsettings.cpp b/src/app/puzzle/layout/vplayoutsettings.cpp index 619a62c33..a112787ad 100644 --- a/src/app/puzzle/layout/vplayoutsettings.cpp +++ b/src/app/puzzle/layout/vplayoutsettings.cpp @@ -100,8 +100,8 @@ void VPLayoutSettings::SetTilesSize(qreal width, qreal height) //--------------------------------------------------------------------------------------------------------------------- void VPLayoutSettings::SetTilesSizeConverted(qreal width, qreal height) { - m_tilesSize.setWidth(UnitConvertor(width, GetUnit(), Unit::Px)); - m_tilesSize.setHeight(UnitConvertor(height, GetUnit(), Unit::Px)); + m_tilesSize.setWidth(UnitConvertor(width, m_unit, Unit::Px)); + m_tilesSize.setHeight(UnitConvertor(height, m_unit, Unit::Px)); } //--------------------------------------------------------------------------------------------------------------------- @@ -142,12 +142,6 @@ auto VPLayoutSettings::GetTilesSizeConverted() const -> QSizeF return GetTilesSize(GetUnit()); } -//--------------------------------------------------------------------------------------------------------------------- -auto VPLayoutSettings::GetTilesOrientation() -> PageOrientation -{ - return m_tilesSize.height() >= m_tilesSize.width() ? PageOrientation::Portrait : PageOrientation::Landscape; -} - //--------------------------------------------------------------------------------------------------------------------- void VPLayoutSettings::SetTilesMargins(qreal left, qreal top, qreal right, qreal bottom) { @@ -497,21 +491,6 @@ auto VPLayoutSettings::GetSheetSizeConverted() const -> QSizeF return convertedSize; } -//--------------------------------------------------------------------------------------------------------------------- -auto VPLayoutSettings::GetOrientation() -> PageOrientation -{ - return m_orientation; -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPLayoutSettings::SetOrientation(PageOrientation orientation) -{ - if(orientation != m_orientation) - { - m_orientation = orientation; - } -} - //--------------------------------------------------------------------------------------------------------------------- void VPLayoutSettings::SetSheetMargins(qreal left, qreal top, qreal right, qreal bottom) { diff --git a/src/app/puzzle/layout/vplayoutsettings.h b/src/app/puzzle/layout/vplayoutsettings.h index 4fc95bb22..aabfc9897 100644 --- a/src/app/puzzle/layout/vplayoutsettings.h +++ b/src/app/puzzle/layout/vplayoutsettings.h @@ -191,12 +191,6 @@ public: */ auto GetTilesSizeConverted() const -> QSizeF; - /** - * @brief GetOrientation Returns the orientation of the tiles - * @return orientation of the tiles - */ - auto GetTilesOrientation() -> PageOrientation; - /** * @brief SetTilesMargins, set the margins of the tiles, the values have to be in Unit::Px * @param left in Unit::Px @@ -332,18 +326,6 @@ public: */ auto GetSheetSizeConverted() const -> QSizeF; - /** - * @brief GetOrientation Returns the orientation of the sheet - * @return orientation of the sheet - */ - auto GetOrientation() -> PageOrientation; - - /** - * @brief SetOrientation Sets the orientation of the sheet to the given value - * @param orientation the new page orientation - */ - void SetOrientation(PageOrientation orientation); - /** * @brief SetSheetMargins, set the margins of the sheet, the values have to be in Unit::Px * @param left in Unit::Px @@ -488,11 +470,6 @@ private: */ QSizeF m_size{}; - /** - * @brief holds the orientation of the sheet - */ - PageOrientation m_orientation {PageOrientation::Portrait}; - // margins /** * @brief m_margins the margins in Unit::Px diff --git a/src/app/puzzle/layout/vpsheet.cpp b/src/app/puzzle/layout/vpsheet.cpp index 4de346e05..0538215a5 100644 --- a/src/app/puzzle/layout/vpsheet.cpp +++ b/src/app/puzzle/layout/vpsheet.cpp @@ -28,6 +28,7 @@ #include "vpsheet.h" #include "vplayout.h" +#include "vppiece.h" //--------------------------------------------------------------------------------------------------------------------- VPSheet::VPSheet(const VPLayoutPtr &layout) : @@ -45,8 +46,6 @@ auto VPSheet::GetLayout() const -> VPLayoutPtr //--------------------------------------------------------------------------------------------------------------------- auto VPSheet::GetPieces() const -> QList { - QList list; - VPLayoutPtr layout = GetLayout(); if (not layout.isNull()) { @@ -56,6 +55,31 @@ auto VPSheet::GetPieces() const -> QList return {}; } +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheet::GetSelectedPieces() const -> QList +{ + VPLayoutPtr layout = GetLayout(); + if (not layout.isNull()) + { + QList list = layout->PiecesForSheet(m_uuid); + + QList selected; + selected.reserve(list.size()); + + for (const auto& piece : list) + { + if (not piece.isNull() && piece->IsSelected()) + { + selected.append(piece); + } + } + + return selected; + } + + return {}; +} + //--------------------------------------------------------------------------------------------------------------------- auto VPSheet::GetName() const -> QString { diff --git a/src/app/puzzle/layout/vpsheet.h b/src/app/puzzle/layout/vpsheet.h index 81ac3907c..46bfe0243 100644 --- a/src/app/puzzle/layout/vpsheet.h +++ b/src/app/puzzle/layout/vpsheet.h @@ -55,6 +55,8 @@ public: auto GetPieces() const -> QList; + auto GetSelectedPieces() const -> QList; + /** * @brief GetName Returns the name of the sheet * @return the name diff --git a/src/app/puzzle/scene/vpgraphicspiece.cpp b/src/app/puzzle/scene/vpgraphicspiece.cpp index 81e2b2006..c2168b8da 100644 --- a/src/app/puzzle/scene/vpgraphicspiece.cpp +++ b/src/app/puzzle/scene/vpgraphicspiece.cpp @@ -76,7 +76,7 @@ VPGraphicsPiece::VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent) //--------------------------------------------------------------------------------------------------------------------- auto VPGraphicsPiece::GetPiece() -> VPPiecePtr { - return m_piece; + return m_piece.toStrongRef(); } //--------------------------------------------------------------------------------------------------------------------- @@ -245,7 +245,7 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter) if (painter != nullptr) { painter->save(); - painter->setBrush(isSelected() ? selectionBrush : noBrush); + painter->setBrush(piece->IsSelected() ? selectionBrush : noBrush); painter->drawPath(m_seamLine); painter->restore(); } @@ -362,55 +362,48 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter) //--------------------------------------------------------------------------------------------------------------------- void VPGraphicsPiece::GroupMove(const QPointF &pos) { - if (scene() != nullptr) + VPPiecePtr piece = m_piece.toStrongRef(); + if (piece.isNull()) { - QList list = scene()->selectedItems(); + return; + } - if (list.isEmpty()) + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + auto PreparePieces = [layout]() + { + QList pieces; + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { - return; + return sheet->GetSelectedPieces(); } - VPPiecePtr piece = m_piece.toStrongRef(); - if (piece.isNull()) - { - return; - } + return pieces; + }; - VPLayoutPtr layout = piece->Layout(); - if (layout.isNull()) - { - return; - } + QList pieces = PreparePieces(); + QPointF newPos = pos - m_moveStartPoint; - auto PreparePieces = [list]() - { - QVector pieces; - for (auto *item : list) - { - if (item->type() == VPGraphicsPiece::Type) - { - auto *pieceItem = dynamic_cast(item); - pieces.append(pieceItem->GetPiece()); - } - } + if (qFuzzyIsNull(newPos.x()) && qFuzzyIsNull(newPos.y())) + { + return; + } - return pieces; - }; - - QVector pieces = PreparePieces(); - QPointF newPos = pos - m_moveStartPoint; - - if (pieces.size() == 1) - { - auto *command = new VPUndoPieceMove(pieces.first(), newPos.x(), newPos.y(), allowChangeMerge); - layout->UndoStack()->push(command); - } - else if (pieces.size() > 1) - { - auto *command = new VPUndoPiecesMove(pieces, newPos.x(), newPos.y(), allowChangeMerge); - layout->UndoStack()->push(command); - } + if (pieces.size() == 1) + { + auto *command = new VPUndoPieceMove(pieces.first(), newPos.x(), newPos.y(), allowChangeMerge); + layout->UndoStack()->push(command); + } + else if (pieces.size() > 1) + { + auto *command = new VPUndoPiecesMove(pieces, newPos.x(), newPos.y(), allowChangeMerge); + layout->UndoStack()->push(command); } } @@ -435,8 +428,13 @@ auto VPGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &valu VPPiecePtr piece = m_piece.toStrongRef(); if (not piece.isNull()) { - emit PieceSelectionChanged(); piece->SetSelected(value.toBool()); + + VPLayoutPtr layout = piece->Layout(); + if (not layout.isNull()) + { + emit layout->PieceSelectionChanged(piece); + } } } } diff --git a/src/app/puzzle/scene/vpgraphicspiece.h b/src/app/puzzle/scene/vpgraphicspiece.h index 62d2d22e1..da7ea0b51 100644 --- a/src/app/puzzle/scene/vpgraphicspiece.h +++ b/src/app/puzzle/scene/vpgraphicspiece.h @@ -52,7 +52,6 @@ public: enum { Type = UserType + static_cast(PGraphicsItem::Piece)}; signals: - void PieceSelectionChanged(); void HideTransformationHandles(bool hide); void PieceTransformationChanged(); diff --git a/src/app/puzzle/scene/vpgraphicspiececontrols.cpp b/src/app/puzzle/scene/vpgraphicspiececontrols.cpp index 852ecaf25..8716b7313 100644 --- a/src/app/puzzle/scene/vpgraphicspiececontrols.cpp +++ b/src/app/puzzle/scene/vpgraphicspiececontrols.cpp @@ -37,6 +37,7 @@ #include "../vmisc/compatibility.h" #include "../vwidgets/global.h" #include "../layout/vplayout.h" +#include "../layout/vppiece.h" #include "../undocommands/vpundopiecerotate.h" #include "../undocommands/vpundooriginmove.h" #include "vpgraphicspiece.h" @@ -479,16 +480,21 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { auto PreparePieces = [this]() { - QVector pieces; - for (auto *item : m_selectedPieces) + QList pieces; + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) { - pieces.append(item->GetPiece()); + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) + { + pieces = sheet->GetSelectedPieces(); + } } return pieces; }; - QVector pieces = PreparePieces(); + QList pieces = PreparePieces(); VPLayoutPtr layout = m_layout.toStrongRef(); if (not layout.isNull()) @@ -662,7 +668,7 @@ auto VPGraphicsPieceControls::ControllersRect() const -> QRectF //--------------------------------------------------------------------------------------------------------------------- auto VPGraphicsPieceControls::ArrowPath() const -> QPainterPath { - const qreal scale = SceneScale(scene()); + const qreal scale = SceneScale(scene())/2; QPainterPath arrow; QRectF pieceRect = ControllersRect(); @@ -764,23 +770,17 @@ auto VPGraphicsPieceControls::ArrowPath() const -> QPainterPath } //--------------------------------------------------------------------------------------------------------------------- -auto VPGraphicsPieceControls::SelectedPieces() const -> QVector +auto VPGraphicsPieceControls::SelectedPieces() const -> QList { - QVector pieces; - QGraphicsScene *scene = this->scene(); - if (scene != nullptr) + QList pieces; + + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) { - QList list = scene->selectedItems(); - for (auto *item : list) + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { - if (item->type() == VPGraphicsPiece::Type) - { - auto *pieceItem = dynamic_cast(item); - if (pieceItem != nullptr) - { - pieces.append(pieceItem); - } - } + pieces = sheet->GetSelectedPieces(); } } @@ -788,12 +788,15 @@ auto VPGraphicsPieceControls::SelectedPieces() const -> QVector &selectedPieces) -> QRectF +auto VPGraphicsPieceControls::PiecesBoundingRect(const QList &selectedPieces) -> QRectF { QRectF rect; - for (auto *item : selectedPieces) + for (const auto& item : selectedPieces) { - rect = rect.united(item->sceneBoundingRect()); + if (not item.isNull()) + { + rect = rect.united(item->MappedDetailBoundingRect()); + } } return rect; diff --git a/src/app/puzzle/scene/vpgraphicspiececontrols.h b/src/app/puzzle/scene/vpgraphicspiececontrols.h index 9c838cec8..07b26e655 100644 --- a/src/app/puzzle/scene/vpgraphicspiececontrols.h +++ b/src/app/puzzle/scene/vpgraphicspiececontrols.h @@ -114,7 +114,7 @@ private: VPTransformationOrigon m_savedOrigin{}; bool m_originSaved{false}; bool allowChangeMerge{false}; - QVector m_selectedPieces{}; + QList m_selectedPieces{}; bool m_ignorePieceTransformation{false}; auto TopLeftControl(QPainter *painter = nullptr) const -> QPainterPath; @@ -130,8 +130,8 @@ private: auto HandleCorner(const QPointF &pos) const -> int; - auto SelectedPieces() const -> QVector; - static auto PiecesBoundingRect(const QVector &selectedPieces) -> QRectF; + auto SelectedPieces() const -> QList; + static auto PiecesBoundingRect(const QList &selectedPieces) -> QRectF; }; #endif // VPGRAPHICSPIECECONTROLS_H diff --git a/src/app/puzzle/scene/vpgraphicssheet.cpp b/src/app/puzzle/scene/vpgraphicssheet.cpp index d4a2e28f3..af5257948 100644 --- a/src/app/puzzle/scene/vpgraphicssheet.cpp +++ b/src/app/puzzle/scene/vpgraphicssheet.cpp @@ -113,10 +113,6 @@ auto VPGraphicsSheet::GetSheetRect() const -> QRectF QPoint topLeft = QPoint(0,0); QSizeF size = layout->LayoutSettings().GetSheetSize(); - if(layout->LayoutSettings().GetOrientation() == PageOrientation::Landscape) - { - size.transpose(); - } QRectF rect = QRectF(topLeft, size); return rect; } @@ -130,17 +126,17 @@ auto VPGraphicsSheet::GetMarginsRect() const -> QRectF return {}; } - QMarginsF margins = layout->LayoutSettings().GetSheetMargins(); QSizeF size = layout->LayoutSettings().GetSheetSize(); - if(layout->LayoutSettings().GetOrientation() == PageOrientation::Landscape) + if (not layout->LayoutSettings().IgnoreMargins()) { - size.transpose(); + QMarginsF margins = layout->LayoutSettings().GetSheetMargins(); + QRectF rect = QRectF(QPointF(margins.left(), margins.top()), + QPointF(size.width()-margins.right(), size.height()-margins.bottom())); + return rect; } - QRectF rect = QRectF(QPointF(margins.left(),margins.top()), - QPointF(size.width()-margins.right(), size.height()-margins.bottom())); - return rect; + return QRectF(0, 0, size.width(), size.height()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/puzzle/scene/vpgraphicstilegrid.cpp b/src/app/puzzle/scene/vpgraphicstilegrid.cpp index 3ce3d539b..3154d3323 100644 --- a/src/app/puzzle/scene/vpgraphicstilegrid.cpp +++ b/src/app/puzzle/scene/vpgraphicstilegrid.cpp @@ -13,13 +13,7 @@ VPGraphicsTileGrid::VPGraphicsTileGrid(const VPLayoutPtr &layout, VPTileFactory } //--------------------------------------------------------------------------------------------------------------------- -VPGraphicsTileGrid::~VPGraphicsTileGrid() -{ - -} - -//--------------------------------------------------------------------------------------------------------------------- -QRectF VPGraphicsTileGrid::boundingRect() const +auto VPGraphicsTileGrid::boundingRect() const -> QRectF { VPLayoutPtr layout = m_layout.toStrongRef(); if(not layout.isNull() && layout->LayoutSettings().GetShowTiles()) diff --git a/src/app/puzzle/scene/vpgraphicstilegrid.h b/src/app/puzzle/scene/vpgraphicstilegrid.h index 11fb45b63..b30b70195 100644 --- a/src/app/puzzle/scene/vpgraphicstilegrid.h +++ b/src/app/puzzle/scene/vpgraphicstilegrid.h @@ -42,7 +42,7 @@ class VPGraphicsTileGrid : public QGraphicsItem { public: explicit VPGraphicsTileGrid(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QGraphicsItem *parent = nullptr); - ~VPGraphicsTileGrid(); + ~VPGraphicsTileGrid()=default; QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; diff --git a/src/app/puzzle/scene/vpmaingraphicsview.cpp b/src/app/puzzle/scene/vpmaingraphicsview.cpp index 19267a8df..e87e090ca 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.cpp +++ b/src/app/puzzle/scene/vpmaingraphicsview.cpp @@ -70,6 +70,8 @@ VPMainGraphicsView::VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory SCASSERT(not m_layout.isNull()) setScene(m_scene); + connect(m_scene, &VMainGraphicsScene::ItemClicked, this, &VPMainGraphicsView::on_ItemClicked); + m_graphicsSheet = new VPGraphicsSheet(m_layout); m_graphicsSheet->setPos(0, 0); m_scene->addItem(m_graphicsSheet); @@ -262,6 +264,8 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event) VPLayoutPtr layout = m_layout.toStrongRef(); if (not layout.isNull()) { + emit layout->PieceSelectionChanged(piece); + auto *command = new VPUndoMovePieceOnSheet(VPSheetPtr(), piece); layout->UndoStack()->push(command); } @@ -429,11 +433,12 @@ void VPMainGraphicsView::RestoreOrigin() const origin.custom = false; QRectF boundingRect; - for (auto *graphicsPiece : m_graphicsPieces) + QList selectedPieces = sheet->GetSelectedPieces(); + for (const auto& piece : selectedPieces) { - if (graphicsPiece->isSelected()) + if (piece->IsSelected()) { - boundingRect = boundingRect.united(graphicsPiece->sceneBoundingRect()); + boundingRect = boundingRect.united(piece->MappedDetailBoundingRect()); } } origin.origin = boundingRect.center(); @@ -444,6 +449,60 @@ void VPMainGraphicsView::RestoreOrigin() const } } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainGraphicsView::on_ItemClicked(QGraphicsItem *item) +{ + if (item == nullptr || (item->type() != VPGraphicsPiece::Type && + item->type() != VPGraphicsPieceControls::Type && + item->type() != VPGraphicsTransformationOrigin::Type)) + { + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) + { + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) + { + QList selectedPieces = sheet->GetSelectedPieces(); + for (const auto& piece : selectedPieces) + { + if (piece->IsSelected()) + { + piece->SetSelected(false); + } + } + + if (not selectedPieces.isEmpty()) + { + emit layout->PieceSelectionChanged(VPPiecePtr()); + } + } + } + } + else + { + if (item->type() == VPGraphicsPiece::Type) + { + auto *pieceItem = dynamic_cast(item); + if (pieceItem != nullptr) + { + VPPiecePtr piece = pieceItem->GetPiece(); + if (not piece.isNull()) + { + if (not piece->IsSelected()) + { + piece->SetSelected(true); + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) + { + emit layout->PieceSelectionChanged(piece); + } + } + } + } + } + } +} + //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece) { @@ -453,7 +512,7 @@ void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece) connect(layout.get(), &VPLayout::PieceTransformationChanged, piece, &VPGraphicsPiece::on_RefreshPiece); - connect(piece, &VPGraphicsPiece::PieceSelectionChanged, + connect(layout.get(), &VPLayout::PieceSelectionChanged, m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); connect(piece, &VPGraphicsPiece::PieceTransformationChanged, m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); @@ -485,19 +544,21 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) auto PreparePieces = [this]() { - QVector pieces; - for (auto *item : m_graphicsPieces) + QList pieces; + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) { - if (item->isSelected()) + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { - pieces.append(item->GetPiece()); + pieces = sheet->GetSelectedPieces(); } } return pieces; }; - QVector pieces = PreparePieces(); + QList pieces = PreparePieces(); if (pieces.size() == 1) { @@ -535,19 +596,21 @@ void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy) auto PreparePieces = [this]() { - QVector pieces; - for (auto *graphicsPiece : m_graphicsPieces) + QList pieces; + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) { - if (graphicsPiece->isSelected()) + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { - pieces.append(graphicsPiece->GetPiece()); + pieces = sheet->GetSelectedPieces(); } } return pieces; }; - QVector pieces = PreparePieces(); + QList pieces = PreparePieces(); if (pieces.size() == 1) { auto *command = new VPUndoPieceMove(pieces.first(), dx, dy, m_allowChangeMerge); diff --git a/src/app/puzzle/scene/vpmaingraphicsview.h b/src/app/puzzle/scene/vpmaingraphicsview.h index 8033fdc2f..a2d8896f9 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.h +++ b/src/app/puzzle/scene/vpmaingraphicsview.h @@ -95,6 +95,7 @@ protected: private slots: void RestoreOrigin() const; + void on_ItemClicked(QGraphicsItem* item); private: Q_DISABLE_COPY(VPMainGraphicsView) diff --git a/src/app/puzzle/share/resources/puzzleicon.qrc b/src/app/puzzle/share/resources/puzzleicon.qrc index 33d297039..6c117d3fe 100644 --- a/src/app/puzzle/share/resources/puzzleicon.qrc +++ b/src/app/puzzle/share/resources/puzzleicon.qrc @@ -5,10 +5,6 @@ puzzleicon/64x64/iconCurrentPiece.png puzzleicon/64x64/iconLayers.png puzzleicon/64x64/iconTiles.png - puzzleicon/64x64/iconLandscape.png - puzzleicon/64x64/iconPortrait.png - puzzleicon/64x64/iconGrainlineVertical.png - puzzleicon/64x64/iconGrainlineHorizontal.png puzzleicon/64x64/iconProperties.png puzzleicon/svg/icon_scissors.svg puzzleicon/svg/icon_scissors_vertical.svg @@ -18,10 +14,6 @@ puzzleicon/svg/cursor_rotate.svg puzzleicon/svg/icon_rotate_90_anticlockwise.svg puzzleicon/svg/icon_rotate_90_clockwise.svg - puzzleicon/64x64/iconRotate90Anticlockwise.png - puzzleicon/64x64/iconRotate90Clockwise.png - puzzleicon/64x64/iconRotateGrainlineHorizontal.png - puzzleicon/64x64/iconRotateGrainlineVertical.png puzzleicon/svg/icon_rotate_grainline_horizontal.svg puzzleicon/svg/icon_rotate_grainline_vertical.svg diff --git a/src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineHorizontal.png b/src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineHorizontal.png deleted file mode 100644 index 394d48fc0f3253915d3bc2d7afed89fec1d5d295..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 979 zcmV;^11$WBP)EX>4Tx04R}tkv&MmP!xqv(@Kk09PFUtkfAzR5EXIMDionYs1;guFnQ@8G-*g$ zTpR`0f`dPcRR6lU)^quLz(AA*w-{S;m|sCE>Zg?&0J6U5saW-}`g*syT}RK9P8q8D^DugLrzg zYH;2sj7IPWeK{ zWtH<5XRTagtv>k+!#RCrnd?-;NMI35kRU=q4JDLOMT~Zx6bmUjk9+us9KS>^g4!CxZD8-o($QP9m!86k8{ps& z7%foty2raiopby5PHTQY{daPB$6l&&00006VoOIv0Q3M$08806x7z>!010qNS#tmY z4c7nw4c7reD4Tcy000McNliruN@X!1~ z8bV4*QI=AYC1pX%pR%IZ*ibgg#%?HUB@04RBE?3Nl(AqZE3vS_f{lfmQlut{c{b$ zHA%o_ti_wz23mpUKu?df`f101m ze9_nPdlGlCqSpj$FC)Ke2J6LqOF+|cJjD8`5^xZYv1J;wr49*zJ$QnxRh>G4d!4eh z0A@hbwlcuG+ba&^JeGC|`T_4t(gxe^Ei0wfud)!$MQ7UIH;CnJ*P4qStShC;7o5fe zxLO`;EV43zGyQmuuZ!?xJAhTqPhc-@V?&n*#!LC%jjB4@cDmQ7_{>&gWtaDS!`ag3 zzjoklmnn0tMx%SbOFus2K&M^cRoMn#PV>+-A5|^B?@AxXsyg)%hw!ZC+u&q}YcH@5 zucsQ-aU90z0-6D%TKB9*ek- z#S)8EbyHN`t&(<~O-hi;rvE@^-sgR1p7)3Mo%zi3z`@Q!045Ft06@UX((F2C5`X9v zH>dX+`VRpB=w1j0<6wos$lz{A1cihJ0st~6AqQ>QYb@FCYh;GHC>SFgNp^UuLWW1a zRXSU4`V#JeSNn^>SEwbAQhk^l+S8NW|7S`@BSnysEW-qSSff?YuA%usucbLq0#D@FQ#)+gz zrJn{>QFu&av5u@uexZBuDcvwKH%}pzSxi_c<2!A1+dJkkD{9c+Xe?8FZrC6)*A0oU zU+Aw6d)epIr*1xtTrQ1rU+wI7ubFW_E@7pvCbu*U;|qH&{Y7kqWsR>&!JYkO?W(S( zKj7a|M6)mtedV8AqrgP<&pD*P2KQ3fJv-QufPhI`m?EhJF@GWojgKY$(%aIV9o~Tl zbCr;kYd+R$lM3u7C8RFKa4{kvh*>GyC5UP)u}9HcL*4>5&Ol^PkHr$4q($4HrlHt~ zt%PDj!2OF-0z^_0d_&=l&jBIUH#UM@5^`_=NwT|LJ+{B?!NI~EU}IqhFaR6CW=^Md zp5yT1EZw6x1ZRH;WQr^za7>ZE(OBHr>lQp@oV;z{|;a1Lch!)A>Z;<&4e#RINC5=sEo}?k;k?FhrWkXKR z!DvFyb@is|+@{Vo+VH-AE#zb5`LV8QbX4JCqF=9C)cU3od-?LlX7j$gjMZcLpH_v) zCurG#j+rjBtz|0XE}SWqAM7)+2-@Vv?(}_VC$^FdS5Dz7EVS(0%6A+X8~|$5S`T8(`GG0U$vFM^QlNu)98f|q*aeN3 zHWDi+j(TqveaqN9q!$6j(WmPwsShLuuF=!CNy%c8&>2_#)sa!>+o@!o*-bavvkXdTl$7578(5R8b9I-8=sSya#IkO zmmr2u#IkV8bFDGxtLu@XZu17>&mS#0Hke#E))Nf^7fexyNZCXl<*w#1Y~fKfqIf3I zcJcAKBniIEs@(-NoRTCSYvlP^Rc(5x5GK?$kc7hB==W-YjDeRYpVJOdG4z2VlW(4` zdwJ}H8Q_ih;Z3U@`EXe1U|^{wcIb diff --git a/src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineVertical.png b/src/app/puzzle/share/resources/puzzleicon/64x64/iconGrainlineVertical.png deleted file mode 100644 index e2a49f1ab5f9de6dc46fb46e121005f78d3f8dec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 984 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 diff --git a/src/app/puzzle/share/resources/puzzleicon/64x64/iconPortrait.png b/src/app/puzzle/share/resources/puzzleicon/64x64/iconPortrait.png deleted file mode 100644 index 46077bbc50ba6956e3294f57d0e5a7120067203b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 980 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 LNkvXXu0mjfk?lX2 diff --git a/src/app/puzzle/share/resources/puzzleicon/64x64/iconRotateGrainlineVertical@2x.png b/src/app/puzzle/share/resources/puzzleicon/64x64/iconRotateGrainlineVertical@2x.png deleted file mode 100644 index e4af4320d5ccc7ca42c98b99fedb9c753a597377..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2641 zcmV-X3a<5uP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H13EoLW zK~#90?VWp!T}2(oKX=<@AEjMdXyu_&3?&xD3YJ2k2n(nQ{Lv<+F+PF@wLXY~5g*Wq zmMByuCSt*0d{G4i)Bqw1KB}cH8fgu!6)03GU0U0MO=$~#?Ja-&_U4{FJ#+5NoX4Dd zXFkcK-Mwe$e19{)d7R(O+*70T=mDkzCq>dkU;vl^j32qC!7kunwH}Dd0 z$Z>iGxD}WS^c85g*Bk|02K)v%fcr{UrB_BY&I67pq$E7!bl^6mU|m{*3D?ws$-ptlW8_Jf&J$)dNs9r!od3vxg3Ti`=T>n)mTz!#8sKpu|pOJGt7x+_B$a5dRm z{YK!6lvC*{P6cj3qK8>**#ulzvUVqo2Oc0>VXXt+M{&_U8zutR0{Ew&PAe;rseVkGQn&MrXnk0rbhmN&gk-6 zaXhdZ^YZy4ZBRaaz~h)3x5$N9ha8DSFHOtoW*1_0sUfRfCI$@yA9o=Z*|4z)iA=hn z8@Lm5C%D{&SRFoxnIQ*}T|O?T0lyg0@k2)%K!RFJFe|sc$Q-Lu%)l(RKMZ`piBe%P zvU1pP#DxyEbOArb%n8;}p=e<*GD|fv;ImGY3JW=WU*T@x6Am?v0q(`D3>Q05n!q

Nx#2V2(R!^a4v0bg5FE3alWWhOEcyioV^AOhCf2FDi63(tnZj1+JKY zbnm+5xgK#GCv+jPdR?(A7=0qAOa_4$G&CLp)&M8EkqOAEsma3G^=@R!uBAFI8CXHLqDWBjJvVw1ni=2hmZvvmyx%xD|98LyR+P= z+v0DoGZ42Ri?|F7AT8OZ@*C+VrK@f-2K_Dab>w`cDSaTD5=~C89D{6U))BT6H#>N` zfd@4;w(7lZC|P@y6VcyGvD7f{LF5UJ+mYGvC7OSz+coV0PB9df2Q}% zi@uSNQ5`vA)o97{GzC1Ei@9dZp>>omuk;U!IWyRb0rYI#iyUbK(W%;Za6vTl^HVbX zE3%7asm9Ig$eI2!IU6}MP)6l9(j&NuYJN#m-!;IQNN79h^WDVsca#3Ou^qjM)x8B6 zoyH83D}OhzGa+q7y)pCU*tJ`bU{^G4K%$E4aT6oxM{k??4$|jB4uOoDK#bVX9epU#-+vYZVq3Y7z>X3te)64@ua zCpR*SKJ!14QP_FN;mAhUxdrKpHphN9gmkf0qY5p)5BV0f<0nT+PDuuk}1uvr6%XMLQx;L6u;dWt=4U zxxu$JGQN%WdozY=y`$Y60HonPM(cWdmrdpur)0Pnci-%h6_o>2@sU-B9_0I#RCVmqsh- z*td115gfpCd~|>?35?*S(SasDIzZ?FB6w-Ef-nj61TQOEg^v!P!ppMo(&#{w-~dg$ z92$ZHH1V=5d^Fn2maf7_2Tvl=m8@5=m09bbPOLIAcTS=cxiN?NpOHBVF(EL zM{oeo@zDWPU40k=0{-En1B4zRf^QDsWhJNKn**fbrE~b^0A5yd8ooII1Sc4UZw`=F z`CdAPZw?TM;iChD$G`}_IY1Z!V)*6&ff&9yfS0X24c{C9f)k9wHwOrFfEd0x0C-x_ zDtvQ*8uG26s?WT`HwOsB@X-OhZ0Ra|bAT`jjNzLDfTtC$!Z!y9JwOcK93YM003P6F zC8sggwSbHq0gQ|M+=sk&UBxuiPTvnq)VSwP~pJ_R8N% zXT4I^D<%Oev9J7Hz-6VY4&=&oU_IuQzaRLr1HFL)7z8$>U-@<5J5H1a3gi7q3}43q z?xg)g9l$)tS^|zZ1Nf9{5w3X+hs*%PN2`{^00000NkvXXu0mjfLWapY diff --git a/src/app/puzzle/undocommands/vpundomovepieceonsheet.cpp b/src/app/puzzle/undocommands/vpundomovepieceonsheet.cpp index 32a0c1a76..fa277a1dd 100644 --- a/src/app/puzzle/undocommands/vpundomovepieceonsheet.cpp +++ b/src/app/puzzle/undocommands/vpundomovepieceonsheet.cpp @@ -59,7 +59,7 @@ void VPUndoMovePieceOnSheet::undo() if (not activateSheet.isNull()) { layout = activateSheet->GetLayout(); - if (not layout.isNull() && not activateSheet->TrashSheet()) + if (not layout.isNull() && not activateSheet->TrashSheet() && layout->GetFocusedSheet() != activateSheet) { layout->SetFocusedSheet(activateSheet); } @@ -69,10 +69,12 @@ void VPUndoMovePieceOnSheet::undo() if (not piece.isNull()) { piece->SetSheet(sourceSheet); + piece->SetSelected(false); if (not layout.isNull()) { emit layout->PieceSheetChanged(piece); + emit layout->PieceSelectionChanged(piece); } } } @@ -92,7 +94,7 @@ void VPUndoMovePieceOnSheet::redo() if (not activateSheet.isNull()) { layout = activateSheet->GetLayout(); - if (not layout.isNull() && not activateSheet->TrashSheet()) + if (not layout.isNull() && not activateSheet->TrashSheet() && layout->GetFocusedSheet() != activateSheet) { layout->SetFocusedSheet(activateSheet); } diff --git a/src/app/puzzle/undocommands/vpundooriginmove.cpp b/src/app/puzzle/undocommands/vpundooriginmove.cpp index b2e5e21b6..b9e66add8 100644 --- a/src/app/puzzle/undocommands/vpundooriginmove.cpp +++ b/src/app/puzzle/undocommands/vpundooriginmove.cpp @@ -59,7 +59,10 @@ void VPUndoOriginMove::undo() return; } - layout->SetFocusedSheet(sheet); + if (layout->GetFocusedSheet() != sheet) + { + layout->SetFocusedSheet(sheet); + } sheet->SetTransformationOrigin(m_oldOrigin); layout->TransformationOriginChanged(); @@ -80,7 +83,10 @@ void VPUndoOriginMove::redo() return; } - layout->SetFocusedSheet(sheet); + if (layout->GetFocusedSheet() != sheet) + { + layout->SetFocusedSheet(sheet); + } sheet->SetTransformationOrigin(m_origin); emit layout->TransformationOriginChanged(); diff --git a/src/app/puzzle/undocommands/vpundopiecemove.cpp b/src/app/puzzle/undocommands/vpundopiecemove.cpp index 3b90642bd..c8941a32f 100644 --- a/src/app/puzzle/undocommands/vpundopiecemove.cpp +++ b/src/app/puzzle/undocommands/vpundopiecemove.cpp @@ -59,7 +59,10 @@ void VPUndoPieceMove::undo() return; } - layout->SetFocusedSheet(piece->Sheet()); + if (layout->GetFocusedSheet() != piece->Sheet()) + { + layout->SetFocusedSheet(piece->Sheet()); + } piece->SetMatrix(m_oldTransform); emit layout->PieceTransformationChanged(piece); @@ -80,7 +83,10 @@ void VPUndoPieceMove::redo() return; } - layout->SetFocusedSheet(piece->Sheet()); + if (layout->GetFocusedSheet() != piece->Sheet()) + { + layout->SetFocusedSheet(piece->Sheet()); + } piece->Translate(m_dx, m_dy); emit layout->PieceTransformationChanged(piece); @@ -117,7 +123,7 @@ auto VPUndoPieceMove::id() const -> int // move pieces //--------------------------------------------------------------------------------------------------------------------- -VPUndoPiecesMove::VPUndoPiecesMove(const QVector &pieces, qreal dx, qreal dy, bool allowMerge, +VPUndoPiecesMove::VPUndoPiecesMove(const QList &pieces, qreal dx, qreal dy, bool allowMerge, QUndoCommand *parent) : VPUndoCommand(allowMerge, parent), m_dx(dx), @@ -149,7 +155,11 @@ void VPUndoPiecesMove::undo() return; } - layout->SetFocusedSheet(Sheet()); + VPSheetPtr sheet = Sheet(); + if (layout->GetFocusedSheet() != sheet) + { + layout->SetFocusedSheet(sheet); + } for (const auto& piece : m_pieces) { @@ -179,7 +189,11 @@ void VPUndoPiecesMove::redo() return; } - layout->SetFocusedSheet(Sheet()); + VPSheetPtr sheet = Sheet(); + if (layout->GetFocusedSheet() != sheet) + { + layout->SetFocusedSheet(sheet); + } for (const auto& piece : m_pieces) { diff --git a/src/app/puzzle/undocommands/vpundopiecemove.h b/src/app/puzzle/undocommands/vpundopiecemove.h index 9c4bf09e3..fe84e3413 100644 --- a/src/app/puzzle/undocommands/vpundopiecemove.h +++ b/src/app/puzzle/undocommands/vpundopiecemove.h @@ -38,7 +38,7 @@ class VPUndoPieceMove : public VPUndoCommand { Q_OBJECT public: - explicit VPUndoPieceMove(const VPPiecePtr &piece, qreal dx, qreal dy, bool allowMerge, + explicit VPUndoPieceMove(const VPPiecePtr &piece, qreal dx, qreal dy, bool allowMerge = false, QUndoCommand *parent = nullptr); virtual ~VPUndoPieceMove()=default; @@ -84,7 +84,7 @@ class VPUndoPiecesMove : public VPUndoCommand { Q_OBJECT public: - explicit VPUndoPiecesMove(const QVector &pieces, qreal dx, qreal dy, bool allowMerge, + explicit VPUndoPiecesMove(const QList &pieces, qreal dx, qreal dy, bool allowMerge = false, QUndoCommand *parent = nullptr); virtual ~VPUndoPiecesMove()=default; diff --git a/src/app/puzzle/undocommands/vpundopiecerotate.cpp b/src/app/puzzle/undocommands/vpundopiecerotate.cpp index f947c4d94..a264b70c6 100644 --- a/src/app/puzzle/undocommands/vpundopiecerotate.cpp +++ b/src/app/puzzle/undocommands/vpundopiecerotate.cpp @@ -59,7 +59,10 @@ void VPUndoPieceRotate::undo() return; } - layout->SetFocusedSheet(piece->Sheet()); + if (layout->GetFocusedSheet() != piece->Sheet()) + { + layout->SetFocusedSheet(piece->Sheet()); + } piece->SetMatrix(m_oldTransform); emit layout->PieceTransformationChanged(piece); @@ -80,7 +83,10 @@ void VPUndoPieceRotate::redo() return; } - layout->SetFocusedSheet(piece->Sheet()); + if (layout->GetFocusedSheet() != piece->Sheet()) + { + layout->SetFocusedSheet(piece->Sheet()); + } piece->Rotate(m_origin, m_angle); emit layout->PieceTransformationChanged(piece); @@ -116,7 +122,7 @@ auto VPUndoPieceRotate::id() const -> int // rotate pieces //--------------------------------------------------------------------------------------------------------------------- -VPUndoPiecesRotate::VPUndoPiecesRotate(const QVector &pieces, const QPointF &origin, qreal angle, +VPUndoPiecesRotate::VPUndoPiecesRotate(const QList &pieces, const QPointF &origin, qreal angle, bool allowMerge, QUndoCommand *parent) : VPUndoCommand(allowMerge, parent), m_origin(origin), @@ -148,7 +154,11 @@ void VPUndoPiecesRotate::undo() return; } - layout->SetFocusedSheet(Sheet()); + VPSheetPtr sheet = Sheet(); + if (layout->GetFocusedSheet() != sheet) + { + layout->SetFocusedSheet(sheet); + } for (const auto& piece : m_pieces) { @@ -178,7 +188,11 @@ void VPUndoPiecesRotate::redo() return; } - layout->SetFocusedSheet(Sheet()); + VPSheetPtr sheet = Sheet(); + if (layout->GetFocusedSheet() != sheet) + { + layout->SetFocusedSheet(sheet); + } for (const auto& piece : m_pieces) { diff --git a/src/app/puzzle/undocommands/vpundopiecerotate.h b/src/app/puzzle/undocommands/vpundopiecerotate.h index 96a480e36..c9f5ab25e 100644 --- a/src/app/puzzle/undocommands/vpundopiecerotate.h +++ b/src/app/puzzle/undocommands/vpundopiecerotate.h @@ -38,7 +38,7 @@ class VPUndoPieceRotate : public VPUndoCommand { Q_OBJECT public: - VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge, + VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge = false, QUndoCommand *parent = nullptr); virtual ~VPUndoPieceRotate()=default; @@ -85,8 +85,8 @@ class VPUndoPiecesRotate : public VPUndoCommand { Q_OBJECT public: - explicit VPUndoPiecesRotate(const QVector &pieces, const QPointF &origin, qreal angle, bool allowMerge, - QUndoCommand *parent = nullptr); + explicit VPUndoPiecesRotate(const QList &pieces, const QPointF &origin, qreal angle, + bool allowMerge = false, QUndoCommand *parent = nullptr); virtual ~VPUndoPiecesRotate()=default; virtual void undo() override; diff --git a/src/app/puzzle/vpexporter.cpp b/src/app/puzzle/vpexporter.cpp index df4a2d86f..9a886bb12 100644 --- a/src/app/puzzle/vpexporter.cpp +++ b/src/app/puzzle/vpexporter.cpp @@ -44,10 +44,6 @@ void VPExporter::Export(VPLayout* layout, LayoutExportFormats format, VPMainGrap SetFileName(fileName); QSizeF size = QSizeF(layout->GetFocusedSheet()->GetLayout()->LayoutSettings().GetSheetSize()); - if(layout->GetFocusedSheet()->GetLayout()->LayoutSettings().GetOrientation() == PageOrientation::Landscape) - { - size.transpose(); - } const QRectF rect = QRectF(0, 0, size.width(), size.height()); SetImageRect(rect); diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index b65acc6df..d2c4a9d75 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -49,6 +49,8 @@ #include "layout/vpsheet.h" #include "dialogs/dialogpuzzlepreferences.h" #include "undocommands/vpundoaddsheet.h" +#include "undocommands/vpundopiecerotate.h" +#include "undocommands/vpundopiecemove.h" #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) #include "../vmisc/backport/qscopeguard.h" @@ -66,6 +68,56 @@ Q_LOGGING_CATEGORY(pWindow, "p.window") QT_WARNING_POP +namespace +{ +//--------------------------------------------------------------------------------------------------------------------- +void SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value) +{ + spinBox->blockSignals(true); + spinBox->setValue(value); + spinBox->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void SetCheckBoxValue(QCheckBox *checkbox, bool value) +{ + checkbox->blockSignals(true); + checkbox->setChecked(value); + checkbox->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void SetLineEditValue(QLineEdit *lineEdit, const QString &value) +{ + lineEdit->blockSignals(true); + lineEdit->setText(value); + lineEdit->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void SetPlainTextEditValue(QPlainTextEdit *textEdit, const QString &value) +{ + textEdit->blockSignals(true); + textEdit->setPlainText(value); + textEdit->blockSignals(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PiecesBoundingRect(const QList &selectedPieces) -> QRectF +{ + QRectF rect; + for (const auto& item : selectedPieces) + { + if (not item.isNull()) + { + rect = rect.united(item->MappedDetailBoundingRect()); + } + } + + return rect; +} +} // namespace + //--------------------------------------------------------------------------------------------------------------------- VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : VAbstractMainWindow(parent), @@ -78,6 +130,21 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : { ui->setupUi(this); + connect(m_layout.get(), &VPLayout::PieceSelectionChanged, this, &VPMainWindow::on_PieceSelectionChanged); + connect(m_layout.get(), &VPLayout::LayoutChanged, this, [this]() + { + LayoutWasSaved(false); + }); + connect(m_layout.get(), &VPLayout::PieceTransformationChanged, this, [this]() + { + SetPropertyTabCurrentPieceData(); + }); + + connect(m_undoStack, &QUndoStack::cleanChanged, this, [this](bool clean) + { + LayoutWasSaved(clean); + }); + // init the tile factory m_tileFactory = new VPTileFactory(m_layout, VPApplication::VApp()->Settings()); m_tileFactory->refreshTileInfos(); @@ -113,11 +180,14 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : UpdateWindowTitle(); } }); + + m_graphicsView->RefreshLayout(); } //--------------------------------------------------------------------------------------------------------------------- VPMainWindow::~VPMainWindow() { + delete m_undoStack; delete ui; delete m_carrousel; } @@ -205,6 +275,8 @@ auto VPMainWindow::LoadFile(QString path) -> bool m_layout->SetFocusedSheet(); + m_oldLayoutUnit = m_layout->LayoutSettings().GetUnit(); + // updates the properties with the loaded data SetPropertiesData(); @@ -212,6 +284,7 @@ auto VPMainWindow::LoadFile(QString path) -> bool m_graphicsView->RefreshLayout(); m_graphicsView->RefreshPieces(); m_tileFactory->refreshTileInfos(); + VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView); return true; } @@ -429,48 +502,211 @@ void VPMainWindow::SetupMenu() //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitProperties() { + ui->tabWidgetProperties->setCurrentIndex(0); + + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + m_oldLayoutUnit = settings->LayoutUnit(); + InitPropertyTabCurrentPiece(); InitPropertyTabCurrentSheet(); - InitPropertyTabLayout(); InitPropertyTabTiles(); + InitPropertyTabLayout(); } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitPropertyTabCurrentPiece() { - // FIXME ---- For MVP we hide a few things. To be displayed when functions there - ui->groupBoxLayoutControl->hide(); - ui->groupBoxCurrentPieceGeometry->hide(); + connect(ui->lineEditCurrentPieceName, &QLineEdit::textEdited, this, [this](const QString &text) + { + QList selectedPieces = SelectedPieces(); + if (selectedPieces.size() == 1) + { + VPPiecePtr selectedPiece = selectedPieces.first(); + if (not selectedPiece.isNull()) + { + selectedPiece->SetName(text); + LayoutWasSaved(false); + } + } + }); + connect(ui->plainTextEditCurrentPieceUUID, &QPlainTextEdit::textChanged, this, [this]() + { + QList selectedPieces = SelectedPieces(); + if (selectedPieces.size() == 1) + { + VPPiecePtr selectedPiece = selectedPieces.first(); + if (not selectedPiece.isNull()) + { + const QUuid temp = QUuid(ui->plainTextEditCurrentPieceUUID->toPlainText()); + if (not temp.isNull()) + { + selectedPiece->SetUUID(temp); + } + LayoutWasSaved(false); + } + } + }); - // ------------------------------ placement ----------------------------------- - connect(ui->doubleSpinBoxCurrentPieceBoxPositionX, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_CurrentPiecePositionEdited); - connect(ui->doubleSpinBoxCurrentPieceBoxPositionY, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_CurrentPiecePositionEdited); + connect(ui->checkBoxCurrentPieceShowSeamline, &QCheckBox::toggled, this, [this](bool checked) + { + QList selectedPieces = SelectedPieces(); + if (selectedPieces.size() == 1) + { + VPPiecePtr selectedPiece = selectedPieces.first(); + if (not selectedPiece.isNull()) + { +// selectedPiece->SetShowSeamline(checked); +// LayoutWasSaved(false); + } + } + }); + + connect(ui->checkBoxCurrentPieceMirrorPiece, &QCheckBox::toggled, this, [this](bool checked) + { + QList selectedPieces = SelectedPieces(); + if (selectedPieces.size() == 1) + { + VPPiecePtr selectedPiece = selectedPieces.first(); + if (not selectedPiece.isNull()) + { + selectedPiece->SetMirror(checked); + LayoutWasSaved(false); + emit m_layout->PieceTransformationChanged(selectedPiece); + } + } + }); + + // Translate + ui->comboBoxTranslateUnit->addItem(tr("Millimiters"), QVariant(UnitsToStr(Unit::Mm))); + ui->comboBoxTranslateUnit->addItem(tr("Centimeters"), QVariant(UnitsToStr(Unit::Cm))); + ui->comboBoxTranslateUnit->addItem(tr("Inches"), QVariant(UnitsToStr(Unit::Inch))); + ui->comboBoxTranslateUnit->addItem(tr("Pixels"), QVariant(UnitsToStr(Unit::Px))); + + m_oldPieceTranslationUnit = Unit::Mm; + ui->comboBoxTranslateUnit->blockSignals(true); + ui->comboBoxTranslateUnit->setCurrentIndex(0); + ui->comboBoxTranslateUnit->blockSignals(false); + + const int minTranslate = -1000; + const int maxTranslate = 1000; + + ui->doubleSpinBoxCurrentPieceBoxPositionX->setMinimum( + UnitConvertor(minTranslate, Unit::Cm, m_oldPieceTranslationUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionX->setMaximum( + UnitConvertor(maxTranslate, Unit::Cm, m_oldPieceTranslationUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue(0); + + ui->doubleSpinBoxCurrentPieceBoxPositionY->setMinimum( + UnitConvertor(minTranslate, Unit::Cm, m_oldPieceTranslationUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setMaximum( + UnitConvertor(maxTranslate, Unit::Cm, m_oldPieceTranslationUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue(0); + + connect(ui->comboBoxTranslateUnit, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() + { + const Unit newUnit = TranslateUnit(); + const qreal oldTranslateX = ui->doubleSpinBoxCurrentPieceBoxPositionX->value(); + const qreal oldTranslateY = ui->doubleSpinBoxCurrentPieceBoxPositionY->value(); + + ui->doubleSpinBoxCurrentPieceBoxPositionX->setMinimum(UnitConvertor(minTranslate, Unit::Cm, newUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionX->setMaximum(UnitConvertor(maxTranslate, Unit::Cm, newUnit)); + + ui->doubleSpinBoxCurrentPieceBoxPositionY->setMinimum(UnitConvertor(minTranslate, Unit::Cm, newUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setMaximum(UnitConvertor(maxTranslate, Unit::Cm, newUnit)); + + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue( + UnitConvertor(oldTranslateX, m_oldPieceTranslationUnit, newUnit)); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue( + UnitConvertor(oldTranslateY, m_oldPieceTranslationUnit, newUnit)); + + m_oldPieceTranslationUnit = newUnit; + }); + + SetCheckBoxValue(ui->checkBoxRelativeTranslation, true); + connect(ui->checkBoxRelativeTranslation, &QCheckBox::toggled, this, &VPMainWindow::on_RelativeTranslationChanged); + + // Rotate + ui->doubleSpinBoxCurrentPieceAngle->setValue(0); + + ui->toolButtonCurrentPieceRotationAnticlockwise->setChecked(true); + ui->checkBoxTransformSeparately->setChecked(false); + + QPushButton *bApply = ui->buttonBox->button(QDialogButtonBox::Apply); + SCASSERT(bApply != nullptr) + connect(bApply, &QPushButton::clicked, this, &VPMainWindow::on_ApplyPieceTransformation); + + QPushButton *bReset = ui->buttonBox->button(QDialogButtonBox::Reset); + SCASSERT(bReset != nullptr) + connect(bReset, &QPushButton::clicked, this, &VPMainWindow::on_ResetPieceTransformationSettings); } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitPropertyTabCurrentSheet() { - // FIXME ---- For MVP we hide a few things. To be displayed when functions there - ui->pushButtonSheetRemoveUnusedLength->hide(); - ui->groupBoxSheetControl->hide(); + connect(ui->lineEditSheetName, &QLineEdit::textEdited, this, [this](const QString &text) + { + if (not m_layout.isNull()) + { + VPSheetPtr sheet = m_layout->GetFocusedSheet(); + if (not sheet.isNull()) + { + sheet->SetName(text); + LayoutWasSaved(false); - // some of the UI Elements are connected to the slots via auto-connect - // see https://doc.qt.io/qt-5/designer-using-a-ui-file.html#widgets-and-dialogs-with-auto-connect + if(m_carrousel != nullptr) + { + m_carrousel->RefreshSheetNames(); + } + } + } + }); - // -------------------- layout width, length, orientation ------------------------ - connect(ui->doubleSpinBoxSheetWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, + // -------------------- layout units --------------------------- + 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))); + + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(UnitsToStr(settings->LayoutUnit())); + if (indexUnit != -1) + { + ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit); + } + + connect(ui->comboBoxLayoutUnit, QOverload::of(&QComboBox::currentIndexChanged), + this, &VPMainWindow::on_ConvertPaperSize); + + // -------------------- sheet template --------------------------- + VAbstractLayoutDialog::InitTemplates(ui->comboBoxSheetTemplates); + + connect(ui->comboBoxSheetTemplates, QOverload::of(&QComboBox::currentIndexChanged), + this, [this]{SheetSize(SheetTemplate());}); + + // -------------------- paper size --------------------------- + MinimumSheetPaperSize(); + + const QString suffix = " " + UnitsToStr(LayoutUnit(), true); + + ui->doubleSpinBoxSheetPaperWidth->setSuffix(suffix); + ui->doubleSpinBoxSheetPaperHeight->setSuffix(suffix); + + connect(ui->doubleSpinBoxSheetPaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, &VPMainWindow::on_SheetSizeChanged); - connect(ui->doubleSpinBoxSheetLength, QOverload::of(&QDoubleSpinBox::valueChanged), this, + connect(ui->doubleSpinBoxSheetPaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), this, &VPMainWindow::on_SheetSizeChanged); - connect(ui->radioButtonSheetPortrait, QOverload::of(&QRadioButton::clicked), this, + connect(ui->toolButtonSheetPortraitOritation, &QToolButton::toggled, this, &VPMainWindow::on_SheetOrientationChanged); - connect(ui->radioButtonSheetLandscape, QOverload::of(&QRadioButton::clicked), this, + connect(ui->toolButtonSheetLandscapeOrientation, &QToolButton::toggled, this, &VPMainWindow::on_SheetOrientationChanged); // -------------------- margins ------------------------ + ui->doubleSpinBoxSheetMarginLeft->setSuffix(suffix); + ui->doubleSpinBoxSheetMarginRight->setSuffix(suffix); + ui->doubleSpinBoxSheetMarginTop->setSuffix(suffix); + ui->doubleSpinBoxSheetMarginBottom->setSuffix(suffix); + connect(ui->doubleSpinBoxSheetMarginTop, QOverload::of(&QDoubleSpinBox::valueChanged), this, &VPMainWindow::on_SheetMarginChanged); connect(ui->doubleSpinBoxSheetMarginRight, QOverload::of(&QDoubleSpinBox::valueChanged), this, @@ -480,111 +716,176 @@ void VPMainWindow::InitPropertyTabCurrentSheet() connect(ui->doubleSpinBoxSheetMarginLeft, QOverload::of(&QDoubleSpinBox::valueChanged), this, &VPMainWindow::on_SheetMarginChanged); - // ------------------- follow grainline ----------------------- - connect(ui->radioButtonSheetFollowGrainlineNo, QOverload::of(&QRadioButton::clicked), this, - &VPMainWindow::on_SheetFollowGrainlineChanged); - connect(ui->radioButtonSheetFollowGrainlineVertical, QOverload::of(&QRadioButton::clicked), this, - &VPMainWindow::on_SheetFollowGrainlineChanged); - connect(ui->radioButtonSheetFollowGrainlineHorizontal, QOverload::of(&QRadioButton::clicked), this, - &VPMainWindow::on_SheetFollowGrainlineChanged); - - // -------------------- sheet template --------------------------- - - // FIXME: find a nicer way to initiliase it - QVector sheetTemplates = QVector(); - sheetTemplates.append(PaperSizeTemplate::A0); - sheetTemplates.append(PaperSizeTemplate::A1); - sheetTemplates.append(PaperSizeTemplate::A2); - sheetTemplates.append(PaperSizeTemplate::A3); - sheetTemplates.append(PaperSizeTemplate::A4); - sheetTemplates.append(PaperSizeTemplate::Letter); - sheetTemplates.append(PaperSizeTemplate::Legal); - sheetTemplates.append(PaperSizeTemplate::Tabloid); - sheetTemplates.append(PaperSizeTemplate::Roll24in); - sheetTemplates.append(PaperSizeTemplate::Roll30in); - sheetTemplates.append(PaperSizeTemplate::Roll36in); - sheetTemplates.append(PaperSizeTemplate::Roll42in); - sheetTemplates.append(PaperSizeTemplate::Roll44in); - sheetTemplates.append(PaperSizeTemplate::Roll48in); - sheetTemplates.append(PaperSizeTemplate::Roll62in); - sheetTemplates.append(PaperSizeTemplate::Roll72in); - sheetTemplates.append(PaperSizeTemplate::Custom); - - ui->comboBoxSheetTemplate->blockSignals(true); - VPLayoutSettings::PopulateComboBox(&sheetTemplates, ui->comboBoxSheetTemplate); - ui->comboBoxSheetTemplate->blockSignals(false); - - ui->comboBoxSheetTemplate->setCurrentIndex(0); - - // ---------------------- export format -------------------------- - - VPExporter exporter; - for (auto &v : exporter.InitFormats()) + connect(ui->checkBoxLayoutIgnoreFileds, &QCheckBox::stateChanged, this, [this](int state) { - ui->comboBoxSheetExportFormat->addItem(v.first, QVariant(static_cast(v.second))); - } + if (not m_layout.isNull()) + { + ui->doubleSpinBoxSheetMarginLeft->setDisabled(state != 0); + ui->doubleSpinBoxSheetMarginRight->setDisabled(state != 0); + ui->doubleSpinBoxSheetMarginTop->setDisabled(state != 0); + ui->doubleSpinBoxSheetMarginBottom->setDisabled(state != 0); + + m_layout->LayoutSettings().SetIgnoreMargins(state != 0); + LayoutWasSaved(false); + m_tileFactory->refreshTileInfos(); + m_graphicsView->RefreshLayout(); + } + }); + + ui->groupBoxSheetGrid->setVisible(false); // temporary hide } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitPropertyTabTiles() { - // -------------------- layout width, length, orientation ------------------------ - connect(ui->doubleSpinBoxTilesWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_TilesSizeChanged); - connect(ui->doubleSpinBoxTilesLength, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_TilesSizeChanged); - connect(ui->radioButtonTilesPortrait, QOverload::of(&QRadioButton::clicked), this, - &VPMainWindow::on_TilesOrientationChanged); - connect(ui->radioButtonTilesLandscape, QOverload::of(&QRadioButton::clicked), this, - &VPMainWindow::on_TilesOrientationChanged); - // -------------------- tiles template - QVector tilesTemplates = QVector(); - tilesTemplates.append(PaperSizeTemplate::A0); - tilesTemplates.append(PaperSizeTemplate::A1); - tilesTemplates.append(PaperSizeTemplate::A2); - tilesTemplates.append(PaperSizeTemplate::A3); - tilesTemplates.append(PaperSizeTemplate::A4); - tilesTemplates.append(PaperSizeTemplate::Letter); - tilesTemplates.append(PaperSizeTemplate::Legal); - tilesTemplates.append(PaperSizeTemplate::Custom); + VAbstractLayoutDialog::InitTileTemplates(ui->comboBoxTileTemplates, true); - ui->comboBoxTilesTemplate->blockSignals(true); - VPLayoutSettings::PopulateComboBox(&tilesTemplates, ui->comboBoxTilesTemplate); - ui->comboBoxTilesTemplate->blockSignals(false); + connect(ui->comboBoxTileTemplates, QOverload::of(&QComboBox::currentIndexChanged), + this, [this]{TileSize(TileTemplate());}); - ui->comboBoxTilesTemplate->setCurrentIndex(4); //A4 + // -------------------- paper size --------------------------- + MinimumTilePaperSize(); + const QString suffix = " " + UnitsToStr(LayoutUnit(), true); + + ui->doubleSpinBoxTilePaperWidth->setSuffix(suffix); + ui->doubleSpinBoxTilePaperHeight->setSuffix(suffix); + + connect(ui->doubleSpinBoxTilePaperWidth, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &VPMainWindow::on_TilesSizeChanged); + connect(ui->doubleSpinBoxTilePaperHeight, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &VPMainWindow::on_TilesSizeChanged); + connect(ui->toolButtonTilePortraitOrientation, &QToolButton::toggled, this, + &VPMainWindow::on_TilesOrientationChanged); + connect(ui->toolButtonTileLandscapeOrientation, &QToolButton::toggled, this, + &VPMainWindow::on_TilesOrientationChanged); // -------------------- margins ------------------------ - connect(ui->doubleSpinBoxTilesMarginTop, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_TilesMarginChanged); - connect(ui->doubleSpinBoxTilesMarginRight, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_TilesMarginChanged); - connect(ui->doubleSpinBoxTilesMarginBottom, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_TilesMarginChanged); - connect(ui->doubleSpinBoxTilesMarginLeft, QOverload::of(&QDoubleSpinBox::valueChanged), this, - &VPMainWindow::on_TilesMarginChanged); -} + ui->doubleSpinBoxTileMarginLeft->setSuffix(suffix); + ui->doubleSpinBoxTileMarginRight->setSuffix(suffix); + ui->doubleSpinBoxTileMarginTop->setSuffix(suffix); + ui->doubleSpinBoxTileMarginBottom->setSuffix(suffix); + connect(ui->doubleSpinBoxTileMarginTop, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &VPMainWindow::on_TilesMarginChanged); + connect(ui->doubleSpinBoxTileMarginRight, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &VPMainWindow::on_TilesMarginChanged); + connect(ui->doubleSpinBoxTileMarginBottom, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &VPMainWindow::on_TilesMarginChanged); + connect(ui->doubleSpinBoxTileMarginLeft, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &VPMainWindow::on_TilesMarginChanged); + + connect(ui->checkBoxTileIgnoreFileds, &QCheckBox::stateChanged, this, [this](int state) + { + if (not m_layout.isNull()) + { + ui->doubleSpinBoxTileMarginLeft->setDisabled(state != 0); + ui->doubleSpinBoxTileMarginRight->setDisabled(state != 0); + ui->doubleSpinBoxTileMarginTop->setDisabled(state != 0); + ui->doubleSpinBoxTileMarginBottom->setDisabled(state != 0); + + m_layout->LayoutSettings().SetIgnoreTilesMargins(state != 0); + LayoutWasSaved(false); + m_tileFactory->refreshTileInfos(); + m_graphicsView->RefreshLayout(); + } + }); + + // -------------------- control ------------------------ + connect(ui->checkBoxTilesShowTiles, &QCheckBox::toggled, this, [this](bool checked) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetShowTiles(checked); + LayoutWasSaved(false); + m_graphicsView->RefreshLayout(); + } + }); +} //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitPropertyTabLayout() { - // FIXME ---- For MVP we hide a few things. To be displayed when functions there - ui->groupBoxLayoutControl->hide(); + connect(ui->lineEditLayoutName, &QLineEdit::textEdited, this, [this](const QString &text) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetTitle(text); + LayoutWasSaved(false); + } + }); - // -------------------- init the unit combobox --------------------- - ui->comboBoxLayoutUnit->addItem(tr("Centimeters"), QVariant(UnitsToStr(Unit::Cm))); - ui->comboBoxLayoutUnit->addItem(tr("Millimiters"), QVariant(UnitsToStr(Unit::Mm))); - ui->comboBoxLayoutUnit->addItem(tr("Inches"), QVariant(UnitsToStr(Unit::Inch))); + connect(ui->plainTextEditLayoutDescription, &QPlainTextEdit::textChanged, this, [this]() + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetDescription(ui->plainTextEditLayoutDescription->toPlainText()); + LayoutWasSaved(false); + } + }); - // set default unit - TODO when we have the setting for the unit -// const qint32 indexUnit = -1;//ui->comboBoxLayoutUnit->findData(qApp->ValentinaSettings()->GetUnit()); -// if (indexUnit != -1) -// { -// ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit); -// } + connect(ui->checkBoxLayoutWarningPiecesSuperposition, &QCheckBox::toggled, this, [this](bool checked) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetWarningSuperpositionOfPieces(checked); + LayoutWasSaved(false); + // TODO update the QGraphicView + } + }); + + connect(ui->checkBoxLayoutWarningPiecesOutOfBound, &QCheckBox::toggled, this, [this](bool checked) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetWarningPiecesOutOfBound(checked); + LayoutWasSaved(false); + // TODO update the QGraphicView + } + }); + + connect(ui->checkBoxSheetStickyEdges, &QCheckBox::toggled, this, [this](bool checked) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetStickyEdges(checked); + LayoutWasSaved(false); + } + }); + + connect(ui->checkBoxFollowGainline, &QCheckBox::toggled, this, [this](bool checked) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetFollowGrainline(checked); + LayoutWasSaved(false); + // TODO update the QGraphicView + } + }); + + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + ui->doubleSpinBoxSheetPiecesGap->setMaximum( + UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, settings->LayoutUnit())); + ui->doubleSpinBoxSheetPiecesGap->setSuffix(" " + UnitsToStr(LayoutUnit(), true)); + connect(ui->doubleSpinBoxSheetPiecesGap, QOverload::of(&QDoubleSpinBox::valueChanged), this, + [this](double d) + { + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetPiecesGapConverted(d); + LayoutWasSaved(false); + // TODO update the QGraphicView + } + }); + + connect(ui->pushButtonLayoutExport, &QPushButton::clicked, this, [this]() + { + if (not m_layout.isNull()) + { + // TODO export layout + } + }); } //--------------------------------------------------------------------------------------------------------------------- @@ -600,158 +901,307 @@ void VPMainWindow::InitCarrousel() //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::SetPropertiesData() { - if(m_layout == nullptr) - { - // TODO : hide the tabs when there is no layout - } - else - { - SetPropertyTabCurrentPieceData(); - SetPropertyTabSheetData(); - SetPropertyTabTilesData(); - SetPropertyTabLayoutData(); - } + SetPropertyTabCurrentPieceData(); + SetPropertyTabSheetData(); + SetPropertyTabTilesData(); + SetPropertyTabLayoutData(); } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::SetPropertyTabCurrentPieceData() { - if(m_selectedPieces.count() == 0) + QList selectedPieces = SelectedPieces(); + + if(selectedPieces.isEmpty()) { // show the content "no piece selected" + ui->labelCurrentPieceNoPieceSelected->setVisible(true); - ui->containerCurrentPieceNoData->setVisible(true); - ui->containerCurrentPieceData->setVisible(false); - ui->containerCurrentPieceMultipleData->setVisible(false); + ui->groupBoxCurrentPieceInfo->setVisible(false); + ui->groupBoxPieceTransformation->setVisible(false); + ui-> groupBoxCurrentPieceSeamline->setVisible(false); + ui->groupBoxCurrentPieceGeometry->setVisible(false); } - else if(m_selectedPieces.count() == 1) + else if(selectedPieces.count() == 1) { - // show the content "selected piece data" - ui->containerCurrentPieceNoData->setVisible(false); - ui->containerCurrentPieceData->setVisible(true); - ui->containerCurrentPieceMultipleData->setVisible(false); + ui->labelCurrentPieceNoPieceSelected->setVisible(false); - VPPiece *selectedPiece = m_selectedPieces.first(); + ui->groupBoxCurrentPieceInfo->setVisible(true); + ui->groupBoxPieceTransformation->setVisible(true); + ui-> groupBoxCurrentPieceSeamline->setVisible(true); + ui->groupBoxCurrentPieceGeometry->setVisible(true); + + VPPiecePtr selectedPiece = selectedPieces.first(); // set the value to the current piece - ui->lineEditCurrentPieceName->setText(selectedPiece->GetName()); - ui->plainTextEditCurrentPieceUUID->setPlainText(selectedPiece->GetUUID().toString()); + SetLineEditValue(ui->lineEditCurrentPieceName, selectedPiece->GetName()); + SetPlainTextEditValue(ui->plainTextEditCurrentPieceUUID, selectedPiece->GetUUID().toString()); -// ui->checkBoxCurrentPieceShowSeamline->setChecked(selectedPiece->GetShowSeamLine()); - ui->checkBoxCurrentPieceMirrorPiece->setChecked(selectedPiece->IsMirror()); +// SetCheckBoxValue(ui->checkBoxCurrentPieceShowSeamline, selectedPiece->GetShowSeamLine()); + SetCheckBoxValue(ui->checkBoxCurrentPieceMirrorPiece, selectedPiece->IsMirror()); - QPointF pos = selectedPiece->GetPosition(); - SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX, - UnitConvertor(pos.x(), Unit::Px, m_layout->LayoutSettings().GetUnit())); - SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY, - UnitConvertor(pos.y(), Unit::Px, m_layout->LayoutSettings().GetUnit())); + if (not ui->checkBoxRelativeTranslation->isChecked()) + { + QRectF rect = PiecesBoundingRect(selectedPieces); -// qreal angle = selectedPiece->GetRotation(); -// SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle); + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue( + UnitConvertor(rect.topLeft().x(), Unit::Px, TranslateUnit())); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue( + UnitConvertor(rect.topLeft().y(), Unit::Px, TranslateUnit())); + } } else { // show the content "multiple pieces selected" - ui->containerCurrentPieceNoData->setVisible(false); - ui->containerCurrentPieceData->setVisible(false); - ui->containerCurrentPieceMultipleData->setVisible(true); + ui->labelCurrentPieceNoPieceSelected->setVisible(true); - // if needed in the future, we can show some properties that coul be edited for all the pieces + ui->groupBoxCurrentPieceInfo->setVisible(false); + ui->groupBoxPieceTransformation->setVisible(true); + ui->groupBoxCurrentPieceSeamline->setVisible(false); + ui->groupBoxCurrentPieceGeometry->setVisible(false); + + if (not ui->checkBoxRelativeTranslation->isChecked()) + { + QRectF rect = PiecesBoundingRect(selectedPieces); + + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue( + UnitConvertor(rect.topLeft().x(), Unit::Px, TranslateUnit())); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue( + UnitConvertor(rect.topLeft().y(), Unit::Px, TranslateUnit())); + } } } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::SetPropertyTabSheetData() { - // set name // TODO FIXME make it better - ui->lineEditSheetName->setText(m_layout->GetFocusedSheet()->GetName()); - - // set Width / Length - QSizeF size = m_layout->LayoutSettings().GetSheetSizeConverted(); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetWidth, size.width()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetLength, size.height()); - - // Set Orientation - if(m_layout->LayoutSettings().GetOrientation() == PageOrientation::Portrait) + if (not m_layout.isNull()) { - ui->radioButtonSheetPortrait->setChecked(true); + ui->groupBoxSheetInfos->setDisabled(false); + VPSheetPtr sheet = m_layout->GetFocusedSheet(); + SetLineEditValue(ui->lineEditSheetName, not sheet.isNull() ? sheet->GetName() : QString()); + + ui->groupBoxPaperFormat->setDisabled(false); + const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(UnitsToStr(m_layout->LayoutSettings().GetUnit())); + if (indexUnit != -1) + { + ui->comboBoxLayoutUnit->blockSignals(true); + ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit); + ui->comboBoxLayoutUnit->blockSignals(false); + } + else + { + ui->comboBoxLayoutUnit->setCurrentIndex(0); + } + + const QString suffix = " " + UnitsToStr(LayoutUnit(), true); + + ui->doubleSpinBoxSheetPaperWidth->setSuffix(suffix); + ui->doubleSpinBoxSheetPaperHeight->setSuffix(suffix); + + ui->doubleSpinBoxSheetMarginLeft->setSuffix(suffix); + ui->doubleSpinBoxSheetMarginRight->setSuffix(suffix); + ui->doubleSpinBoxSheetMarginTop->setSuffix(suffix); + ui->doubleSpinBoxSheetMarginBottom->setSuffix(suffix); + + // set Width / Length + QSizeF size = m_layout->LayoutSettings().GetSheetSizeConverted(); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperWidth, size.width()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperHeight, size.height()); + + SheetPaperSizeChanged(); + FindSheetTemplate(); + + // set margins + ui->groupBoxSheetMargin->setDisabled(false); + QMarginsF margins = m_layout->LayoutSettings().GetSheetMarginsConverted(); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginLeft, margins.left()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginTop, margins.top()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginRight, margins.right()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginBottom, margins.bottom()); + + CorrectSheetMaxMargins(); + + const bool ignoreMargins = m_layout->LayoutSettings().IgnoreMargins(); + SetCheckBoxValue(ui->checkBoxLayoutIgnoreFileds, ignoreMargins); + + ui->doubleSpinBoxSheetMarginLeft->setDisabled(ignoreMargins); + ui->doubleSpinBoxSheetMarginRight->setDisabled(ignoreMargins); + ui->doubleSpinBoxSheetMarginTop->setDisabled(ignoreMargins); + ui->doubleSpinBoxSheetMarginBottom->setDisabled(ignoreMargins); + + // set placement grid + ui->groupBoxSheetGrid->setDisabled(false); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetGridColWidth, + m_layout->LayoutSettings().GetGridColWidthConverted()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetGridRowHeight, + m_layout->LayoutSettings().GetGridRowHeightConverted()); + + SetCheckBoxValue(ui->checkBoxSheetShowGrid, m_layout->LayoutSettings().GetShowGrid()); + + ui->groupBoxSheetExport->setDisabled(false); } else { - ui->radioButtonSheetLandscape->setChecked(true); + ui->groupBoxSheetInfos->setDisabled(true); + SetLineEditValue(ui->lineEditSheetName, QString()); + + ui->groupBoxPaperFormat->setDisabled(true); + + ui->comboBoxLayoutUnit->blockSignals(true); + ui->comboBoxLayoutUnit->setCurrentIndex(-1); + ui->comboBoxLayoutUnit->blockSignals(false); + + ui->comboBoxSheetTemplates->blockSignals(true); + ui->comboBoxSheetTemplates->setCurrentIndex(-1); + ui->comboBoxSheetTemplates->blockSignals(false); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperWidth, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperHeight, 0); + + ui->groupBoxSheetMargin->setDisabled(true); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginLeft, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginTop, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginRight, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginBottom, 0); + + SetCheckBoxValue(ui->checkBoxLayoutIgnoreFileds, false); + + ui->groupBoxSheetGrid->setDisabled(true); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetGridColWidth, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetGridRowHeight, 0); + + SetCheckBoxValue(ui->checkBoxSheetShowGrid, false); + + ui->groupBoxSheetExport->setDisabled(true); } - - // set margins - QMarginsF margins = m_layout->LayoutSettings().GetSheetMarginsConverted(); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginLeft, margins.left()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginTop, margins.top()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginRight, margins.right()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginBottom, margins.bottom()); - - // set placement grid - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetGridColWidth, m_layout->LayoutSettings().GetGridColWidthConverted()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetGridRowHeight, m_layout->LayoutSettings().GetGridRowHeightConverted()); - SetCheckBoxValue(ui->checkBoxSheetShowGrid, m_layout->LayoutSettings().GetShowGrid()); - - // set pieces gap - SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, m_layout->LayoutSettings().GetPiecesGapConverted()); - - // set the checkboxes - SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().GetStickyEdges()); } - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::SetPropertyTabTilesData() { - // set Width / Length - QSizeF size = m_layout->LayoutSettings().GetTilesSizeConverted(); - SetDoubleSpinBoxValue(ui->doubleSpinBoxTilesWidth, size.width()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxTilesLength, size.height()); - - // Set Orientation - if(m_layout->LayoutSettings().GetTilesOrientation() == PageOrientation::Portrait) + if (not m_layout.isNull()) { - ui->radioButtonSheetPortrait->setChecked(true); + ui->groupBoxTilePaperFormat->setDisabled(false); + // set Width / Length + QSizeF size = m_layout->LayoutSettings().GetTilesSizeConverted(); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperWidth, size.width()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperHeight, size.height()); + + TilePaperSizeChanged(); + FindTileTemplate(); + + // set margins + ui->groupBoxTileMargins->setDisabled(false); + QMarginsF margins = m_layout->LayoutSettings().GetTilesMarginsConverted(); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginLeft, margins.left()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginTop, margins.top()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginRight, margins.right()); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginBottom, margins.bottom()); + + CorrectTileMaxMargins(); + + const bool ignoreMargins = m_layout->LayoutSettings().IgnoreTilesMargins(); + SetCheckBoxValue(ui->checkBoxTileIgnoreFileds, ignoreMargins); + + ui->doubleSpinBoxTileMarginLeft->setDisabled(ignoreMargins); + ui->doubleSpinBoxTileMarginRight->setDisabled(ignoreMargins); + ui->doubleSpinBoxTileMarginTop->setDisabled(ignoreMargins); + ui->doubleSpinBoxTileMarginBottom->setDisabled(ignoreMargins); + + const QString suffix = " " + UnitsToStr(LayoutUnit(), true); + + ui->doubleSpinBoxTilePaperWidth->setSuffix(suffix); + ui->doubleSpinBoxTilePaperHeight->setSuffix(suffix); + + ui->doubleSpinBoxTileMarginLeft->setSuffix(suffix); + ui->doubleSpinBoxTileMarginRight->setSuffix(suffix); + ui->doubleSpinBoxTileMarginTop->setSuffix(suffix); + ui->doubleSpinBoxTileMarginBottom->setSuffix(suffix); + + ui->groupBoxTilesControl->setDisabled(false); + + SetCheckBoxValue(ui->checkBoxTilesShowTiles, m_layout->LayoutSettings().GetShowTiles()); + + ui->groupBoxTilesExport->setDisabled(false); } else { - ui->radioButtonSheetLandscape->setChecked(true); + ui->groupBoxTilePaperFormat->setDisabled(true); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperWidth, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperHeight, 0); + + ui->groupBoxTileMargins->setDisabled(true); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginLeft, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginTop, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginRight, 0); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginBottom, 0); + + SetCheckBoxValue(ui->checkBoxTileIgnoreFileds, false); + + ui->groupBoxTilesControl->setDisabled(true); + + SetCheckBoxValue(ui->checkBoxTilesShowTiles, false); + + ui->groupBoxTilesExport->setDisabled(true); } - - // set margins - QMarginsF margins = m_layout->LayoutSettings().GetTilesMarginsConverted(); - SetDoubleSpinBoxValue(ui->doubleSpinBoxTilesMarginLeft, margins.left()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxTilesMarginTop, margins.top()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxTilesMarginRight, margins.right()); - SetDoubleSpinBoxValue(ui->doubleSpinBoxTilesMarginBottom, margins.bottom()); - - // set "show tiles" checkbox - SetCheckBoxValue(ui->checkBoxTilesShowTiles, m_layout->LayoutSettings().GetShowTiles()); } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::SetPropertyTabLayoutData() { - // set the title and description - ui->lineEditLayoutName->setText(m_layout->LayoutSettings().GetTitle()); - ui->plainTextEditLayoutDescription->setPlainText(m_layout->LayoutSettings().GetDescription()); - - // set Unit - int index = ui->comboBoxLayoutUnit->findData(QVariant(UnitsToStr(m_layout->LayoutSettings().GetUnit()))); - if(index != -1) + if (not m_layout.isNull()) { - ui->comboBoxLayoutUnit->blockSignals(true); // FIXME: is there a better way to block the signals? - ui->comboBoxLayoutUnit->setCurrentIndex(index); - ui->comboBoxLayoutUnit->blockSignals(false); - } + // set the title and description + ui->groupBoxLayoutInfos->setDisabled(false); + SetLineEditValue(ui->lineEditLayoutName, m_layout->LayoutSettings().GetTitle()); + SetPlainTextEditValue(ui->plainTextEditLayoutDescription, m_layout->LayoutSettings().GetDescription()); - // set controls - SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesOutOfBound, - m_layout->LayoutSettings().GetWarningPiecesOutOfBound()); - SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition, - m_layout->LayoutSettings().GetWarningSuperpositionOfPieces()); + // set controls + ui->groupBoxLayoutControl->setDisabled(false); + SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesOutOfBound, + m_layout->LayoutSettings().GetWarningPiecesOutOfBound()); + SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition, + m_layout->LayoutSettings().GetWarningSuperpositionOfPieces()); + SetCheckBoxValue(ui->checkBoxSheetStickyEdges, + m_layout->LayoutSettings().GetStickyEdges()); + SetCheckBoxValue(ui->checkBoxFollowGainline, + m_layout->LayoutSettings().GetFollowGrainline()); + + // set pieces gap + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, m_layout->LayoutSettings().GetPiecesGapConverted()); + + ui->doubleSpinBoxSheetPiecesGap->setSuffix(" " + UnitsToStr(LayoutUnit(), true)); + + ui->groupBoxLayoutExport->setDisabled(false); + } + else + { + ui->groupBoxLayoutInfos->setDisabled(true); + SetLineEditValue(ui->lineEditLayoutName, QString()); + SetPlainTextEditValue(ui->plainTextEditLayoutDescription, QString()); + + ui->groupBoxLayoutControl->setDisabled(true); + + ui->comboBoxLayoutUnit->blockSignals(true); + ui->comboBoxLayoutUnit->setCurrentIndex(-1); + ui->comboBoxLayoutUnit->blockSignals(false); + + // set controls + SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesOutOfBound, false); + SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition, false); + SetCheckBoxValue(ui->checkBoxSheetStickyEdges, false); + SetCheckBoxValue(ui->checkBoxFollowGainline, false); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, 0); + + ui->groupBoxLayoutExport->setDisabled(true); + } } @@ -830,22 +1280,6 @@ void VPMainWindow::InitScaleToolBar() ui->toolBarScale->addSeparator(); } -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value) -{ - spinBox->blockSignals(true); - spinBox->setValue(value); - spinBox->blockSignals(false); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::SetCheckBoxValue(QCheckBox *checkbox, bool value) -{ - checkbox->blockSignals(true); - checkbox->setChecked(value); - checkbox->blockSignals(false); -} - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::UpdateWindowTitle() { @@ -957,7 +1391,7 @@ auto VPMainWindow::MaybeSave() -> bool if (this->isWindowModified()) { QScopedPointer messageBox(new QMessageBox(tr("Unsaved changes"), - tr("Measurements have been modified.\n" + tr("Layout has been modified.\n" "Do you want to save your changes?"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel, this, Qt::Sheet)); @@ -993,75 +1427,75 @@ auto VPMainWindow::MaybeSave() -> bool //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::generateTiledPdf(QString fileName) { - if(not fileName.isEmpty()) - { - m_graphicsView->PrepareForExport(); - m_tileFactory->refreshTileInfos(); +// if(not fileName.isEmpty()) +// { +// m_graphicsView->PrepareForExport(); +// m_tileFactory->refreshTileInfos(); - PageOrientation tilesOrientation = m_layout->LayoutSettings().GetTilesOrientation(); +// PageOrientation tilesOrientation = m_layout->LayoutSettings().GetTilesOrientation(); - // ------------- Set up the printer - QScopedPointer printer(new QPrinter()); +// // ------------- Set up the printer +// QScopedPointer printer(new QPrinter()); - printer->setCreator(QGuiApplication::applicationDisplayName()+QChar(QChar::Space)+ - QCoreApplication::applicationVersion()); - printer->setPageOrientation(QPageLayout::Portrait); // in the pdf file the pages should always be in portrait +// printer->setCreator(QGuiApplication::applicationDisplayName()+QChar(QChar::Space)+ +// QCoreApplication::applicationVersion()); +// printer->setPageOrientation(QPageLayout::Portrait); // in the pdf file the pages should always be in portrait - // here we might need to so some rounding for the size. - printer->setPageSize(QPageSize(m_layout->LayoutSettings().GetTilesSize(Unit::Mm), - QPageSize::Millimeter)); - printer->setFullPage(true); +// // here we might need to so some rounding for the size. +// printer->setPageSize(QPageSize(m_layout->LayoutSettings().GetTilesSize(Unit::Mm), +// QPageSize::Millimeter)); +// printer->setFullPage(true); - #ifdef Q_OS_MAC - printer->setOutputFormat(QPrinter::NativeFormat); - #else - printer->setOutputFormat(QPrinter::PdfFormat); - #endif +// #ifdef Q_OS_MAC +// printer->setOutputFormat(QPrinter::NativeFormat); +// #else +// printer->setOutputFormat(QPrinter::PdfFormat); +// #endif - printer->setOutputFileName(fileName); - printer->setResolution(static_cast(PrintDPI)); - printer->setDocName(m_layout->GetFocusedSheet()->GetName()); +// printer->setOutputFileName(fileName); +// printer->setResolution(static_cast(PrintDPI)); +// printer->setDocName(m_layout->GetFocusedSheet()->GetName()); - // ------------- Set up the painter - QPainter painter; - if (not painter.begin(printer.data())) - { // failed to open file - qCritical() << tr("Failed to open file, is it writable?"); - return; - } - painter.setFont( QFont( QStringLiteral("Arial"), 8, QFont::Normal ) ); - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setBrush ( QBrush ( Qt::NoBrush ) ); +// // ------------- Set up the painter +// QPainter painter; +// if (not painter.begin(printer.data())) +// { // failed to open file +// qCritical() << tr("Failed to open file, is it writable?"); +// return; +// } +// painter.setFont( QFont( QStringLiteral("Arial"), 8, QFont::Normal ) ); +// painter.setRenderHint(QPainter::Antialiasing, true); +// painter.setBrush ( QBrush ( Qt::NoBrush ) ); - if(tilesOrientation == PageOrientation::Landscape) - { - // The landscape tiles have to be rotated, because the pages - // stay portrait in the pdf - painter.rotate(90); - painter.translate(0, -ToPixel(printer->pageRect(QPrinter::Millimeter).width(), Unit::Mm)); - } +// if(tilesOrientation == PageOrientation::Landscape) +// { +// // The landscape tiles have to be rotated, because the pages +// // stay portrait in the pdf +// painter.rotate(90); +// painter.translate(0, -ToPixel(printer->pageRect(QPrinter::Millimeter).width(), Unit::Mm)); +// } - for(int row=0;rowgetRowNb();row++) // for each row of the tiling grid - { - for(int col=0;colgetColNb();col++) // for each column of tiling grid - { - if(not (row == 0 && col == 0)) - { - if (not printer->newPage()) - { - qWarning("failed in flushing page to disk, disk full?"); - return; - } - } +// for(int row=0;rowgetRowNb();row++) // for each row of the tiling grid +// { +// for(int col=0;colgetColNb();col++) // for each column of tiling grid +// { +// if(not (row == 0 && col == 0)) +// { +// if (not printer->newPage()) +// { +// qWarning("failed in flushing page to disk, disk full?"); +// return; +// } +// } - m_tileFactory->drawTile(&painter, m_graphicsView, row, col); - } - } +// m_tileFactory->drawTile(&painter, m_graphicsView, row, col); +// } +// } - painter.end(); +// painter.end(); - m_graphicsView->CleanAfterExport(); - } +// m_graphicsView->CleanAfterExport(); +// } } //--------------------------------------------------------------------------------------------------------------------- @@ -1140,6 +1574,291 @@ void VPMainWindow::ConnectToPreferences(const QSharedPointer QList +{ + QList selectedPieces; + if (not m_layout.isNull()) + { + VPSheetPtr activeSheet = m_layout->GetFocusedSheet(); + if (not activeSheet.isNull()) + { + selectedPieces = activeSheet->GetSelectedPieces(); + } + } + + return selectedPieces; +} + +//--------------------------------------------------------------------------------------------------------------------- +Unit VPMainWindow::TranslateUnit() const +{ + return StrToUnits(ui->comboBoxTranslateUnit->currentData().toString()); +} + +//--------------------------------------------------------------------------------------------------------------------- +Unit VPMainWindow::LayoutUnit() const +{ + return StrToUnits(ui->comboBoxLayoutUnit->currentData().toString()); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPMainWindow::Template(VAbstractLayoutDialog::PaperSizeTemplate t) const -> QSizeF +{ + 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 VPMainWindow::SheetTemplate() const -> QSizeF +{ + auto t = static_cast(ui->comboBoxSheetTemplates->currentData().toInt()); + return Template(t); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPMainWindow::TileTemplate() const -> QSizeF +{ + auto t = static_cast(ui->comboBoxTileTemplates->currentData().toInt()); + return Template(t); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::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 VPMainWindow::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 VPMainWindow::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->doubleSpinBoxSheetPiecesGap->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->doubleSpinBoxSheetPiecesGap->setDecimals(5); + break; + default: + break; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::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 VPMainWindow::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); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::MinimumSheetPaperSize() +{ + const qreal value = UnitConvertor(1, Unit::Px, m_oldLayoutUnit); + ui->doubleSpinBoxSheetPaperWidth->setMinimum(value); + ui->doubleSpinBoxSheetPaperHeight->setMinimum(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::MinimumTilePaperSize() +{ + const qreal value = UnitConvertor(1, Unit::Px, m_oldLayoutUnit); + ui->doubleSpinBoxTilePaperWidth->setMinimum(value); + ui->doubleSpinBoxTilePaperHeight->setMinimum(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::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 = box->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); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::FindSheetTemplate() +{ + const qreal width = ui->doubleSpinBoxSheetPaperWidth->value(); + const qreal height = ui->doubleSpinBoxSheetPaperHeight->value(); + FindTemplate(ui->comboBoxSheetTemplates, width, height); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::FindTileTemplate() +{ + const qreal width = ui->doubleSpinBoxTilePaperWidth->value(); + const qreal height = ui->doubleSpinBoxTilePaperHeight->value(); + FindTemplate(ui->comboBoxTileTemplates, width, height); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::CorrectTileMaxMargins() +{ + 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 VPMainWindow::CorrectSheetMaxMargins() +{ + 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); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::CorrectMaxMargins() +{ + CorrectSheetMaxMargins(); + CorrectTileMaxMargins(); +} + //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_actionNew_triggered() { @@ -1393,23 +2112,11 @@ void VPMainWindow::on_actionAboutPuzzle_triggered() } //--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_comboBoxLayoutUnit_currentIndexChanged(int index) +void VPMainWindow::on_LayoutUnitChanged(int index) { Q_UNUSED(index); QVariant comboBoxValue = ui->comboBoxLayoutUnit->currentData(); - - if(comboBoxValue == QVariant(UnitsToStr(Unit::Cm))) - { - m_layout->LayoutSettings().SetUnit(Unit::Cm); - } - else if(comboBoxValue == QVariant(UnitsToStr(Unit::Mm))) - { - m_layout->LayoutSettings().SetUnit(Unit::Mm); - } - else if(comboBoxValue == QVariant(UnitsToStr(Unit::Inch))) - { - m_layout->LayoutSettings().SetUnit(Unit::Inch); - } + m_layout->LayoutSettings().SetUnit(StrToUnits(comboBoxValue.toString())); SetPropertyTabCurrentPieceData(); SetPropertyTabSheetData(); @@ -1417,87 +2124,44 @@ void VPMainWindow::on_comboBoxLayoutUnit_currentIndexChanged(int index) } //--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_lineEditSheetName_textChanged(const QString &text) +void VPMainWindow::on_SheetSizeChanged() { - m_layout->GetFocusedSheet()->SetName(text); - - if(m_carrousel != nullptr) + if (not m_layout.isNull()) { - m_carrousel->RefreshSheetNames(); + m_layout->LayoutSettings().SetSheetSizeConverted( + ui->doubleSpinBoxSheetPaperWidth->value(), + ui->doubleSpinBoxSheetPaperHeight->value()); + FindSheetTemplate(); + SheetPaperSizeChanged(); + CorrectMaxMargins(); + LayoutWasSaved(false); + + m_tileFactory->refreshTileInfos(); + m_graphicsView->RefreshLayout(); } } //--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_comboBoxSheetTemplate_currentIndexChanged(int index) +void VPMainWindow::on_SheetOrientationChanged(bool checked) { - PaperSizeTemplate tmpl = static_cast( - ui->comboBoxSheetTemplate->itemData(index).toInt() - ); - - QSizeF tmplSize = VPLayoutSettings::GetTemplateSize(tmpl); - if(!tmplSize.isEmpty()) + if (checked && not m_layout.isNull()) { - ui->doubleSpinBoxSheetWidth->blockSignals(true); - ui->doubleSpinBoxSheetLength->blockSignals(true); + const qreal width = ui->doubleSpinBoxSheetPaperWidth->value(); + const qreal height = ui->doubleSpinBoxSheetPaperHeight->value(); - ui->doubleSpinBoxSheetWidth->setValue(UnitConvertor(tmplSize.width(), Unit::Px, - m_layout->LayoutSettings().GetUnit())); - ui->doubleSpinBoxSheetLength->setValue(UnitConvertor(tmplSize.height(), Unit::Px, - m_layout->LayoutSettings().GetUnit())); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperWidth, height); + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperHeight, width); - on_SheetSizeChanged(false); + m_layout->LayoutSettings().SetSheetSizeConverted(height, width); - ui->doubleSpinBoxSheetWidth->blockSignals(false); - ui->doubleSpinBoxSheetLength->blockSignals(false); + SheetPaperSizeChanged(); + CorrectMaxMargins(); + LayoutWasSaved(false); + m_tileFactory->refreshTileInfos(); + m_graphicsView->RefreshLayout(); } } -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_SheetSizeChanged(bool changedViaSizeCombobox) -{ - m_layout->LayoutSettings().SetSheetSizeConverted( - ui->doubleSpinBoxSheetWidth->value(), - ui->doubleSpinBoxSheetLength->value() - ); - - if(changedViaSizeCombobox) - { - ui->comboBoxSheetTemplate->blockSignals(true); - - // we don't try to get the right size, because it doesn't work well because of mm / inch conversion - int index = ui->comboBoxSheetTemplate->findData( - QVariant(static_cast(PaperSizeTemplate::Custom))); - - ui->comboBoxSheetTemplate->setCurrentIndex(index); - ui->comboBoxSheetTemplate->blockSignals(false); - } - - m_tileFactory->refreshTileInfos(); - - // TODO Undo / Redo - - m_graphicsView->RefreshLayout(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_SheetOrientationChanged() -{ - // Updates the orientation - if(ui->radioButtonSheetPortrait->isChecked()) - { - m_layout->LayoutSettings().SetOrientation(PageOrientation::Portrait); - } - else - { - m_layout->LayoutSettings().SetOrientation(PageOrientation::Landscape); - } - m_tileFactory->refreshTileInfos(); - - // TODO Undo / Redo - - m_graphicsView->RefreshLayout(); -} - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_pushButtonSheetRemoveUnusedLength_clicked() { @@ -1515,16 +2179,17 @@ void VPMainWindow::on_pushButtonSheetRemoveUnusedLength_clicked() //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_SheetMarginChanged() { - m_layout->LayoutSettings().SetSheetMarginsConverted( - ui->doubleSpinBoxSheetMarginLeft->value(), - ui->doubleSpinBoxSheetMarginTop->value(), - ui->doubleSpinBoxSheetMarginRight->value(), - ui->doubleSpinBoxSheetMarginBottom->value() - ); + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetSheetMarginsConverted( + ui->doubleSpinBoxSheetMarginLeft->value(), + ui->doubleSpinBoxSheetMarginTop->value(), + ui->doubleSpinBoxSheetMarginRight->value(), + ui->doubleSpinBoxSheetMarginBottom->value()); - // TODO Undo / Redo - - m_graphicsView->RefreshLayout(); + LayoutWasSaved(false); + m_graphicsView->RefreshLayout(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -1549,93 +2214,58 @@ void VPMainWindow::on_doubleSpinBoxSheetGridRowHeight_valueChanged(double value) } //--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_comboBoxTilesTemplate_currentIndexChanged(int index) +void VPMainWindow::on_TilesSizeChanged() { - PaperSizeTemplate tmpl = static_cast( - ui->comboBoxTilesTemplate->itemData(index).toInt() - ); - - QSizeF tmplSize = VPLayoutSettings::GetTemplateSize(tmpl); - if(!tmplSize.isEmpty()) + if (not m_layout.isNull()) { - ui->doubleSpinBoxTilesWidth->blockSignals(true); - ui->doubleSpinBoxTilesLength->blockSignals(true); + m_layout->LayoutSettings().SetTilesSizeConverted( + ui->doubleSpinBoxTilePaperWidth->value(), + ui->doubleSpinBoxTilePaperHeight->value()); + FindTileTemplate(); + TilePaperSizeChanged(); + CorrectMaxMargins(); + LayoutWasSaved(false); - ui->doubleSpinBoxTilesWidth->setValue(UnitConvertor(tmplSize.width(), Unit::Px, - m_layout->LayoutSettings().GetUnit())); - ui->doubleSpinBoxTilesLength->setValue(UnitConvertor(tmplSize.height(), Unit::Px, - m_layout->LayoutSettings().GetUnit())); - - on_TilesSizeChanged(false); - - ui->doubleSpinBoxTilesWidth->blockSignals(false); - ui->doubleSpinBoxTilesLength->blockSignals(false); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_TilesSizeChanged(bool changedViaSizeCombobox) -{ - m_layout->LayoutSettings().SetTilesSizeConverted(ui->doubleSpinBoxTilesWidth->value(), - ui->doubleSpinBoxTilesLength->value()); - m_tileFactory->refreshTileInfos(); - - if(changedViaSizeCombobox) - { - ui->comboBoxTilesTemplate->blockSignals(true); - - // we don't try to get the right size, because it doesn't work well because of mm / inch conversion - int index = ui->comboBoxTilesTemplate->findData( - QVariant(static_cast(PaperSizeTemplate::Custom))); - - ui->comboBoxTilesTemplate->setCurrentIndex(index); - ui->comboBoxTilesTemplate->blockSignals(false); - } - - // TODO Undo / Redo - - if(m_graphicsView != nullptr) - { + m_tileFactory->refreshTileInfos(); m_graphicsView->RefreshLayout(); } } //--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_TilesOrientationChanged() +void VPMainWindow::on_TilesOrientationChanged(bool checked) { - // Updates the orientation - m_tileFactory->refreshTileInfos(); + if (checked && not m_layout.isNull()) + { + const qreal width = ui->doubleSpinBoxTilePaperWidth->value(); + const qreal height = ui->doubleSpinBoxTilePaperHeight->value(); - // TODO Undo / Redo + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperWidth, height); + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperHeight, width); - m_graphicsView->RefreshLayout(); + m_layout->LayoutSettings().SetTilesSizeConverted(height, width); + + TilePaperSizeChanged(); + CorrectMaxMargins(); + LayoutWasSaved(false); + m_tileFactory->refreshTileInfos(); + m_graphicsView->RefreshLayout(); + } } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_TilesMarginChanged() { - m_layout->LayoutSettings().SetTilesMarginsConverted( - ui->doubleSpinBoxTilesMarginLeft->value(), - ui->doubleSpinBoxTilesMarginTop->value(), - ui->doubleSpinBoxTilesMarginRight->value(), - ui->doubleSpinBoxTilesMarginBottom->value() - ); - m_tileFactory->refreshTileInfos(); - - // TODO Undo / Redo - - m_graphicsView->RefreshLayout(); -} - - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_checkBoxTilesShowTiles_toggled(bool checked) -{ - m_layout->LayoutSettings().SetShowTiles(checked); - - // TODO Undo / Redo - - m_graphicsView->RefreshLayout(); + if (not m_layout.isNull()) + { + m_layout->LayoutSettings().SetTilesMarginsConverted( + ui->doubleSpinBoxTileMarginLeft->value(), + ui->doubleSpinBoxTileMarginTop->value(), + ui->doubleSpinBoxTileMarginRight->value(), + ui->doubleSpinBoxTileMarginBottom->value()); + LayoutWasSaved(false); + m_tileFactory->refreshTileInfos(); + m_graphicsView->RefreshLayout(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -1654,146 +2284,44 @@ void VPMainWindow::on_pushButtonTilesExport_clicked() generateTiledPdf(fileName); } - - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_SheetFollowGrainlineChanged() -{ - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText("TODO VPMainWindow::on_SheetFollowGrainlineChanged"); - int ret = msgBox.exec(); - - Q_UNUSED(ret); - - // TODO -} - - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_doubleSpinBoxSheetPiecesGap_valueChanged(double value) -{ - m_layout->LayoutSettings().SetPiecesGapConverted(value); - - // TODO Undo / Redo - // TODO update the QGraphicView -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_checkBoxLayoutWarningPiecesSuperposition_toggled(bool checked) -{ - m_layout->LayoutSettings().SetWarningSuperpositionOfPieces(checked); - - // TODO Undo / Redo - // TODO update the QGraphicView -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_checkBoxLayoutWarningPiecesOutOfBound_toggled(bool checked) -{ - m_layout->LayoutSettings().SetWarningPiecesOutOfBound(checked); - - // TODO Undo / Redo - // TODO update the QGraphicView -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_checkBoxSheetStickyEdges_toggled(bool checked) -{ - m_layout->LayoutSettings().SetStickyEdges(checked); - - // TODO Undo / Redo - // TODO update the QGraphicView -} - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_pushButtonSheetExport_clicked() { - LayoutExportFormats format = static_cast(ui->comboBoxSheetExportFormat->currentData().toInt()); +// LayoutExportFormats format = static_cast(ui->comboBoxSheetExportFormat->currentData().toInt()); - VPExporter exporter; - exporter.Export(m_layout.get(), format, m_graphicsView); +// VPExporter exporter; +// exporter.Export(m_layout.get(), format, m_graphicsView); } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_checkBoxCurrentPieceShowSeamline_toggled(bool checked) { - if(m_selectedPieces.count() == 1) - { +// if(m_selectedPieces.count() == 1) +// { // m_selectedPieces.first()->SetShowSeamLine(checked); - } +// } } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_checkBoxCurrentPieceMirrorPiece_toggled(bool checked) { - if(m_selectedPieces.count() == 1) - { - m_selectedPieces.first()->SetMirror(checked); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_pushButtonCurrentPieceRotate90Anticlockwise_clicked() -{ - if(m_selectedPieces.count() == 1) - { -// m_selectedPieces.first()->RotateBy(90); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_pushButtonCurrentPieceRotate90Clockwise_clicked() -{ - if(m_selectedPieces.count() == 1) - { -// m_selectedPieces.first()->RotateBy(-90); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_pushButtonCurrentPieceRotateGrainlineVertical_clicked() -{ - if(m_selectedPieces.count() == 1) - { -// m_selectedPieces.first()->RotateToGrainline(90, true); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_pushButtonCurrentPieceRotateGrainlineHorizontal_clicked() -{ - if(m_selectedPieces.count() == 1) - { -// m_selectedPieces.first()->RotateToGrainline(0, true); - } +// if(m_selectedPieces.count() == 1) +// { +// m_selectedPieces.first()->SetMirror(checked); +// } } //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_doubleSpinBoxCurrentPieceAngle_valueChanged(double value) { - if(m_selectedPieces.count() == 1) - { +// if(m_selectedPieces.count() == 1) +// { // VPPiece *piece = m_selectedPieces.first(); // piece->SetRotation(value); - } +// } } -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_CurrentPiecePositionEdited() -{ - if(m_selectedPieces.count() == 1) - { - VPPiece *piece = m_selectedPieces.first(); - QPointF pos(UnitConvertor(ui->doubleSpinBoxCurrentPieceBoxPositionX->value(), - m_layout->LayoutSettings().GetUnit(), Unit::Px), - UnitConvertor(ui->doubleSpinBoxCurrentPieceBoxPositionY->value(), - m_layout->LayoutSettings().GetUnit(), Unit::Px)); - piece->SetPosition(pos); - } -} - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_CarrouselLocationChanged(Qt::DockWidgetArea area) { @@ -1810,41 +2338,10 @@ void VPMainWindow::on_CarrouselLocationChanged(Qt::DockWidgetArea area) //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_PieceSelectionChanged() { -// m_selectedPieces = m_layout->GetSelectedPieces(); - // update the property of the piece currently selected SetPropertyTabCurrentPieceData(); } - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_PiecePositionChanged() -{ - if(m_selectedPieces.count() == 1) - { - VPPiece *piece = m_selectedPieces.first(); - QPointF pos = piece->GetPosition(); - - SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX, - UnitConvertor(pos.x(), Unit::Px, m_layout->LayoutSettings().GetUnit())); - SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY, - UnitConvertor(pos.y(), Unit::Px, m_layout->LayoutSettings().GetUnit())); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_PieceRotationChanged() -{ - if(m_selectedPieces.count() == 1) - { -// VPPiece *piece = m_selectedPieces.first(); -// qreal angle = piece->GetRotation(); - -// SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle); - } -} - - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_ScaleChanged(qreal scale) { @@ -1934,10 +2431,293 @@ void VPMainWindow::ToolBarStyles() void VPMainWindow::on_actionAddSheet_triggered() { VPSheetPtr sheet(new VPSheet(m_layout)); - sheet->SetName(QObject::tr("Sheet %1").arg(m_layout->GetSheets().size()+1)); + sheet->SetName(tr("Sheet %1").arg(m_layout->GetSheets().size()+1)); m_layout->UndoStack()->push(new VPUndoAddSheet(sheet)); } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_ApplyPieceTransformation() +{ + if (m_layout.isNull()) + { + return; + } + const int index = ui->tabWidgetPieceTransformation->currentIndex(); + if (ui->tabWidgetPieceTransformation->indexOf(ui->tabTranslate) == index) + { // translate + const qreal dx = UnitConvertor(ui->doubleSpinBoxCurrentPieceBoxPositionX->value(), TranslateUnit(), Unit::Px); + const qreal dy = UnitConvertor(ui->doubleSpinBoxCurrentPieceBoxPositionY->value(), TranslateUnit(), Unit::Px); + + QList selectedPieces = SelectedPieces(); + if (selectedPieces.isEmpty()) + { + return; + } + + if (ui->checkBoxRelativeTranslation->isChecked()) + { + if (ui->checkBoxTransformSeparately->isChecked()) + { + if (selectedPieces.size() > 1) + { + m_layout->UndoStack()->beginMacro(tr("translate pieces")); + } + + QRectF rect = PiecesBoundingRect(selectedPieces); + for (const auto& piece : selectedPieces) + { + if (not piece.isNull()) + { + const QRectF pieceRect = piece->MappedDetailBoundingRect(); + qreal pieceDx = dx; + qreal pieceDy = dy; + + if (not qFuzzyIsNull(rect.width())) + { + pieceDx += dx*((pieceRect.topLeft().x()-rect.topLeft().x())/rect.width())*2.; + } + + if (not qFuzzyIsNull(rect.height())) + { + pieceDy += dy*((pieceRect.topLeft().y()-rect.topLeft().y())/rect.height())*2.; + } + + auto *command = new VPUndoPieceMove(piece, pieceDx, pieceDy); + m_layout->UndoStack()->push(command); + } + } + + if (selectedPieces.size() > 1) + { + m_layout->UndoStack()->endMacro(); + } + } + else + { + auto *command = new VPUndoPiecesMove(selectedPieces, dx, dy); + m_layout->UndoStack()->push(command); + } + } + else + { + QRectF rect = PiecesBoundingRect(selectedPieces); + qreal pieceDx = dx - rect.topLeft().x(); + qreal pieceDy = dy - rect.topLeft().y(); + + if (selectedPieces.size() == 1) + { + auto *command = new VPUndoPieceMove(selectedPieces.first(), pieceDx, pieceDy); + m_layout->UndoStack()->push(command); + } + else + { + auto *command = new VPUndoPiecesMove(selectedPieces, pieceDx, pieceDy); + m_layout->UndoStack()->push(command); + } + } + } + else if (ui->tabWidgetPieceTransformation->indexOf(ui->tabRotate) == index) + { // rotate + qreal angle = ui->doubleSpinBoxCurrentPieceAngle->value(); + + if (ui->toolButtonCurrentPieceRotationClockwise->isChecked()) + { + angle *= -1; + } + + QList selectedPieces = SelectedPieces(); + if (selectedPieces.isEmpty()) + { + return; + } + + if (ui->checkBoxTransformSeparately->isChecked()) + { + m_layout->UndoStack()->beginMacro(tr("rotate pieces")); + for (const auto& piece : selectedPieces) + { + if (not piece.isNull()) + { + const QRectF rect = piece->MappedDetailBoundingRect(); + auto *command = new VPUndoPieceRotate(piece, rect.center(), angle); + m_layout->UndoStack()->push(command); + } + } + m_layout->UndoStack()->endMacro(); + } + else + { + VPSheetPtr sheet = m_layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return; + } + + VPTransformationOrigon origin = sheet->TransformationOrigin(); + auto *command = new VPUndoPiecesRotate(selectedPieces, origin.origin, angle); + m_layout->UndoStack()->push(command); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_ResetPieceTransformationSettings() +{ + const int index = ui->tabWidgetPieceTransformation->currentIndex(); + if (ui->tabWidgetPieceTransformation->indexOf(ui->tabTranslate) == index) + { // translate + if (ui->checkBoxRelativeTranslation->isChecked()) + { + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue(0); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue(0); + } + else + { + int unitIndex = ui->comboBoxTranslateUnit->findData(QVariant(UnitsToStr(Unit::Px))); + if (unitIndex != -1) + { + ui->comboBoxTranslateUnit->setCurrentIndex(unitIndex); + } + } + } + else if (ui->tabWidgetPieceTransformation->indexOf(ui->tabRotate) == index) + { // rotate + ui->doubleSpinBoxCurrentPieceAngle->setValue(0); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_RelativeTranslationChanged(bool checked) +{ + if (checked) + { + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue(0); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue(0); + } + else + { + QRectF rect = PiecesBoundingRect(SelectedPieces()); + + ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue( + UnitConvertor(rect.topLeft().x(), Unit::Px, TranslateUnit())); + ui->doubleSpinBoxCurrentPieceBoxPositionY->setValue( + UnitConvertor(rect.topLeft().y(), Unit::Px, TranslateUnit())); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_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->doubleSpinBoxSheetPiecesGap->value(), m_oldLayoutUnit, layoutUnit); + + m_oldLayoutUnit = layoutUnit; + m_layout->LayoutSettings().SetUnit(layoutUnit); + CorrectPaperDecimals(); + MinimumSheetPaperSize(); + MinimumTilePaperSize(); + + const QString suffix = " " + UnitsToStr(layoutUnit, true); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperWidth, newSheetWidth); + ui->doubleSpinBoxSheetPaperWidth->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPaperHeight, newSheetHeight); + ui->doubleSpinBoxSheetPaperHeight->setSuffix(suffix); + + on_SheetSizeChanged(); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginLeft, newSheetLeftMargin); + ui->doubleSpinBoxSheetMarginLeft->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginRight, newSheetRightMargin); + ui->doubleSpinBoxSheetMarginRight->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginTop, newSheetTopMargin); + ui->doubleSpinBoxSheetMarginTop->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetMarginBottom, newSheetBottomMargin); + ui->doubleSpinBoxSheetMarginBottom->setSuffix(suffix); + + on_SheetMarginChanged(); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperWidth, newTileWidth); + ui->doubleSpinBoxTilePaperWidth->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTilePaperHeight, newTileHeight); + ui->doubleSpinBoxTilePaperHeight->setSuffix(suffix); + + on_TilesSizeChanged(); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginLeft, newTileLeftMargin); + ui->doubleSpinBoxTileMarginLeft->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginRight, newTileRightMargin); + ui->doubleSpinBoxTileMarginRight->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginTop, newTileTopMargin); + ui->doubleSpinBoxTileMarginTop->setSuffix(suffix); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxTileMarginBottom, newTileBottomMargin); + ui->doubleSpinBoxTileMarginBottom->setSuffix(suffix); + + on_TilesMarginChanged(); + + ui->doubleSpinBoxSheetPiecesGap->setMaximum( + UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Cm, layoutUnit)); + ui->doubleSpinBoxSheetPiecesGap->setValue(newGap); + ui->doubleSpinBoxSheetPiecesGap->setSuffix(suffix); + + CorrectMaxMargins(); +} + //--------------------------------------------------------------------------------------------------------------------- #if defined(Q_OS_MAC) void VPMainWindow::AboutToShowDockMenu() diff --git a/src/app/puzzle/vpmainwindow.h b/src/app/puzzle/vpmainwindow.h index 227f939e5..848ba6fb3 100644 --- a/src/app/puzzle/vpmainwindow.h +++ b/src/app/puzzle/vpmainwindow.h @@ -45,6 +45,7 @@ #include "../vlayout/vlayoutdef.h" #include "../vwidgets/vabstractmainwindow.h" #include "../vmisc/vlockguard.h" +#include "../vlayout/dialogs/vabstractlayoutdialog.h" namespace Ui { @@ -154,40 +155,24 @@ private slots: void on_actionAboutPuzzle_triggered(); /** - * @brief on_comboBoxLayoutUnit_currentIndexChanged When the unit is changed in + * @brief on_LayoutUnitChanged When the unit is changed in * the layout property tab. * The slot is automatically connected through name convention. * @param index the index of the selected unit */ - void on_comboBoxLayoutUnit_currentIndexChanged(int index); - - /** - * @brief on_lineEditSheetName_textChanged When the name of the sheet is changed - * in the sheet layout tab - * @param text name of the sheet - */ - void on_lineEditSheetName_textChanged(const QString &text); - - /** - * @brief on_comboBoxLayoutTemplate_currentIndexChanged When the template is - * changed in the sheet property tab. - * The slot is automatically connected through name convention. - * @param index the index of the selected templated - */ - void on_comboBoxSheetTemplate_currentIndexChanged(int index); + void on_LayoutUnitChanged(int index); /** * @brief on_SheetSizeChanged When the width or the length has been changed in * the sheet property tab - * @param changedViaSizeCombobox true if the change happened through the combobox */ - void on_SheetSizeChanged(bool changedViaSizeCombobox = true); + void on_SheetSizeChanged(); /** * @brief on_SheetOrientationChanged When one of the radio boxes for the sheet * orientation has been clicked */ - void on_SheetOrientationChanged(); + void on_SheetOrientationChanged(bool checked); /** * @brief on_pushButtonLayoutRemoveUnusedLength_clicked When the button @@ -225,40 +210,17 @@ private slots: */ void on_doubleSpinBoxSheetGridRowHeight_valueChanged(double value); - /** - * @brief LayoutFollowGrainlineChanged When one of the radio boxes for the - * "Follow grainline" has been clicked in the sheet property tab. - */ - void on_SheetFollowGrainlineChanged(); - - /** - * @brief on_doubleSpinBoxLayoutPiecesGap_valueChanged When the "pieces gap" - * value is changed in the layout property tab. - * The slot is automatically connected through name convention. - * @param value the new value of the pieces gap - */ - void on_doubleSpinBoxSheetPiecesGap_valueChanged(double value); - - /** - * @brief on_comboBoxTilesTemplate_currentIndexChanged When the template is - * changed in the tiles property tab. - * The slot is automatically connected through name convention. - * @param index the index of the selected templated - */ - void on_comboBoxTilesTemplate_currentIndexChanged(int index); - /** * @brief on_TilesSizeChanged When the width or the length has been changed in * the tiles property tab - * @param changedViaSizeCombobox true if the change happened through the combobox */ - void on_TilesSizeChanged(bool changedViaSizeCombobox = true); + void on_TilesSizeChanged(); /** * @brief on_TilesOrientationChanged When one of the radio boxes for the tiles * orientation has been clicked */ - void on_TilesOrientationChanged(); + void on_TilesOrientationChanged(bool checked); /** * @brief on_TilesMarginChanged When one of the margin values has been changed @@ -266,44 +228,11 @@ private slots: */ void on_TilesMarginChanged(); - /** - * @brief on_checkBoxTilesShowTiles_toggled When the checkbox "show tiles" is - * clicked - * @param checked show tiles - */ - void on_checkBoxTilesShowTiles_toggled(bool checked); - /** * @brief on_pushButtonTilesExport_clicked When the export tiles button is clicked */ void on_pushButtonTilesExport_clicked(); - /** - * @brief on_checkBoxLayoutWarningPiecesSuperposition_toggled When the - * "Warning when pieces superposition" checkbox value in the layout - * property tab is toggled. - * The slot is automatically connected through name convention. - * @param checked the new checked value - */ - void on_checkBoxLayoutWarningPiecesSuperposition_toggled(bool checked); - - /** - * @brief on_checkBoxLayoutWarningPiecesOutOfBound_toggled When the - * "Warning when pieces out of bound" checkbox value in the layout property - * tab is toggled. - * The slot is automatically connected through name convention. - * @param checked the new checked value - */ - void on_checkBoxLayoutWarningPiecesOutOfBound_toggled(bool checked); - - /** - * @brief on_checkBoxLayoutStickyEdges_toggled When the "Sticky edges" - * checkbox value in the layout property tab is toggled. - * The slot is automatically connected through name convention. - * @param checked the new checked value - */ - void on_checkBoxSheetStickyEdges_toggled(bool checked); - /** * @brief on_pushButtonLayoutExport_clicked When the button * "Export layout" in the layout property is clicked. @@ -327,30 +256,6 @@ private slots: */ void on_checkBoxCurrentPieceMirrorPiece_toggled(bool checked); - /** - * @brief on_pushButtonCurrentPieceRotate90Antilockwise_clicked When the 90 - * anticlockwise angle button is clicked - */ - void on_pushButtonCurrentPieceRotate90Anticlockwise_clicked(); - - /** - * @brief on_pushButtonCurrentPieceRotate90Clockwise_clicked When the 90 - * clockwise angle button is clicked - */ - void on_pushButtonCurrentPieceRotate90Clockwise_clicked(); - - /** - * @brief on_pushButtonCurrentPieceRotateGrainlineVertical_clicked - * When the grainline vertical angle button is clicked - */ - void on_pushButtonCurrentPieceRotateGrainlineVertical_clicked(); - - /** - * @brief on_pushButtonCurrentPieceRotateGrainlineHorizontal_clicked - * When the grainline horizontal angle button is clicked - */ - void on_pushButtonCurrentPieceRotateGrainlineHorizontal_clicked(); - /** * @brief on_doubleSpinBoxCurrentPieceAngle_valueChanged When the * "Current Piece Angle" value in the current piece property is changed @@ -359,12 +264,6 @@ private slots: */ void on_doubleSpinBoxCurrentPieceAngle_valueChanged(double value); - /** - * @brief on_CurrentPiecePositionChanged When the positionX or the positionY - * is changed in the current piece tab - */ - void on_CurrentPiecePositionEdited(); - /** * @brief CarrouselLocationChanged When the piece carrousel's location * has been changed @@ -377,16 +276,6 @@ private slots: */ void on_PieceSelectionChanged(); - /** - * @brief on_PiecePositionChanged When the current piece position has changed - */ - void on_PiecePositionChanged(); - - /** - * @brief on_PieceRotationChanged When the current piece rotation has changed - */ - void on_PieceRotationChanged(); - /** * @brief on_ScaleChanged When the scale of the graphic view is changed */ @@ -406,6 +295,14 @@ private slots: void on_actionAddSheet_triggered(); + void on_ApplyPieceTransformation(); + + void on_ResetPieceTransformationSettings(); + + void on_RelativeTranslationChanged(bool checked); + + void on_ConvertPaperSize(); + #if defined(Q_OS_MAC) void AboutToShowDockMenu(); #endif //defined(Q_OS_MAC) @@ -422,7 +319,6 @@ private: QUndoStack *m_undoStack; VPLayoutPtr m_layout; - QListm_selectedPieces{QList()}; VPTileFactory *m_tileFactory{nullptr}; @@ -449,6 +345,9 @@ private: QAction *undoAction{nullptr}; QAction *redoAction{nullptr}; + Unit m_oldPieceTranslationUnit{Unit::Mm}; + Unit m_oldLayoutUnit{Unit::Mm}; + /** * @brief CreatePiece creates a piece from the given VLayoutPiece data * @param rawPiece the raw piece data @@ -535,22 +434,6 @@ private: */ void SetPropertyTabLayoutData(); - /** - * @brief SetDoubleSpinBoxValue sets the given spinbox to the given value. - * the signals are blocked before changing the value and unblocked after - * @param spinBox pointer to spinbox - * @param value spinbox value - */ - void SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value); - - /** - * @brief SetCheckBoxValue sets the given checkbox to the given value. - * the signals are blocked before changing the value and unblocked after - * @param checkbox pointer to checkbox - * @param value checkbox value - */ - void SetCheckBoxValue(QCheckBox *checkbox, bool value); - void ReadSettings(); void WriteSettings(); @@ -567,6 +450,34 @@ private: auto IsLayoutReadOnly() const -> bool; void ConnectToPreferences(const QSharedPointer &preferences); + + auto SelectedPieces() const -> QList; + + auto TranslateUnit() const -> Unit; + auto LayoutUnit() const -> Unit; + + QSizeF Template(VAbstractLayoutDialog::PaperSizeTemplate t) const; + QSizeF SheetTemplate() const; + QSizeF TileTemplate() const; + + void SheetSize(const QSizeF &size); + void TileSize(const QSizeF &size); + + void CorrectPaperDecimals(); + + void SheetPaperSizeChanged(); + void TilePaperSizeChanged(); + + void MinimumSheetPaperSize(); + void MinimumTilePaperSize(); + + void FindTemplate(QComboBox *box, qreal width, qreal height); + void FindSheetTemplate(); + void FindTileTemplate(); + + void CorrectTileMaxMargins(); + void CorrectSheetMaxMargins(); + void CorrectMaxMargins(); }; #endif // VPMAINWINDOW_H diff --git a/src/app/puzzle/vpmainwindow.ui b/src/app/puzzle/vpmainwindow.ui index 46f18ca67..4e8403308 100644 --- a/src/app/puzzle/vpmainwindow.ui +++ b/src/app/puzzle/vpmainwindow.ui @@ -111,8 +111,8 @@ - 24 - 37 + 30 + 46 @@ -151,10 +151,10 @@ - + - 378 - 524287 + 140 + 153 @@ -180,22 +180,16 @@ true - + 0 0 - - - 360 - 0 - - QTabWidget::Rounded - 2 + 0 @@ -255,11 +249,11 @@ 0 0 - 342 - 1370 + 358 + 700 - + @@ -340,6 +334,223 @@ + + + + + 0 + 0 + + + + Transformation + + + + + + 0 + + + + Translate + + + + + + Placement + + + + + + + + Horizontal: + + + + + + + -10000.000000000000000 + + + 10000.000000000000000 + + + 0.100000000000000 + + + + + + + + + + Vertical: + + + + + + + -10000.000000000000000 + + + 10000.000000000000000 + + + 0.100000000000000 + + + + + + + + + Relative translation + + + true + + + + + + + + + + + Rotate + + + + + + Rotation + + + + + + + + + + .. + + + true + + + buttonGroupRotationDirection + + + + + + + 3 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + .. + + + true + + + true + + + buttonGroupRotationDirection + + + + + + + + 0 + 0 + + + + Angle: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Apply to each piece separately + + + + + + + QDialogButtonBox::Apply|QDialogButtonBox::Reset + + + + + + @@ -375,237 +586,28 @@ - - - - Rotation - - - - - - Angle: - - - - - - - 360.000000000000000 - - - 1.000000000000000 - - - - - - - - - Rotate the piece by 90° clockwise - - - - - - - :/puzzleicon/64x64/iconRotate90Clockwise.png:/puzzleicon/64x64/iconRotate90Clockwise.png - - - - 32 - 32 - - - - - - - - Rotate the piece by 90° anti-clockwise - - - - - - - :/puzzleicon/64x64/iconRotate90Anticlockwise.png:/puzzleicon/64x64/iconRotate90Anticlockwise.png - - - - 32 - 32 - - - - - - - - Rotate the piece so that the grainline is vertical - - - - - - - :/puzzleicon/64x64/iconRotateGrainlineVertical.png:/puzzleicon/64x64/iconRotateGrainlineVertical.png - - - - 32 - 32 - - - - - - - - Rotate the piece so that the grainline is horizontal - - - - - - - :/puzzleicon/64x64/iconRotateGrainlineHorizontal.png:/puzzleicon/64x64/iconRotateGrainlineHorizontal.png - - - - 32 - 32 - - - - - - - - - - - - - Placement - - - - - - X: - - - - - - - -10000.000000000000000 - - - 10000.000000000000000 - - - 0.100000000000000 - - - - - - - Y: - - - - - - - -10000.000000000000000 - - - 10000.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 400 - - - - No piece selected - - - Qt::AlignCenter - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 400 - - - - Multiple pieces selected - - - Qt::AlignCenter - - - - + + + + + 0 + 1 + + + + + 18 + + + + No piece selected + + + Qt::AlignCenter + @@ -669,12 +671,12 @@ 0 - -170 - 342 - 870 + 0 + 344 + 748 - + @@ -712,111 +714,173 @@ - + + + false + Format - + + false + + + false + + + false + + - + + + QFormLayout::ExpandingFieldsGrow + - + - Template + Unit: - + - + + + + 0 + 0 + + - Width + Templates: - - - 2 - - - 100000.000000000000000 - - + + + + + + + Qt::Horizontal + + + + + - - - Length - - - - - - - 2 - - - 100000.000000000000000 - - - - - - - Orientation - - - - - + - - - Portrait - + - + ... - - :/puzzleicon/64x64/iconPortrait.png:/puzzleicon/64x64/iconPortrait.png + + :/icon/16x16/portrait.png:/icon/16x16/portrait.png - - - 32 - 32 - + + true true + + true + + + buttonGroupSheetOrientation + - - - Landscape - + - + ... - - :/puzzleicon/64x64/iconLandscape.png:/puzzleicon/64x64/iconLandscape.png + + :/icon/16x16/landscape.png:/icon/16x16/landscape.png - - - 32 - 32 - + + true + + false + + + true + + + buttonGroupSheetOrientation + + + + + + 0 + 0 + + + + Width: + + + + + + + + 0 + 0 + + + + Length: + + + + + + + + 94 + 0 + + + + 2 + + + 99999.000000000000000 + + + + + + + + 94 + 0 + + + + 2 + + + 99999.990000000005239 + + + @@ -834,75 +898,92 @@ 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 + + - Right: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Top: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.100000000000000 - - - - - - - 0.100000000000000 - - - - - - - Left: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - 0.100000000000000 - - - - - - - 0.100000000000000 - - - - - - - Bottom: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Ignore margins @@ -961,116 +1042,11 @@ - - - Control - - - - - - - - Follow grainline - - - - - - - - - No - - - true - - - - - - - Vertical grainline - - - - - - - :/puzzleicon/64x64/iconGrainlineVertical.png:/puzzleicon/64x64/iconGrainlineVertical.png - - - - 28 - 28 - - - - - - - - Horizontal grainline - - - - - - - :/puzzleicon/64x64/iconGrainlineHorizontal.png:/puzzleicon/64x64/iconGrainlineHorizontal.png - - - - 28 - 28 - - - - - - - - - - Pieces gap - - - - - - - - - - - - Sticky edges - - - - - - - - + Export - - - - - - Format - - - - - - - - @@ -1143,11 +1119,11 @@ 0 0 - 356 + 358 700 - + @@ -1162,98 +1138,162 @@ - + + + false + Format - + + false + + + false + + + false + + - - - + + + QFormLayout::ExpandingFieldsGrow + + + + + + 0 + 0 + + - Width + Templates: - - - - 100000.000000000000000 - - + + + + + + + + Qt::Horizontal + + + + + - - - Length - - - - - - - 100000.000000000000000 - - - - - - - Orientation - - - - - + - + - + ... - - :/puzzleicon/64x64/iconPortrait.png:/puzzleicon/64x64/iconPortrait.png + + :/icon/16x16/portrait.png:/icon/16x16/portrait.png - - - 32 - 32 - + + true true + + true + + + buttonGroupTileOrientation + - + - + ... - - :/puzzleicon/64x64/iconLandscape.png:/puzzleicon/64x64/iconLandscape.png + + :/icon/16x16/landscape.png:/icon/16x16/landscape.png - - - 32 - 32 - + + true + + false + + + true + + + buttonGroupTileOrientation + - + + + + 0 + 0 + + - Template + Width: + + + + + + + + 0 + 0 + + + + Height: + + + + + + + + 94 + 0 + + + + 2 + + + 99999.000000000000000 - + + + + 94 + 0 + + + + 2 + + + 99999.990000000005239 + + @@ -1261,76 +1301,96 @@ - + 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 + + - Right: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Left: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.100000000000000 - - - - - - - 0.100000000000000 - - - - - - - Top: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.100000000000000 - - - - - - - Bottom: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.100000000000000 + Ignore margins @@ -1431,11 +1491,11 @@ 0 0 - 356 + 358 700 - + @@ -1460,7 +1520,7 @@ - Name + Name: @@ -1486,29 +1546,6 @@ - - - - Format - - - - - - - - Unit - - - - - - - - - - - @@ -1529,21 +1566,52 @@ + + + + Sticky edges + + + + + + + Follow grainline + + + + + + + + + Pieces gap: + + + + + + + + - - - Qt::Vertical + + + Export - - - 20 - 40 - - - + + + + + Export Layout + + + + + @@ -1781,11 +1849,9 @@ - tabWidgetProperties scrollAreaCurrentPiece scrollAreaSheet scrollAreaTiles - scrollAreaLayout lineEditCurrentPieceName plainTextEditCurrentPieceUUID checkBoxCurrentPieceShowSeamline @@ -1794,41 +1860,22 @@ doubleSpinBoxCurrentPieceBoxPositionX doubleSpinBoxCurrentPieceBoxPositionY lineEditSheetName - comboBoxSheetTemplate - doubleSpinBoxSheetWidth - doubleSpinBoxSheetLength - radioButtonSheetPortrait - radioButtonSheetLandscape - pushButtonSheetRemoveUnusedLength - doubleSpinBoxSheetMarginTop - doubleSpinBoxSheetMarginLeft - doubleSpinBoxSheetMarginRight - doubleSpinBoxSheetMarginBottom - radioButtonSheetFollowGrainlineNo - radioButtonSheetFollowGrainlineVertical - radioButtonSheetFollowGrainlineHorizontal - doubleSpinBoxSheetPiecesGap - checkBoxSheetStickyEdges - comboBoxSheetExportFormat pushButtonSheetExport - doubleSpinBoxTilesWidth - doubleSpinBoxTilesLength - radioButtonTilesPortrait - radioButtonTilesLandscape - doubleSpinBoxTilesMarginTop - doubleSpinBoxTilesMarginLeft - doubleSpinBoxTilesMarginRight - doubleSpinBoxTilesMarginBottom checkBoxTilesShowTiles pushButtonTilesExport lineEditLayoutName plainTextEditLayoutDescription - comboBoxLayoutUnit checkBoxLayoutWarningPiecesSuperposition checkBoxLayoutWarningPiecesOutOfBound + + + + + + diff --git a/src/app/puzzle/vpsettings.cpp b/src/app/puzzle/vpsettings.cpp index e93947ccf..b54d97648 100644 --- a/src/app/puzzle/vpsettings.cpp +++ b/src/app/puzzle/vpsettings.cpp @@ -273,6 +273,13 @@ auto VPSettings::GetLayoutFollowGrainline() const -> bool return value(*settingLayoutFollowGrainline, false).toBool(); } +//--------------------------------------------------------------------------------------------------------------------- +qreal VPSettings::GetMaxLayoutPieceGap() +{ + return UnitConvertor(50, Unit::Cm, Unit::Px); +} + +//--------------------------------------------------------------------------------------------------------------------- void VPSettings::SetLayoutPieceGap(qreal value) { setValue(*settingLayoutPieceGap, value); diff --git a/src/app/puzzle/vpsettings.h b/src/app/puzzle/vpsettings.h index 74d26178c..d4098db40 100644 --- a/src/app/puzzle/vpsettings.h +++ b/src/app/puzzle/vpsettings.h @@ -90,6 +90,7 @@ public: void SetLayoutFollowGrainline(bool value); auto GetLayoutFollowGrainline() const -> bool; + static auto GetMaxLayoutPieceGap() -> qreal; void SetLayoutPieceGap(qreal value); auto GetLayoutPieceGap() const -> qreal; diff --git a/src/app/puzzle/vptilefactory.cpp b/src/app/puzzle/vptilefactory.cpp index a0c321b3a..452f13592 100644 --- a/src/app/puzzle/vptilefactory.cpp +++ b/src/app/puzzle/vptilefactory.cpp @@ -22,44 +22,39 @@ void VPTileFactory::refreshTileInfos() VPLayoutPtr layout = m_layout.toStrongRef(); if(not layout.isNull()) { - PageOrientation tilesOrientation = layout->LayoutSettings().GetTilesOrientation(); - QSizeF tilesSize = layout->LayoutSettings().GetTilesSize(); + QSizeF tilesSize = layout->LayoutSettings().GetTilesSize(); QMarginsF tilesMargins = layout->LayoutSettings().GetTilesMargins(); // sets the drawing height - m_drawingAreaHeight = (tilesOrientation == PageOrientation::Portrait)? - tilesSize.height() : tilesSize.width(); - m_drawingAreaHeight -= - tilesMargins.top() + tilesMargins.bottom() + m_infoStripeWidth; + m_drawingAreaHeight = tilesSize.height(); - // sets the drawing width - m_drawingAreaWidth = (tilesOrientation == PageOrientation::Portrait)? - tilesSize.width() : tilesSize.height(); - m_drawingAreaWidth -= - tilesMargins.left() + tilesMargins.right() + m_infoStripeWidth; - - - QSizeF sheetSize = layout->LayoutSettings().GetSheetSize(); - qreal totalDrawingWidth = 0; - qreal totaldrawingHeight = 0; - - if(layout->LayoutSettings().GetOrientation() == PageOrientation::Portrait) + if (not layout->LayoutSettings().IgnoreTilesMargins()) { - totalDrawingWidth = sheetSize.width(); - totaldrawingHeight = sheetSize.height(); + m_drawingAreaHeight -= tilesMargins.top() + tilesMargins.bottom() + m_infoStripeWidth; } else { - totalDrawingWidth = sheetSize.height(); - totaldrawingHeight = sheetSize.width(); + m_drawingAreaHeight += m_infoStripeWidth; } - m_nbCol = qCeil(totalDrawingWidth/m_drawingAreaWidth); - m_nbRow = qCeil(totaldrawingHeight/m_drawingAreaHeight); + // sets the drawing width + m_drawingAreaWidth = tilesSize.width(); + + if (not layout->LayoutSettings().IgnoreTilesMargins()) + { + m_drawingAreaWidth -= tilesMargins.left() + tilesMargins.right() + m_infoStripeWidth; + } + else + { + m_drawingAreaWidth += m_infoStripeWidth; + } + + QSizeF sheetSize = layout->LayoutSettings().GetSheetSize(); + m_nbCol = qCeil(sheetSize.width()/m_drawingAreaWidth); + m_nbRow = qCeil(sheetSize.height()/m_drawingAreaHeight); } } - //--------------------------------------------------------------------------------------------------------------------- void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView, int row, int col) { diff --git a/src/app/puzzle/xml/vplayoutfilewriter.cpp b/src/app/puzzle/xml/vplayoutfilewriter.cpp index aee2b5e34..d6a2d7ee4 100644 --- a/src/app/puzzle/xml/vplayoutfilewriter.cpp +++ b/src/app/puzzle/xml/vplayoutfilewriter.cpp @@ -147,8 +147,6 @@ void VPLayoutFileWriter::WriteFile(const VPLayoutPtr &layout, QIODevice *file) .arg(APP_VERSION_STR)); WriteLayout(layout); writeEndDocument(); - - file->close(); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/dialogs/dialogsavelayout.cpp b/src/app/valentina/dialogs/dialogsavelayout.cpp index 7bc84791f..fb3bd0f3f 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.cpp +++ b/src/app/valentina/dialogs/dialogsavelayout.cpp @@ -149,7 +149,7 @@ DialogSaveLayout::DialogSaveLayout(int count, Draw mode, const QString &fileName ui->lineEditPath->setText(VAbstractValApplication::VApp()->ValentinaSettings()->GetPathLayout()); - InitTemplates(ui->comboBoxTemplates); + InitTileTemplates(ui->comboBoxTemplates); connect(ui->toolButtonScaleConnected, &QToolButton::clicked, this, &DialogSaveLayout::ToggleScaleConnection); @@ -163,20 +163,6 @@ DialogSaveLayout::DialogSaveLayout(int count, Draw mode, const QString &fileName ShowExample();//Show example for current format. } -//--------------------------------------------------------------------------------------------------------------------- -void DialogSaveLayout::InitTemplates(QComboBox *comboBoxTemplates) -{ - SCASSERT(comboBoxTemplates != nullptr) - VAbstractLayoutDialog::InitTemplates(comboBoxTemplates); - - // remove unused formats - for (int i = static_cast(PaperSizeTemplate::Roll24in); i <= static_cast(PaperSizeTemplate::Custom); ++i) - { - comboBoxTemplates->removeItem(comboBoxTemplates->findData(i)); - } -} - - //--------------------------------------------------------------------------------------------------------------------- void DialogSaveLayout::SelectFormat(LayoutExportFormats format) diff --git a/src/app/valentina/dialogs/dialogsavelayout.h b/src/app/valentina/dialogs/dialogsavelayout.h index 9c4950f17..3daee718f 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.h +++ b/src/app/valentina/dialogs/dialogsavelayout.h @@ -83,7 +83,6 @@ public: protected: virtual void showEvent(QShowEvent *event) override; - void InitTemplates(QComboBox *comboBoxTemplates); private slots: void Save(); diff --git a/src/libs/vlayout/dialogs/vabstractlayoutdialog.cpp b/src/libs/vlayout/dialogs/vabstractlayoutdialog.cpp index 1df41c2cf..aa060591e 100644 --- a/src/libs/vlayout/dialogs/vabstractlayoutdialog.cpp +++ b/src/libs/vlayout/dialogs/vabstractlayoutdialog.cpp @@ -84,6 +84,23 @@ void VAbstractLayoutDialog::InitTemplates(QComboBox *comboBoxTemplates) comboBoxTemplates->setCurrentIndex(-1); } +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractLayoutDialog::InitTileTemplates(QComboBox *comboBoxTemplates, bool keepCustom) +{ + SCASSERT(comboBoxTemplates != nullptr) + InitTemplates(comboBoxTemplates); + + // remove unused formats + for (int i = static_cast(PaperSizeTemplate::Roll24in); i <= static_cast(PaperSizeTemplate::Custom); ++i) + { + if (keepCustom && i == static_cast(PaperSizeTemplate::Custom)) + { + continue; + } + comboBoxTemplates->removeItem(comboBoxTemplates->findData(i)); + } +} + //--------------------------------------------------------------------------------------------------------------------- auto VAbstractLayoutDialog::GetTemplateSize(PaperSizeTemplate tmpl, Unit unit) -> QSizeF { diff --git a/src/libs/vlayout/dialogs/vabstractlayoutdialog.h b/src/libs/vlayout/dialogs/vabstractlayoutdialog.h index 07323945f..6ba849af1 100644 --- a/src/libs/vlayout/dialogs/vabstractlayoutdialog.h +++ b/src/libs/vlayout/dialogs/vabstractlayoutdialog.h @@ -62,6 +62,7 @@ public: static auto GetTemplateSize(PaperSizeTemplate tmpl, Unit unit) -> QSizeF; static void InitTemplates(QComboBox *comboBoxTemplates); + static void InitTileTemplates(QComboBox *comboBoxTemplates, bool keepCustom = false); protected: typedef QStringList FormatsVector; diff --git a/src/libs/vmisc/share/resources/icons/win.icon.theme/16x16/actions/object-rotate-right.png b/src/libs/vmisc/share/resources/icons/win.icon.theme/16x16/actions/object-rotate-right.png new file mode 100644 index 0000000000000000000000000000000000000000..0bf5159f63b34d345fe9e9d0a7e6eb98a20dd4b7 GIT binary patch literal 1246 zcmV<41R?v0P)1M000C# zNklu|mwc_R_aV<%v(nD>FN>Lu|<}JFlG3?rYe?aGEZo7Rx@Y)is?>J`(5;~hK|vTJ77&?`%b9?L{DhTKuDb1RmHy{ zM%o^U5S?;cC69yXKiel6Gxzxdy@}E{9MBcr%i8ryzaN`IoIlo@$SvVhNPp--vG#)}Dt7`c>W?em%h@g_4?6Cg`RFh9T*O)+6 zQ*yi{2m%93r`S(~!2V~BA*fcDSox$uU}fp?1A8E-``ldRGYAPQKWDZGf<4Q!c^v_B zj!i|F{#)TVc?HZcFIxJj7iO3hb;S09|CC~feh%ROsJIMaR_6(o`3rbI{lpeae^_w& zn`GX^L}P9lg5TpqGvDihi97R~yMKmB1M-hXWr1?x(Rm1yw&tCs5AT-edLfLD`08oD zH1G?^RojGs-?qHvBcFlNH9uUE3CgVex9N-g#{M1zxxui(Sq+MzIl9&~PFmyTZ`Z($%sN2)0N>TeFxkv zcR421g2#uu^SXV(Q@cmIb{hC9_cfcX1Mk=@3;Losv*|E`b8Bh}f=ls^D31n^rEib9 za1cgbOqq304$g{g*?E6}Q}ot?Rdz7q<<{2K_29fYWnke(kQuih>6#8MZ9Bd$x(Ke* zQcaFBkS$9;i=fvB+~HMh>NhG8tRx8ocnHH!C2eu@0tde&?SVY7k4v&{a|64ZiK|Sb zz^*K@#^eqT1Ck!yl)>=1$+9$Ga4byrbV>!sqGSdCgk_^93&BdasSQCoB+hn_0j#X_ z!Q+%LOroz3%>=8@*Ut;ChG8r8O@~07*qo IM6N<$g0QPhRR910 literal 0 HcmV?d00001 diff --git a/src/libs/vmisc/share/resources/icons/win.icon.theme/24x24/actions/object-rotate-right.png b/src/libs/vmisc/share/resources/icons/win.icon.theme/24x24/actions/object-rotate-right.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d8f5bbce108fdf7dfd6883200d51a8f6b62eed GIT binary patch literal 10415 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 Z;C~P1zh$T4LD&EQ002ovPDHLkV1i#A>=gh2 literal 0 HcmV?d00001 diff --git a/src/libs/vmisc/share/resources/icons/win.icon.theme/32x32/actions/object-rotate-right.png b/src/libs/vmisc/share/resources/icons/win.icon.theme/32x32/actions/object-rotate-right.png new file mode 100644 index 0000000000000000000000000000000000000000..353989137b43f09d9307f12b9e0579f2483ec906 GIT binary patch literal 2077 zcmV+&2;%pNP)*mt9^W~? zcH2I}g}5B9RRU@Njer(_y(1DYLO=pv3Voh|0Ncil4o|ra#^Xe&*q3I}kX( zX`D6(u9X7HDI_M$3uh#p5)iCdPOHYat10>P7=J)m?hVs`nORj4$P%sdyol#`G1s?? zvN$tI|8;<;>?ZtmAMl9s!rDF@PY@vEGBT_tm+NTd-bBD35cI>%#;~coD!Movg$IuW z03uGWme#Htuir8zsx>5kQI#~c_riY&2#mYZYBAdb0D*XJvT(YK#Z5u^_nQN6RhV^! z56m7FMw?7b3@{An1&1d@cBw>Uo)qJ`dD|5KOv(up5U@HWKrxq5oHdl`!GwSn$Etd# zpQw&(v2rqTt2r?oB0O#VcB~&i{}Ql+L+qT$?(Zef%AM2oeM1+O@mU0z$Y=rJR#A6E zX?06T%FcTOFPAjxc+53k7GB%xUR(bV_3@c;KEF>Mpi>;quX*LI zZFgfG@#mTAIV9odr98KBMz=*{W3&&L7C4hbyZ3# zrw{i1WJ7XjAyq^79cLkUWq zAH6zx&5d|SBJih(lgq`A_q-c9acqA*Dx8Gw?Y92N{rI%qcc<}W+|5N=Ix9Y4;o2FY z1yuKzj`{%-VD1l~)%O|l{;!F@+^+L!T|KySM2vpP;SZztP#p38PN)TGyY38Gn_K!G zdLT%r`YwA>uca{|p4bPPpSL3-0aQB=6c#{lKy*OT$r&~E7A0o0uSR+Ougv%)xL!pa zPD;w?^~TDpujS@FTsAO5v-IrB0f&XFcBG|9B={CNBZCAKBsy5{hLTFtz{r$Si7fU5 z!?j6axVz5x@o$z5Q6} z$agke9m-1T?a?nS$e3q11pn2M5fOPoN`^QASo2bll*@^bm7ZlY0{1izM9x^yq>OR|XXp*LoRE7NfDzT77-@=u|hA z42KkpkbtzE4)pPk%Us;hWOczrj0)A>%-=h130yCs6_}W+3GzW9m=)1@kFqLL_m>m) zPj0br5|jy@R&}QGr^IRSpRqjw)(2P~MD>|`Anmu}n$E1jtePLYb-}b=M`^;TW9mk6 zms700sfmRmiFa4$#ctVm>tz%utfu(>0Sk_QF%mmpqp%|idjVTPkMy0_5*Dw!G==p! zt*5f#>cKZx2k71I3ggK75+$535$KxzV{v%$ho}46>|ASalu9HGm%p9ZuXmU?PR(Xv zM-+BL7DHTlSlrb8sTT_>A{dF_K+i{?FNr%mY*0`U5wMU4T-ZJV!{8aCB11c^EBr2Lm0&F6oy`NRgivO?+$pU!#3tK2`1O|5-C3 zBZ2kod*J9FF{#T>&MT{|@5<~uYbveNl3+6O^Kn1EXwHDNc{BT!3R*JX;aDyhOjRT# znwA!uenLvl^y6pmPO{l~SvwNE@U3b$Wy$ODq06(kPB=v|H$ST-KW$&YluaSr7o5IO z5_s^)tzLiJ`8)i6xiPf*ktrDR!ldz3m1wo9B0nFG8(*f6Ipyc0X4^7rhx0%OJ0sx+ zMZvlt{g#r>+sKfGnvIni#{d8K=2WmnV`L=-{sD5~<1Q1H;#2?t z03v!+SaefwW^{L9a%BJjSi>tXFW1Y=%Pvk%EJ)SMFG>dhHrNJObUhoG00000NkvXX Hu0mjfr$E-m literal 0 HcmV?d00001 diff --git a/src/libs/vmisc/share/resources/theme.qrc b/src/libs/vmisc/share/resources/theme.qrc index 7d28e0b69..ce2d67a93 100644 --- a/src/libs/vmisc/share/resources/theme.qrc +++ b/src/libs/vmisc/share/resources/theme.qrc @@ -102,5 +102,8 @@ icons/win.icon.theme/16x16/actions/view-refresh.png icons/win.icon.theme/24x24/actions/view-refresh.png icons/win.icon.theme/32x32/actions/view-refresh.png + icons/win.icon.theme/16x16/actions/object-rotate-right.png + icons/win.icon.theme/24x24/actions/object-rotate-right.png + icons/win.icon.theme/32x32/actions/object-rotate-right.png