Undo/Redo piece rotate.

This commit is contained in:
Roman Telezhynskyi 2021-08-18 20:33:47 +03:00
parent 0908b5a1f7
commit a35e46f845
26 changed files with 1152 additions and 402 deletions

View File

@ -34,6 +34,7 @@
#include "../vmisc/backport/qoverload.h"
#include "../layout/vpsheet.h"
#include "../layout/vplayout.h"
#include <QLoggingCategory>
#include <QMenu>
@ -42,12 +43,12 @@
Q_LOGGING_CATEGORY(pCarrousel, "p.carrousel")
//---------------------------------------------------------------------------------------------------------------------
VPCarrousel::VPCarrousel(VPLayout *layout, QWidget *parent) :
VPCarrousel::VPCarrousel(const VPLayoutPtr &layout, QWidget *parent) :
QWidget(parent),
ui(new Ui::VPCarrousel),
m_layout(layout)
{
SCASSERT(m_layout != nullptr)
SCASSERT(not layout.isNull())
ui->setupUi(this);
ui->listWidget->SetCarrousel(this);
@ -55,6 +56,8 @@ VPCarrousel::VPCarrousel(VPLayout *layout, QWidget *parent) :
connect(ui->comboBoxPieceList, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&VPCarrousel::on_ActivePieceListChanged);
connect(layout.get(), &VPLayout::ActiveSheetChanged, this, &VPCarrousel::on_ActiveSheetChanged);
// ------ then we fill the carrousel with the layout content
Refresh();
}
@ -73,26 +76,27 @@ void VPCarrousel::Refresh()
// Do not rely on m_layout because we do not control it.
m_pieceLists = QList<VPCarrouselSheet>();
if (m_layout != nullptr)
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
{
VPCarrouselSheet carrouselSheet;
carrouselSheet.unplaced = true;
carrouselSheet.active = false;
carrouselSheet.name = tr("Unplaced pieces");
carrouselSheet.pieces = m_layout->GetUnplacedPieces();
carrouselSheet.pieces = layout->GetUnplacedPieces();
m_pieceLists.append(carrouselSheet);
}
QList<VPSheet *> sheets = m_layout->GetSheets();
for (auto *sheet : sheets)
QList<VPSheetPtr> sheets = layout->GetSheets();
for (const auto &sheet : sheets)
{
if (sheet->IsVisible())
if (not sheet.isNull() && sheet->IsVisible())
{
VPCarrouselSheet carrouselSheet;
carrouselSheet.unplaced = false;
carrouselSheet.active = (sheet == m_layout->GetFocusedSheet());
carrouselSheet.active = (sheet == layout->GetFocusedSheet());
carrouselSheet.name = sheet->GetName();
carrouselSheet.pieces = sheet->GetPieces();
carrouselSheet.sheetUuid = sheet->Uuid();
@ -121,18 +125,41 @@ void VPCarrousel::Refresh()
RefreshOrientation();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::on_ActiveSheetChanged(const VPSheetPtr &sheet)
{
if (not sheet.isNull())
{
int index = ui->comboBoxPieceList->findData(sheet->Uuid());
if (index != -1)
{
ui->comboBoxPieceList->setCurrentIndex(index);
}
}
else
{
ui->comboBoxPieceList->setCurrentIndex(0);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::RefreshSheetNames()
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return;
}
for (int i=0; i < m_pieceLists.size(); ++i)
{
if (not m_pieceLists.at(i).unplaced)
{
VPSheet *sheet = m_layout->GetSheet(m_pieceLists.at(i).sheetUuid);
if (sheet != nullptr)
VPSheetPtr sheet = layout->GetSheet(m_pieceLists.at(i).sheetUuid);
if (not sheet.isNull())
{
m_pieceLists[i].name = sheet->GetName();
m_pieceLists[i].active = (sheet == m_layout->GetFocusedSheet());
m_pieceLists[i].active = (sheet == layout->GetFocusedSheet());
}
}
else
@ -158,6 +185,12 @@ void VPCarrousel::on_ActivePieceListChanged(int index)
{
qCDebug(pCarrousel, "index changed %i", index);
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return;
}
if (not m_pieceLists.isEmpty() && index >= 0 && index < m_pieceLists.size())
{
ui->listWidget->SetCurrentPieceList(m_pieceLists.at(index).pieces);
@ -165,20 +198,22 @@ void VPCarrousel::on_ActivePieceListChanged(int index)
if (index > 0)
{
QUuid sheetUuid = ui->comboBoxPieceList->currentData().toUuid();
VPSheet *sheet = m_layout->GetSheet(sheetUuid);
VPSheetPtr sheet = layout->GetSheet(sheetUuid);
if (sheet != nullptr)
if (not sheet.isNull())
{
m_layout->SetFocusedSheet(sheet);
emit on_ActiveSheetChanged();
m_ignoreActiveSheetChange = true;
layout->SetFocusedSheet(sheet);
m_ignoreActiveSheetChange = false;
}
}
}
else
{
ui->listWidget->SetCurrentPieceList(QList<VPPiece *>());
m_layout->SetFocusedSheet(nullptr);
emit on_ActiveSheetChanged();
ui->listWidget->SetCurrentPieceList(QList<VPPiecePtr>());
m_ignoreActiveSheetChange = true;
layout->SetFocusedSheet(VPSheetPtr());
m_ignoreActiveSheetChange = false;
}
RefreshSheetNames();

View File

@ -32,8 +32,8 @@
#include <QWidget>
#include <QComboBox>
#include <QScrollArea>
#include "../layout/vplayout.h"
#include "../layout/vppiece.h"
#include "../layout/layoutdef.h"
namespace Ui
{
@ -45,7 +45,7 @@ struct VPCarrouselSheet
bool unplaced{true};
bool active{false};
QString name{};
QList<VPPiece *> pieces{};
QList<VPPiecePtr> pieces{};
QUuid sheetUuid{};
};
@ -53,7 +53,7 @@ class VPCarrousel : public QWidget
{
Q_OBJECT
public:
explicit VPCarrousel(VPLayout *layout, QWidget *parent = nullptr);
explicit VPCarrousel(const VPLayoutPtr &layout, QWidget *parent = nullptr);
virtual ~VPCarrousel() = default;
/**
@ -69,8 +69,6 @@ public:
*/
void RefreshOrientation();
void RefreshSheetNames();
/**
@ -78,14 +76,12 @@ public:
*/
void Clear();
signals:
void on_ActiveSheetChanged();
public slots:
/**
* @brief Refresh Refreshes the content of the carrousel
*/
void Refresh();
void on_ActiveSheetChanged(const VPSheetPtr &sheet);
protected:
virtual void changeEvent(QEvent* event) override;
@ -102,12 +98,14 @@ private:
Q_DISABLE_COPY(VPCarrousel)
Ui::VPCarrousel *ui;
VPLayout *m_layout{nullptr};
VPLayoutWeakPtr m_layout{};
QList<VPCarrouselSheet> m_pieceLists{};
Qt::Orientation m_orientation{Qt::Vertical};
bool m_ignoreActiveSheetChange{false};
static auto GetSheetName(const VPCarrouselSheet &sheet) -> QString;
};

View File

@ -44,7 +44,7 @@ Q_LOGGING_CATEGORY(pCarrouselPiece, "p.carrouselPiece")
//---------------------------------------------------------------------------------------------------------------------
VPCarrouselPiece::VPCarrouselPiece(VPPiece *piece, QListWidget* parent) :
VPCarrouselPiece::VPCarrouselPiece(const VPPiecePtr &piece, QListWidget* parent) :
QListWidgetItem(parent, Type),
m_piece(piece)
{
@ -57,7 +57,7 @@ VPCarrouselPiece::VPCarrouselPiece(VPPiece *piece, QListWidget* parent) :
}
//---------------------------------------------------------------------------------------------------------------------
auto VPCarrouselPiece::GetPiece() -> VPPiece *
auto VPCarrouselPiece::GetPiece() const -> VPPiecePtr
{
return m_piece;
}
@ -65,13 +65,23 @@ auto VPCarrouselPiece::GetPiece() -> VPPiece *
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPiece::RefreshSelection()
{
setSelected(m_piece->IsSelected());
VPPiecePtr piece = GetPiece();
if (not piece.isNull())
{
setSelected(piece->IsSelected());
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPCarrouselPiece::CreatePieceIcon(const QSize &size, bool isDragIcon) const -> QIcon
{
QRectF boundingRect = m_piece->DetailBoundingRect();
VPPiecePtr piece = GetPiece();
if (piece.isNull())
{
return {};
}
QRectF boundingRect = piece->DetailBoundingRect();
qreal canvasSize = qMax(boundingRect.height(), boundingRect.width());
QRectF canvas = QRectF(0, 0, canvasSize, canvasSize);
@ -133,7 +143,7 @@ auto VPCarrouselPiece::CreatePieceIcon(const QSize &size, bool isDragIcon) const
painter.setBrush(QBrush(Qt::white));
}
m_piece->DrawMiniature(painter);
piece->DrawMiniature(painter);
painter.end();

View File

@ -31,21 +31,21 @@
#include <QMouseEvent>
#include <QListWidgetItem>
class VPPiece;
#include "../layout/layoutdef.h"
class VPCarrouselPiece : public QListWidgetItem
{
public:
enum { Type = UserType + 1};
explicit VPCarrouselPiece(VPPiece *piece, QListWidget* parent);
explicit VPCarrouselPiece(const VPPiecePtr &piece, QListWidget* parent);
virtual ~VPCarrouselPiece() = default;
/**
* @brief GetPiece Returns the corresponding layout piece
* @return the corresponding layout piece
*/
auto GetPiece() -> VPPiece *;
auto GetPiece() const -> VPPiecePtr;
/**
* @brief RefreshSelection refreshes the selection of the piece according to the selection information of m_piece
@ -62,7 +62,7 @@ public:
private:
Q_DISABLE_COPY(VPCarrouselPiece)
VPPiece *m_piece;
VPPieceWeakPtr m_piece;
};
#endif // VPCARROUSELPIECE_H

View File

@ -38,6 +38,7 @@
#include "../vmisc/backport/qoverload.h"
#include "vpmimedatapiece.h"
#include "../layout/vpsheet.h"
#include "../layout/vplayout.h"
#include <QLoggingCategory>
@ -68,18 +69,21 @@ void VPCarrouselPieceList::Refresh()
if(not m_pieceList.isEmpty())
{
// create the corresponding carrousel pieces
for (auto *piece : m_pieceList)
for (auto piece : m_pieceList)
{
if (not piece.isNull())
{
// update the label of the piece
auto* carrouselpiece = new VPCarrouselPiece(piece, this);
carrouselpiece->setSelected(piece->IsSelected());
}
}
sortItems();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::SetCurrentPieceList(const QList<VPPiece *> &pieceList)
void VPCarrouselPieceList::SetCurrentPieceList(const QList<VPPiecePtr> &pieceList)
{
m_pieceList = pieceList;
@ -135,7 +139,7 @@ void VPCarrouselPieceList::startDrag(Qt::DropActions supportedActions)
// starts the dragging
auto *drag = new QDrag(this);
auto *mimeData = new VPMimeDataPiece();
VPPiece* piece = pieceItem->GetPiece();
VPPiecePtr piece = pieceItem->GetPiece();
mimeData->SetPiecePtr(piece);
QPixmap pixmap = pieceItem->CreatePieceIcon(QSize(120, 120), true).pixmap(QSize(120, 120));
@ -189,18 +193,23 @@ void VPCarrouselPieceList::contextMenuEvent(QContextMenuEvent *event)
QAction *selectedAction = menu.exec(event->globalPos());
VPPiece *piece = pieceItem->GetPiece();
VPLayout *layout = piece->Layout();
VPPiecePtr piece = pieceItem->GetPiece();
VPLayoutPtr layout = piece->Layout();
if (piece.isNull() || layout.isNull())
{
return;
}
if (selectedAction == moveAction)
{
VPSheet *sheet = layout->GetFocusedSheet();
VPSheetPtr sheet = layout->GetFocusedSheet();
piece->SetSheet(sheet);
emit layout->PieceSheetChanged(piece);
}
else if (selectedAction == deleteAction)
{
VPSheet *sheet = layout->GetTrashSheet();
VPSheetPtr sheet = layout->GetTrashSheet();
piece->SetSheet(sheet);
emit layout->PieceSheetChanged(piece);
}

View File

@ -50,7 +50,7 @@ public:
* @brief SetCurrentPieceList Sets the current piece list to the given piece list and redraw
* the carrousel.
*/
void SetCurrentPieceList(const QList<VPPiece *> &pieceList);
void SetCurrentPieceList(const QList<VPPiecePtr> &pieceList);
/**
* @brief SetCarrousel Sets the carrousel corresponding to the list
@ -76,7 +76,7 @@ protected:
private:
Q_DISABLE_COPY(VPCarrouselPieceList)
QList<VPPiece *> m_pieceList{};
QList<VPPiecePtr> m_pieceList{};
QPoint m_dragStart{};
VPCarrousel *m_carrousel{nullptr};
};

View File

@ -0,0 +1,45 @@
/************************************************************************
**
** @file layoutdef.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 16 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef LAYOUTDEF_H
#define LAYOUTDEF_H
#include <QSharedPointer>
class VPLayout;
using VPLayoutPtr = QSharedPointer<VPLayout>;
using VPLayoutWeakPtr = QWeakPointer<VPLayout>;
class VPPiece;
using VPPiecePtr = QSharedPointer<VPPiece>;
using VPPieceWeakPtr = QWeakPointer<VPPiece>;
class VPSheet;
using VPSheetPtr = QSharedPointer<VPSheet>;
using VPSheetWeakPtr = QWeakPointer<VPSheet>;
#endif // LAYOUTDEF_H

View File

@ -31,109 +31,118 @@
#include "vpsheet.h"
#include <QLoggingCategory>
#include <QUndoStack>
Q_LOGGING_CATEGORY(pLayout, "p.layout")
//---------------------------------------------------------------------------------------------------------------------
VPLayout::VPLayout(QObject *parent) :
QObject(parent),
m_trashSheet(new VPSheet(this))
{}
//---------------------------------------------------------------------------------------------------------------------
VPLayout::~VPLayout()
VPLayout::VPLayout(QUndoStack *undoStack) :
m_undoStack(undoStack)
{
qDeleteAll(m_pieces);
SCASSERT(m_undoStack != nullptr)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddPiece(VPPiece *piece)
VPLayoutPtr VPLayout::CreateLayout(QUndoStack *undoStack)
{
if ((piece != nullptr) && not m_pieces.contains(piece))
SCASSERT(undoStack != nullptr)
undoStack->clear();
VPLayoutPtr layout(new VPLayout(undoStack));
layout->AddTrashSheet(VPSheetPtr(new VPSheet(layout)));
return layout;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddPiece(const VPLayoutPtr &layout, const VPPiecePtr &piece)
{
piece->SetLayout(layout);
layout->AddPiece(piece);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddPiece(const VPPiecePtr &piece)
{
if ((piece != nullptr) && not m_pieces.contains(piece->GetUniqueID()))
{
piece->SetLayout(this);
m_pieces.append(piece);
m_pieces.insert(piece->GetUniqueID(), piece);
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetPieces() const -> QList<VPPiece *>
auto VPLayout::GetPieces() const -> QList<VPPiecePtr>
{
return m_pieces;
return m_pieces.values();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetUnplacedPieces() const -> QList<VPPiece *>
auto VPLayout::GetUnplacedPieces() const -> QList<VPPiecePtr>
{
return PiecesForSheet(nullptr);
return PiecesForSheet(VPSheetPtr());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetTrashedPieces() const -> QList<VPPiece *>
auto VPLayout::GetTrashedPieces() const -> QList<VPPiecePtr>
{
return PiecesForSheet(m_trashSheet);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::AddSheet() -> VPSheet*
{
auto *newSheet = new VPSheet(this);
m_sheets.append(newSheet);
return newSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::AddSheet(VPSheet *sheet) -> VPSheet*
{
if ((sheet != nullptr) && not m_sheets.contains(sheet))
if (m_trashSheet.isNull())
{
return {};
}
return PiecesForSheet(m_trashSheet->Uuid());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr
{
if (not sheet.isNull() && GetSheet(sheet->Uuid()).isNull())
{
sheet->setParent(this);
m_sheets.append(sheet);
}
return sheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetSheets() -> QList<VPSheet *>
auto VPLayout::GetSheets() -> QList<VPSheetPtr>
{
return m_sheets;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetSheet(const QUuid &uuid) -> VPSheet *
auto VPLayout::GetSheet(const QUuid &uuid) -> VPSheetPtr
{
for (auto *sheet : m_sheets)
auto sheet = std::find_if(m_sheets.begin(), m_sheets.end(),
[uuid](const VPSheetPtr &sheet) { return sheet->Uuid() == uuid; });
if (sheet != m_sheets.end())
{
if (sheet->Uuid() == uuid)
{
return sheet;
}
return *sheet;
}
return nullptr;
return {};
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::SetFocusedSheet(VPSheet *focusedSheet)
void VPLayout::SetFocusedSheet(const VPSheetPtr &focusedSheet)
{
if (m_sheets.isEmpty())
{
m_focusedSheet = nullptr;
m_focusedSheet = {};
}
else
{
m_focusedSheet = focusedSheet == nullptr ? m_sheets.first() : focusedSheet;
m_focusedSheet = focusedSheet.isNull() ? m_sheets.first() : focusedSheet;
}
emit ActiveSheetChanged(m_focusedSheet);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetFocusedSheet() -> VPSheet*
auto VPLayout::GetFocusedSheet() -> VPSheetPtr
{
return m_focusedSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetTrashSheet() -> VPSheet*
auto VPLayout::GetTrashSheet() -> VPSheetPtr
{
return m_trashSheet;
}
@ -145,14 +154,14 @@ auto VPLayout::LayoutSettings() -> VPLayoutSettings &
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::PiecesForSheet(const VPSheet *sheet) const -> QList<VPPiece *>
auto VPLayout::PiecesForSheet(const VPSheetPtr &sheet) const -> QList<VPPiecePtr>
{
QList<VPPiece *> list;
QList<VPPiecePtr> list;
list.reserve(m_pieces.size());
for (auto *piece : m_pieces)
for (auto piece : m_pieces)
{
if ((piece != nullptr) && piece->Sheet() == sheet)
if (not piece.isNull() && piece->Sheet() == sheet)
{
list.append(piece);
}
@ -160,3 +169,57 @@ auto VPLayout::PiecesForSheet(const VPSheet *sheet) const -> QList<VPPiece *>
return list;
}
//---------------------------------------------------------------------------------------------------------------------
QList<VPPiecePtr> VPLayout::PiecesForSheet(const QUuid &uuid) const
{
QList<VPPiecePtr> list;
list.reserve(m_pieces.size());
for (auto piece : m_pieces)
{
if (not piece.isNull())
{
VPSheetPtr sheet = piece->Sheet();
if (not sheet.isNull() && sheet->Uuid() == uuid)
{
list.append(piece);
}
}
}
return list;
}
//---------------------------------------------------------------------------------------------------------------------
QUndoStack *VPLayout::UndoStack() const
{
return m_undoStack;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::SetUndoStack(QUndoStack *newUndoStack)
{
m_undoStack = newUndoStack;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::Clear()
{
if (m_undoStack != nullptr)
{
m_undoStack->clear();
}
m_pieces.clear();
m_trashSheet->Clear();
m_sheets.clear();
m_focusedSheet.clear();
m_layoutSettings = VPLayoutSettings();
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddTrashSheet(const VPSheetPtr &sheet)
{
m_trashSheet = sheet;
}

View File

@ -29,64 +29,86 @@
#define VPLAYOUT_H
#include <QList>
#include <QMap>
#include "def.h"
#include "vplayoutsettings.h"
#include "layoutdef.h"
class VPPiece;
class VPSheet;
class QUndoStack;
class VPLayout : public QObject
{
Q_OBJECT
public:
explicit VPLayout(QObject *parent=nullptr);
virtual ~VPLayout();
virtual ~VPLayout() = default;
void AddPiece(VPPiece *piece);
auto GetPieces() const -> QList<VPPiece *>;
auto GetUnplacedPieces() const -> QList<VPPiece *>;
auto GetTrashedPieces() const -> QList<VPPiece *>;
static auto CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr;
static void AddPiece(const VPLayoutPtr &layout, const VPPiecePtr &piece);
auto AddSheet() -> VPSheet*;
auto AddSheet(VPSheet *sheet) -> VPSheet*;
auto GetSheets() -> QList<VPSheet *>;
auto GetSheet(const QUuid &uuid) -> VPSheet *;
auto GetPieces() const -> QList<VPPiecePtr>;
auto GetUnplacedPieces() const -> QList<VPPiecePtr>;
auto GetTrashedPieces() const -> QList<VPPiecePtr>;
auto AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr;
auto GetSheets() -> QList<VPSheetPtr>;
auto GetSheet(const QUuid &uuid) -> VPSheetPtr;
/**
* @brief SetFocusedSheet Sets the focused sheet, to which pieces are added from the carrousel via drag
* and drop
* @param focusedSheet the new active sheet. If nullptr, then it sets automaticaly the first sheet from m_sheets
*/
void SetFocusedSheet(VPSheet *focusedSheet = nullptr);
void SetFocusedSheet(const VPSheetPtr &focusedSheet = VPSheetPtr());
/**
* @brief GetFocusedSheet Returns the focused sheet, to which pieces are added from the carrousel via drag
* and drop
* @return the focused sheet
*/
auto GetFocusedSheet() -> VPSheet*;
auto GetFocusedSheet() -> VPSheetPtr;
auto GetTrashSheet() -> VPSheet*;
void AddTrashSheet(const VPSheetPtr &sheet);
auto GetTrashSheet() -> VPSheetPtr;
auto LayoutSettings() -> VPLayoutSettings &;
auto PiecesForSheet(const VPSheet* sheet) const -> QList<VPPiece *>;
auto PiecesForSheet(const VPSheetPtr &sheet) const -> QList<VPPiecePtr>;
auto PiecesForSheet(const QUuid &uuid) const -> QList<VPPiecePtr>;
QUndoStack *UndoStack() const;
void SetUndoStack(QUndoStack *newUndoStack);
void Clear();
signals:
void PieceSheetChanged(VPPiece *piece);
void PieceSheetChanged(const VPPiecePtr &piece);
void ActiveSheetChanged(const VPSheetPtr &focusedSheet);
void PieceTransformationChanged(const VPPiecePtr &piece);
protected:
explicit VPLayout(QUndoStack *undoStack);
void AddPiece(const VPPiecePtr &piece);
private:
Q_DISABLE_COPY(VPLayout)
QList<VPPiece *> m_pieces{};
QMap<QString, VPPiecePtr> m_pieces{};
VPSheet* m_trashSheet;
VPSheetPtr m_trashSheet{};
QList<VPSheet*> m_sheets{};
VPSheet *m_focusedSheet{nullptr};
QList<VPSheetPtr> m_sheets{};
VPSheetPtr m_focusedSheet{};
VPLayoutSettings m_layoutSettings{};
QUndoStack *m_undoStack;
};
Q_DECLARE_METATYPE(VPLayoutPtr)
#endif // VPLAYOUT_H

View File

@ -7,6 +7,9 @@ SOURCES += \
$$PWD/dialogs/dialogpuzzlepreferences.cpp \
$$PWD/dialogs/vpdialogabout.cpp \
$$PWD/main.cpp \
$$PWD/undocommands/vpundocommand.cpp \
$$PWD/undocommands/vpundopiecemove.cpp \
$$PWD/undocommands/vpundopiecerotate.cpp \
$$PWD/vpapplication.cpp \
$$PWD/carousel/vpcarrousel.cpp \
$$PWD/carousel/vpcarrouselpiece.cpp \
@ -38,8 +41,12 @@ HEADERS += \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.h \
$$PWD/dialogs/dialogpuzzlepreferences.h \
$$PWD/dialogs/vpdialogabout.h \
$$PWD/layout/layoutdef.h \
$$PWD/scene/scenedef.h \
$$PWD/stable.h \
$$PWD/undocommands/vpundocommand.h \
$$PWD/undocommands/vpundopiecemove.h \
$$PWD/undocommands/vpundopiecerotate.h \
$$PWD/vpapplication.h \
$$PWD/carousel/vpcarrousel.h \
$$PWD/carousel/vpcarrouselpiece.h \

View File

@ -46,6 +46,8 @@
#include "vlayoutpiecepath.h"
#include "vplacelabelitem.h"
#include "undocommands/vpundopiecemove.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
@ -55,7 +57,7 @@ constexpr qreal penWidth = 1;
}
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsPiece::VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent) :
VPGraphicsPiece::VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent) :
QGraphicsObject(parent),
m_piece(piece)
{
@ -71,25 +73,11 @@ VPGraphicsPiece::VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent) :
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::GetPiece() -> VPPiece*
auto VPGraphicsPiece::GetPiece() -> VPPiecePtr
{
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::TranslatePiece(qreal dx, qreal dy)
{
TranslatePiece(QPointF(dx, dy));
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::TranslatePiece(const QPointF &p)
{
prepareGeometryChange();
m_piece->Translate(p);
PaintPiece(); // refresh shapes
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::boundingRect() const -> QRectF
{
@ -149,6 +137,7 @@ void VPGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
GroupMove(event->pos());
m_moveStartPoint = event->pos();
allowChangeMerge = true;
}
//---------------------------------------------------------------------------------------------------------------------
@ -161,18 +150,29 @@ void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::OpenHandCursor);
GroupMove(event->pos());
emit HideTransformationHandles(false);
allowChangeMerge = false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu menu;
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
QList<VPSheet *> sheets = m_piece->Layout()->GetSheets();
sheets.removeAll(m_piece->Sheet());
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return;
}
QMenu menu;
QList<VPSheetPtr> sheets = layout->GetSheets();
sheets.removeAll(piece->Sheet());
QVector<QAction*> moveToActions;
@ -180,13 +180,16 @@ void VPGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu *moveMenu = menu.addMenu(tr("Move to"));
for (auto *sheet : sheets)
for (const auto &sheet : sheets)
{
if (not sheet.isNull())
{
QAction* moveToSheet = moveMenu->addAction(sheet->GetName());
moveToSheet->setData(QVariant::fromValue(sheet));
moveToActions.append(moveToSheet);
}
}
}
// remove from layout action
QAction *removeAction = menu.addAction(tr("Remove from Sheet"));
@ -195,13 +198,13 @@ void VPGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
if (moveToActions.contains(selectedAction))
{
m_piece->SetSheet(qvariant_cast<VPSheet *>(selectedAction->data()));
emit m_piece->Layout()->PieceSheetChanged(m_piece);
piece->SetSheet(qvariant_cast<VPSheetPtr>(selectedAction->data()));
emit layout->PieceSheetChanged(piece);
}
else if (selectedAction == removeAction)
{
m_piece->SetSheet(nullptr);
emit m_piece->Layout()->PieceSheetChanged(m_piece);
piece->SetSheet(nullptr);
emit layout->PieceSheetChanged(piece);
}
}
@ -211,11 +214,14 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
QBrush noBrush(Qt::NoBrush);
QBrush selectionBrush(QColor(255,160,160,60));
QRectF rect = m_piece->MappedDetailBoundingRect();
QPointF p = rect.topLeft();
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
// initialises the seam line
QVector<QPointF> seamLinePoints = m_piece->GetMappedContourPoints();
QVector<QPointF> seamLinePoints = piece->GetMappedContourPoints();
if(!seamLinePoints.isEmpty())
{
m_seamLine = QPainterPath();
@ -235,7 +241,7 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
}
// initiliases the cutting line
QVector<QPointF> cuttingLinepoints = m_piece->GetMappedSeamAllowancePoints();
QVector<QPointF> cuttingLinepoints = piece->GetMappedSeamAllowancePoints();
if(!cuttingLinepoints.isEmpty())
{
m_cuttingLine = QPainterPath();
@ -255,9 +261,9 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
}
// initialises the grainline
if(m_piece->IsGrainlineEnabled())
if(piece->IsGrainlineEnabled())
{
QVector<QPointF> grainLinepoints = m_piece->GetMappedGrainline();
QVector<QPointF> grainLinepoints = piece->GetMappedGrainline();
if(!grainLinepoints.isEmpty())
{
QPainterPath grainline;
@ -282,10 +288,10 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
}
// initialises the internal paths
QVector<VLayoutPiecePath> internalPaths = m_piece->GetInternalPaths();
QVector<VLayoutPiecePath> internalPaths = piece->GetInternalPaths();
for (const auto& piecePath : internalPaths)
{
QPainterPath path = m_piece->GetMatrix().map(piecePath.GetPainterPath());
QPainterPath path = piece->GetMatrix().map(piecePath.GetPainterPath());
if (painter != nullptr)
{
@ -297,7 +303,7 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
}
// initialises the passmarks
QVector<VLayoutPassmark> passmarks = m_piece->GetMappedPassmarks();
QVector<VLayoutPassmark> passmarks = piece->GetMappedPassmarks();
for(auto &passmark : passmarks)
{
QPainterPath passmarkPath;
@ -317,7 +323,7 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
}
// initialises the place labels (buttons etc)
QVector<VLayoutPlaceLabel> placeLabels = m_piece->GetMappedPlaceLabels();
QVector<VLayoutPlaceLabel> placeLabels = piece->GetMappedPlaceLabels();
for(auto &placeLabel : placeLabels)
{
QPainterPath path = VPlaceLabelItem::LabelShapePath(placeLabel.shape);
@ -345,27 +351,63 @@ void VPGraphicsPiece::GroupMove(const QPointF &pos)
if (scene() != nullptr)
{
QList<QGraphicsItem *> list = scene()->selectedItems();
if (list.isEmpty())
{
return;
}
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return;
}
auto PreparePieces = [list]()
{
QVector<VPPiecePtr> pieces;
for (auto *item : list)
{
if (item->type() == UserType + static_cast<int>(PGraphicsItem::Piece))
if (item->type() == VPGraphicsPiece::Type)
{
auto *pieceItem = dynamic_cast<VPGraphicsPiece*>(item);
pieceItem->TranslatePiece(pos-m_moveStartPoint);
pieces.append(pieceItem->GetPiece());
}
}
emit PiecePositionChanged();
return pieces;
};
QVector<VPPiecePtr> 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);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_Rotate(const QPointF &center, qreal angle)
void VPGraphicsPiece::on_RefreshPiece(const VPPiecePtr &piece)
{
if (isSelected())
if (m_piece == piece)
{
prepareGeometryChange();
m_piece->Rotate(center, angle);
PaintPiece(); // Update shapes
update();
PaintPiece(); // refresh shapes
emit PieceTransformationChanged();
}
}
@ -375,9 +417,13 @@ auto VPGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &valu
if (scene() != nullptr)
{
if(change == ItemSelectedHasChanged)
{
VPPiecePtr piece = m_piece.toStrongRef();
if (not piece.isNull())
{
emit PieceSelectionChanged();
m_piece->SetSelected(value.toBool());
piece->SetSelected(value.toBool());
}
}
}

View File

@ -33,24 +33,20 @@
#include <QCursor>
#include "scenedef.h"
class VPPiece;
#include "../layout/layoutdef.h"
class VPGraphicsPiece : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent = nullptr);
explicit VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent = nullptr);
~VPGraphicsPiece() = default;
/**
* @brief GetPiece Returns the piece that corresponds to the graphics piece
* @return the piece
*/
auto GetPiece() -> VPPiece*;
void TranslatePiece(qreal dx, qreal dy);
void TranslatePiece(const QPointF &p);
auto GetPiece() -> VPPiecePtr;
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::Piece)};
@ -58,10 +54,10 @@ public:
signals:
void PieceSelectionChanged();
void HideTransformationHandles(bool hide);
void PiecePositionChanged();
void PieceTransformationChanged();
public slots:
void on_Rotate(const QPointF &center, qreal angle);
void on_RefreshPiece(const VPPiecePtr &piece);
protected:
auto boundingRect() const -> QRectF override;
@ -78,7 +74,7 @@ protected:
private:
Q_DISABLE_COPY(VPGraphicsPiece)
VPPiece *m_piece;
VPPieceWeakPtr m_piece;
QPainterPath m_cuttingLine{};
QPainterPath m_seamLine{};
@ -88,6 +84,8 @@ private:
QCursor m_rotateCursor{};
bool allowChangeMerge{false};
void PaintPiece(QPainter *painter=nullptr);
void GroupMove(const QPointF &pos);

View File

@ -37,6 +37,8 @@
#include "../vmisc/compatibility.h"
#include "../vwidgets/global.h"
#include "../layout/vplayout.h"
#include "../undocommands/vpundopiecerotate.h"
#include "vpgraphicspiece.h"
namespace
{
@ -67,11 +69,11 @@ enum class HandleCorner : int
BottomLeft = 4
};
auto TransformationOrigin(VPLayout *layout, const QRectF &boundingRect) -> QPointF
auto TransformationOrigin(const VPLayoutPtr &layout, const QRectF &boundingRect) -> QPointF
{
SCASSERT(layout != nullptr)
VPSheet *sheet = layout->GetFocusedSheet();
if (sheet != nullptr)
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
return origin.origin;
@ -82,7 +84,7 @@ auto TransformationOrigin(VPLayout *layout, const QRectF &boundingRect) -> QPoin
} // namespace
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTransformationOrigin::VPGraphicsTransformationOrigin(VPLayout *layout, QGraphicsItem *parent)
VPGraphicsTransformationOrigin::VPGraphicsTransformationOrigin(const VPLayoutPtr &layout, QGraphicsItem *parent)
: QGraphicsObject(parent),
m_layout(layout),
m_color(defaultColor)
@ -113,14 +115,14 @@ void VPGraphicsTransformationOrigin::on_ShowOrigin(bool show)
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsTransformationOrigin::boundingRect() const
auto VPGraphicsTransformationOrigin::boundingRect() const -> QRectF
{
constexpr qreal halfPenWidth = penWidth/2.;
return Center2().boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsTransformationOrigin::shape() const
auto VPGraphicsTransformationOrigin::shape() const -> QPainterPath
{
return Center2();
}
@ -170,8 +172,11 @@ void VPGraphicsTransformationOrigin::mousePressEvent(QGraphicsSceneMouseEvent *e
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
origin.origin = event->scenePos();
@ -179,6 +184,7 @@ void VPGraphicsTransformationOrigin::mouseMoveEvent(QGraphicsSceneMouseEvent *ev
sheet->SetTransformationOrigin(origin);
}
prepareGeometryChange();
}
QGraphicsObject::mouseMoveEvent(event);
}
@ -251,7 +257,7 @@ auto VPGraphicsTransformationOrigin::RotationCenter(QPainter *painter) const ->
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsTransformationOrigin::Center1() const
auto VPGraphicsTransformationOrigin::Center1() const -> QPainterPath
{
const qreal scale = SceneScale(scene());
qreal radius = centerRadius1/scale;
@ -265,7 +271,7 @@ QPainterPath VPGraphicsTransformationOrigin::Center1() const
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsTransformationOrigin::Center2() const
auto VPGraphicsTransformationOrigin::Center2() const -> QPainterPath
{
const qreal scale = SceneScale(scene());
qreal radius = centerRadius2/scale;
@ -280,7 +286,7 @@ QPainterPath VPGraphicsTransformationOrigin::Center2() const
// VPGraphicsPieceControls
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsPieceControls::VPGraphicsPieceControls(VPLayout *layout, QGraphicsItem *parent)
VPGraphicsPieceControls::VPGraphicsPieceControls(const VPLayoutPtr &layout, QGraphicsItem *parent)
: QGraphicsObject(parent),
m_layout(layout)
{
@ -294,13 +300,22 @@ VPGraphicsPieceControls::VPGraphicsPieceControls(VPLayout *layout, QGraphicsItem
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::on_UpdateControls()
{
m_pieceRect = PiecesBoundingRect();
if (m_ignorePieceTransformation)
{
return;
}
m_selectedPieces = SelectedPieces();
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
setVisible(not m_pieceRect.isNull());
if (not m_pieceRect.isNull())
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
if (not origin.custom)
@ -311,6 +326,7 @@ void VPGraphicsPieceControls::on_UpdateControls()
}
}
}
}
emit ShowOrigin(not m_pieceRect.isNull());
prepareGeometryChange();
@ -320,6 +336,7 @@ void VPGraphicsPieceControls::on_UpdateControls()
void VPGraphicsPieceControls::on_HideHandles(bool hide)
{
m_controlsVisible = not hide;
update();
}
//---------------------------------------------------------------------------------------------------------------------
@ -364,6 +381,7 @@ void VPGraphicsPieceControls::mousePressEvent(QGraphicsSceneMouseEvent *event)
m_rotationStartPoint = event->scenePos();
m_controlsVisible = false;
m_handleCorner = HandleCorner(event->scenePos());
m_ignorePieceTransformation = true;
prepareGeometryChange();
}
else
@ -380,12 +398,15 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (not m_originSaved)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
m_savedOrigin = sheet->TransformationOrigin();
m_originSaved = true;
m_pieceRect = PiecesBoundingRect();
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
VPTransformationOrigon origin;
origin.custom = true;
@ -412,16 +433,20 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
}
}
}
}
else
{
if (m_originSaved)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (sheet != nullptr)
{
if (not m_savedOrigin.custom)
{
m_pieceRect = PiecesBoundingRect();
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
m_savedOrigin.origin = m_pieceRect.center();
}
sheet->SetTransformationOrigin(m_savedOrigin);
@ -430,6 +455,7 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
m_originSaved = false;
}
}
}
QPointF rotationNewPoint = event->scenePos();
@ -442,7 +468,33 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
if (not qFuzzyIsNull(angle))
{
emit Rotate(rotationOrigin, angle);
auto PreparePieces = [this]()
{
QVector<VPPiecePtr> pieces;
for (auto *item : m_selectedPieces)
{
pieces.append(item->GetPiece());
}
return pieces;
};
QVector<VPPiecePtr> pieces = PreparePieces();
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
if (pieces.size() == 1)
{
auto *command = new VPUndoPieceRotate(pieces.first(), rotationOrigin, angle, allowChangeMerge);
layout->UndoStack()->push(command);
}
else if (pieces.size() > 1)
{
auto *command = new VPUndoPiecesRotate(pieces, rotationOrigin, angle, allowChangeMerge);
layout->UndoStack()->push(command);
}
}
}
if (m_originSaved && m_savedOrigin.custom)
@ -453,6 +505,7 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
}
m_rotationStartPoint = rotationNewPoint;
allowChangeMerge = true;
QGraphicsObject::mouseMoveEvent(event);
}
@ -462,15 +515,19 @@ void VPGraphicsPieceControls::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if(event->button() == Qt::LeftButton)
{
m_controlsVisible = true;
m_ignorePieceTransformation = false;
if (m_originSaved)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
if (not m_savedOrigin.custom)
{
m_pieceRect = PiecesBoundingRect();
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
m_savedOrigin.origin = m_pieceRect.center();
}
sheet->SetTransformationOrigin(m_savedOrigin);
@ -478,12 +535,20 @@ void VPGraphicsPieceControls::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
m_originSaved = false;
}
}
on_UpdateControls();
allowChangeMerge = false;
}
QGraphicsObject::mouseReleaseEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::SetIgnorePieceTransformation(bool newIgnorePieceTransformation)
{
m_ignorePieceTransformation = newIgnorePieceTransformation;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::TopLeftControl(QPainter *painter) const -> QPainterPath
{
@ -522,7 +587,7 @@ auto VPGraphicsPieceControls::BottomRightControl(QPainter *painter) const -> QPa
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsPieceControls::Handles() const
auto VPGraphicsPieceControls::Handles() const -> QPainterPath
{
QPainterPath path;
@ -690,21 +755,37 @@ auto VPGraphicsPieceControls::ArrowPath() const -> QPainterPath
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsPieceControls::PiecesBoundingRect() const
auto VPGraphicsPieceControls::SelectedPieces() const -> QVector<VPGraphicsPiece *>
{
QRectF rect;
QVector<VPGraphicsPiece *> pieces;
QGraphicsScene *scene = this->scene();
if (scene != nullptr)
{
QList<QGraphicsItem *> list = scene->selectedItems();
for (auto *item : list)
{
if (item->type() == UserType + static_cast<int>(PGraphicsItem::Piece))
if (item->type() == VPGraphicsPiece::Type)
{
auto *pieceItem = dynamic_cast<VPGraphicsPiece*>(item);
if (pieceItem != nullptr)
{
pieces.append(pieceItem);
}
}
}
}
return pieces;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::PiecesBoundingRect(const QVector<VPGraphicsPiece *> &selectedPieces) const -> QRectF
{
QRectF rect;
for (auto *item : selectedPieces)
{
rect = rect.united(item->sceneBoundingRect());
}
}
}
return rect;
}

View File

@ -35,12 +35,13 @@
#include "../layout/vpsheet.h"
class VPLayout;
class VPGraphicsPiece;
class VPGraphicsTransformationOrigin : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsTransformationOrigin(VPLayout *layout, QGraphicsItem * parent = nullptr);
explicit VPGraphicsTransformationOrigin(const VPLayoutPtr &layout, QGraphicsItem * parent = nullptr);
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::TransformationOrigin)};
@ -66,7 +67,7 @@ private:
Q_DISABLE_COPY(VPGraphicsTransformationOrigin)
bool m_originVisible{true};
VPLayout *m_layout;
VPLayoutWeakPtr m_layout{};
QColor m_color;
auto RotationCenter(QPainter *painter = nullptr) const -> QPainterPath;
@ -78,13 +79,14 @@ class VPGraphicsPieceControls : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsPieceControls(VPLayout *layout, QGraphicsItem * parent = nullptr);
explicit VPGraphicsPieceControls(const VPLayoutPtr &layout, QGraphicsItem * parent = nullptr);
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::Handles)};
void SetIgnorePieceTransformation(bool newIgnorePieceTransformation);
signals:
void Rotate(const QPointF &center, qreal angle);
void ShowOrigin(bool show);
void TransformationOriginChanged();
@ -106,10 +108,13 @@ private:
QRectF m_pieceRect{};
QPointF m_rotationStartPoint{};
bool m_controlsVisible{true};
VPLayout *m_layout;
VPLayoutWeakPtr m_layout{};
int m_handleCorner{0};
VPTransformationOrigon m_savedOrigin{};
bool m_originSaved{false};
bool allowChangeMerge{false};
QVector<VPGraphicsPiece *> m_selectedPieces{};
bool m_ignorePieceTransformation{false};
auto TopLeftControl(QPainter *painter = nullptr) const -> QPainterPath;
auto TopRightControl(QPainter *painter = nullptr) const -> QPainterPath;
@ -122,7 +127,8 @@ private:
auto ArrowPath() const -> QPainterPath;
auto PiecesBoundingRect() const -> QRectF;
auto SelectedPieces() const -> QVector<VPGraphicsPiece *>;
auto PiecesBoundingRect(const QVector<VPGraphicsPiece *> &selectedPieces) const -> QRectF;
auto HandleCorner(const QPointF &pos) const -> int;
};

View File

@ -1,4 +1,4 @@
/************************************************************************
/*******************************************************************
**
** @file vpgraphicssheet.cpp
** @author Ronan Le Tiec
@ -33,7 +33,7 @@
#include <QtMath>
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsSheet::VPGraphicsSheet(VPLayout *layout, QGraphicsItem *parent):
VPGraphicsSheet::VPGraphicsSheet(const VPLayoutPtr &layout, QGraphicsItem *parent):
QGraphicsItem(parent),
m_layout(layout),
m_boundingRect(GetSheetRect())
@ -66,12 +66,14 @@ void VPGraphicsSheet::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
painter->drawRect(sheetRect);
}
if(m_layout->LayoutSettings().GetShowGrid())
VPLayoutPtr layout = m_layout.toStrongRef();
if(not layout.isNull() && layout->LayoutSettings().GetShowGrid())
{
pen.setColor(QColor(204,204,204));
painter->setPen(pen);
qreal colWidth = m_layout->LayoutSettings().GetGridColWidth();
qreal colWidth = layout->LayoutSettings().GetGridColWidth();
if(colWidth > 0)
{
qreal colX = colWidth;
@ -83,7 +85,7 @@ void VPGraphicsSheet::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
}
}
qreal rowHeight = m_layout->LayoutSettings().GetGridRowHeight();
qreal rowHeight = layout->LayoutSettings().GetGridRowHeight();
if(rowHeight > 0)
{
qreal rowY = rowHeight;
@ -101,11 +103,17 @@ void VPGraphicsSheet::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsSheet::GetSheetRect() const
auto VPGraphicsSheet::GetSheetRect() const -> QRectF
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return {};
}
QPoint topLeft = QPoint(0,0);
QSizeF size = m_layout->LayoutSettings().GetSheetSize();
if(m_layout->LayoutSettings().GetOrientation() == PageOrientation::Landscape)
QSizeF size = layout->LayoutSettings().GetSheetSize();
if(layout->LayoutSettings().GetOrientation() == PageOrientation::Landscape)
{
size.transpose();
}
@ -114,20 +122,24 @@ QRectF VPGraphicsSheet::GetSheetRect() const
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsSheet::GetMarginsRect() const
auto VPGraphicsSheet::GetMarginsRect() const -> QRectF
{
QMarginsF margins = m_layout->LayoutSettings().GetSheetMargins();
QSizeF size = m_layout->LayoutSettings().GetSheetSize();
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return {};
}
if(m_layout->LayoutSettings().GetOrientation() == PageOrientation::Landscape)
QMarginsF margins = layout->LayoutSettings().GetSheetMargins();
QSizeF size = layout->LayoutSettings().GetSheetSize();
if(layout->LayoutSettings().GetOrientation() == PageOrientation::Landscape)
{
size.transpose();
}
QRectF rect = QRectF(
QPointF(margins.left(),margins.top()),
QPointF(size.width()-margins.right(), size.height()-margins.bottom())
);
QRectF rect = QRectF(QPointF(margins.left(),margins.top()),
QPointF(size.width()-margins.right(), size.height()-margins.bottom()));
return rect;
}
@ -144,7 +156,7 @@ void VPGraphicsSheet::SetShowBorder(bool value)
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsSheet::boundingRect() const
auto VPGraphicsSheet::boundingRect() const -> QRectF
{
return m_boundingRect;
}

View File

@ -32,19 +32,21 @@
#include <QGraphicsItem>
#include <QPainter>
#include "../layout/layoutdef.h"
class VPLayout;
class VPGraphicsSheet : public QGraphicsItem
{
public:
explicit VPGraphicsSheet(VPLayout *sheet, QGraphicsItem *parent = nullptr);
explicit VPGraphicsSheet(const VPLayoutPtr &layout, QGraphicsItem *parent = nullptr);
~VPGraphicsSheet()=default;
QRectF boundingRect() const override;
auto boundingRect() const -> QRectF override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QRectF GetSheetRect() const;
QRectF GetMarginsRect() const;
auto GetSheetRect() const -> QRectF;
auto GetMarginsRect() const -> QRectF;
/**
* @brief SetShowMargin Sets Wether we see the margin
@ -61,7 +63,7 @@ public:
private:
Q_DISABLE_COPY(VPGraphicsSheet)
VPLayout *m_layout{nullptr};
VPLayoutWeakPtr m_layout{};
QRectF m_boundingRect;
bool m_showMargin{true};

View File

@ -4,7 +4,7 @@
#include "../layout/vplayout.h"
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTileGrid::VPGraphicsTileGrid(VPLayout *layout, VPTileFactory *tileFactory,QGraphicsItem *parent):
VPGraphicsTileGrid::VPGraphicsTileGrid(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QGraphicsItem *parent):
QGraphicsItem(parent),
m_tileFactory(tileFactory),
m_layout(layout)
@ -21,7 +21,8 @@ VPGraphicsTileGrid::~VPGraphicsTileGrid()
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsTileGrid::boundingRect() const
{
if(m_layout->LayoutSettings().GetShowTiles())
VPLayoutPtr layout = m_layout.toStrongRef();
if(not layout.isNull() && layout->LayoutSettings().GetShowTiles())
{
return QRectF(0,
0,
@ -39,7 +40,8 @@ void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem
Q_UNUSED(widget);
Q_UNUSED(option);
if(m_layout->LayoutSettings().GetShowTiles())
VPLayoutPtr layout = m_layout.toStrongRef();
if(not layout.isNull() && layout->LayoutSettings().GetShowTiles())
{
QPen pen(QColor(255,0,0,127), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pen.setCosmetic(true);

View File

@ -33,6 +33,7 @@
#include <QPainter>
#include "../vmisc/def.h"
#include "../layout/layoutdef.h"
class VPTileFactory;
class VPLayout;
@ -40,7 +41,7 @@ class VPLayout;
class VPGraphicsTileGrid : public QGraphicsItem
{
public:
explicit VPGraphicsTileGrid(VPLayout* layout, VPTileFactory *tileFactory, QGraphicsItem *parent = nullptr);
explicit VPGraphicsTileGrid(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QGraphicsItem *parent = nullptr);
~VPGraphicsTileGrid();
QRectF boundingRect() const override;
@ -50,8 +51,8 @@ public:
private:
Q_DISABLE_COPY(VPGraphicsTileGrid)
VPTileFactory *m_tileFactory{nullptr};
VPLayout *m_layout{nullptr};
VPTileFactory * m_tileFactory{nullptr};
VPLayoutWeakPtr m_layout{};
};
#endif // VPGRAPHICSTILEGRID_H

View File

@ -46,6 +46,7 @@
#include "vptilefactory.h"
#include "vpgraphicspiececontrols.h"
#include "../undocommands/vpundopiecemove.h"
#include "../undocommands/vpundopiecerotate.h"
#include <QLoggingCategory>
@ -95,36 +96,6 @@ VPMainGraphicsView::VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory
restoreOrigin->setShortcut(restoreOriginShortcut);
connect(restoreOrigin, &QAction::triggered, this, &VPMainGraphicsView::RestoreOrigin);
this->addAction(restoreOrigin);
auto *rotateByPlus15 = new QAction(this);
rotateByPlus15->setShortcut(QKeySequence(Qt::Key_BracketLeft));
connect(rotateByPlus15, &QAction::triggered, this, &VPMainGraphicsView::RotatePiecesByPlus15);
this->addAction(rotateByPlus15);
auto *rotateByMinus15 = new QAction(this);
rotateByMinus15->setShortcut(QKeySequence(Qt::Key_BracketRight));
connect(rotateByMinus15, &QAction::triggered, this, &VPMainGraphicsView::RotatePiecesByMinus15);
this->addAction(rotateByMinus15);
auto *rotateByPlus90 = new QAction(this);
rotateByPlus90->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_BracketLeft));
connect(rotateByPlus90, &QAction::triggered, this, &VPMainGraphicsView::RotatePiecesByPlus90);
this->addAction(rotateByPlus90);
auto *rotateByMinus90 = new QAction(this);
rotateByMinus90->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_BracketRight));
connect(rotateByMinus90, &QAction::triggered, this, &VPMainGraphicsView::RotatePiecesByMinus90);
this->addAction(rotateByMinus90);
auto *rotateByPlus1 = new QAction(this);
rotateByPlus1->setShortcut(QKeySequence(Qt::AltModifier + Qt::Key_BracketLeft));
connect(rotateByPlus1, &QAction::triggered, this, &VPMainGraphicsView::RotatePiecesByPlus1);
this->addAction(rotateByPlus1);
auto *rotateByMinus1 = new QAction(this);
rotateByMinus1->setShortcut(QKeySequence(Qt::AltModifier + Qt::Key_BracketRight));
connect(rotateByMinus1, &QAction::triggered, this, &VPMainGraphicsView::RotatePiecesByMinus1);
this->addAction(rotateByMinus1);
}
//---------------------------------------------------------------------------------------------------------------------
@ -342,17 +313,62 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event)
TranslatePiecesOn(0, 1);
}
}
else if (event->key() == Qt::Key_BracketLeft)
{
if((event->modifiers() & Qt::ControlModifier) != 0U)
{
RotatePiecesByAngle(90);
}
else if((event->modifiers() & Qt::AltModifier) != 0U)
{
RotatePiecesByAngle(1);
}
else
{
RotatePiecesByAngle(15);
}
}
else if (event->key() == Qt::Key_BracketRight)
{
if((event->modifiers() & Qt::ControlModifier) != 0U)
{
RotatePiecesByAngle(-90);
}
else if((event->modifiers() & Qt::AltModifier) != 0U)
{
RotatePiecesByAngle(-1);
}
else
{
RotatePiecesByAngle(-15);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event)
{
VMainGraphicsView::keyReleaseEvent(event);
if (event->key() != Qt::Key_Left && event->key() != Qt::Key_Right && event->key() != Qt::Key_Up &&
event->key() != Qt::Key_Down)
if (event->key() == Qt::Key_Left ||
event->key() == Qt::Key_Right ||
event->key() == Qt::Key_Up ||
event->key() == Qt::Key_Down ||
event->key() == Qt::Key_BracketLeft ||
event->key() == Qt::Key_BracketRight)
{
if (not event->isAutoRepeat())
{
m_allowChangeMerge = false;
}
}
if (event->key() == Qt::Key_BracketLeft || event->key() == Qt::Key_BracketRight)
{
if (not event->isAutoRepeat())
{
m_rotationControls->SetIgnorePieceTransformation(false);
}
}
VMainGraphicsView::keyReleaseEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
@ -428,42 +444,6 @@ void VPMainGraphicsView::RestoreOrigin() const
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByPlus15() const
{
RotatePiecesByAngle(15);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByMinus15() const
{
RotatePiecesByAngle(-15);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByPlus90() const
{
RotatePiecesByAngle(90);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByMinus90() const
{
RotatePiecesByAngle(-90);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByPlus1() const
{
RotatePiecesByAngle(1);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByMinus1() const
{
RotatePiecesByAngle(-1);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece)
{
@ -477,7 +457,6 @@ void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece)
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
connect(piece, &VPGraphicsPiece::PieceTransformationChanged,
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
connect(m_rotationControls, &VPGraphicsPieceControls::Rotate, piece, &VPGraphicsPiece::on_Rotate);
connect(piece, &VPGraphicsPiece::HideTransformationHandles,
m_rotationControls, &VPGraphicsPieceControls::on_HideHandles);
connect(piece, &VPGraphicsPiece::HideTransformationHandles,
@ -485,8 +464,10 @@ void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece)
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) const
void VPMainGraphicsView::RotatePiecesByAngle(qreal angle)
{
m_rotationControls->SetIgnorePieceTransformation(true);
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
@ -501,14 +482,34 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) const
VPTransformationOrigon origin = sheet->TransformationOrigin();
for(auto *graphicsPiece : m_graphicsPieces)
auto PreparePieces = [this]()
{
if (graphicsPiece->isSelected())
QVector<VPPiecePtr> pieces;
for (auto *item : m_graphicsPieces)
{
graphicsPiece->on_Rotate(origin.origin, angle);
m_rotationControls->on_UpdateControls();
if (item->isSelected())
{
pieces.append(item->GetPiece());
}
}
return pieces;
};
QVector<VPPiecePtr> pieces = PreparePieces();
if (pieces.size() == 1)
{
auto *command = new VPUndoPieceRotate(pieces.first(), origin.origin, angle, m_allowChangeMerge);
layout->UndoStack()->push(command);
}
else if (pieces.size() > 1)
{
auto *command = new VPUndoPiecesRotate(pieces, origin.origin, angle, m_allowChangeMerge);
layout->UndoStack()->push(command);
}
m_allowChangeMerge = true;
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -98,12 +98,6 @@ protected:
private slots:
void RestoreOrigin() const;
void RotatePiecesByPlus15() const;
void RotatePiecesByMinus15() const;
void RotatePiecesByPlus90() const;
void RotatePiecesByMinus90() const;
void RotatePiecesByPlus1() const;
void RotatePiecesByMinus1() const;
private:
Q_DISABLE_COPY(VPMainGraphicsView)
@ -134,7 +128,7 @@ private:
void ConnectPiece(VPGraphicsPiece *piece);
void RotatePiecesByAngle(qreal angle) const;
void RotatePiecesByAngle(qreal angle);
void TranslatePiecesOn(qreal dx, qreal dy);
};

View File

@ -37,7 +37,9 @@ namespace ML
enum class UndoCommand: qint8
{
MovePiece = 0,
MovePieces = 1
MovePieces = 1,
RotatePiece = 2,
RotatePieces = 3,
};
}

View File

@ -0,0 +1,266 @@
/************************************************************************
**
** @file vpundopiecerotate.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 18 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpundopiecerotate.h"
#include "../layout/vppiece.h"
#include "../layout/vplayout.h"
//---------------------------------------------------------------------------------------------------------------------
VPUndoPieceRotate::VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge,
QUndoCommand *parent)
: VPUndoCommand(parent),
m_piece(piece),
m_origin(origin),
m_angle(angle),
m_allowMerge(allowMerge)
{
SCASSERT(not piece.isNull())
m_oldTransform = piece->GetMatrix();
setText(QObject::tr("rotate piece"));
}
//---------------------------------------------------------------------------------------------------------------------
void VPUndoPieceRotate::undo()
{
VPPiecePtr piece = Piece();
if (piece.isNull())
{
return;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return;
}
layout->SetFocusedSheet(piece->Sheet());
piece->SetMatrix(m_oldTransform);
emit layout->PieceTransformationChanged(piece);
}
//---------------------------------------------------------------------------------------------------------------------
void VPUndoPieceRotate::redo()
{
VPPiecePtr piece = Piece();
if (piece.isNull())
{
return;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return;
}
layout->SetFocusedSheet(piece->Sheet());
piece->Rotate(m_origin, m_angle);
emit layout->PieceTransformationChanged(piece);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPieceRotate::mergeWith(const QUndoCommand *command) -> bool
{
if (command->id() != id()) // make sure other is also an VPUndoPieceMove command
{
return false;
}
const auto *moveCommand = dynamic_cast<const VPUndoPieceRotate *>(command);
SCASSERT(moveCommand != nullptr)
VPPiecePtr piece = Piece();
if (not moveCommand->AllowMerge() || (moveCommand->Piece().isNull() || piece.isNull()) ||
moveCommand->Piece() != piece || moveCommand->Origin() != m_origin)
{
return false;
}
m_angle += moveCommand->Angle();
return true;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPieceRotate::id() const -> int
{
return static_cast<int>(ML::UndoCommand::RotatePiece);
}
// rotate pieces
//---------------------------------------------------------------------------------------------------------------------
VPUndoPiecesRotate::VPUndoPiecesRotate(const QVector<VPPiecePtr> &pieces, const QPointF &origin, qreal angle,
bool allowMerge, QUndoCommand *parent)
: VPUndoCommand(parent),
m_origin(origin),
m_angle(angle),
m_allowMerge(allowMerge)
{
setText(QObject::tr("rotate pieces"));
for (const auto& piece : pieces)
{
if (not piece.isNull())
{
m_pieces.append(piece);
m_oldTransforms.insert(piece->GetUniqueID(), piece->GetMatrix());
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPUndoPiecesRotate::undo()
{
if (m_pieces.isEmpty())
{
return;
}
VPLayoutPtr layout = Layout();
if (layout.isNull())
{
return;
}
layout->SetFocusedSheet(Sheet());
for (const auto& piece : m_pieces)
{
VPPiecePtr p = piece.toStrongRef();
if (not p.isNull())
{
if (m_oldTransforms.contains(p->GetUniqueID()))
{
p->SetMatrix(m_oldTransforms.value(p->GetUniqueID()));
emit layout->PieceTransformationChanged(p);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPUndoPiecesRotate::redo()
{
if (m_pieces.isEmpty())
{
return;
}
VPLayoutPtr layout = Layout();
if (layout.isNull())
{
return;
}
layout->SetFocusedSheet(Sheet());
for (const auto& piece : m_pieces)
{
VPPiecePtr p = piece.toStrongRef();
if (not p.isNull())
{
p->Rotate(m_origin, m_angle);
emit layout->PieceTransformationChanged(p);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPiecesRotate::mergeWith(const QUndoCommand *command) -> bool
{
if (command->id() != id()) // make sure other is also an VPUndoPieceMove command
{
return false;
}
const auto *moveCommand = dynamic_cast<const VPUndoPiecesRotate *>(command);
SCASSERT(moveCommand != nullptr)
if (not moveCommand->AllowMerge() || moveCommand->PieceIds() != PieceIds() || moveCommand->Origin() != m_origin)
{
return false;
}
m_angle += moveCommand->Angle();
return true;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPiecesRotate::id() const -> int
{
return static_cast<int>(ML::UndoCommand::RotatePieces);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPiecesRotate::PieceIds() const -> QSet<QString>
{
QSet<QString> ids;
for (const auto& piece : m_pieces)
{
VPPiecePtr p = piece.toStrongRef();
if (not p.isNull())
{
ids.insert(p->GetUniqueID());
}
};
return ids;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPiecesRotate::Layout() const -> VPLayoutPtr
{
for (const auto& piece : m_pieces)
{
VPPiecePtr p = piece.toStrongRef();
if (not p.isNull())
{
return p->Layout();
}
}
return nullptr;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPUndoPiecesRotate::Sheet() const -> VPSheetPtr
{
for (const auto& piece : m_pieces)
{
VPPiecePtr p = piece.toStrongRef();
if (not p.isNull())
{
return p->Sheet();
}
}
return nullptr;
}

View File

@ -0,0 +1,142 @@
/************************************************************************
**
** @file vpundopiecerotate.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 18 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPUNDOPIECEROTATE_H
#define VPUNDOPIECEROTATE_H
#include "vpundocommand.h"
#include <QTransform>
#include "../layout/layoutdef.h"
class VPUndoPieceRotate : public VPUndoCommand
{
Q_OBJECT
public:
VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge,
QUndoCommand *parent = nullptr);
virtual ~VPUndoPieceRotate()=default;
virtual void undo() override;
virtual void redo() override;
// cppcheck-suppress unusedFunction
virtual auto mergeWith(const QUndoCommand *command) -> bool override;
virtual auto id() const -> int override ;
auto Piece() const -> VPPiecePtr;
auto Origin() const -> QPointF;
auto Angle() const -> qreal;
auto AllowMerge() const -> bool;
private:
Q_DISABLE_COPY(VPUndoPieceRotate)
VPPieceWeakPtr m_piece;
QTransform m_oldTransform{};
QPointF m_origin;
qreal m_angle;
bool m_allowMerge;
};
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPieceRotate::Piece() const -> VPPiecePtr
{
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPieceRotate::Origin() const -> QPointF
{
return m_origin;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPieceRotate::Angle() const -> qreal
{
return m_angle;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPieceRotate::AllowMerge() const -> bool
{
return m_allowMerge;
}
// Rotate pieces
class VPUndoPiecesRotate : public VPUndoCommand
{
Q_OBJECT
public:
explicit VPUndoPiecesRotate(const QVector<VPPiecePtr> &pieces, const QPointF &origin, qreal angle, bool allowMerge,
QUndoCommand *parent = nullptr);
virtual ~VPUndoPiecesRotate()=default;
virtual void undo() override;
virtual void redo() override;
// cppcheck-suppress unusedFunction
virtual auto mergeWith(const QUndoCommand *command) -> bool override;
virtual auto id() const -> int override ;
auto PieceIds() const -> QSet<QString>;
auto Origin() const -> QPointF;
auto Angle() const -> qreal;
auto AllowMerge() const -> bool;
private:
Q_DISABLE_COPY(VPUndoPiecesRotate)
QVector<VPPieceWeakPtr> m_pieces{};
QMap<QString, QTransform> m_oldTransforms{};
QPointF m_origin;
qreal m_angle;
bool m_allowMerge;
auto Layout() const -> VPLayoutPtr;
auto Sheet() const -> VPSheetPtr;
};
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPiecesRotate::Origin() const -> QPointF
{
return m_origin;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPiecesRotate::Angle() const -> qreal
{
return m_angle;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPUndoPiecesRotate::AllowMerge() const -> bool
{
return m_allowMerge;
}
#endif // VPUNDOPIECEROTATE_H

View File

@ -179,7 +179,7 @@ auto StringToMarkerShape(const QString &string) -> PlaceLabelImg
} // namespace
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutFileReader::ReadFile(VPLayout *layout, QFile *file) -> bool
auto VPLayoutFileReader::ReadFile(const VPLayoutPtr &layout, QFile *file) -> bool
{
setDevice(file);
@ -199,7 +199,7 @@ auto VPLayoutFileReader::ReadFile(VPLayout *layout, QFile *file) -> bool
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadLayout(VPLayout *layout)
void VPLayoutFileReader::ReadLayout(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagLayout);
@ -232,7 +232,7 @@ void VPLayoutFileReader::ReadLayout(VPLayout *layout)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadProperties(VPLayout *layout)
void VPLayoutFileReader::ReadProperties(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagProperties);
@ -288,7 +288,7 @@ void VPLayoutFileReader::ReadProperties(VPLayout *layout)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadControl(VPLayout *layout)
void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagControl);
@ -304,7 +304,7 @@ void VPLayoutFileReader::ReadControl(VPLayout *layout)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadUnplacedPieces(VPLayout *layout)
void VPLayoutFileReader::ReadUnplacedPieces(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagUnplacedPieces);
@ -312,7 +312,7 @@ void VPLayoutFileReader::ReadUnplacedPieces(VPLayout *layout)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadTiles(VPLayout *layout)
void VPLayoutFileReader::ReadTiles(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagTiles);
@ -347,7 +347,7 @@ void VPLayoutFileReader::ReadTiles(VPLayout *layout)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadSheets(VPLayout *layout)
void VPLayoutFileReader::ReadSheets(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagSheets);
@ -366,7 +366,7 @@ void VPLayoutFileReader::ReadSheets(VPLayout *layout)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadSheet(VPLayout *layout)
void VPLayoutFileReader::ReadSheet(const VPLayoutPtr &layout)
{
AssertRootTag(ML::TagSheet);
@ -376,7 +376,7 @@ void VPLayoutFileReader::ReadSheet(VPLayout *layout)
ML::TagPieces // 1
};
QScopedPointer<VPSheet> sheet (new VPSheet(layout));
VPSheetPtr sheet(new VPSheet(layout));
while (readNextStartElement())
{
@ -386,11 +386,7 @@ void VPLayoutFileReader::ReadSheet(VPLayout *layout)
sheet->SetName(readElementText());
break;
case 1: // pieces
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
ReadPieces(layout, sheet.get());
#else
ReadPieces(layout, sheet.data());
#endif
ReadPieces(layout, sheet);
break;
default:
qCDebug(MLReader, "Ignoring tag %s", qUtf8Printable(name().toString()));
@ -401,21 +397,21 @@ void VPLayoutFileReader::ReadSheet(VPLayout *layout)
readElementText();
layout->AddSheet(sheet.take());
layout->AddSheet(sheet);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadPieces(VPLayout *layout, VPSheet *sheet)
void VPLayoutFileReader::ReadPieces(const VPLayoutPtr &layout, const VPSheetPtr &sheet)
{
while (readNextStartElement())
{
if (name() == ML::TagPiece)
{
QScopedPointer<VPPiece>piece(new VPPiece());
ReadPiece(piece.data());
VPPiecePtr piece(new VPPiece());
ReadPiece(piece);
piece->SetSheet(sheet);
layout->AddPiece(piece.take());
VPLayout::AddPiece(layout, piece);
}
else
{
@ -426,7 +422,7 @@ void VPLayoutFileReader::ReadPieces(VPLayout *layout, VPSheet *sheet)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadPiece(VPPiece *piece)
void VPLayoutFileReader::ReadPiece(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagPiece);
@ -490,7 +486,7 @@ void VPLayoutFileReader::ReadPiece(VPPiece *piece)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadSeamAllowance(VPPiece *piece)
void VPLayoutFileReader::ReadSeamAllowance(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagSeamAllowance);
@ -512,7 +508,7 @@ void VPLayoutFileReader::ReadSeamAllowance(VPPiece *piece)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadGrainline(VPPiece *piece)
void VPLayoutFileReader::ReadGrainline(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagGrainline);
@ -533,7 +529,7 @@ void VPLayoutFileReader::ReadGrainline(VPPiece *piece)
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadNotches(VPPiece *piece)
void VPLayoutFileReader::ReadNotches(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagNotches);
@ -576,7 +572,7 @@ auto VPLayoutFileReader::ReadNotch() -> VLayoutPassmark
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadInternalPaths(VPPiece *piece)
void VPLayoutFileReader::ReadInternalPaths(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagInternalPaths);
@ -615,7 +611,7 @@ auto VPLayoutFileReader::ReadInternalPath() -> VLayoutPiecePath
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadMarkers(VPPiece *piece)
void VPLayoutFileReader::ReadMarkers(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagMarkers);
@ -658,7 +654,7 @@ auto VPLayoutFileReader::ReadMarker() -> VLayoutPlaceLabel
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadLabels(VPPiece *piece)
void VPLayoutFileReader::ReadLabels(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagLabels);

View File

@ -1630,6 +1630,12 @@ void VAbstractPiece::SetUUID(const QString &uuid)
d->m_uuid = temp.isNull() ? QUuid::createUuid() : temp;
}
//---------------------------------------------------------------------------------------------------------------------
QString VAbstractPiece::GetUniqueID() const
{
return d->m_uuid.toString();
}
//---------------------------------------------------------------------------------------------------------------------
qreal VSAPoint::GetSABefore(qreal width) const
{

View File

@ -96,6 +96,12 @@ public:
void SetUUID(const QUuid &uuid);
void SetUUID(const QString &uuid);
/**
* @brief GetUniqueID returns unique piece id. Combines UUID and gradation label.
* @return unique piece id.
*/
QString GetUniqueID() const;
static QVector<QPointF> Equidistant(QVector<VSAPoint> points, qreal width, const QString &name);
static qreal SumTrapezoids(const QVector<QPointF> &points);
static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);