Piece rotation.
This commit is contained in:
parent
b366986f7a
commit
3fbe96c2a7
|
@ -33,7 +33,7 @@
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
|
||||||
#include "../vmisc/backport/qoverload.h"
|
#include "../vmisc/backport/qoverload.h"
|
||||||
#include "vpsheet.h"
|
#include "../layout/vpsheet.h"
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
|
@ -32,8 +32,8 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include "vplayout.h"
|
#include "../layout/vplayout.h"
|
||||||
#include "vppiece.h"
|
#include "../layout/vppiece.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
|
@ -76,7 +76,7 @@
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>VPCarrouselPieceList</class>
|
<class>VPCarrouselPieceList</class>
|
||||||
<extends>QListWidget</extends>
|
<extends>QListWidget</extends>
|
||||||
<header>vpcarrouselpiecelist.h</header>
|
<header>carousel/vpcarrouselpiecelist.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
|
@ -35,7 +35,8 @@
|
||||||
#include "vpmimedatapiece.h"
|
#include "vpmimedatapiece.h"
|
||||||
#include "vpcarrouselpiecelist.h"
|
#include "vpcarrouselpiecelist.h"
|
||||||
#include "vpcarrousel.h"
|
#include "vpcarrousel.h"
|
||||||
#include "vpsheet.h"
|
#include "../layout/vpsheet.h"
|
||||||
|
#include "../layout/vppiece.h"
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ auto VPCarrouselPiece::GetPiece() -> VPPiece *
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPCarrouselPiece::RefreshSelection()
|
void VPCarrouselPiece::RefreshSelection()
|
||||||
{
|
{
|
||||||
setSelected(m_piece->GetIsSelected());
|
setSelected(m_piece->IsSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
|
@ -31,8 +31,7 @@
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
|
|
||||||
#include "vppiece.h"
|
class VPPiece;
|
||||||
|
|
||||||
|
|
||||||
class VPCarrouselPiece : public QListWidgetItem
|
class VPCarrouselPiece : public QListWidgetItem
|
||||||
{
|
{
|
|
@ -37,7 +37,7 @@
|
||||||
#include "vpcarrouselpiece.h"
|
#include "vpcarrouselpiece.h"
|
||||||
#include "../vmisc/backport/qoverload.h"
|
#include "../vmisc/backport/qoverload.h"
|
||||||
#include "vpmimedatapiece.h"
|
#include "vpmimedatapiece.h"
|
||||||
#include "vpsheet.h"
|
#include "../layout/vpsheet.h"
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
@ -72,8 +72,7 @@ void VPCarrouselPieceList::Refresh()
|
||||||
{
|
{
|
||||||
// update the label of the piece
|
// update the label of the piece
|
||||||
auto* carrouselpiece = new VPCarrouselPiece(piece, this);
|
auto* carrouselpiece = new VPCarrouselPiece(piece, this);
|
||||||
carrouselpiece->setSelected(piece->GetIsSelected());
|
carrouselpiece->setSelected(piece->IsSelected());
|
||||||
connect(piece, &VPPiece::SelectionChanged, this, &VPCarrouselPieceList::on_SelectionChangedExternal);
|
|
||||||
}
|
}
|
||||||
sortItems();
|
sortItems();
|
||||||
}
|
}
|
||||||
|
@ -146,7 +145,7 @@ void VPCarrouselPieceList::startDrag(Qt::DropActions supportedActions)
|
||||||
if(drag->exec() == Qt::MoveAction)
|
if(drag->exec() == Qt::MoveAction)
|
||||||
{
|
{
|
||||||
m_carrousel->Refresh();
|
m_carrousel->Refresh();
|
||||||
piece->SetIsSelected(true);
|
piece->SetSelected(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,6 +31,8 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
|
||||||
|
#include "../layout/vppiece.h"
|
||||||
|
|
||||||
const QString VPMimeDataPiece::mineFormatPiecePtr = QStringLiteral("application/vnd.puzzle.piece.ptr");
|
const QString VPMimeDataPiece::mineFormatPiecePtr = QStringLiteral("application/vnd.puzzle.piece.ptr");
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
|
||||||
#include "vppiece.h"
|
class VPPiece;
|
||||||
|
|
||||||
class VPMimeDataPiece : public QMimeData
|
class VPMimeDataPiece : public QMimeData
|
||||||
{
|
{
|
||||||
|
@ -65,5 +65,4 @@ private:
|
||||||
VPPiece *m_piece{nullptr};
|
VPPiece *m_piece{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // VPMIMEDATAPIECE_H
|
#endif // VPMIMEDATAPIECE_H
|
|
@ -30,7 +30,6 @@
|
||||||
#include "vppiece.h"
|
#include "vppiece.h"
|
||||||
#include "vpsheet.h"
|
#include "vpsheet.h"
|
||||||
|
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(pLayout, "p.layout")
|
Q_LOGGING_CATEGORY(pLayout, "p.layout")
|
171
src/app/puzzle/layout/vppiece.cpp
Normal file
171
src/app/puzzle/layout/vppiece.cpp
Normal 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;
|
||||||
|
}
|
96
src/app/puzzle/layout/vppiece.h
Normal file
96
src/app/puzzle/layout/vppiece.h
Normal 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
|
|
@ -85,3 +85,30 @@ void VPSheet::SetVisible(bool visible)
|
||||||
{
|
{
|
||||||
m_visible = 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;
|
||||||
|
}
|
|
@ -40,6 +40,18 @@
|
||||||
class VPLayout;
|
class VPLayout;
|
||||||
class VPPiece;
|
class VPPiece;
|
||||||
|
|
||||||
|
enum class GrainlineType : qint8
|
||||||
|
{
|
||||||
|
Vertical,
|
||||||
|
Horizontal
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VPTransformationOrigon
|
||||||
|
{
|
||||||
|
QPointF origin{};
|
||||||
|
bool custom{false};
|
||||||
|
};
|
||||||
|
|
||||||
class VPSheet : public QObject
|
class VPSheet : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -73,6 +85,11 @@ public:
|
||||||
bool IsVisible() const;
|
bool IsVisible() const;
|
||||||
void SetVisible(bool visible);
|
void SetVisible(bool visible);
|
||||||
|
|
||||||
|
auto GrainlineType() const -> GrainlineType;
|
||||||
|
|
||||||
|
auto TransformationOrigin() const -> const VPTransformationOrigon &;
|
||||||
|
void SetTransformationOrigin(const VPTransformationOrigon &newTransformationOrigin);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(VPSheet)
|
Q_DISABLE_COPY(VPSheet)
|
||||||
|
|
||||||
|
@ -83,6 +100,8 @@ private:
|
||||||
QUuid m_uuid{QUuid::createUuid()};
|
QUuid m_uuid{QUuid::createUuid()};
|
||||||
|
|
||||||
bool m_visible{true};
|
bool m_visible{true};
|
||||||
|
|
||||||
|
VPTransformationOrigon m_transformationOrigin{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VPSHEET_H
|
#endif // VPSHEET_H
|
|
@ -8,23 +8,24 @@ SOURCES += \
|
||||||
$$PWD/dialogs/vpdialogabout.cpp \
|
$$PWD/dialogs/vpdialogabout.cpp \
|
||||||
$$PWD/main.cpp \
|
$$PWD/main.cpp \
|
||||||
$$PWD/vpapplication.cpp \
|
$$PWD/vpapplication.cpp \
|
||||||
$$PWD/vpcarrousel.cpp \
|
$$PWD/carousel/vpcarrousel.cpp \
|
||||||
$$PWD/vpcarrouselpiece.cpp \
|
$$PWD/carousel/vpcarrouselpiece.cpp \
|
||||||
$$PWD/vpcarrouselpiecelist.cpp \
|
$$PWD/carousel/vpcarrouselpiecelist.cpp \
|
||||||
$$PWD/vpcommandline.cpp \
|
$$PWD/vpcommandline.cpp \
|
||||||
$$PWD/vpcommands.cpp \
|
$$PWD/vpcommands.cpp \
|
||||||
$$PWD/vpexporter.cpp \
|
$$PWD/vpexporter.cpp \
|
||||||
$$PWD/vpgraphicspiece.cpp \
|
$$PWD/scene/vpgraphicspiece.cpp \
|
||||||
$$PWD/vpgraphicssheet.cpp \
|
$$PWD/scene/vpgraphicspiececontrols.cpp \
|
||||||
$$PWD/vpgraphicstilegrid.cpp \
|
$$PWD/scene/vpgraphicssheet.cpp \
|
||||||
$$PWD/vplayout.cpp \
|
$$PWD/scene/vpgraphicstilegrid.cpp \
|
||||||
$$PWD/vplayoutsettings.cpp \
|
$$PWD/layout/vplayout.cpp \
|
||||||
$$PWD/vpmaingraphicsview.cpp \
|
$$PWD/layout/vplayoutsettings.cpp \
|
||||||
|
$$PWD/scene/vpmaingraphicsview.cpp \
|
||||||
$$PWD/vpmainwindow.cpp \
|
$$PWD/vpmainwindow.cpp \
|
||||||
$$PWD/vpmimedatapiece.cpp \
|
$$PWD/carousel/vpmimedatapiece.cpp \
|
||||||
$$PWD/vppiece.cpp \
|
$$PWD/layout/vppiece.cpp \
|
||||||
$$PWD/vpsettings.cpp \
|
$$PWD/vpsettings.cpp \
|
||||||
$$PWD/vpsheet.cpp \
|
$$PWD/layout/vpsheet.cpp \
|
||||||
$$PWD/vptilefactory.cpp \
|
$$PWD/vptilefactory.cpp \
|
||||||
$$PWD/xml/vplayoutfilereader.cpp \
|
$$PWD/xml/vplayoutfilereader.cpp \
|
||||||
$$PWD/xml/vplayoutfilewriter.cpp \
|
$$PWD/xml/vplayoutfilewriter.cpp \
|
||||||
|
@ -37,25 +38,27 @@ HEADERS += \
|
||||||
$$PWD/dialogs/configpages/puzzlepreferencespathpage.h \
|
$$PWD/dialogs/configpages/puzzlepreferencespathpage.h \
|
||||||
$$PWD/dialogs/dialogpuzzlepreferences.h \
|
$$PWD/dialogs/dialogpuzzlepreferences.h \
|
||||||
$$PWD/dialogs/vpdialogabout.h \
|
$$PWD/dialogs/vpdialogabout.h \
|
||||||
|
$$PWD/scene/scenedef.h \
|
||||||
$$PWD/stable.h \
|
$$PWD/stable.h \
|
||||||
$$PWD/vpapplication.h \
|
$$PWD/vpapplication.h \
|
||||||
$$PWD/vpcarrousel.h \
|
$$PWD/carousel/vpcarrousel.h \
|
||||||
$$PWD/vpcarrouselpiece.h \
|
$$PWD/carousel/vpcarrouselpiece.h \
|
||||||
$$PWD/vpcarrouselpiecelist.h \
|
$$PWD/carousel/vpcarrouselpiecelist.h \
|
||||||
$$PWD/vpcommandline.h \
|
$$PWD/vpcommandline.h \
|
||||||
$$PWD/vpcommands.h \
|
$$PWD/vpcommands.h \
|
||||||
$$PWD/vpexporter.h \
|
$$PWD/vpexporter.h \
|
||||||
$$PWD/vpgraphicspiece.h \
|
$$PWD/scene/vpgraphicspiece.h \
|
||||||
$$PWD/vpgraphicssheet.h \
|
$$PWD/scene/vpgraphicspiececontrols.h \
|
||||||
$$PWD/vpgraphicstilegrid.h \
|
$$PWD/scene/vpgraphicssheet.h \
|
||||||
$$PWD/vplayout.h \
|
$$PWD/scene/vpgraphicstilegrid.h \
|
||||||
$$PWD/vplayoutsettings.h \
|
$$PWD/layout/vplayout.h \
|
||||||
$$PWD/vpmaingraphicsview.h \
|
$$PWD/layout/vplayoutsettings.h \
|
||||||
|
$$PWD/scene/vpmaingraphicsview.h \
|
||||||
$$PWD/vpmainwindow.h \
|
$$PWD/vpmainwindow.h \
|
||||||
$$PWD/vpmimedatapiece.h \
|
$$PWD/carousel/vpmimedatapiece.h \
|
||||||
$$PWD/vppiece.h \
|
$$PWD/layout/vppiece.h \
|
||||||
$$PWD/vpsettings.h \
|
$$PWD/vpsettings.h \
|
||||||
$$PWD/vpsheet.h \
|
$$PWD/layout/vpsheet.h \
|
||||||
$$PWD/vptilefactory.h \
|
$$PWD/vptilefactory.h \
|
||||||
$$PWD/xml/vplayoutfilereader.h \
|
$$PWD/xml/vplayoutfilereader.h \
|
||||||
$$PWD/xml/vplayoutfilewriter.h \
|
$$PWD/xml/vplayoutfilewriter.h \
|
||||||
|
@ -66,5 +69,5 @@ FORMS += \
|
||||||
$$PWD/dialogs/configpages/puzzlepreferencespathpage.ui \
|
$$PWD/dialogs/configpages/puzzlepreferencespathpage.ui \
|
||||||
$$PWD/dialogs/dialogpuzzlepreferences.ui \
|
$$PWD/dialogs/dialogpuzzlepreferences.ui \
|
||||||
$$PWD/dialogs/vpdialogabout.ui \
|
$$PWD/dialogs/vpdialogabout.ui \
|
||||||
$$PWD/vpcarrousel.ui \
|
$$PWD/carousel/vpcarrousel.ui \
|
||||||
$$PWD/vpmainwindow.ui
|
$$PWD/vpmainwindow.ui
|
||||||
|
|
38
src/app/puzzle/scene/scenedef.h
Normal file
38
src/app/puzzle/scene/scenedef.h
Normal 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
|
|
@ -39,9 +39,9 @@
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
#include "vppiece.h"
|
#include "../layout/vppiece.h"
|
||||||
#include "vplayout.h"
|
#include "../layout/vplayout.h"
|
||||||
#include "vpsheet.h"
|
#include "../layout/vpsheet.h"
|
||||||
|
|
||||||
#include "vlayoutpiecepath.h"
|
#include "vlayoutpiecepath.h"
|
||||||
#include "vplacelabelitem.h"
|
#include "vplacelabelitem.h"
|
||||||
|
@ -49,6 +49,11 @@
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
|
Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr qreal penWidth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPGraphicsPiece::VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent) :
|
VPGraphicsPiece::VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent) :
|
||||||
QGraphicsObject(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));
|
QPixmap cursor_pixmap = QIcon("://puzzleicon/svg/cursor_rotate.svg").pixmap(QSize(32,32));
|
||||||
m_rotateCursor= QCursor(cursor_pixmap, 16, 16);
|
m_rotateCursor= QCursor(cursor_pixmap, 16, 16);
|
||||||
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
void VPGraphicsPiece::Init()
|
|
||||||
{
|
|
||||||
// set some infos
|
// set some infos
|
||||||
setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
|
setFlags(ItemIsSelectable | ItemSendsGeometryChanges);
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
setCursor(QCursor(Qt::OpenHandCursor));
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
|
||||||
// initialises the seam line
|
PaintPiece();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -153,15 +76,23 @@ auto VPGraphicsPiece::GetPiece() -> VPPiece*
|
||||||
return m_piece;
|
return m_piece;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VPGraphicsPiece::TranslatePiece(const QPointF &p)
|
||||||
|
{
|
||||||
|
m_piece->Translate(p);
|
||||||
|
prepareGeometryChange();
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
auto VPGraphicsPiece::boundingRect() const -> QRectF
|
auto VPGraphicsPiece::boundingRect() const -> QRectF
|
||||||
{
|
{
|
||||||
|
constexpr qreal halfPenWidth = penWidth/2.;
|
||||||
if(!m_cuttingLine.isEmpty())
|
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(widget);
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
|
|
||||||
QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
|
QPen pen(Qt::black, penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
|
||||||
QBrush noBrush(Qt::NoBrush);
|
|
||||||
QBrush selectionBrush(QColor(255,160,160,60));
|
|
||||||
QBrush blackBrush(Qt::black);
|
|
||||||
|
|
||||||
painter->setPen(pen);
|
painter->setPen(pen);
|
||||||
|
|
||||||
// selection
|
PaintPiece(painter);
|
||||||
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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void VPGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
bool selectionState = isSelected();
|
|
||||||
//perform the default behaviour
|
//perform the default behaviour
|
||||||
QGraphicsObject::mousePressEvent(event);
|
QGraphicsObject::mousePressEvent(event);
|
||||||
|
|
||||||
// change the cursor when clicking the left button
|
// change the cursor when clicking the left button
|
||||||
if((event->button() == Qt::LeftButton))
|
if((event->button() == Qt::LeftButton))
|
||||||
{
|
|
||||||
if((event->modifiers() & Qt::AltModifier) != 0U)
|
|
||||||
{
|
|
||||||
setCursor(m_rotateCursor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
setCursor(Qt::ClosedHandCursor);
|
setCursor(Qt::ClosedHandCursor);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// change the selected state when clicking left button
|
m_moveStartPoint = event->pos();
|
||||||
if (event->button() == Qt::LeftButton)
|
emit HideTransformationHandles(true);
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
|
void VPGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if((event->buttons() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier))
|
QGraphicsObject::mouseMoveEvent(event);
|
||||||
{
|
|
||||||
//FIXME: it flickers between the arrow cursor and the rotate cursor
|
|
||||||
setCursor(m_rotateCursor);
|
|
||||||
|
|
||||||
QPointF rotationNewPoint = event->scenePos();
|
GroupMove(event->pos());
|
||||||
QPointF rotationCenter = sceneBoundingRect().center();
|
|
||||||
|
|
||||||
// get the angle from the center to the initial click point
|
m_moveStartPoint = event->pos();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
bool selectionState = isSelected();
|
|
||||||
|
|
||||||
//perform the default behaviour
|
//perform the default behaviour
|
||||||
QGraphicsItem::mouseReleaseEvent(event);
|
QGraphicsItem::mouseReleaseEvent(event);
|
||||||
|
|
||||||
|
@ -352,32 +154,8 @@ void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
if (event->button() == Qt::LeftButton)
|
if (event->button() == Qt::LeftButton)
|
||||||
{
|
{
|
||||||
setCursor(Qt::OpenHandCursor);
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
GroupMove(event->pos());
|
||||||
setSelected(selectionState);
|
emit HideTransformationHandles(false);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
QRectF rect = m_piece->MappedDetailBoundingRect();
|
||||||
void VPGraphicsPiece::on_PiecePositionChanged()
|
QPointF p = rect.topLeft();
|
||||||
{
|
|
||||||
setPos(m_piece->GetPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
// initialises the seam line
|
||||||
void VPGraphicsPiece::on_PieceRotationChanged()
|
QVector<QPointF> seamLinePoints = m_piece->GetMappedContourPoints();
|
||||||
{
|
if(!seamLinePoints.isEmpty())
|
||||||
setTransformOriginPoint(boundingRect().center());
|
|
||||||
setRotation(-m_piece->GetRotation());
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
void VPGraphicsPiece::on_PiecePropertiesChanged()
|
|
||||||
{
|
|
||||||
if(scene() != nullptr)
|
|
||||||
{
|
{
|
||||||
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 ¢er, 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)
|
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(change == ItemSelectedHasChanged)
|
||||||
{
|
{
|
||||||
if(m_piece->GetIsSelected() != isSelected())
|
emit PieceSelectionChanged();
|
||||||
{
|
m_piece->SetSelected(value.toBool());
|
||||||
m_piece->SetIsSelected(isSelected());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
|
|
||||||
|
#include "scenedef.h"
|
||||||
|
|
||||||
class VPPiece;
|
class VPPiece;
|
||||||
|
|
||||||
class VPGraphicsPiece : public QGraphicsObject
|
class VPGraphicsPiece : public QGraphicsObject
|
||||||
|
@ -41,37 +43,24 @@ public:
|
||||||
explicit VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent = nullptr);
|
explicit VPGraphicsPiece(VPPiece *piece, QGraphicsItem *parent = nullptr);
|
||||||
~VPGraphicsPiece() = default;
|
~VPGraphicsPiece() = default;
|
||||||
|
|
||||||
void Init();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief GetPiece Returns the piece that corresponds to the graphics piece
|
* @brief GetPiece Returns the piece that corresponds to the graphics piece
|
||||||
* @return the piece
|
* @return the piece
|
||||||
*/
|
*/
|
||||||
auto GetPiece() -> VPPiece*;
|
auto GetPiece() -> VPPiece*;
|
||||||
|
|
||||||
|
void TranslatePiece(const QPointF &p);
|
||||||
|
|
||||||
virtual int type() const override {return Type;}
|
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:
|
public slots:
|
||||||
/**
|
void on_Rotate(const QPointF ¢er, qreal angle);
|
||||||
* @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();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
auto boundingRect() const -> QRectF override;
|
auto boundingRect() const -> QRectF override;
|
||||||
|
@ -79,11 +68,9 @@ protected:
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
|
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
|
||||||
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
|
||||||
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
|
|
||||||
|
|
||||||
auto itemChange(GraphicsItemChange change, const QVariant &value) -> QVariant override;
|
auto itemChange(GraphicsItemChange change, const QVariant &value) -> QVariant override;
|
||||||
|
|
||||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
|
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
|
||||||
|
@ -94,17 +81,15 @@ private:
|
||||||
|
|
||||||
QPainterPath m_cuttingLine{};
|
QPainterPath m_cuttingLine{};
|
||||||
QPainterPath m_seamLine{};
|
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{};
|
QPointF m_rotationStartPoint{};
|
||||||
|
|
||||||
QCursor m_rotateCursor{};
|
QCursor m_rotateCursor{};
|
||||||
|
|
||||||
|
void PaintPiece(QPainter *painter=nullptr);
|
||||||
|
|
||||||
|
void GroupMove(const QPointF &pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VPGRAPHICSPIECE_H
|
#endif // VPGRAPHICSPIECE_H
|
736
src/app/puzzle/scene/vpgraphicspiececontrols.cpp
Normal file
736
src/app/puzzle/scene/vpgraphicspiececontrols.cpp
Normal 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);
|
||||||
|
}
|
129
src/app/puzzle/scene/vpgraphicspiececontrols.h
Normal file
129
src/app/puzzle/scene/vpgraphicspiececontrols.h
Normal 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 ¢er, 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
|
|
@ -27,7 +27,9 @@
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
#include "vpgraphicssheet.h"
|
#include "vpgraphicssheet.h"
|
||||||
#include "vplayout.h"
|
#include "../layout/vplayout.h"
|
||||||
|
#include "../layout/vpsheet.h"
|
||||||
|
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
|
@ -32,7 +32,7 @@
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
#include "vpsheet.h"
|
class VPSheet;
|
||||||
|
|
||||||
class VPGraphicsSheet : public QGraphicsItem
|
class VPGraphicsSheet : public QGraphicsItem
|
||||||
{
|
{
|
|
@ -1,7 +1,7 @@
|
||||||
#include "vpgraphicstilegrid.h"
|
#include "vpgraphicstilegrid.h"
|
||||||
|
|
||||||
#include "vptilefactory.h"
|
#include "../vptilefactory.h"
|
||||||
#include "vplayout.h"
|
#include "../layout/vplayout.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPGraphicsTileGrid::VPGraphicsTileGrid(VPLayout *layout, VPTileFactory *tileFactory,QGraphicsItem *parent):
|
VPGraphicsTileGrid::VPGraphicsTileGrid(VPLayout *layout, VPTileFactory *tileFactory,QGraphicsItem *parent):
|
|
@ -33,16 +33,27 @@
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
#include "vpmimedatapiece.h"
|
#include "../scene/vpgraphicssheet.h"
|
||||||
#include "vplayout.h"
|
#include "../scene/vpgraphicspiece.h"
|
||||||
#include "vpsheet.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 "../vwidgets/vmaingraphicsscene.h"
|
||||||
#include "vptilefactory.h"
|
#include "vptilefactory.h"
|
||||||
|
#include "vpgraphicspiececontrols.h"
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(pMainGraphicsView, "p.mainGraphicsView")
|
Q_LOGGING_CATEGORY(pMainGraphicsView, "p.mainGraphicsView")
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const QKeySequence restoreOriginShortcut = QKeySequence(Qt::ControlModifier + Qt::Key_Asterisk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFactory, QWidget *parent) :
|
VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFactory, QWidget *parent) :
|
||||||
|
@ -53,17 +64,65 @@ VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFact
|
||||||
SCASSERT(m_layout != nullptr)
|
SCASSERT(m_layout != nullptr)
|
||||||
setScene(m_scene);
|
setScene(m_scene);
|
||||||
|
|
||||||
m_graphicsSheet = new VPGraphicsSheet(layout->GetFocusedSheet());
|
m_graphicsSheet = new VPGraphicsSheet(m_layout->GetFocusedSheet());
|
||||||
m_graphicsSheet->setPos(0, 0);
|
m_graphicsSheet->setPos(0, 0);
|
||||||
m_scene->addItem(m_graphicsSheet);
|
m_scene->addItem(m_graphicsSheet);
|
||||||
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
m_graphicsTileGrid = new VPGraphicsTileGrid(layout, tileFactory);
|
m_graphicsTileGrid = new VPGraphicsTileGrid(m_layout, tileFactory);
|
||||||
m_scene->addItem(m_graphicsTileGrid);
|
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
|
// add the connections
|
||||||
connect(m_layout, &VPLayout::PieceSheetChanged, this, &VPMainGraphicsView::on_PieceSheetChanged);
|
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);
|
auto *graphicsPiece = new VPGraphicsPiece(piece);
|
||||||
m_graphicsPieces.append(graphicsPiece);
|
m_graphicsPieces.append(graphicsPiece);
|
||||||
|
|
||||||
scene()->addItem(graphicsPiece);
|
scene()->addItem(graphicsPiece);
|
||||||
|
ConnectPiece(graphicsPiece);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,9 +239,8 @@ void VPMainGraphicsView::dropEvent(QDropEvent *event)
|
||||||
qCDebug(pMainGraphicsView(), "element dropped, %s", qUtf8Printable(piece->GetName()));
|
qCDebug(pMainGraphicsView(), "element dropped, %s", qUtf8Printable(piece->GetName()));
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
|
|
||||||
QPoint point = event->pos();
|
piece->ClearTransformations();
|
||||||
piece->SetPosition(mapToScene(point));
|
piece->SetPosition(mapToScene(event->pos()));
|
||||||
piece->SetRotation(0);
|
|
||||||
|
|
||||||
// change the piecelist of the piece
|
// change the piecelist of the piece
|
||||||
piece->SetSheet(m_layout->GetFocusedSheet());
|
piece->SetSheet(m_layout->GetFocusedSheet());
|
||||||
|
@ -192,6 +250,8 @@ void VPMainGraphicsView::dropEvent(QDropEvent *event)
|
||||||
|
|
||||||
scene()->addItem(graphicsPiece);
|
scene()->addItem(graphicsPiece);
|
||||||
|
|
||||||
|
ConnectPiece(graphicsPiece);
|
||||||
|
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,9 +268,9 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
VPPiece *piece = graphicsPiece->GetPiece();
|
VPPiece *piece = graphicsPiece->GetPiece();
|
||||||
|
|
||||||
if(piece->GetIsSelected())
|
if(piece->IsSelected())
|
||||||
{
|
{
|
||||||
piece->SetIsSelected(false);
|
piece->SetSelected(false);
|
||||||
piece->SetSheet(nullptr);
|
piece->SetSheet(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,8 +288,12 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
|
|
||||||
VPSheet *sheet = m_layout->GetFocusedSheet();
|
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"));
|
QAction *removeSheetAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Remove sheet"));
|
||||||
removeSheetAction->setEnabled(sheet != nullptr && m_layout->GetSheets().size() > 1);
|
removeSheetAction->setEnabled(sheet != nullptr && m_layout->GetSheets().size() > 1);
|
||||||
|
|
||||||
|
@ -251,6 +315,104 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event)
|
||||||
emit on_SheetRemoved();
|
emit on_SheetRemoved();
|
||||||
RefreshPieces();
|
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)
|
if(_graphicsPiece == nullptr)
|
||||||
{
|
{
|
||||||
|
piece->ClearTransformations();
|
||||||
_graphicsPiece = new VPGraphicsPiece(piece);
|
_graphicsPiece = new VPGraphicsPiece(piece);
|
||||||
m_graphicsPieces.append(_graphicsPiece);
|
m_graphicsPieces.append(_graphicsPiece);
|
||||||
|
ConnectPiece(_graphicsPiece);
|
||||||
}
|
}
|
||||||
scene()->addItem(_graphicsPiece);
|
scene()->addItem(_graphicsPiece);
|
||||||
}
|
}
|
|
@ -29,15 +29,17 @@
|
||||||
#ifndef VPMAINGRAPHICSVIEW_H
|
#ifndef VPMAINGRAPHICSVIEW_H
|
||||||
#define VPMAINGRAPHICSVIEW_H
|
#define VPMAINGRAPHICSVIEW_H
|
||||||
|
|
||||||
#include "vpgraphicssheet.h"
|
|
||||||
#include "vpgraphicspiece.h"
|
|
||||||
#include "vptilefactory.h"
|
|
||||||
#include "vpgraphicstilegrid.h"
|
|
||||||
#include "../vwidgets/vmaingraphicsview.h"
|
#include "../vwidgets/vmaingraphicsview.h"
|
||||||
|
|
||||||
class VMainGraphicsScene;
|
class VMainGraphicsScene;
|
||||||
|
class VPGraphicsPieceControls;
|
||||||
|
class VPGraphicsTransformationOrigin;
|
||||||
class VPTileFactory;
|
class VPTileFactory;
|
||||||
|
class VPGraphicsPiece;
|
||||||
|
class VPLayout;
|
||||||
|
class VPGraphicsTileGrid;
|
||||||
|
class VPGraphicsSheet;
|
||||||
|
class VPPiece;
|
||||||
|
|
||||||
class VPMainGraphicsView : public VMainGraphicsView
|
class VPMainGraphicsView : public VMainGraphicsView
|
||||||
{
|
{
|
||||||
|
@ -92,6 +94,15 @@ protected:
|
||||||
|
|
||||||
void drawTilesLine();
|
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:
|
private:
|
||||||
Q_DISABLE_COPY(VPMainGraphicsView)
|
Q_DISABLE_COPY(VPMainGraphicsView)
|
||||||
|
|
||||||
|
@ -101,6 +112,9 @@ private:
|
||||||
|
|
||||||
VPGraphicsTileGrid *m_graphicsTileGrid{nullptr};
|
VPGraphicsTileGrid *m_graphicsTileGrid{nullptr};
|
||||||
|
|
||||||
|
VPGraphicsPieceControls *m_rotationControls{nullptr};
|
||||||
|
VPGraphicsTransformationOrigin *m_rotationOrigin{nullptr};
|
||||||
|
|
||||||
VPLayout *m_layout;
|
VPLayout *m_layout;
|
||||||
|
|
||||||
QList<VPGraphicsPiece*> m_graphicsPieces{};
|
QList<VPGraphicsPiece*> m_graphicsPieces{};
|
||||||
|
@ -115,6 +129,10 @@ private:
|
||||||
*/
|
*/
|
||||||
bool m_showGridTmp{false};
|
bool m_showGridTmp{false};
|
||||||
|
|
||||||
|
void ConnectPiece(VPGraphicsPiece *piece);
|
||||||
|
|
||||||
|
void RotatePiecesByAngle(qreal angle) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VPMAINGRAPHICSVIEW_H
|
#endif // VPMAINGRAPHICSVIEW_H
|
|
@ -4,8 +4,8 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "../vwidgets/vmaingraphicsscene.h"
|
#include "../vwidgets/vmaingraphicsscene.h"
|
||||||
#include "vpsheet.h"
|
#include "layout/vpsheet.h"
|
||||||
#include "vpmaingraphicsview.h"
|
#include "scene/vpmaingraphicsview.h"
|
||||||
#include "../vobj/vobjpaintdevice.h"
|
#include "../vobj/vobjpaintdevice.h"
|
||||||
#include "../vdxf/vdxfpaintdevice.h"
|
#include "../vdxf/vdxfpaintdevice.h"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "vplayout.h"
|
#include "layout/vplayout.h"
|
||||||
#include "../vmisc/def.h"
|
#include "../vmisc/def.h"
|
||||||
#include "vcommonsettings.h"
|
#include "vcommonsettings.h"
|
||||||
#include "../vlayout/vlayoutdef.h"
|
#include "../vlayout/vlayoutdef.h"
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include "../ifc/xml/vlayoutconverter.h"
|
#include "../ifc/xml/vlayoutconverter.h"
|
||||||
#include "../ifc/exception/vexception.h"
|
#include "../ifc/exception/vexception.h"
|
||||||
#include "../vwidgets/vmaingraphicsscene.h"
|
#include "../vwidgets/vmaingraphicsscene.h"
|
||||||
#include "vpsheet.h"
|
#include "layout/vpsheet.h"
|
||||||
#include "dialogs/dialogpuzzlepreferences.h"
|
#include "dialogs/dialogpuzzlepreferences.h"
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
|
#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!
|
// 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;
|
return piece;
|
||||||
}
|
}
|
||||||
|
@ -603,8 +598,8 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
|
||||||
ui->lineEditCurrentPieceName->setText(selectedPiece->GetName());
|
ui->lineEditCurrentPieceName->setText(selectedPiece->GetName());
|
||||||
ui->plainTextEditCurrentPieceUUID->setPlainText(selectedPiece->GetUUID().toString());
|
ui->plainTextEditCurrentPieceUUID->setPlainText(selectedPiece->GetUUID().toString());
|
||||||
|
|
||||||
ui->checkBoxCurrentPieceShowSeamline->setChecked(selectedPiece->GetShowSeamLine());
|
// ui->checkBoxCurrentPieceShowSeamline->setChecked(selectedPiece->GetShowSeamLine());
|
||||||
ui->checkBoxCurrentPieceMirrorPiece->setChecked(selectedPiece->GetPieceMirrored());
|
ui->checkBoxCurrentPieceMirrorPiece->setChecked(selectedPiece->IsMirror());
|
||||||
|
|
||||||
QPointF pos = selectedPiece->GetPosition();
|
QPointF pos = selectedPiece->GetPosition();
|
||||||
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX,
|
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionX,
|
||||||
|
@ -612,8 +607,8 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
|
||||||
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY,
|
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY,
|
||||||
UnitConvertor(pos.y(), Unit::Px, m_layout->LayoutSettings().GetUnit()));
|
UnitConvertor(pos.y(), Unit::Px, m_layout->LayoutSettings().GetUnit()));
|
||||||
|
|
||||||
qreal angle = selectedPiece->GetRotation();
|
// qreal angle = selectedPiece->GetRotation();
|
||||||
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
|
// SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1694,7 +1689,7 @@ void VPMainWindow::on_checkBoxCurrentPieceShowSeamline_toggled(bool checked)
|
||||||
{
|
{
|
||||||
if(m_selectedPieces.count() == 1)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
if(m_selectedPieces.count() == 1)
|
||||||
{
|
{
|
||||||
VPPiece *piece = m_selectedPieces.first();
|
// VPPiece *piece = m_selectedPieces.first();
|
||||||
piece->SetRotation(value);
|
// piece->SetRotation(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1811,10 +1806,10 @@ void VPMainWindow::on_PieceRotationChanged()
|
||||||
{
|
{
|
||||||
if(m_selectedPieces.count() == 1)
|
if(m_selectedPieces.count() == 1)
|
||||||
{
|
{
|
||||||
VPPiece *piece = m_selectedPieces.first();
|
// VPPiece *piece = m_selectedPieces.first();
|
||||||
qreal angle = piece->GetRotation();
|
// qreal angle = piece->GetRotation();
|
||||||
|
|
||||||
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
|
// SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "../vmisc/def.h"
|
#include "../vmisc/def.h"
|
||||||
#include "vpcarrousel.h"
|
#include "carousel/vpcarrousel.h"
|
||||||
#include "vpmaingraphicsview.h"
|
#include "scene/vpmaingraphicsview.h"
|
||||||
#include "vplayout.h"
|
#include "layout/vplayout.h"
|
||||||
#include "vppiece.h"
|
#include "layout/vppiece.h"
|
||||||
#include "../vlayout/vlayoutpiece.h"
|
#include "../vlayout/vlayoutpiece.h"
|
||||||
#include "vptilefactory.h"
|
#include "vptilefactory.h"
|
||||||
#include "vpexporter.h"
|
#include "vpexporter.h"
|
||||||
|
|
|
@ -669,7 +669,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>-170</y>
|
||||||
<width>342</width>
|
<width>342</width>
|
||||||
<height>870</height>
|
<height>870</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -3,9 +3,11 @@
|
||||||
#include <QtSvg>
|
#include <QtSvg>
|
||||||
|
|
||||||
#include "../vwidgets/vmaingraphicsscene.h"
|
#include "../vwidgets/vmaingraphicsscene.h"
|
||||||
#include "vpsheet.h"
|
#include "layout/vpsheet.h"
|
||||||
#include "vpmaingraphicsview.h"
|
#include "scene/vpmaingraphicsview.h"
|
||||||
|
#include "layout/vplayout.h"
|
||||||
|
#include "../vmisc/def.h"
|
||||||
|
#include "../vmisc/vcommonsettings.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPTileFactory::VPTileFactory(VPLayout *layout, VCommonSettings *commonSettings):
|
VPTileFactory::VPTileFactory(VPLayout *layout, VCommonSettings *commonSettings):
|
||||||
|
@ -21,7 +23,6 @@ VPTileFactory::~VPTileFactory()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPTileFactory::refreshTileInfos()
|
void VPTileFactory::refreshTileInfos()
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,11 +32,10 @@
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "vplayout.h"
|
|
||||||
#include "../vmisc/def.h"
|
|
||||||
#include "vcommonsettings.h"
|
|
||||||
|
|
||||||
class VPMainGraphicsView;
|
class VPMainGraphicsView;
|
||||||
|
class VPLayout;
|
||||||
|
class VCommonSettings;
|
||||||
|
class QPainter;
|
||||||
|
|
||||||
class VPTileFactory : QObject
|
class VPTileFactory : QObject
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "vplayoutfilereader.h"
|
#include "vplayoutfilereader.h"
|
||||||
#include "vplayoutfilewriter.h"
|
#include "vplayoutfilewriter.h"
|
||||||
#include "vplayoutliterals.h"
|
#include "vplayoutliterals.h"
|
||||||
#include "vpsheet.h"
|
#include "../layout/vpsheet.h"
|
||||||
#include "../ifc/exception/vexception.h"
|
#include "../ifc/exception/vexception.h"
|
||||||
#include "../ifc/exception/vexceptionconversionerror.h"
|
#include "../ifc/exception/vexceptionconversionerror.h"
|
||||||
|
|
||||||
|
@ -297,11 +297,11 @@ void VPLayoutFileReader::ReadPiece(VPPiece *piece)
|
||||||
QString uuidStr = ReadAttributeString(attribs, ML::AttrID, QUuid::createUuid().toString());
|
QString uuidStr = ReadAttributeString(attribs, ML::AttrID, QUuid::createUuid().toString());
|
||||||
piece->SetUUID(QUuid(uuidStr));
|
piece->SetUUID(QUuid(uuidStr));
|
||||||
|
|
||||||
bool showSeamline = ReadAttributeBool(attribs, ML::AttrShowSeamline, trueStr);
|
// bool showSeamline = ReadAttributeBool(attribs, ML::AttrShowSeamline, trueStr);
|
||||||
piece->SetShowSeamLine(showSeamline);
|
// piece->SetShowSeamLine(showSeamline);
|
||||||
|
|
||||||
bool pieceMirrored = ReadAttributeBool(attribs, ML::AttrMirrored, falseStr);
|
bool pieceMirrored = ReadAttributeBool(attribs, ML::AttrMirrored, falseStr);
|
||||||
piece->SetPieceMirrored(pieceMirrored);
|
piece->SetMirror(pieceMirrored);
|
||||||
// TODO read the further attributes
|
// TODO read the further attributes
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
|
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include "../ifc/xml/vabstractconverter.h"
|
#include "../ifc/xml/vabstractconverter.h"
|
||||||
#include "vplayout.h"
|
#include "../layout/vplayout.h"
|
||||||
#include "vppiece.h"
|
#include "../layout/vppiece.h"
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
#include "vplayoutfilewriter.h"
|
#include "vplayoutfilewriter.h"
|
||||||
#include "vplayout.h"
|
#include "../layout/vplayout.h"
|
||||||
#include "vpsheet.h"
|
#include "../layout/vpsheet.h"
|
||||||
#include "vppiece.h"
|
#include "../layout/vppiece.h"
|
||||||
#include "vplayoutliterals.h"
|
#include "vplayoutliterals.h"
|
||||||
#include "../ifc/xml/vlayoutconverter.h"
|
#include "../ifc/xml/vlayoutconverter.h"
|
||||||
#include "../vmisc/projectversion.h"
|
#include "../vmisc/projectversion.h"
|
||||||
|
@ -142,8 +142,8 @@ void VPLayoutFileWriter::WritePiece(VPPiece *piece)
|
||||||
writeStartElement(ML::TagPiece);
|
writeStartElement(ML::TagPiece);
|
||||||
SetAttribute(ML::AttrID, piece->GetUUID().toString());
|
SetAttribute(ML::AttrID, piece->GetUUID().toString());
|
||||||
SetAttribute(ML::AttrName, piece->GetName());
|
SetAttribute(ML::AttrName, piece->GetName());
|
||||||
SetAttribute(ML::AttrMirrored, piece->GetPieceMirrored());
|
SetAttribute(ML::AttrMirrored, piece->IsMirror());
|
||||||
SetAttribute(ML::AttrShowSeamline, piece->GetShowSeamLine());
|
// SetAttribute(ML::AttrShowSeamline, piece->GetShowSeamLine());
|
||||||
SetAttribute(ML::AttrTransform, "string representation of the transformation"); // TODO / Fixme get the right value
|
SetAttribute(ML::AttrTransform, "string representation of the transformation"); // TODO / Fixme get the right value
|
||||||
|
|
||||||
// TODO cuttingLine
|
// TODO cuttingLine
|
||||||
|
|
|
@ -876,9 +876,15 @@ void VLayoutPiece::SetId(vidtype id)
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VLayoutPiece::Translate(qreal dx, qreal dy)
|
void VLayoutPiece::Translate(qreal dx, qreal dy)
|
||||||
|
{
|
||||||
|
Translate(QPointF(dx, dy));
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VLayoutPiece::Translate(const QPointF &p)
|
||||||
{
|
{
|
||||||
QTransform m;
|
QTransform m;
|
||||||
m.translate(dx, dy);
|
m.translate(p.x(), p.y());
|
||||||
d->matrix *= m;
|
d->matrix *= m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,7 @@ public:
|
||||||
bool IsMirror() const;
|
bool IsMirror() const;
|
||||||
void SetMirror(bool value);
|
void SetMirror(bool value);
|
||||||
|
|
||||||
|
void Translate(const QPointF &p);
|
||||||
void Translate(qreal dx, qreal dy);
|
void Translate(qreal dx, qreal dy);
|
||||||
void Scale(qreal sx, qreal sy);
|
void Scale(qreal sx, qreal sy);
|
||||||
void Rotate(const QPointF &originPoint, qreal degrees);
|
void Rotate(const QPointF &originPoint, qreal degrees);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user