Piece rotation.

This commit is contained in:
Roman Telezhynskyi 2021-08-09 15:09:10 +03:00
parent b366986f7a
commit 3fbe96c2a7
43 changed files with 1723 additions and 828 deletions

View File

@ -33,7 +33,7 @@
#include <QFontMetrics>
#include "../vmisc/backport/qoverload.h"
#include "vpsheet.h"
#include "../layout/vpsheet.h"
#include <QLoggingCategory>
#include <QMenu>

View File

@ -32,8 +32,8 @@
#include <QWidget>
#include <QComboBox>
#include <QScrollArea>
#include "vplayout.h"
#include "vppiece.h"
#include "../layout/vplayout.h"
#include "../layout/vppiece.h"
namespace Ui
{

View File

@ -76,7 +76,7 @@
<customwidget>
<class>VPCarrouselPieceList</class>
<extends>QListWidget</extends>
<header>vpcarrouselpiecelist.h</header>
<header>carousel/vpcarrouselpiecelist.h</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -35,7 +35,8 @@
#include "vpmimedatapiece.h"
#include "vpcarrouselpiecelist.h"
#include "vpcarrousel.h"
#include "vpsheet.h"
#include "../layout/vpsheet.h"
#include "../layout/vppiece.h"
#include <QLoggingCategory>
@ -64,7 +65,7 @@ auto VPCarrouselPiece::GetPiece() -> VPPiece *
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPiece::RefreshSelection()
{
setSelected(m_piece->GetIsSelected());
setSelected(m_piece->IsSelected());
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -31,8 +31,7 @@
#include <QMouseEvent>
#include <QListWidgetItem>
#include "vppiece.h"
class VPPiece;
class VPCarrouselPiece : public QListWidgetItem
{

View File

@ -37,7 +37,7 @@
#include "vpcarrouselpiece.h"
#include "../vmisc/backport/qoverload.h"
#include "vpmimedatapiece.h"
#include "vpsheet.h"
#include "../layout/vpsheet.h"
#include <QLoggingCategory>
@ -72,8 +72,7 @@ void VPCarrouselPieceList::Refresh()
{
// update the label of the piece
auto* carrouselpiece = new VPCarrouselPiece(piece, this);
carrouselpiece->setSelected(piece->GetIsSelected());
connect(piece, &VPPiece::SelectionChanged, this, &VPCarrouselPieceList::on_SelectionChangedExternal);
carrouselpiece->setSelected(piece->IsSelected());
}
sortItems();
}
@ -146,7 +145,7 @@ void VPCarrouselPieceList::startDrag(Qt::DropActions supportedActions)
if(drag->exec() == Qt::MoveAction)
{
m_carrousel->Refresh();
piece->SetIsSelected(true);
piece->SetSelected(true);
}
}
}

View File

@ -31,6 +31,8 @@
#include <QPainter>
#include <QPixmap>
#include "../layout/vppiece.h"
const QString VPMimeDataPiece::mineFormatPiecePtr = QStringLiteral("application/vnd.puzzle.piece.ptr");
//---------------------------------------------------------------------------------------------------------------------

View File

@ -31,7 +31,7 @@
#include <QMimeData>
#include "vppiece.h"
class VPPiece;
class VPMimeDataPiece : public QMimeData
{
@ -65,5 +65,4 @@ private:
VPPiece *m_piece{nullptr};
};
#endif // VPMIMEDATAPIECE_H

View File

@ -30,7 +30,6 @@
#include "vppiece.h"
#include "vpsheet.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pLayout, "p.layout")

View File

@ -0,0 +1,171 @@
/************************************************************************
**
** @file vppiece.cpp
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @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) 2020 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 "vppiece.h"
#include <QtMath>
#include "../vmisc/def.h"
#include "vpsheet.h"
#include <QIcon>
#include <QLoggingCategory>
#include <QPainter>
Q_LOGGING_CATEGORY(pPiece, "p.piece")
//---------------------------------------------------------------------------------------------------------------------
VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
: VLayoutPiece(layoutPiece)
{
ClearTransformations();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::ClearTransformations()
{
// Reset the piece position to the default state
QTransform matrix;
SetMatrix(matrix);
// translate the piece so that the top left corner of the bouding rect of the piece is at the position
// (0,0) in the sheet coordinate system
const QPointF offset = MappedDetailBoundingRect().topLeft();
matrix.translate(-offset.x() ,-offset.y());
SetMatrix(matrix);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPosition(QPointF point)
{
QTransform matrix = GetMatrix();
const QPointF offset = MappedDetailBoundingRect().topLeft();
matrix.translate(point.x() - offset.x(), point.y() - offset.y());
SetMatrix(matrix);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetPosition() -> QPointF
{
QTransform matrix = GetMatrix();
return QPointF(matrix.dx(), matrix.dy());
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::RotateToGrainline()
{
if (not IsGrainlineEnabled() || m_sheet == nullptr)
{
return;
}
const QVector<QPointF> grainlinePoints = GetMappedGrainline();
if (grainlinePoints.count() < 2)
{
return;
}
QLineF grainline(grainlinePoints.first(), grainlinePoints.last());
QLineF canonical(grainlinePoints.first().x(), grainlinePoints.first().y(),
grainlinePoints.first().x()+100, grainlinePoints.first().y());
GrainlineType grainlineType = m_sheet->GrainlineType();
auto DegreesAtFront = [grainline, canonical, grainlineType]()
{
QLineF atFront = canonical;
if (grainlineType == GrainlineType::Vertical)
{
atFront.setAngle(90);
}
return grainline.angleTo(atFront);
};
auto DegreesAtRear = [grainline, canonical, grainlineType]()
{
QLineF atRear = canonical;
atRear.setAngle(grainlineType == GrainlineType::Vertical ? 270 : 180);
return grainline.angleTo(atRear);
};
GrainlineArrowDirection type = GrainlineArrowType();
qreal degrees = 0;
if (type == GrainlineArrowDirection::atFront)
{
degrees = DegreesAtFront();
}
else if (type == GrainlineArrowDirection::atRear)
{
degrees = DegreesAtRear();
}
else
{
degrees = qMin(DegreesAtFront(), DegreesAtRear());
}
Rotate(MappedDetailBoundingRect().center(), degrees);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetSelected(bool value)
{
m_isSelected = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::IsSelected() const -> bool
{
return m_isSelected;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::Sheet() const -> VPSheet *
{
return m_sheet;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetSheet(VPSheet *newSheet)
{
m_sheet = newSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::Layout() const -> VPLayout *
{
return m_layout;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetLayout(VPLayout *layout)
{
SCASSERT(layout != nullptr)
m_layout = layout;
}

View File

@ -0,0 +1,96 @@
/************************************************************************
**
** @file vppiece.h
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @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) 2020 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 VPPIECE_H
#define VPPIECE_H
#include <QUuid>
#include <QVector>
#include <QPoint>
#include <QTransform>
#include "../vlayout/vlayoutpiece.h"
class VPLayout;
class VPSheet;
class VPPiece : public VLayoutPiece
{
public:
VPPiece() = default;
explicit VPPiece(const VLayoutPiece &layoutPiece);
virtual ~VPPiece() = default;
void ClearTransformations();
/**
* @brief SetPosition Sets the position of the piece, in relation to the origin of the scene
* @param point the point where to set the piece
*/
void SetPosition(QPointF point);
/**
* @brief GetPosition Returns the position of the piece
* @return the position of the piece
*/
auto GetPosition() -> QPointF;
/**
* @brief RotateToGrainline rotates the piece to follow the grainline
*/
void RotateToGrainline();
/**
* @brief SetSelected Sets wether the piece is selected
* @param value true if the piece is selected
*/
void SetSelected(bool value);
/**
* @brief IsSelected Returns wether the piece is selected. It emit the signal SelectionChanged
* @return true if the piece is selected
*/
auto IsSelected() const -> bool;
auto Sheet() const -> VPSheet *;
void SetSheet(VPSheet *newSheet);
auto Layout() const -> VPLayout *;
void SetLayout(VPLayout *layout);
private:
Q_DISABLE_COPY(VPPiece)
VPLayout *m_layout{nullptr};
VPSheet *m_sheet{nullptr};
bool m_isSelected{false};
};
#endif // VPPIECE_H

View File

@ -85,3 +85,30 @@ void VPSheet::SetVisible(bool visible)
{
m_visible = visible;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GrainlineType() const -> enum GrainlineType
{
if (m_layout != nullptr)
{
QSizeF size = m_layout->LayoutSettings().GetSheetSize();
if (size.height() < size.width())
{
return GrainlineType::Horizontal;
}
}
return GrainlineType::Vertical;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::TransformationOrigin() const -> const VPTransformationOrigon &
{
return m_transformationOrigin;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetTransformationOrigin(const VPTransformationOrigon &newTransformationOrigin)
{
m_transformationOrigin = newTransformationOrigin;
}

View File

@ -40,6 +40,18 @@
class VPLayout;
class VPPiece;
enum class GrainlineType : qint8
{
Vertical,
Horizontal
};
struct VPTransformationOrigon
{
QPointF origin{};
bool custom{false};
};
class VPSheet : public QObject
{
Q_OBJECT
@ -73,6 +85,11 @@ public:
bool IsVisible() const;
void SetVisible(bool visible);
auto GrainlineType() const -> GrainlineType;
auto TransformationOrigin() const -> const VPTransformationOrigon &;
void SetTransformationOrigin(const VPTransformationOrigon &newTransformationOrigin);
private:
Q_DISABLE_COPY(VPSheet)
@ -83,6 +100,8 @@ private:
QUuid m_uuid{QUuid::createUuid()};
bool m_visible{true};
VPTransformationOrigon m_transformationOrigin{};
};
#endif // VPSHEET_H

View File

@ -8,23 +8,24 @@ SOURCES += \
$$PWD/dialogs/vpdialogabout.cpp \
$$PWD/main.cpp \
$$PWD/vpapplication.cpp \
$$PWD/vpcarrousel.cpp \
$$PWD/vpcarrouselpiece.cpp \
$$PWD/vpcarrouselpiecelist.cpp \
$$PWD/carousel/vpcarrousel.cpp \
$$PWD/carousel/vpcarrouselpiece.cpp \
$$PWD/carousel/vpcarrouselpiecelist.cpp \
$$PWD/vpcommandline.cpp \
$$PWD/vpcommands.cpp \
$$PWD/vpexporter.cpp \
$$PWD/vpgraphicspiece.cpp \
$$PWD/vpgraphicssheet.cpp \
$$PWD/vpgraphicstilegrid.cpp \
$$PWD/vplayout.cpp \
$$PWD/vplayoutsettings.cpp \
$$PWD/vpmaingraphicsview.cpp \
$$PWD/scene/vpgraphicspiece.cpp \
$$PWD/scene/vpgraphicspiececontrols.cpp \
$$PWD/scene/vpgraphicssheet.cpp \
$$PWD/scene/vpgraphicstilegrid.cpp \
$$PWD/layout/vplayout.cpp \
$$PWD/layout/vplayoutsettings.cpp \
$$PWD/scene/vpmaingraphicsview.cpp \
$$PWD/vpmainwindow.cpp \
$$PWD/vpmimedatapiece.cpp \
$$PWD/vppiece.cpp \
$$PWD/carousel/vpmimedatapiece.cpp \
$$PWD/layout/vppiece.cpp \
$$PWD/vpsettings.cpp \
$$PWD/vpsheet.cpp \
$$PWD/layout/vpsheet.cpp \
$$PWD/vptilefactory.cpp \
$$PWD/xml/vplayoutfilereader.cpp \
$$PWD/xml/vplayoutfilewriter.cpp \
@ -37,25 +38,27 @@ HEADERS += \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.h \
$$PWD/dialogs/dialogpuzzlepreferences.h \
$$PWD/dialogs/vpdialogabout.h \
$$PWD/scene/scenedef.h \
$$PWD/stable.h \
$$PWD/vpapplication.h \
$$PWD/vpcarrousel.h \
$$PWD/vpcarrouselpiece.h \
$$PWD/vpcarrouselpiecelist.h \
$$PWD/carousel/vpcarrousel.h \
$$PWD/carousel/vpcarrouselpiece.h \
$$PWD/carousel/vpcarrouselpiecelist.h \
$$PWD/vpcommandline.h \
$$PWD/vpcommands.h \
$$PWD/vpexporter.h \
$$PWD/vpgraphicspiece.h \
$$PWD/vpgraphicssheet.h \
$$PWD/vpgraphicstilegrid.h \
$$PWD/vplayout.h \
$$PWD/vplayoutsettings.h \
$$PWD/vpmaingraphicsview.h \
$$PWD/scene/vpgraphicspiece.h \
$$PWD/scene/vpgraphicspiececontrols.h \
$$PWD/scene/vpgraphicssheet.h \
$$PWD/scene/vpgraphicstilegrid.h \
$$PWD/layout/vplayout.h \
$$PWD/layout/vplayoutsettings.h \
$$PWD/scene/vpmaingraphicsview.h \
$$PWD/vpmainwindow.h \
$$PWD/vpmimedatapiece.h \
$$PWD/vppiece.h \
$$PWD/carousel/vpmimedatapiece.h \
$$PWD/layout/vppiece.h \
$$PWD/vpsettings.h \
$$PWD/vpsheet.h \
$$PWD/layout/vpsheet.h \
$$PWD/vptilefactory.h \
$$PWD/xml/vplayoutfilereader.h \
$$PWD/xml/vplayoutfilewriter.h \
@ -66,5 +69,5 @@ FORMS += \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.ui \
$$PWD/dialogs/dialogpuzzlepreferences.ui \
$$PWD/dialogs/vpdialogabout.ui \
$$PWD/vpcarrousel.ui \
$$PWD/carousel/vpcarrousel.ui \
$$PWD/vpmainwindow.ui

View File

@ -0,0 +1,38 @@
/************************************************************************
**
** @file scenedef.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 7 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 SCENEDEF_H
#define SCENEDEF_H
enum class PGraphicsItem : int
{
Piece = 1,
Handles = 2,
TransformationOrigin = 3
};
#endif // SCENEDEF_H

View File

@ -39,9 +39,9 @@
#include <QGraphicsScene>
#include <QApplication>
#include "vppiece.h"
#include "vplayout.h"
#include "vpsheet.h"
#include "../layout/vppiece.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include "vlayoutpiecepath.h"
#include "vplacelabelitem.h"
@ -49,6 +49,11 @@
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
namespace
{
constexpr qreal penWidth = 1;
}
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsPiece::VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent) :
QGraphicsObject(parent),
@ -57,94 +62,12 @@ VPGraphicsPiece::VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent) :
QPixmap cursor_pixmap = QIcon("://puzzleicon/svg/cursor_rotate.svg").pixmap(QSize(32,32));
m_rotateCursor= QCursor(cursor_pixmap, 16, 16);
Init();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::Init()
{
// set some infos
setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
setFlags(ItemIsSelectable | ItemSendsGeometryChanges);
setAcceptHoverEvents(true);
setCursor(QCursor(Qt::OpenHandCursor));
setCursor(Qt::OpenHandCursor);
// initialises the seam line
QVector<QPointF> seamLinePoints = m_piece->GetMappedContourPoints();
if(!seamLinePoints.isEmpty())
{
m_seamLine.moveTo(seamLinePoints.first());
for (int i = 1; i < seamLinePoints.size(); i++)
{
m_seamLine.lineTo(seamLinePoints.at(i));
}
}
// initiliases the cutting line
QVector<QPointF> cuttingLinepoints = m_piece->GetMappedSeamAllowancePoints();
if(!cuttingLinepoints.isEmpty())
{
m_cuttingLine.moveTo(cuttingLinepoints.first());
for (int i = 1; i < cuttingLinepoints.size(); i++)
{
m_cuttingLine.lineTo(cuttingLinepoints.at(i));
}
}
// initialises the grainline
if(m_piece->IsGrainlineEnabled())
{
QVector<QPointF> grainLinepoints = m_piece->GetMappedGrainline();
if(!grainLinepoints.isEmpty())
{
m_grainline.moveTo(grainLinepoints.first());
for (int i = 1; i < grainLinepoints.size(); i++)
{
m_grainline.lineTo(grainLinepoints.at(i));
}
}
}
// initialises the internal paths
QVector<VLayoutPiecePath> internalPaths = m_piece->GetInternalPaths();
for (const auto& piecePath : internalPaths)
{
QPainterPath path = m_piece->GetMatrix().map(piecePath.GetPainterPath());
m_internalPaths.append(path);
m_internalPathsPenStyle.append(piecePath.PenStyle());
}
// initialises the passmarks
QVector<VLayoutPassmark> passmarks = m_piece->GetMappedPassmarks();
for(auto &passmark : passmarks)
{
for (auto &line : passmark.lines)
{
m_passmarks.moveTo(line.p1());
m_passmarks.lineTo(line.p2());
}
}
// initialises the place labels (buttons etc)
QVector<VLayoutPlaceLabel> placeLabels = m_piece->GetPlaceLabels();
for(auto &placeLabel : placeLabels)
{
QPainterPath path = VPlaceLabelItem::LabelShapePath(placeLabel.shape);
m_placeLabels.append(path);
}
// TODO : initialises the text labels
// Init position
on_PiecePositionChanged();
on_PieceRotationChanged();
on_PieceSelectionChanged();
// Initialises the connectors
connect(m_piece, &VPPiece::SelectionChanged, this, &VPGraphicsPiece::on_PieceSelectionChanged);
connect(m_piece, &VPPiece::PositionChanged, this, &VPGraphicsPiece::on_PiecePositionChanged);
connect(m_piece, &VPPiece::RotationChanged, this, &VPGraphicsPiece::on_PieceRotationChanged);
connect(m_piece, &VPPiece::PropertiesChanged, this, &VPGraphicsPiece::on_PiecePropertiesChanged);
PaintPiece();
}
//---------------------------------------------------------------------------------------------------------------------
@ -153,15 +76,23 @@ auto VPGraphicsPiece::GetPiece() -> VPPiece*
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::TranslatePiece(const QPointF &p)
{
m_piece->Translate(p);
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::boundingRect() const -> QRectF
{
constexpr qreal halfPenWidth = penWidth/2.;
if(!m_cuttingLine.isEmpty())
{
return m_cuttingLine.boundingRect();
return m_cuttingLine.boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
return m_seamLine.boundingRect();
return m_seamLine.boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
@ -181,170 +112,41 @@ void VPGraphicsPiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
Q_UNUSED(widget);
Q_UNUSED(option);
QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
QBrush noBrush(Qt::NoBrush);
QBrush selectionBrush(QColor(255,160,160,60));
QBrush blackBrush(Qt::black);
QPen pen(Qt::black, penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
// selection
if(isSelected())
{
painter->setBrush(selectionBrush);
}
else
{
painter->setBrush(noBrush);
}
// paint the cutting line
if(!m_cuttingLine.isEmpty())
{
painter->drawPath(m_cuttingLine);
painter->setBrush(noBrush);
}
// paint the seam line
if(!m_seamLine.isEmpty() && m_piece->GetShowSeamLine())
{
painter->drawPath(m_seamLine);
}
painter->setBrush(noBrush);
// paint the grainline
if(!m_grainline.isEmpty())
{
// here to fill the grainlines arrow. Not wanted for mvp
// later maybe if it's configurable
// painter->setBrush(blackBrush);
painter->drawPath(m_grainline);
}
// paint the internal paths
painter->setBrush(noBrush);
if(!m_internalPaths.isEmpty())
{
Qt::PenStyle penStyleTmp = pen.style();
for (int i = 0; i < m_internalPaths.size(); i++)
{
painter->setPen(m_internalPathsPenStyle.at(i));
painter->drawPath(m_internalPaths.at(i));
}
painter->setPen(penStyleTmp);
}
// paint the passmarks
if(!m_passmarks.isEmpty())
{
painter->drawPath(m_passmarks);
}
// paint the place labels (buttons etc)
if(!m_placeLabels.isEmpty())
{
for(auto &placeLabel : m_placeLabels)
{
painter->drawPath(placeLabel);
}
}
// TODO Detail & Piece Label
// QPointF position = m_piece->GetPatternTextPosition();
// QStringList texts = m_piece->GetPatternText();
// painter->drawText();
// when using m_piece->GetItem(), the results were quite bad
PaintPiece(painter);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
bool selectionState = isSelected();
//perform the default behaviour
QGraphicsObject::mousePressEvent(event);
// change the cursor when clicking the left button
if((event->button() == Qt::LeftButton))
{
if((event->modifiers() & Qt::AltModifier) != 0U)
{
setCursor(m_rotateCursor);
}
else
{
setCursor(Qt::ClosedHandCursor);
}
}
// change the selected state when clicking left button
if (event->button() == Qt::LeftButton)
{
setSelected(true);
if (event->modifiers() & Qt::ControlModifier)
{
setSelected(!selectionState);
}
else
{
setSelected(true);
}
}
if((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
{
m_rotationStartPoint = event->scenePos();
m_moveStartPoint = event->pos();
emit HideTransformationHandles(true);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
void VPGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if((event->buttons() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
{
//FIXME: it flickers between the arrow cursor and the rotate cursor
setCursor(m_rotateCursor);
QGraphicsObject::mouseMoveEvent(event);
QPointF rotationNewPoint = event->scenePos();
QPointF rotationCenter = sceneBoundingRect().center();
GroupMove(event->pos());
// get the angle from the center to the initial click point
qreal init_x = m_rotationStartPoint.x() - rotationCenter.x();
qreal init_y = m_rotationStartPoint.y() - rotationCenter.y();
qreal initial_angle = qAtan2(init_y, init_x);
qreal x = rotationNewPoint.x() - rotationCenter.x();
qreal y = rotationNewPoint.y() - rotationCenter.y();
qreal mv_angle = qAtan2(y,x);
qreal angle = (initial_angle-mv_angle)*180/M_PI;
setTransformOriginPoint(boundingRect().center());
setRotation(-(angle+m_piece->GetRotation()));
event->accept();
}
else
{
QGraphicsItem::mouseMoveEvent(event);
}
m_moveStartPoint = event->pos();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
bool selectionState = isSelected();
//perform the default behaviour
QGraphicsItem::mouseReleaseEvent(event);
@ -352,32 +154,8 @@ void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::OpenHandCursor);
setSelected(selectionState);
if(m_piece->GetPosition() != pos())
{
m_piece->SetPosition(pos());
}
}
if((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
{
m_piece->SetRotation(-rotation());
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if(event->modifiers() & Qt::AltModifier)
{
//FIXME: it flickers between the arrow cursor and the rotate cursor
setCursor(m_rotateCursor);
}
else
{
setCursor(Qt::OpenHandCursor);
GroupMove(event->pos());
emit HideTransformationHandles(false);
}
}
@ -421,30 +199,166 @@ void VPGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_PieceSelectionChanged()
void VPGraphicsPiece::PaintPiece(QPainter *painter)
{
setSelected(m_piece->GetIsSelected());
}
QBrush noBrush(Qt::NoBrush);
QBrush selectionBrush(QColor(255,160,160,60));
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_PiecePositionChanged()
{
setPos(m_piece->GetPosition());
}
QRectF rect = m_piece->MappedDetailBoundingRect();
QPointF p = rect.topLeft();
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_PieceRotationChanged()
{
setTransformOriginPoint(boundingRect().center());
setRotation(-m_piece->GetRotation());
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_PiecePropertiesChanged()
{
if(scene() != nullptr)
// initialises the seam line
QVector<QPointF> seamLinePoints = m_piece->GetMappedContourPoints();
if(!seamLinePoints.isEmpty())
{
scene()->update();
m_seamLine = QPainterPath();
m_seamLine.moveTo(seamLinePoints.first());
for (int i = 1; i < seamLinePoints.size(); i++)
{
m_seamLine.lineTo(seamLinePoints.at(i));
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(isSelected() ? selectionBrush : noBrush);
painter->drawPath(m_seamLine);
painter->restore();
}
}
// initiliases the cutting line
QVector<QPointF> cuttingLinepoints = m_piece->GetMappedSeamAllowancePoints();
if(!cuttingLinepoints.isEmpty())
{
m_cuttingLine = QPainterPath();
m_cuttingLine.moveTo(cuttingLinepoints.first());
for (int i = 1; i < cuttingLinepoints.size(); i++)
{
m_cuttingLine.lineTo(cuttingLinepoints.at(i));
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(isSelected() ? selectionBrush : noBrush);
painter->drawPath(m_cuttingLine);
painter->restore();
}
}
// initialises the grainline
if(m_piece->IsGrainlineEnabled())
{
QVector<QPointF> grainLinepoints = m_piece->GetMappedGrainline();
if(!grainLinepoints.isEmpty())
{
QPainterPath grainline;
grainline.moveTo(grainLinepoints.first());
for (int i = 1; i < grainLinepoints.size(); i++)
{
grainline.lineTo(grainLinepoints.at(i));
}
if (painter != nullptr)
{
painter->save();
// here to fill the grainlines arrow. Not wanted for mvp
// later maybe if it's configurable
// painter->setBrush(blackBrush);
painter->setBrush(noBrush);
painter->drawPath(grainline);
painter->restore();
}
}
}
// initialises the internal paths
QVector<VLayoutPiecePath> internalPaths = m_piece->GetInternalPaths();
for (const auto& piecePath : internalPaths)
{
QPainterPath path = m_piece->GetMatrix().map(piecePath.GetPainterPath());
if (painter != nullptr)
{
painter->save();
painter->setPen(piecePath.PenStyle());
painter->drawPath(path);
painter->restore();
}
}
// initialises the passmarks
QVector<VLayoutPassmark> passmarks = m_piece->GetMappedPassmarks();
for(auto &passmark : passmarks)
{
QPainterPath passmarkPath;
for (auto &line : passmark.lines)
{
passmarkPath.moveTo(line.p1());
passmarkPath.lineTo(line.p2());
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(noBrush);
painter->drawPath(passmarkPath);
painter->restore();
}
}
// initialises the place labels (buttons etc)
QVector<VLayoutPlaceLabel> placeLabels = m_piece->GetPlaceLabels();
for(auto &placeLabel : placeLabels)
{
QPainterPath path = VPlaceLabelItem::LabelShapePath(placeLabel.shape);
if (painter != nullptr)
{
painter->save();
painter->setBrush(noBrush);
painter->drawPath(path);
painter->restore();
}
}
// TODO : initialises the text labels
// QPointF position = m_piece->GetPatternTextPosition();
// QStringList texts = m_piece->GetPatternText();
// painter->drawText();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::GroupMove(const QPointF &pos)
{
if (scene() != nullptr)
{
QList<QGraphicsItem *> list = scene()->selectedItems();
for (auto *item : list)
{
if (item->type() == UserType + static_cast<int>(PGraphicsItem::Piece))
{
auto *pieceItem = dynamic_cast<VPGraphicsPiece*>(item);
pieceItem->TranslatePiece(pos-m_moveStartPoint);
}
}
emit PiecePositionChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_Rotate(const QPointF &center, qreal angle)
{
if (isSelected())
{
prepareGeometryChange();
m_piece->Rotate(center, angle);
PaintPiece(); // Update shapes
update();
}
}
@ -453,21 +367,10 @@ auto VPGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &valu
{
if (scene() != nullptr)
{
// we do this in the mouseRelease button to avoid updated this property all the time.
// if(change == ItemPositionHasChanged)
// {
// blockSignals(true);
// m_piece->SetPosition(pos());
// blockSignals(false);
// }
if(change == ItemSelectedHasChanged)
{
if(m_piece->GetIsSelected() != isSelected())
{
m_piece->SetIsSelected(isSelected());
}
emit PieceSelectionChanged();
m_piece->SetSelected(value.toBool());
}
}

View File

@ -32,6 +32,8 @@
#include <QGraphicsItem>
#include <QCursor>
#include "scenedef.h"
class VPPiece;
class VPGraphicsPiece : public QGraphicsObject
@ -41,37 +43,24 @@ public:
explicit VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent = nullptr);
~VPGraphicsPiece() = default;
void Init();
/**
* @brief GetPiece Returns the piece that corresponds to the graphics piece
* @return the piece
*/
auto GetPiece() -> VPPiece*;
void TranslatePiece(const QPointF &p);
virtual int type() const override {return Type;}
enum { Type = UserType + 1};
enum { Type = UserType + static_cast<int>(PGraphicsItem::Piece)};
signals:
void PieceSelectionChanged();
void HideTransformationHandles(bool hide);
void PiecePositionChanged();
public slots:
/**
* @brief on_PieceSelectionChanged Slot called when the piece selection was changed
*/
void on_PieceSelectionChanged();
/**
* @brief on_PiecePositionChanged Slot called when the piece position was changed
*/
void on_PiecePositionChanged();
/**
* @brief on_PieceRotationChanged Slot called when the piece rotation was changed
*/
void on_PieceRotationChanged();
/**
* @brief on_PiecePropertiesChanged Slot called when the showSeamline / mirrored was changed
*/
void on_PiecePropertiesChanged();
void on_Rotate(const QPointF &center, qreal angle);
protected:
auto boundingRect() const -> QRectF override;
@ -79,11 +68,9 @@ protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
auto itemChange(GraphicsItemChange change, const QVariant &value) -> QVariant override;
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
@ -94,17 +81,15 @@ private:
QPainterPath m_cuttingLine{};
QPainterPath m_seamLine{};
QPainterPath m_grainline{};
QPainterPath m_passmarks{};
QVector<QPainterPath> m_internalPaths{};
QVector<Qt::PenStyle> m_internalPathsPenStyle{};
QVector<QPainterPath> m_placeLabels{};
QPointF m_moveStartPoint{};
QPointF m_rotationStartPoint{};
QCursor m_rotateCursor{};
void PaintPiece(QPainter *painter=nullptr);
void GroupMove(const QPointF &pos);
};
#endif // VPGRAPHICSPIECE_H

View File

@ -0,0 +1,736 @@
/************************************************************************
**
** @file vpgraphicspiececontrols.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 2 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 "vpgraphicspiececontrols.h"
#include <QCursor>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QIcon>
#include <QPainter>
#include <QtDebug>
#include "../vmisc/compatibility.h"
#include "../vwidgets/global.h"
#include "../layout/vplayout.h"
namespace
{
const qreal arcStartAngle = 105;
const qreal arcAngle = 25;
const qreal arcRadius = 15;
const qreal arrowTail = 2;
const qreal arrowSide = 2;
const qreal arrowLength = 4;
const qreal arrow1Angle = 13;
const qreal arrow2Angle = 38;
constexpr qreal penWidth = 2;
const qreal centerRadius1 = 5;
const qreal centerRadius2 = 10;
const QColor defaultColor = Qt::black;
const QColor hoverColor = Qt::green;
enum class HandleCorner : int
{
Invalid = 0,
TopLeft = 1,
TopRight = 2,
BottomRight = 3,
BottomLeft = 4
};
auto TransformationOrigin(VPLayout *layout, const QRectF &boundingRect) -> QPointF
{
SCASSERT(layout != nullptr)
VPSheet *sheet = layout->GetFocusedSheet();
if (sheet != nullptr)
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
return origin.origin;
}
return boundingRect.center();
}
} // namespace
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTransformationOrigin::VPGraphicsTransformationOrigin(VPLayout *layout, QGraphicsItem *parent)
: QGraphicsObject(parent),
m_layout(layout),
m_color(defaultColor)
{
SCASSERT(m_layout != nullptr)
setCursor(Qt::OpenHandCursor);
setZValue(1);
setAcceptHoverEvents(true);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::SetTransformationOrigin()
{
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::on_HideHandles(bool hide)
{
m_originVisible = not hide;
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::on_ShowOrigin(bool show)
{
setVisible(show);
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsTransformationOrigin::boundingRect() const
{
constexpr qreal halfPenWidth = penWidth/2.;
return Center2().boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsTransformationOrigin::shape() const
{
return Center2();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
const qreal scale = SceneScale(scene());
QPen pen(m_color, penWidth/scale, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
if (m_originVisible)
{
painter->save();
painter->setBrush(QBrush(m_color));
painter->drawPath(Center1());
painter->restore();
painter->save();
painter->setBrush(QBrush());
painter->drawPath(Center2());
painter->restore();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
// change the cursor when clicking the left button
if((event->button() == Qt::LeftButton))
{
setCursor(Qt::ClosedHandCursor);
event->accept();
}
else
{
//perform the default behaviour
QGraphicsObject::mousePressEvent(event);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
origin.origin = event->scenePos();
origin.custom = true;
sheet->SetTransformationOrigin(origin);
}
prepareGeometryChange();
QGraphicsObject::mouseMoveEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
//perform the default behaviour
QGraphicsItem::mouseReleaseEvent(event);
// change the cursor when clicking left button
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::OpenHandCursor);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
m_color = hoverColor;
QGraphicsObject::hoverEnterEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
m_color = defaultColor;
QGraphicsObject::hoverEnterEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTransformationOrigin::RotationCenter(QPainter *painter) const -> QPainterPath
{
QPainterPath path;
const qreal scale = SceneScale(scene());
qreal radius = centerRadius1/scale;
QPointF transformationOrigin = TransformationOrigin(m_layout, QRectF());
QRectF rect(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
QPainterPath center1;
center1.addEllipse(rect);
if (painter != nullptr)
{
painter->save();
painter->setBrush(QBrush(m_color));
painter->drawPath(Center1());
painter->restore();
}
path.addPath(center1);
radius = centerRadius2/scale;
rect = QRectF(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
QPainterPath center2;
center2.addEllipse(rect);
if (painter != nullptr)
{
painter->save();
painter->setBrush(QBrush());
painter->drawPath(Center2());
painter->restore();
}
path.addPath(center2);
return path;
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsTransformationOrigin::Center1() const
{
const qreal scale = SceneScale(scene());
qreal radius = centerRadius1/scale;
QPointF transformationOrigin = TransformationOrigin(m_layout, QRectF());
QRectF rect(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
QPainterPath center1;
center1.addEllipse(rect);
return center1;
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsTransformationOrigin::Center2() const
{
const qreal scale = SceneScale(scene());
qreal radius = centerRadius2/scale;
QPointF transformationOrigin = TransformationOrigin(m_layout, QRectF());
QRectF rect = QRectF(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
QPainterPath center2;
center2.addEllipse(rect);
return center2;
}
// VPGraphicsPieceControls
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsPieceControls::VPGraphicsPieceControls(VPLayout *layout, QGraphicsItem *parent)
: QGraphicsObject(parent),
m_layout(layout)
{
SCASSERT(m_layout != nullptr)
QPixmap cursor_pixmap = QIcon("://puzzleicon/svg/cursor_rotate.svg").pixmap(QSize(32,32));
setCursor(QCursor(cursor_pixmap, 16, 16));
setZValue(1);
setAcceptHoverEvents(true);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::on_UpdateControls()
{
m_pieceRect = PiecesBoundingRect();
setVisible(not m_pieceRect.isNull());
if (not m_pieceRect.isNull())
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
if (not origin.custom)
{
origin.origin = m_pieceRect.center();
sheet->SetTransformationOrigin(origin);
emit TransformationOriginChanged();
}
}
}
emit ShowOrigin(not m_pieceRect.isNull());
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::on_HideHandles(bool hide)
{
m_controlsVisible = not hide;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::boundingRect() const -> QRectF
{
constexpr qreal halfPenWidth = penWidth/2.;
return Handles().boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::shape() const -> QPainterPath
{
return Handles();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
const qreal scale = SceneScale(scene());
QPen pen(defaultColor, penWidth/scale, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
if (m_controlsVisible)
{
TopLeftControl(painter);
TopRightControl(painter);
BottomLeftControl(painter);
BottomRightControl(painter);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
m_rotationStartPoint = event->scenePos();
m_controlsVisible = false;
m_handleCorner = HandleCorner(event->scenePos());
prepareGeometryChange();
}
else
{
QGraphicsObject::mousePressEvent(event);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if((event->modifiers() & Qt::ShiftModifier) != 0U
&& static_cast<enum HandleCorner>(m_handleCorner) != HandleCorner::Invalid)
{
if (not m_originSaved)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
{
m_savedOrigin = sheet->TransformationOrigin();
m_originSaved = true;
m_pieceRect = PiecesBoundingRect();
VPTransformationOrigon origin;
origin.custom = true;
if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::TopLeft)
{
origin.origin = m_pieceRect.topLeft();
}
else if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::TopRight)
{
origin.origin = m_pieceRect.topRight();
}
else if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::BottomRight)
{
origin.origin = m_pieceRect.bottomRight();
}
else if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::BottomLeft)
{
origin.origin = m_pieceRect.bottomLeft();
}
sheet->SetTransformationOrigin(origin);
emit TransformationOriginChanged();
}
}
}
else
{
if (m_originSaved)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
{
if (not m_savedOrigin.custom)
{
m_pieceRect = PiecesBoundingRect();
m_savedOrigin.origin = m_pieceRect.center();
}
sheet->SetTransformationOrigin(m_savedOrigin);
emit TransformationOriginChanged();
}
m_originSaved = false;
}
}
QPointF rotationNewPoint = event->scenePos();
// get the angle from the center to the initial click point
QPointF rotationOrigin = TransformationOrigin(m_layout, m_pieceRect);
QLineF initPosition(rotationOrigin, m_rotationStartPoint);
QLineF initRotationPosition(rotationOrigin, rotationNewPoint);
qreal angle = initPosition.angleTo(initRotationPosition);
if (not qFuzzyIsNull(angle))
{
emit Rotate(rotationOrigin, angle);
}
if (m_originSaved && m_savedOrigin.custom)
{
QLineF line(rotationOrigin, m_savedOrigin.origin);
line.setAngle(line.angle()+angle);
m_savedOrigin.origin = line.p2();
}
m_rotationStartPoint = rotationNewPoint;
QGraphicsObject::mouseMoveEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
m_controlsVisible = true;
if (m_originSaved)
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
{
if (not m_savedOrigin.custom)
{
m_pieceRect = PiecesBoundingRect();
m_savedOrigin.origin = m_pieceRect.center();
}
sheet->SetTransformationOrigin(m_savedOrigin);
emit TransformationOriginChanged();
}
m_originSaved = false;
}
on_UpdateControls();
}
QGraphicsObject::mouseReleaseEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::TopLeftControl(QPainter *painter) const -> QPainterPath
{
return Controller(QTransform(), painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::TopRightControl(QPainter *painter) const -> QPainterPath
{
QTransform t;
t.scale(-1, 1);
t.translate(-(m_pieceRect.topLeft().x() * 2. + m_pieceRect.width()), 0);
return Controller(t, painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::BottomLeftControl(QPainter *painter) const -> QPainterPath
{
QTransform t;
t.scale(1, -1);
t.translate(0, -(m_pieceRect.topLeft().y() * 2. + m_pieceRect.height()));
return Controller(t, painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::BottomRightControl(QPainter *painter) const -> QPainterPath
{
QTransform t;
t.scale(-1, -1);
t.translate(-(m_pieceRect.topLeft().x() * 2. + m_pieceRect.width()),
-(m_pieceRect.topLeft().y() * 2. + m_pieceRect.height()));
return Controller(t, painter);
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPGraphicsPieceControls::Handles() const
{
QPainterPath path;
path.addPath(TopLeftControl());
path.addPath(TopRightControl());
path.addPath(BottomLeftControl());
path.addPath(BottomRightControl());
return path;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::Controller(const QTransform &t, QPainter *painter) const -> QPainterPath
{
if (painter != nullptr)
{
QPen pen = painter->pen();
pen.setColor(defaultColor);
painter->setPen(pen);
}
QBrush colorBrush(defaultColor);
QPainterPath controller = ArrowPath();
controller = t.map(controller);
if (painter != nullptr)
{
painter->save();
painter->setBrush(colorBrush);
painter->drawPath(controller);
painter->restore();
}
return controller;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::ControllersRect() const -> QRectF
{
const qreal scale = SceneScale(scene());
const qreal gap = 2;
QRectF rect = m_pieceRect;
const qreal minWidth = arcRadius/scale+gap;
const qreal minHeight = arcRadius/scale+gap;
if (m_pieceRect.width() < minWidth)
{
qreal diff = minWidth - m_pieceRect.width();
rect.adjust(-diff/2., 0, diff/2., 0);
}
if (m_pieceRect.height() < minHeight)
{
qreal diff = minHeight - m_pieceRect.height();
rect.adjust(0, -diff/2., 0, diff/2.);
}
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::ArrowPath() const -> QPainterPath
{
const qreal scale = SceneScale(scene());
QPainterPath arrow;
QRectF pieceRect = ControllersRect();
QLineF start(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius+1)/scale);
start.setAngle(arcStartAngle);
arrow.moveTo(start.p2());
QLineF baseLine(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow1Angle);
arrow.lineTo(baseLine.p2());
QLineF leftSide = QLineF(baseLine.p2(), baseLine.p1());
leftSide.setLength(arrowSide/scale);
leftSide.setAngle(leftSide.angle()-90);
arrow.lineTo(leftSide.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - arcRadius/scale);
start.setAngle(arcStartAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+(arrowTail+arrowLength)/scale, start.p2().y()));
baseLine.setAngle(arrow1Angle);
arrow.lineTo(baseLine.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius-1)/scale);
start.setAngle(arcStartAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow1Angle);
QLineF rightSide = QLineF(baseLine.p2(), baseLine.p1());
rightSide.setLength(arrowSide/scale);
rightSide.setAngle(rightSide.angle()+90);
arrow.lineTo(rightSide.p2());
arrow.lineTo(baseLine.p2());
arrow.lineTo(start.p2());
// arc 1
QRectF arc1Rect(pieceRect.topLeft().x()-(arcRadius-1)/scale, pieceRect.topLeft().y()-(arcRadius-1)/scale,
(arcRadius-1)/scale*2, (arcRadius-1)/scale*2);
arrow.arcTo(arc1Rect, arcStartAngle, arcAngle);
// arrow 2
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius-1)/scale);
start.setAngle(arcStartAngle+arcAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow2Angle+180);
arrow.lineTo(baseLine.p2());
leftSide = QLineF(baseLine.p2(), baseLine.p1());
leftSide.setLength(arrowSide/scale);
leftSide.setAngle(leftSide.angle()-90);
arrow.lineTo(leftSide.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - arcRadius/scale);
start.setAngle(arcStartAngle+arcAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+(arrowTail+arrowLength)/scale, start.p2().y()));
baseLine.setAngle(arrow2Angle+180);
arrow.lineTo(baseLine.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius+1)/scale);
start.setAngle(arcStartAngle+arcAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow2Angle+180);
rightSide = QLineF(baseLine.p2(), baseLine.p1());
rightSide.setLength(arrowSide/scale);
rightSide.setAngle(rightSide.angle()+90);
arrow.lineTo(rightSide.p2());
arrow.lineTo(baseLine.p2());
arrow.lineTo(start.p2());
// arc 2
QRectF arc2Rect(pieceRect.topLeft().x()-(arcRadius+1)/scale, pieceRect.topLeft().y()-(arcRadius+1)/scale,
(arcRadius+1)/scale*2, (arcRadius+1)/scale*2);
QPainterPath arc;
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius+1)/scale);
start.setAngle(arcStartAngle);
arc.moveTo(start.p2());
arc.arcTo(arc2Rect, arcStartAngle, arcAngle);
arrow.addPath(arc.toReversed());
return arrow;
}
//---------------------------------------------------------------------------------------------------------------------
QRectF VPGraphicsPieceControls::PiecesBoundingRect() const
{
QRectF rect;
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))
{
rect = rect.united(item->sceneBoundingRect());
}
}
}
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::HandleCorner(const QPointF &pos) const -> int
{
if (TopLeftControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::BottomRight);
}
if (TopRightControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::BottomLeft);
}
if (BottomLeftControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::TopRight);
}
if (BottomRightControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::TopLeft);
}
return static_cast<int>(HandleCorner::Invalid);
}

View File

@ -0,0 +1,129 @@
/************************************************************************
**
** @file vpgraphicspiececontrols.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 2 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 VPGRAPHICSPIECECONTROLS_H
#define VPGRAPHICSPIECECONTROLS_H
#include <QColor>
#include <QGraphicsObject>
#include "scenedef.h"
#include "../layout/vpsheet.h"
class VPLayout;
class VPGraphicsTransformationOrigin : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsTransformationOrigin(VPLayout *layout, QGraphicsItem * parent = nullptr);
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::TransformationOrigin)};
public slots:
void SetTransformationOrigin();
void on_HideHandles(bool hide);
void on_ShowOrigin(bool show);
protected:
auto boundingRect() const -> QRectF override;
auto shape() const -> QPainterPath override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private:
Q_DISABLE_COPY(VPGraphicsTransformationOrigin)
bool m_originVisible{true};
VPLayout *m_layout;
QColor m_color;
auto RotationCenter(QPainter *painter = nullptr) const -> QPainterPath;
auto Center1() const -> QPainterPath;
auto Center2() const -> QPainterPath;
};
class VPGraphicsPieceControls : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsPieceControls(VPLayout *layout, QGraphicsItem * parent = nullptr);
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::Handles)};
signals:
void Rotate(const QPointF &center, qreal angle);
void ShowOrigin(bool show);
void TransformationOriginChanged();
public slots:
void on_UpdateControls();
void on_HideHandles(bool hide);
protected:
auto boundingRect() const -> QRectF override;
auto shape() const -> QPainterPath override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
Q_DISABLE_COPY(VPGraphicsPieceControls)
QRectF m_pieceRect{};
QPointF m_rotationStartPoint{};
bool m_controlsVisible{true};
VPLayout *m_layout;
int m_handleCorner{0};
VPTransformationOrigon m_savedOrigin{};
bool m_originSaved{false};
auto TopLeftControl(QPainter *painter = nullptr) const -> QPainterPath;
auto TopRightControl(QPainter *painter = nullptr) const -> QPainterPath;
auto BottomLeftControl(QPainter *painter = nullptr) const -> QPainterPath;
auto BottomRightControl(QPainter *painter = nullptr) const -> QPainterPath;
auto Handles() const -> QPainterPath;
auto Controller(const QTransform &t, QPainter *painter = nullptr) const -> QPainterPath;
auto ControllersRect() const -> QRectF;
auto ArrowPath() const -> QPainterPath;
auto PiecesBoundingRect() const -> QRectF;
auto HandleCorner(const QPointF &pos) const -> int;
};
#endif // VPGRAPHICSPIECECONTROLS_H

View File

@ -27,7 +27,9 @@
*************************************************************************/
#include "vpgraphicssheet.h"
#include "vplayout.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include <QtMath>
//---------------------------------------------------------------------------------------------------------------------

View File

@ -32,7 +32,7 @@
#include <QGraphicsItem>
#include <QPainter>
#include "vpsheet.h"
class VPSheet;
class VPGraphicsSheet : public QGraphicsItem
{

View File

@ -1,7 +1,7 @@
#include "vpgraphicstilegrid.h"
#include "vptilefactory.h"
#include "vplayout.h"
#include "../vptilefactory.h"
#include "../layout/vplayout.h"
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTileGrid::VPGraphicsTileGrid(VPLayout *layout, VPTileFactory *tileFactory,QGraphicsItem *parent):

View File

@ -33,16 +33,27 @@
#include <QKeyEvent>
#include <QMenu>
#include "vpmimedatapiece.h"
#include "vplayout.h"
#include "vpsheet.h"
#include "../scene/vpgraphicssheet.h"
#include "../scene/vpgraphicspiece.h"
#include "../vptilefactory.h"
#include "../scene/vpgraphicstilegrid.h"
#include "../carousel/vpmimedatapiece.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include "../layout/vppiece.h"
#include "../vwidgets/vmaingraphicsscene.h"
#include "vptilefactory.h"
#include "vpgraphicspiececontrols.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pMainGraphicsView, "p.mainGraphicsView")
namespace
{
const QKeySequence restoreOriginShortcut = QKeySequence(Qt::ControlModifier + Qt::Key_Asterisk);
}
//---------------------------------------------------------------------------------------------------------------------
VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFactory, QWidget *parent) :
@ -53,17 +64,65 @@ VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFact
SCASSERT(m_layout != nullptr)
setScene(m_scene);
m_graphicsSheet = new VPGraphicsSheet(layout->GetFocusedSheet());
m_graphicsSheet = new VPGraphicsSheet(m_layout->GetFocusedSheet());
m_graphicsSheet->setPos(0, 0);
m_scene->addItem(m_graphicsSheet);
setAcceptDrops(true);
m_graphicsTileGrid = new VPGraphicsTileGrid(layout, tileFactory);
m_graphicsTileGrid = new VPGraphicsTileGrid(m_layout, tileFactory);
m_scene->addItem(m_graphicsTileGrid);
m_rotationControls = new VPGraphicsPieceControls(m_layout);
m_rotationControls->setVisible(false);
m_scene->addItem(m_rotationControls);
m_rotationOrigin = new VPGraphicsTransformationOrigin(m_layout);
m_rotationOrigin->setVisible(false);
m_scene->addItem(m_rotationOrigin);
connect(m_rotationControls, &VPGraphicsPieceControls::ShowOrigin,
m_rotationOrigin, &VPGraphicsTransformationOrigin::on_ShowOrigin);
connect(m_rotationControls, &VPGraphicsPieceControls::TransformationOriginChanged,
m_rotationOrigin, &VPGraphicsTransformationOrigin::SetTransformationOrigin);
// add the connections
connect(m_layout, &VPLayout::PieceSheetChanged, this, &VPMainGraphicsView::on_PieceSheetChanged);
auto *restoreOrigin = new QAction(this);
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);
}
//---------------------------------------------------------------------------------------------------------------------
@ -94,8 +153,8 @@ void VPMainGraphicsView::RefreshPieces()
{
auto *graphicsPiece = new VPGraphicsPiece(piece);
m_graphicsPieces.append(graphicsPiece);
scene()->addItem(graphicsPiece);
ConnectPiece(graphicsPiece);
}
}
}
@ -180,9 +239,8 @@ void VPMainGraphicsView::dropEvent(QDropEvent *event)
qCDebug(pMainGraphicsView(), "element dropped, %s", qUtf8Printable(piece->GetName()));
event->acceptProposedAction();
QPoint point = event->pos();
piece->SetPosition(mapToScene(point));
piece->SetRotation(0);
piece->ClearTransformations();
piece->SetPosition(mapToScene(event->pos()));
// change the piecelist of the piece
piece->SetSheet(m_layout->GetFocusedSheet());
@ -192,6 +250,8 @@ void VPMainGraphicsView::dropEvent(QDropEvent *event)
scene()->addItem(graphicsPiece);
ConnectPiece(graphicsPiece);
event->acceptProposedAction();
}
}
@ -208,9 +268,9 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event)
{
VPPiece *piece = graphicsPiece->GetPiece();
if(piece->GetIsSelected())
if(piece->IsSelected())
{
piece->SetIsSelected(false);
piece->SetSelected(false);
piece->SetSheet(nullptr);
}
}
@ -228,8 +288,12 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event)
}
QMenu menu;
VPSheet *sheet = m_layout->GetFocusedSheet();
QAction *restoreOriginAction = menu.addAction(tr("Restore transformation origin"));
restoreOriginAction->setShortcut(restoreOriginShortcut);
restoreOriginAction->setEnabled(sheet != nullptr && sheet->TransformationOrigin().custom);
QAction *removeSheetAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Remove sheet"));
removeSheetAction->setEnabled(sheet != nullptr && m_layout->GetSheets().size() > 1);
@ -251,6 +315,104 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event)
emit on_SheetRemoved();
RefreshPieces();
}
else if (selectedAction == restoreOriginAction)
{
RestoreOrigin();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RestoreOrigin() const
{
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet != nullptr)
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
origin.custom = false;
sheet->SetTransformationOrigin(origin);
m_rotationControls->on_UpdateControls();
}
}
//---------------------------------------------------------------------------------------------------------------------
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)
{
SCASSERT(piece != nullptr)
connect(piece, &VPGraphicsPiece::PieceSelectionChanged,
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
connect(piece, &VPGraphicsPiece::PiecePositionChanged,
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,
m_rotationOrigin, &VPGraphicsTransformationOrigin::on_HideHandles);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) const
{
QGraphicsScene *scene = this->scene();
if (scene == nullptr)
{
return;
}
VPSheet *sheet = m_layout->GetFocusedSheet();
if (sheet == nullptr)
{
return;
}
VPTransformationOrigon origin = sheet->TransformationOrigin();
QList<QGraphicsItem *> list = scene->selectedItems();
for (auto *item : list)
{
if (item->type() == VPGraphicsPiece::Type)
{
auto *pieceItem = dynamic_cast<VPGraphicsPiece*>(item);
pieceItem->on_Rotate(origin.origin, angle);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
@ -279,8 +441,10 @@ void VPMainGraphicsView::on_PieceSheetChanged(VPPiece *piece)
{
if(_graphicsPiece == nullptr)
{
piece->ClearTransformations();
_graphicsPiece = new VPGraphicsPiece(piece);
m_graphicsPieces.append(_graphicsPiece);
ConnectPiece(_graphicsPiece);
}
scene()->addItem(_graphicsPiece);
}

View File

@ -29,15 +29,17 @@
#ifndef VPMAINGRAPHICSVIEW_H
#define VPMAINGRAPHICSVIEW_H
#include "vpgraphicssheet.h"
#include "vpgraphicspiece.h"
#include "vptilefactory.h"
#include "vpgraphicstilegrid.h"
#include "../vwidgets/vmaingraphicsview.h"
class VMainGraphicsScene;
class VPGraphicsPieceControls;
class VPGraphicsTransformationOrigin;
class VPTileFactory;
class VPGraphicsPiece;
class VPLayout;
class VPGraphicsTileGrid;
class VPGraphicsSheet;
class VPPiece;
class VPMainGraphicsView : public VMainGraphicsView
{
@ -92,6 +94,15 @@ protected:
void drawTilesLine();
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)
@ -101,6 +112,9 @@ private:
VPGraphicsTileGrid *m_graphicsTileGrid{nullptr};
VPGraphicsPieceControls *m_rotationControls{nullptr};
VPGraphicsTransformationOrigin *m_rotationOrigin{nullptr};
VPLayout *m_layout;
QList<VPGraphicsPiece*> m_graphicsPieces{};
@ -115,6 +129,10 @@ private:
*/
bool m_showGridTmp{false};
void ConnectPiece(VPGraphicsPiece *piece);
void RotatePiecesByAngle(qreal angle) const;
};
#endif // VPMAINGRAPHICSVIEW_H

View File

@ -4,8 +4,8 @@
#include <QMessageBox>
#include "../vwidgets/vmaingraphicsscene.h"
#include "vpsheet.h"
#include "vpmaingraphicsview.h"
#include "layout/vpsheet.h"
#include "scene/vpmaingraphicsview.h"
#include "../vobj/vobjpaintdevice.h"
#include "../vdxf/vdxfpaintdevice.h"

View File

@ -3,7 +3,7 @@
#include <QObject>
#include "vplayout.h"
#include "layout/vplayout.h"
#include "../vmisc/def.h"
#include "vcommonsettings.h"
#include "../vlayout/vlayoutdef.h"

View File

@ -43,7 +43,7 @@
#include "../ifc/xml/vlayoutconverter.h"
#include "../ifc/exception/vexception.h"
#include "../vwidgets/vmaingraphicsscene.h"
#include "vpsheet.h"
#include "layout/vpsheet.h"
#include "dialogs/dialogpuzzlepreferences.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
@ -322,11 +322,6 @@ VPPiece* VPMainWindow::CreatePiece(const VLayoutPiece &rawPiece)
// TODO : set all the information we need for the piece!
//
connect(piece, &VPPiece::SelectionChanged, this, &VPMainWindow::on_PieceSelectionChanged);
connect(piece, &VPPiece::PositionChanged, this, &VPMainWindow::on_PiecePositionChanged);
connect(piece, &VPPiece::RotationChanged, this, &VPMainWindow::on_PieceRotationChanged);
return piece;
}
@ -603,8 +598,8 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
ui->lineEditCurrentPieceName->setText(selectedPiece->GetName());
ui->plainTextEditCurrentPieceUUID->setPlainText(selectedPiece->GetUUID().toString());
ui->checkBoxCurrentPieceShowSeamline->setChecked(selectedPiece->GetShowSeamLine());
ui->checkBoxCurrentPieceMirrorPiece->setChecked(selectedPiece->GetPieceMirrored());
// ui->checkBoxCurrentPieceShowSeamline->setChecked(selectedPiece->GetShowSeamLine());
ui->checkBoxCurrentPieceMirrorPiece->setChecked(selectedPiece->IsMirror());
QPointF pos = selectedPiece->GetPosition();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX,
@ -612,8 +607,8 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY,
UnitConvertor(pos.y(), Unit::Px, m_layout->LayoutSettings().GetUnit()));
qreal angle = selectedPiece->GetRotation();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
// qreal angle = selectedPiece->GetRotation();
// SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
}
else
{
@ -1694,7 +1689,7 @@ void VPMainWindow::on_checkBoxCurrentPieceShowSeamline_toggled(bool checked)
{
if(m_selectedPieces.count() == 1)
{
m_selectedPieces.first()->SetShowSeamLine(checked);
// m_selectedPieces.first()->SetShowSeamLine(checked);
}
}
@ -1703,7 +1698,7 @@ void VPMainWindow::on_checkBoxCurrentPieceMirrorPiece_toggled(bool checked)
{
if(m_selectedPieces.count() == 1)
{
m_selectedPieces.first()->SetPieceMirrored(checked);
m_selectedPieces.first()->SetMirror(checked);
}
}
@ -1712,7 +1707,7 @@ void VPMainWindow::on_pushButtonCurrentPieceRotate90Anticlockwise_clicked()
{
if(m_selectedPieces.count() == 1)
{
m_selectedPieces.first()->RotateBy(90);
// m_selectedPieces.first()->RotateBy(90);
}
}
@ -1721,7 +1716,7 @@ void VPMainWindow::on_pushButtonCurrentPieceRotate90Clockwise_clicked()
{
if(m_selectedPieces.count() == 1)
{
m_selectedPieces.first()->RotateBy(-90);
// m_selectedPieces.first()->RotateBy(-90);
}
}
@ -1730,7 +1725,7 @@ void VPMainWindow::on_pushButtonCurrentPieceRotateGrainlineVertical_clicked()
{
if(m_selectedPieces.count() == 1)
{
m_selectedPieces.first()->RotateToGrainline(90, true);
// m_selectedPieces.first()->RotateToGrainline(90, true);
}
}
@ -1739,7 +1734,7 @@ void VPMainWindow::on_pushButtonCurrentPieceRotateGrainlineHorizontal_clicked()
{
if(m_selectedPieces.count() == 1)
{
m_selectedPieces.first()->RotateToGrainline(0, true);
// m_selectedPieces.first()->RotateToGrainline(0, true);
}
}
@ -1748,8 +1743,8 @@ void VPMainWindow::on_doubleSpinBoxCurrentPieceAngle_valueChanged(double value)
{
if(m_selectedPieces.count() == 1)
{
VPPiece *piece = m_selectedPieces.first();
piece->SetRotation(value);
// VPPiece *piece = m_selectedPieces.first();
// piece->SetRotation(value);
}
}
@ -1811,10 +1806,10 @@ void VPMainWindow::on_PieceRotationChanged()
{
if(m_selectedPieces.count() == 1)
{
VPPiece *piece = m_selectedPieces.first();
qreal angle = piece->GetRotation();
// VPPiece *piece = m_selectedPieces.first();
// qreal angle = piece->GetRotation();
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
// SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
}
}

View File

@ -34,10 +34,10 @@
#include <QPointer>
#include "../vmisc/def.h"
#include "vpcarrousel.h"
#include "vpmaingraphicsview.h"
#include "vplayout.h"
#include "vppiece.h"
#include "carousel/vpcarrousel.h"
#include "scene/vpmaingraphicsview.h"
#include "layout/vplayout.h"
#include "layout/vppiece.h"
#include "../vlayout/vlayoutpiece.h"
#include "vptilefactory.h"
#include "vpexporter.h"

View File

@ -669,7 +669,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-170</y>
<width>342</width>
<height>870</height>
</rect>

View File

@ -1,216 +0,0 @@
/************************************************************************
**
** @file vppiece.cpp
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @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) 2020 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 "vppiece.h"
#include <QtMath>
#include "../vmisc/def.h"
#include <QIcon>
#include <QLoggingCategory>
#include <QPainter>
Q_LOGGING_CATEGORY(pPiece, "p.piece")
//---------------------------------------------------------------------------------------------------------------------
VPPiece::VPPiece(VLayoutPiece layoutPiece): VLayoutPiece(layoutPiece)
{
// Resets the translation of the matrix
QTransform matrix = GetMatrix();
matrix.translate(-matrix.dx() ,-matrix.dy());
SetMatrix(matrix);
// then translate the piece so that the top left corner of the bouding rect of the piece is at the position
// (0,0) in the sheet coordinate system
QRectF boundingRect = MappedDetailBoundingRect();
QPointF offset = boundingRect.topLeft();
matrix = GetMatrix();
matrix.translate(-offset.x() ,-offset.y());
SetMatrix(matrix);
}
//---------------------------------------------------------------------------------------------------------------------
VPPiece::~VPPiece()
{
}
//---------------------------------------------------------------------------------------------------------------------
bool VPPiece::GetShowSeamLine() const
{
return m_showSeamline;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetShowSeamLine(bool value)
{
m_showSeamline = value;
emit PropertiesChanged();
}
//---------------------------------------------------------------------------------------------------------------------
bool VPPiece::GetPieceMirrored() const
{
return m_mirrorPiece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPieceMirrored(bool value)
{
m_mirrorPiece = value;
emit PropertiesChanged();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPosition(QPointF point)
{
m_transform.translate(point.x() - m_transform.dx(), point.y() - m_transform.dy());
emit PositionChanged();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VPPiece::GetPosition()
{
return QPointF(m_transform.dx(),m_transform.dy());
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetRotation(qreal angle)
{
// qreal currentAngle = GetRotation();
// qreal newAngle = angle - currentAngle;
// m_transform.rotate(newAngle);
if(not VFuzzyComparePossibleNulls(m_pieceAngle, angle))
{
m_pieceAngle = angle;
// make sure the angle is [0 <= angle < 360]
while(m_pieceAngle >= 360)
{
m_pieceAngle -= 360;
}
while(m_pieceAngle < 0)
{
m_pieceAngle += 360;
}
emit RotationChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::RotateBy(qreal angle)
{
SetRotation(m_pieceAngle + angle);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::RotateToGrainline(qreal angleOfGrainline, bool add180IfAlreadyInPosition)
{
qreal newAngle = -GrainlineAngle() + angleOfGrainline;
if(newAngle < 0)
{
newAngle += 360;
}
if(not VFuzzyComparePossibleNulls(m_pieceAngle, newAngle))
{
SetRotation(newAngle);
}
else if(add180IfAlreadyInPosition)
{
newAngle += 180;
SetRotation(newAngle);
}
}
//---------------------------------------------------------------------------------------------------------------------
qreal VPPiece::GetRotation()
{
return m_pieceAngle;
// We don't use the QTransform vor now because the math behind it to retrieve the angle is not trivial.
// TODO / FIXME: we can use QTransform later for optimization
// QTransform tmpTransform = m_transform;
// tmpTransform.translate(-tmpTransform.dx(), -tmpTransform.dy()); // make sure there is only the rotation in the matrix
// qreal angle = qRadiansToDegrees(qAcos(tmpTransform.m11()));
// qCDebug(pPiece, "new angle : %f", angle);
// return angle;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetIsSelected(bool value)
{
if(m_isSelected != value)
{
m_isSelected = value;
emit SelectionChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
bool VPPiece::GetIsSelected()
{
return m_isSelected;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::Sheet() const -> VPSheet *
{
return m_sheet;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetSheet(VPSheet *newSheet)
{
m_sheet = newSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::Layout() const -> VPLayout *
{
return m_layout;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetLayout(VPLayout *layout)
{
SCASSERT(layout != nullptr)
m_layout = layout;
}

View File

@ -1,181 +0,0 @@
/************************************************************************
**
** @file vppiece.h
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @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) 2020 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 VPPIECE_H
#define VPPIECE_H
#include <QUuid>
#include <QVector>
#include <QPoint>
#include <QTransform>
#include "../vlayout/vlayoutpiece.h"
class VPLayout;
class VPSheet;
class VPPiece : public QObject, public VLayoutPiece
{
Q_OBJECT
public:
VPPiece() = default;
explicit VPPiece(VLayoutPiece layoutPiece);
virtual ~VPPiece();
/**
* @brief GetShowSeamLine returns wether the seam line of the piece has to be shown or not
* @return true if the seamline has to be shown
*/
bool GetShowSeamLine() const;
/**
* @brief SetShowSeamLine sets wether the seam line of the piece has to be shown or not
* @param value true if the seamline has to be shown
*/
void SetShowSeamLine(bool value);
/**
* @brief GetMirrorPiece returns wether the piece is mirrored or not
* @return true if the piece is mirrored
*/
bool GetPieceMirrored() const;
/**
* @brief SetMirrorPiece sets wether the piece is mirrored or not
* @param value true if the piece will be mirrored
*/
void SetPieceMirrored(bool value);
/**
* @brief SetPosition Sets the position of the piece, in relation to the origin of the scene
* @param point the point where to set the piece
*/
void SetPosition(QPointF point);
/**
* @brief GetPosition Returns the position of the piece
* @return the position of the piece
*/
QPointF GetPosition();
/**
* @brief SetRotation Sets the rotation of the piece to the given angle.
* @param angle the angle of the rotation in degree
*/
void SetRotation(qreal angle);
/**
* @brief GetRotation Returns the angle of rotation
* @return the angle of rotation
*/
qreal GetRotation();
/**
* @brief rotateBy adds the given angle to the current rotation (anti-clockwise)
* @param angle the angle to add
*/
void RotateBy(qreal angle);
/**
* @brief RotateToGrainline rotates the piece, so that the grainline has
* the given angle
*
* @param angleOfGrainline angle of grainline
* @param add180IfAlreadyInPosition automatically adds 180, if the piece is
* already in the grainline position
*/
void RotateToGrainline(qreal angleOfGrainline, bool add180IfAlreadyInPosition = false);
/**
* @brief SetIsSelected Sets wether the piece is selected
* @param value true if the piece is selected
*/
void SetIsSelected(bool value);
/**
* @brief GetIsSelected Returns wether the piece is selected. It emit the signal SelectionChanged
* @return true if the piece is selected
*/
bool GetIsSelected();
QIcon PieceIcon(const QSize &size) const;
auto Sheet() const -> VPSheet *;
void SetSheet(VPSheet *newSheet);
auto Layout() const -> VPLayout *;
void SetLayout(VPLayout *layout);
signals:
/**
* @brief SelectionChanged emited when the selection of the piece was
* changed through the SetIsSelected function
*/
void SelectionChanged();
/**
* @brief PositionChanged emited when the position of the piece was
* changed through the SetPosition function
*/
void PositionChanged();
/**
* @brief RotationChanged emited when the position of the piece was
* changed through the function SetRotation
*/
void RotationChanged();
/**
* @brief PropertiesChanged emited when of the properties showSemaline
* or mirrorpiece where changed.
*/
void PropertiesChanged();
private:
Q_DISABLE_COPY(VPPiece)
VPLayout *m_layout{nullptr};
VPSheet *m_sheet{nullptr};
QVector<QPointF> m_grainline{};
bool m_isGrainlineEnabled{false};
// for now separate the position of the piece to the matrix coming from vlayoutpiece
// because it's difficult to have the origin of the piece by (0,0)
QTransform m_transform{};
// use a separate value for now because it's not easy to get the angle from the transform matrix
qreal m_pieceAngle{0};
bool m_showSeamline{true};
bool m_mirrorPiece{false};
bool m_isSelected{false};
};
#endif // VPPIECE_H

View File

@ -3,9 +3,11 @@
#include <QtSvg>
#include "../vwidgets/vmaingraphicsscene.h"
#include "vpsheet.h"
#include "vpmaingraphicsview.h"
#include "layout/vpsheet.h"
#include "scene/vpmaingraphicsview.h"
#include "layout/vplayout.h"
#include "../vmisc/def.h"
#include "../vmisc/vcommonsettings.h"
//---------------------------------------------------------------------------------------------------------------------
VPTileFactory::VPTileFactory(VPLayout *layout, VCommonSettings *commonSettings):
@ -21,7 +23,6 @@ VPTileFactory::~VPTileFactory()
}
//---------------------------------------------------------------------------------------------------------------------
void VPTileFactory::refreshTileInfos()
{

View File

@ -32,11 +32,10 @@
#include <QtMath>
#include <QObject>
#include "vplayout.h"
#include "../vmisc/def.h"
#include "vcommonsettings.h"
class VPMainGraphicsView;
class VPLayout;
class VCommonSettings;
class QPainter;
class VPTileFactory : QObject
{

View File

@ -30,7 +30,7 @@
#include "vplayoutfilereader.h"
#include "vplayoutfilewriter.h"
#include "vplayoutliterals.h"
#include "vpsheet.h"
#include "../layout/vpsheet.h"
#include "../ifc/exception/vexception.h"
#include "../ifc/exception/vexceptionconversionerror.h"
@ -297,11 +297,11 @@ void VPLayoutFileReader::ReadPiece(VPPiece *piece)
QString uuidStr = ReadAttributeString(attribs, ML::AttrID, QUuid::createUuid().toString());
piece->SetUUID(QUuid(uuidStr));
bool showSeamline = ReadAttributeBool(attribs, ML::AttrShowSeamline, trueStr);
piece->SetShowSeamLine(showSeamline);
// bool showSeamline = ReadAttributeBool(attribs, ML::AttrShowSeamline, trueStr);
// piece->SetShowSeamLine(showSeamline);
bool pieceMirrored = ReadAttributeBool(attribs, ML::AttrMirrored, falseStr);
piece->SetPieceMirrored(pieceMirrored);
piece->SetMirror(pieceMirrored);
// TODO read the further attributes

View File

@ -31,8 +31,8 @@
#include <QXmlStreamReader>
#include "../ifc/xml/vabstractconverter.h"
#include "vplayout.h"
#include "vppiece.h"
#include "../layout/vplayout.h"
#include "../layout/vppiece.h"
#include <QLoggingCategory>

View File

@ -27,9 +27,9 @@
*************************************************************************/
#include "vplayoutfilewriter.h"
#include "vplayout.h"
#include "vpsheet.h"
#include "vppiece.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include "../layout/vppiece.h"
#include "vplayoutliterals.h"
#include "../ifc/xml/vlayoutconverter.h"
#include "../vmisc/projectversion.h"
@ -142,8 +142,8 @@ void VPLayoutFileWriter::WritePiece(VPPiece *piece)
writeStartElement(ML::TagPiece);
SetAttribute(ML::AttrID, piece->GetUUID().toString());
SetAttribute(ML::AttrName, piece->GetName());
SetAttribute(ML::AttrMirrored, piece->GetPieceMirrored());
SetAttribute(ML::AttrShowSeamline, piece->GetShowSeamLine());
SetAttribute(ML::AttrMirrored, piece->IsMirror());
// SetAttribute(ML::AttrShowSeamline, piece->GetShowSeamLine());
SetAttribute(ML::AttrTransform, "string representation of the transformation"); // TODO / Fixme get the right value
// TODO cuttingLine

View File

@ -876,9 +876,15 @@ void VLayoutPiece::SetId(vidtype id)
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::Translate(qreal dx, qreal dy)
{
Translate(QPointF(dx, dy));
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::Translate(const QPointF &p)
{
QTransform m;
m.translate(dx, dy);
m.translate(p.x(), p.y());
d->matrix *= m;
}

View File

@ -128,6 +128,7 @@ public:
bool IsMirror() const;
void SetMirror(bool value);
void Translate(const QPointF &p);
void Translate(qreal dx, qreal dy);
void Scale(qreal sx, qreal sy);
void Rotate(const QPointF &originPoint, qreal degrees);