Compare commits
29 Commits
5ea7817a02
...
7286516cdc
Author | SHA1 | Date |
---|---|---|
Roman Telezhynskyi | 7286516cdc | |
Roman Telezhynskyi | e154ba7440 | |
Roman Telezhynskyi | b4b26b115b | |
Roman Telezhynskyi | 08c4d1e411 | |
Roman Telezhynskyi | 7378cfbe95 | |
Roman Telezhynskyi | e4481754f0 | |
Roman Telezhynskyi | 55cc3a7d54 | |
Roman Telezhynskyi | 39cdbd1c70 | |
Roman Telezhynskyi | 14e542b412 | |
Roman Telezhynskyi | b4c009502b | |
Roman Telezhynskyi | bc31838319 | |
Roman Telezhynskyi | 8f5c5b8cae | |
Roman Telezhynskyi | 3aec5bf341 | |
Roman Telezhynskyi | d331b5dc01 | |
Roman Telezhynskyi | f72d235344 | |
Roman Telezhynskyi | c5a3375d78 | |
Roman Telezhynskyi | 9e3659830e | |
Roman Telezhynskyi | 39d56e34aa | |
Roman Telezhynskyi | d3bdd68c46 | |
Roman Telezhynskyi | f681b5ccaf | |
Roman Telezhynskyi | 2bdd023afe | |
Roman Telezhynskyi | 1a6a830119 | |
Roman Telezhynskyi | 0eef58f2cf | |
Roman Telezhynskyi | cbc137f4e9 | |
Roman Telezhynskyi | fbaf5f0f38 | |
Roman Telezhynskyi | 54ee9e0629 | |
Roman Telezhynskyi | a4e2e1f1bf | |
Roman Telezhynskyi | b25df043bf | |
Roman Telezhynskyi | 5186e80adb |
|
@ -66,6 +66,7 @@
|
|||
- Updated Windows installer.
|
||||
- Automatic crash reports.
|
||||
- Improve compatibility with Richpeace CAD.
|
||||
- New warning "Piece gape position".
|
||||
|
||||
# Valentina 0.7.52 September 12, 2022
|
||||
- Fix crash when default locale is ru.
|
||||
|
|
|
@ -44,7 +44,7 @@ def generate_sym_files(install_root):
|
|||
print(f"Generating symbols for: {os.path.basename(debug_file)}")
|
||||
|
||||
sym_file = os.path.splitext(debug_file)[0] + ".sym"
|
||||
dump_syms_cmd = ["dump_syms", '-o', sym_file, debug_file]
|
||||
dump_syms_cmd = ["dump_syms", '-o', sym_file, '--inlines', debug_file]
|
||||
subprocess.run(dump_syms_cmd, check=True)
|
||||
|
||||
sym_files.append((debug_file, zip_sym(sym_file)))
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[Rules]
|
||||
*.debug=false
|
||||
qt.*.debug=false
|
||||
|
|
|
@ -119,8 +119,9 @@ PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *
|
|||
|
||||
#if !defined(CRASH_REPORTING)
|
||||
ui->groupBoxCrashReports->setDisabled(true);
|
||||
#endif
|
||||
|
||||
ui->checkBoxSendCrashReports->setChecked(false);
|
||||
ui->lineEditCrashUserEmail->setText(QString());
|
||||
#else
|
||||
ui->checkBoxSendCrashReports->setChecked(settings->IsSendCrashReport());
|
||||
connect(ui->checkBoxSendCrashReports, &QCheckBox::stateChanged, this,
|
||||
[this]() { m_sendCrashReportsChanged = true; });
|
||||
|
@ -131,6 +132,7 @@ PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *
|
|||
ui->lineEditCrashUserEmail->setText(settings->GetCrashEmail());
|
||||
connect(ui->lineEditCrashUserEmail, &QLineEdit::editingFinished, this,
|
||||
[this]() { m_crashUserEmailChanged = true; });
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -128,6 +128,8 @@ PuzzlePreferencesLayoutPage::PuzzlePreferencesLayoutPage(QWidget *parent)
|
|||
connect(ui->checkBoxWarningPiecesOutOfBound, &QCheckBox::stateChanged, this,
|
||||
[this]() { m_settingsChanged = true; });
|
||||
connect(ui->checkBoxFollowGrainline, &QCheckBox::stateChanged, this, [this]() { m_settingsChanged = true; });
|
||||
connect(ui->checkBoxWarningPieceGapePosition, &QCheckBox::stateChanged, this,
|
||||
[this]() { m_settingsChanged = true; });
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -166,6 +168,7 @@ auto PuzzlePreferencesLayoutPage::Apply() -> QStringList
|
|||
settings->SetLayoutStickyEdges(ui->checkBoxStickyEdges->isChecked());
|
||||
settings->SetLayoutWarningPiecesOutOfBound(ui->checkBoxWarningPiecesOutOfBound->isChecked());
|
||||
settings->SetLayoutFollowGrainline(ui->checkBoxFollowGrainline->isChecked());
|
||||
settings->SetLayoutWarningPieceGapePosition(ui->checkBoxWarningPieceGapePosition->isChecked());
|
||||
|
||||
settings->SetLayoutLineWidth(ui->spinBoxLineWidth->value());
|
||||
|
||||
|
@ -661,6 +664,7 @@ void PuzzlePreferencesLayoutPage::ReadSettings()
|
|||
ui->checkBoxStickyEdges->setChecked(settings->GetLayoutStickyEdges());
|
||||
ui->checkBoxWarningPiecesOutOfBound->setChecked(settings->GetLayoutWarningPiecesOutOfBound());
|
||||
ui->checkBoxFollowGrainline->setChecked(settings->GetLayoutFollowGrainline());
|
||||
ui->checkBoxWarningPieceGapePosition->setChecked(settings->GetLayoutWarningPieceGapePosition());
|
||||
|
||||
ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, LayoutUnit()));
|
||||
SetPieceGap(settings->GetLayoutPieceGap());
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
<item>
|
||||
<widget class="QToolButton" name="toolButtonSheetPortraitOritation">
|
||||
<property name="text">
|
||||
<string notr="true"></string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
|
||||
|
@ -107,7 +107,7 @@
|
|||
<item>
|
||||
<widget class="QToolButton" name="toolButtonSheetLandscapeOrientation">
|
||||
<property name="text">
|
||||
<string notr="true"></string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
|
||||
|
@ -309,6 +309,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxWarningPieceGapePosition">
|
||||
<property name="text">
|
||||
<string>Warning piece gape position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxStickyEdges">
|
||||
<property name="text">
|
||||
|
@ -475,7 +482,7 @@
|
|||
<item>
|
||||
<widget class="QToolButton" name="toolButtonTilePortraitOrientation">
|
||||
<property name="text">
|
||||
<string notr="true"></string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
|
||||
|
@ -495,7 +502,7 @@
|
|||
<item>
|
||||
<widget class="QToolButton" name="toolButtonTileLandscapeOrientation">
|
||||
<property name="text">
|
||||
<string notr="true"></string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
|
||||
|
|
|
@ -90,6 +90,7 @@ auto VPLayout::CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr
|
|||
|
||||
layout->LayoutSettings().SetWarningSuperpositionOfPieces(settings->GetLayoutWarningPiecesSuperposition());
|
||||
layout->LayoutSettings().SetWarningPiecesOutOfBound(settings->GetLayoutWarningPiecesOutOfBound());
|
||||
layout->LayoutSettings().SetWarningPieceGapePosition(settings->GetLayoutWarningPieceGapePosition());
|
||||
layout->LayoutSettings().SetFollowGrainline(settings->GetLayoutFollowGrainline());
|
||||
layout->LayoutSettings().SetStickyEdges(settings->GetLayoutStickyEdges());
|
||||
layout->LayoutSettings().SetPiecesGap(settings->GetLayoutPieceGap());
|
||||
|
@ -122,13 +123,14 @@ void VPLayout::AddPiece(const VPPiecePtr &piece)
|
|||
|
||||
VPPiece::CleanPosition(piece);
|
||||
|
||||
if (not m_pieces.contains(piece->GetUniqueID()))
|
||||
const QString uniqueId = piece->GetUniqueID();
|
||||
if (not m_pieces.contains(uniqueId))
|
||||
{
|
||||
m_pieces.insert(piece->GetUniqueID(), piece);
|
||||
m_pieces.insert(uniqueId, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
VPPiecePtr const oldPiece = m_pieces.value(piece->GetUniqueID());
|
||||
VPPiecePtr const oldPiece = m_pieces.value(uniqueId);
|
||||
if (not oldPiece.isNull())
|
||||
{
|
||||
oldPiece->Update(piece);
|
||||
|
@ -136,7 +138,7 @@ void VPLayout::AddPiece(const VPPiecePtr &piece)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_pieces.insert(piece->GetUniqueID(), piece);
|
||||
m_pieces.insert(uniqueId, piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -326,6 +328,8 @@ void VPLayout::SetFocusedSheet(const VPSheetPtr &focusedSheet)
|
|||
m_focusedSheet = focusedSheet.isNull() ? m_sheets.constFirst() : focusedSheet;
|
||||
}
|
||||
|
||||
CheckPiecesPositionValidity(m_focusedSheet);
|
||||
|
||||
emit ActiveSheetChanged(m_focusedSheet);
|
||||
}
|
||||
|
||||
|
@ -341,6 +345,12 @@ auto VPLayout::GetTrashSheet() -> VPSheetPtr
|
|||
return m_trashSheet;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPLayout::LayoutSettings() const -> const VPLayoutSettings &
|
||||
{
|
||||
return m_layoutSettings;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPLayout::LayoutSettings() -> VPLayoutSettings &
|
||||
{
|
||||
|
@ -417,10 +427,30 @@ void VPLayout::CheckPiecesPositionValidity() const
|
|||
{
|
||||
for (const auto &sheet : m_sheets)
|
||||
{
|
||||
if (not sheet.isNull())
|
||||
CheckPiecesPositionValidity(sheet);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPLayout::CheckPiecesPositionValidity(const VPSheetPtr &sheet) const
|
||||
{
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
const VPLayoutSettings &settings = LayoutSettings();
|
||||
|
||||
if (settings.GetWarningPiecesOutOfBound())
|
||||
{
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
}
|
||||
|
||||
if (settings.GetWarningSuperpositionOfPieces())
|
||||
{
|
||||
sheet->ValidateSuperpositionOfPieces();
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
}
|
||||
|
||||
if (settings.GetWarningPieceGapePosition())
|
||||
{
|
||||
sheet->ValidatePieceGapePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
void AddTrashSheet(const VPSheetPtr &sheet);
|
||||
auto GetTrashSheet() -> VPSheetPtr;
|
||||
|
||||
auto LayoutSettings() const -> const VPLayoutSettings &;
|
||||
auto LayoutSettings() -> VPLayoutSettings &;
|
||||
|
||||
auto PiecesForSheet(const VPSheetPtr &sheet) const -> QList<VPPiecePtr>;
|
||||
|
@ -90,6 +91,7 @@ public:
|
|||
void Clear();
|
||||
|
||||
void CheckPiecesPositionValidity() const;
|
||||
void CheckPiecesPositionValidity(const VPSheetPtr &sheet) const;
|
||||
|
||||
auto TileFactory() const -> QSharedPointer<VPTileFactory>;
|
||||
void SetTileFactory(const QSharedPointer<VPTileFactory> &newTileFactory);
|
||||
|
|
|
@ -66,6 +66,18 @@ auto VPLayoutSettings::GetWarningPiecesOutOfBound() const -> bool
|
|||
return m_warningPiecesOutOfBound;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPLayoutSettings::SetWarningPieceGapePosition(bool state)
|
||||
{
|
||||
m_warningPieceGapePosition = state;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPLayoutSettings::GetWarningPieceGapePosition() const -> bool
|
||||
{
|
||||
return m_warningPieceGapePosition;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPLayoutSettings::SetTitle(const QString &title)
|
||||
{
|
||||
|
@ -244,7 +256,7 @@ void VPLayoutSettings::SetStickyEdges(bool state)
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPLayoutSettings::GetStickyEdges() const -> bool
|
||||
auto VPLayoutSettings::IsStickyEdges() const -> bool
|
||||
{
|
||||
return m_stickyEdges;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
auto GetDescription() const -> QString;
|
||||
|
||||
void SetStickyEdges(bool state);
|
||||
auto GetStickyEdges() const -> bool;
|
||||
auto IsStickyEdges() const -> bool;
|
||||
|
||||
// Piece
|
||||
|
||||
|
@ -91,6 +91,9 @@ public:
|
|||
void SetWarningPiecesOutOfBound(bool state);
|
||||
auto GetWarningPiecesOutOfBound() const -> bool;
|
||||
|
||||
void SetWarningPieceGapePosition(bool state);
|
||||
auto GetWarningPieceGapePosition() const -> bool;
|
||||
|
||||
/**
|
||||
* @brief SetFollowGrainline Sets the type of grainline for the pieces to follow
|
||||
* @param state the type of grainline
|
||||
|
@ -330,6 +333,7 @@ private:
|
|||
|
||||
bool m_warningSuperpositionOfPieces{false};
|
||||
bool m_warningPiecesOutOfBound{false};
|
||||
bool m_warningPieceGapePosition{false};
|
||||
|
||||
QString m_title{};
|
||||
QString m_description{};
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <QLoggingCategory>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
|
||||
#include "../vmisc/compatibility.h"
|
||||
|
@ -59,7 +60,7 @@ QT_WARNING_POP
|
|||
namespace
|
||||
{
|
||||
constexpr qreal minStickyDistance = MmToPixel(3.);
|
||||
constexpr qreal maxStickyDistance = MmToPixel(10.);
|
||||
constexpr qreal maxStickyDistance = MmToPixel(15.);
|
||||
constexpr qreal stickyShift = MmToPixel(1.);
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -94,46 +95,6 @@ auto CutEdge(const QLineF &edge) -> QVector<QPointF>
|
|||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>
|
||||
{
|
||||
if (path.size() < 2)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
QVector<QPointF> stickyPath;
|
||||
|
||||
for (int i = 0; i < path.size(); ++i)
|
||||
{
|
||||
stickyPath += CutEdge(QLineF(path.at(i), path.at(i < path.size() - 1 ? i + 1 : 0)));
|
||||
}
|
||||
|
||||
return stickyPath;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
|
||||
{
|
||||
qreal distance = INT_MAX;
|
||||
QLineF closestDistance;
|
||||
|
||||
for (auto p1 : path1)
|
||||
{
|
||||
for (auto p2 : path2)
|
||||
{
|
||||
QLineF const d(p1, p2);
|
||||
if (d.length() <= distance)
|
||||
{
|
||||
distance = d.length();
|
||||
closestDistance = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closestDistance;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -262,40 +223,62 @@ void VPPiece::RotateToGrainline(const VPTransformationOrigon &origin)
|
|||
}
|
||||
|
||||
QVector<qreal> angles;
|
||||
angles.reserve(4);
|
||||
angles.reserve(8);
|
||||
|
||||
const VPieceGrainline pieceGrainline = GetGrainline();
|
||||
|
||||
if (pieceGrainline.IsArrowUpEnabled())
|
||||
{
|
||||
angles.append(grainline.angleTo(fabricGrainline));
|
||||
qreal const angle = grainline.angleTo(fabricGrainline);
|
||||
angles.append(angle);
|
||||
angles.append(-(360. - angle));
|
||||
}
|
||||
|
||||
if (pieceGrainline.IsArrowDownEnabled())
|
||||
{
|
||||
QLineF arrow = grainline;
|
||||
arrow.setAngle(arrow.angle() + 180);
|
||||
angles.append(arrow.angleTo(fabricGrainline));
|
||||
|
||||
qreal const angle = arrow.angleTo(fabricGrainline);
|
||||
angles.append(angle);
|
||||
angles.append(-(360. - angle));
|
||||
}
|
||||
|
||||
if (pieceGrainline.IsArrowLeftEnabled())
|
||||
{
|
||||
QLineF arrow = grainline;
|
||||
arrow.setAngle(arrow.angle() + 90);
|
||||
angles.append(arrow.angleTo(fabricGrainline));
|
||||
|
||||
qreal const angle = arrow.angleTo(fabricGrainline);
|
||||
angles.append(angle);
|
||||
angles.append(-(360. - angle));
|
||||
}
|
||||
|
||||
if (pieceGrainline.IsArrowRightEnabled())
|
||||
{
|
||||
QLineF arrow = grainline;
|
||||
arrow.setAngle(arrow.angle() - 90);
|
||||
angles.append(arrow.angleTo(fabricGrainline));
|
||||
|
||||
qreal const angle = arrow.angleTo(fabricGrainline);
|
||||
angles.append(angle);
|
||||
angles.append(-(360. - angle));
|
||||
}
|
||||
|
||||
qreal degrees = 0;
|
||||
if (not angles.isEmpty())
|
||||
{
|
||||
degrees = *std::min_element(angles.constBegin(), angles.constEnd());
|
||||
qreal minAbsAngle = qAbs(angles.constFirst());
|
||||
degrees = angles.constFirst();
|
||||
|
||||
for (int i = 1; i < angles.size(); ++i)
|
||||
{
|
||||
qreal const absAngle = qAbs(angles.at(i));
|
||||
if (absAngle < minAbsAngle)
|
||||
{
|
||||
minAbsAngle = absAngle;
|
||||
degrees = angles.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rotate(origin.custom ? MappedDetailBoundingRect().center() : origin.origin, degrees);
|
||||
|
@ -339,10 +322,22 @@ void VPPiece::FlipHorizontally()
|
|||
SetHorizontallyFlipped(!IsHorizontallyFlipped());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPPiece::HasInvalidPieceGapPosition() const -> bool
|
||||
{
|
||||
return m_invalidPieceGapPosition;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPPiece::SetHasInvalidPieceGapPosition(bool status)
|
||||
{
|
||||
m_invalidPieceGapPosition = status;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool
|
||||
{
|
||||
if (VPLayoutPtr const layout = Layout(); layout.isNull() || not layout->LayoutSettings().GetStickyEdges())
|
||||
if (VPLayoutPtr const layout = Layout(); layout.isNull() || not layout->LayoutSettings().IsStickyEdges())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -374,7 +369,11 @@ auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool
|
|||
return false;
|
||||
}
|
||||
|
||||
const qreal extraZone = qBound(minStickyDistance, match.m_pieceGap * 50 / 100, maxStickyDistance);
|
||||
qreal extraZone = qBound(minStickyDistance, match.m_pieceGap * 50 / 100, maxStickyDistance);
|
||||
if (qFuzzyIsNull(match.m_pieceGap))
|
||||
{
|
||||
extraZone = maxStickyDistance;
|
||||
}
|
||||
const qreal length = match.m_closestDistance.length();
|
||||
|
||||
if (length > match.m_pieceGap && length <= match.m_pieceGap + extraZone)
|
||||
|
@ -419,6 +418,58 @@ auto VPPiece::PathsSuperposition(const QVector<QPointF> &path1, const QVector<QP
|
|||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPPiece::PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>
|
||||
{
|
||||
if (path.size() < 2)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
QVector<QPointF> stickyPath;
|
||||
|
||||
for (int i = 0; i < path.size(); ++i)
|
||||
{
|
||||
stickyPath += CutEdge(QLineF(path.at(i), path.at(i < path.size() - 1 ? i + 1 : 0)));
|
||||
}
|
||||
|
||||
return stickyPath;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPPiece::ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
|
||||
{
|
||||
return QtConcurrent::blockingMappedReduced(
|
||||
path1,
|
||||
[path2](const QPointF &p1)
|
||||
{
|
||||
qreal minLocalDistance = std::numeric_limits<qreal>::max();
|
||||
QLineF localClosestDistance;
|
||||
|
||||
for (const auto &p2 : path2)
|
||||
{
|
||||
QLineF const d(p1, p2);
|
||||
qreal const length = d.length();
|
||||
if (length < minLocalDistance)
|
||||
{
|
||||
minLocalDistance = length;
|
||||
localClosestDistance = d;
|
||||
}
|
||||
}
|
||||
|
||||
return localClosestDistance;
|
||||
},
|
||||
[](QLineF &result, const QLineF &next)
|
||||
{
|
||||
qreal const dist1 = result.length();
|
||||
qreal const dist2 = next.length();
|
||||
if (result.isNull() || dist2 < dist1)
|
||||
{
|
||||
result = next;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPPiece::IsValid(QString &error) const -> bool
|
||||
{
|
||||
|
|
|
@ -110,9 +110,14 @@ public:
|
|||
auto HasSuperpositionWithPieces() const -> bool;
|
||||
void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces);
|
||||
|
||||
auto HasInvalidPieceGapPosition() const -> bool;
|
||||
void SetHasInvalidPieceGapPosition(bool status);
|
||||
|
||||
auto StickyPosition(qreal &dx, qreal &dy) const -> bool;
|
||||
|
||||
static auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool;
|
||||
static auto PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>;
|
||||
static auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF;
|
||||
static void CleanPosition(const VPPiecePtr &piece);
|
||||
|
||||
auto IsValid(QString &error) const -> bool;
|
||||
|
@ -134,6 +139,7 @@ private:
|
|||
bool m_isSelected{false};
|
||||
bool m_outOfBound{false};
|
||||
bool m_hasSuperpositionWithPieces{false};
|
||||
bool m_invalidPieceGapPosition{false};
|
||||
|
||||
quint16 m_copyNumber{1};
|
||||
|
||||
|
|
|
@ -164,6 +164,9 @@ void VPSheetSceneData::PrepareForExport()
|
|||
|
||||
m_pieceSuperpositionTmp = layout->LayoutSettings().GetWarningSuperpositionOfPieces();
|
||||
layout->LayoutSettings().SetWarningSuperpositionOfPieces(false);
|
||||
|
||||
m_pieceGapePositionTmp = layout->LayoutSettings().GetWarningPieceGapePosition();
|
||||
layout->LayoutSettings().SetWarningPieceGapePosition(false);
|
||||
}
|
||||
|
||||
RefreshLayout();
|
||||
|
@ -197,6 +200,7 @@ void VPSheetSceneData::CleanAfterExport()
|
|||
|
||||
layout->LayoutSettings().SetWarningPiecesOutOfBound(m_outOfBoundTmp);
|
||||
layout->LayoutSettings().SetWarningSuperpositionOfPieces(m_pieceSuperpositionTmp);
|
||||
layout->LayoutSettings().SetWarningPieceGapePosition(m_pieceGapePositionTmp);
|
||||
}
|
||||
|
||||
RefreshLayout();
|
||||
|
@ -511,7 +515,7 @@ void VPSheet::ValidateSuperpositionOfPieces() const
|
|||
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
if (piece.isNull())
|
||||
if (piece.isNull() || piece->OutOfBound())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -552,6 +556,77 @@ void VPSheet::ValidateSuperpositionOfPieces() const
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePieceGapePosition(const VPPiecePtr &piece) const
|
||||
{
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (layout.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
|
||||
if (pieceGap <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (piece.isNull() || piece->HasSuperpositionWithPieces() || piece->OutOfBound())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool oldInvalidPieceGapPosition = piece->HasInvalidPieceGapPosition();
|
||||
|
||||
QVector<QPointF> path1;
|
||||
CastTo(piece->GetMappedExternalContourPoints(), path1);
|
||||
path1 = VPPiece::PrepareStickyPath(path1);
|
||||
bool hasInvalidPieceGapPosition = false;
|
||||
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
|
||||
for (const auto &p : pieces)
|
||||
{
|
||||
if (p.isNull() || piece == p)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVector<QPointF> path2;
|
||||
CastTo(p->GetMappedExternalContourPoints(), path2);
|
||||
path2 = VPPiece::PrepareStickyPath(path2);
|
||||
|
||||
QLineF const distance = VPPiece::ClosestDistance(path1, path2);
|
||||
|
||||
if (distance.length() < pieceGap - accuracyPointOnLine)
|
||||
{
|
||||
hasInvalidPieceGapPosition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
piece->SetHasInvalidPieceGapPosition(hasInvalidPieceGapPosition);
|
||||
|
||||
if (oldInvalidPieceGapPosition != piece->HasInvalidPieceGapPosition())
|
||||
{
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
emit layout->PiecePositionValidityChanged(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePieceGapePosition() const
|
||||
{
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
ValidatePieceGapePosition(piece);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
|
||||
{
|
||||
|
@ -699,6 +774,11 @@ void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const
|
|||
{
|
||||
ValidateSuperpositionOfPieces();
|
||||
}
|
||||
|
||||
if (layout->LayoutSettings().GetWarningPieceGapePosition())
|
||||
{
|
||||
ValidatePieceGapePosition(piece);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -128,6 +128,7 @@ private:
|
|||
|
||||
bool m_outOfBoundTmp{false};
|
||||
bool m_pieceSuperpositionTmp{false};
|
||||
bool m_pieceGapePositionTmp{false};
|
||||
|
||||
void ConnectPiece(VPGraphicsPiece *piece) const;
|
||||
};
|
||||
|
@ -183,6 +184,8 @@ public:
|
|||
void SetTrashSheet(bool newTrashSheet);
|
||||
|
||||
void ValidateSuperpositionOfPieces() const;
|
||||
void ValidatePieceGapePosition(const VPPiecePtr &piece) const;
|
||||
void ValidatePieceGapePosition() const;
|
||||
void ValidatePieceOutOfBound(const VPPiecePtr &piece) const;
|
||||
void ValidatePiecesOutOfBound() const;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import qbs.Utilities
|
|||
VToolApp {
|
||||
Depends { name: "buildconfig" }
|
||||
Depends { name: "ib"; condition: qbs.targetOS.contains("macos") }
|
||||
Depends { name: "Qt"; submodules: ["core", "widgets", "svg"] }
|
||||
Depends { name: "Qt"; submodules: ["core", "widgets", "svg", "concurrent"] }
|
||||
Depends { name: "VMiscLib" }
|
||||
Depends { name: "VLayoutLib" }
|
||||
Depends { name: "IFCLib" }
|
||||
|
|
|
@ -72,46 +72,6 @@ QT_WARNING_POP
|
|||
|
||||
namespace
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
|
||||
int maxLineWidth) -> QTransform
|
||||
{
|
||||
if (piece.isNull())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(topLeft.x(), topLeft.y());
|
||||
|
||||
if ((piece->IsVerticallyFlipped() && piece->IsHorizontallyFlipped()) ||
|
||||
(!piece->IsVerticallyFlipped() && !piece->IsHorizontallyFlipped()))
|
||||
{
|
||||
labelMatrix.rotate(angle);
|
||||
}
|
||||
else if (piece->IsVerticallyFlipped() || piece->IsHorizontallyFlipped())
|
||||
{
|
||||
if (piece->IsVerticallyFlipped() && !piece->IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
|
||||
if (piece->IsHorizontallyFlipped() && !piece->IsVerticallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
|
||||
labelMatrix *= piece->GetMatrix();
|
||||
|
||||
return labelMatrix;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto LineFont(const TextLine &tl, const QFont &base) -> QFont
|
||||
{
|
||||
|
@ -297,7 +257,7 @@ void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
{
|
||||
if (VPLayoutPtr const layout = piece->Layout(); not layout.isNull())
|
||||
{
|
||||
if (layout->LayoutSettings().GetStickyEdges() && m_hasStickyPosition)
|
||||
if (layout->LayoutSettings().IsStickyEdges() && m_hasStickyPosition)
|
||||
{
|
||||
auto *command =
|
||||
new VPUndoPieceMove(piece, m_stickyTranslateX, m_stickyTranslateY, m_allowChangeMerge);
|
||||
|
@ -448,7 +408,6 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
|
|||
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
|
||||
const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle();
|
||||
const QColor color = PieceColor();
|
||||
const int maxLineWidth = tm.MaxLineWidthSVGFont(static_cast<int>(dW), penWidth);
|
||||
|
||||
qreal dY = penWidth;
|
||||
|
||||
|
@ -467,7 +426,7 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
|
|||
const QString qsText = tl.m_qsText;
|
||||
const qreal dX = LineAlign(tl, qsText, engine, dW, penWidth);
|
||||
// set up the rotation around top-left corner matrix
|
||||
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
|
||||
const QTransform lineMatrix = piece->LineMatrix(labelShape.at(0), angle, QPointF(dX, dY), dW);
|
||||
|
||||
auto *item = new QGraphicsPathItem(this);
|
||||
item->setPath(engine.DrawPath(QPointF(), qsText));
|
||||
|
@ -505,7 +464,6 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
|
|||
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
|
||||
const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle();
|
||||
const QColor color = PieceColor();
|
||||
const int maxLineWidth = tm.MaxLineWidthOutlineFont(static_cast<int>(dW));
|
||||
qreal const penWidth = VPApplication::VApp()->PuzzleSettings()->GetLayoutLineWidth();
|
||||
|
||||
qreal dY = 0;
|
||||
|
@ -533,7 +491,7 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
|
|||
|
||||
const qreal dX = LineAlign(tl, tl.m_qsText, fm, dW);
|
||||
// set up the rotation around top-left corner matrix
|
||||
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
|
||||
const QTransform lineMatrix = piece->LineMatrix(labelShape.at(0), angle, QPointF(dX, dY), dW);
|
||||
|
||||
if (textAsPaths)
|
||||
{
|
||||
|
@ -1013,6 +971,8 @@ void VPGraphicsPiece::PaintFoldLine(QPainter *painter, const VPPiecePtr &piece)
|
|||
}
|
||||
|
||||
fLine.UpdateFoldLineLabel(m_foldLineLabelText);
|
||||
|
||||
m_foldLineLabelText->setBrush(QBrush(PieceColor()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1058,6 +1018,9 @@ void VPGraphicsPiece::PaintFoldLine(QPainter *painter, const VPPiecePtr &piece)
|
|||
painter->save();
|
||||
QPen pen = painter->pen();
|
||||
pen.setWidthF(penWidth * qMin(piece->GetXScale(), piece->GetYScale()));
|
||||
pen.setColor(PieceColor());
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
pen.setJoinStyle(Qt::RoundJoin);
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(singleLineFont ? Qt::NoBrush : Qt::SolidPattern);
|
||||
painter->drawPath(m_foldLineLabelPath);
|
||||
|
@ -1106,7 +1069,7 @@ void VPGraphicsPiece::GroupMove(const QPointF &pos)
|
|||
auto *command = new VPUndoPieceMove(piece, newPos.x(), newPos.y(), m_allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
|
||||
if (layout->LayoutSettings().GetStickyEdges())
|
||||
if (layout->LayoutSettings().IsStickyEdges())
|
||||
{
|
||||
QVector<QPointF> path;
|
||||
if (not p.isNull() && p->StickyPosition(m_stickyTranslateX, m_stickyTranslateY))
|
||||
|
@ -1159,7 +1122,13 @@ auto VPGraphicsPiece::PieceColor() const -> QColor
|
|||
superposition = piece->HasSuperpositionWithPieces();
|
||||
}
|
||||
|
||||
if (outOfBound || superposition)
|
||||
bool pieceGape = false;
|
||||
if (layout->LayoutSettings().GetWarningPieceGapePosition())
|
||||
{
|
||||
pieceGape = piece->HasInvalidPieceGapPosition();
|
||||
}
|
||||
|
||||
if (outOfBound || superposition || pieceGape)
|
||||
{
|
||||
return VSceneStylesheet::ManualLayoutStyle().PieceErrorColor();
|
||||
}
|
||||
|
|
|
@ -109,6 +109,11 @@ void VPGraphicsTransformationOrigin::on_HideHandles(bool hide)
|
|||
void VPGraphicsTransformationOrigin::on_ShowOrigin(bool show)
|
||||
{
|
||||
setVisible(show);
|
||||
|
||||
if (not show)
|
||||
{
|
||||
m_hoverMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -404,7 +409,6 @@ void VPGraphicsPieceControls::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
|
||||
{
|
||||
m_rotationStartPoint = event->scenePos();
|
||||
m_rotationSum = 0;
|
||||
m_controlsVisible = false;
|
||||
m_handleCorner = SelectedHandleCorner(event->pos());
|
||||
m_ignorePieceTransformation = true;
|
||||
|
@ -433,7 +437,7 @@ void VPGraphicsPieceControls::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
PrepareTransformationOrigin(event->modifiers() & Qt::ShiftModifier);
|
||||
PrepareTransformationOrigin(event->modifiers() & Qt::ShiftModifier); // NOLINT(readability-implicit-bool-conversion)
|
||||
|
||||
QPointF const rotationNewPoint = event->scenePos();
|
||||
|
||||
|
@ -451,24 +455,18 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
||||
if (not qFuzzyIsNull(rotateOn))
|
||||
{
|
||||
QList<VPPiecePtr> const pieces = SelectedPieces();
|
||||
|
||||
VPLayoutPtr const layout = m_layout.toStrongRef();
|
||||
if (not layout.isNull())
|
||||
if (VPLayoutPtr const layout = m_layout.toStrongRef(); not layout.isNull())
|
||||
{
|
||||
CorrectRotationSum(layout, rotationOrigin, rotateOn);
|
||||
QList<VPPiecePtr> const pieces = SelectedPieces();
|
||||
|
||||
if (pieces.size() == 1)
|
||||
{
|
||||
auto *command = new VPUndoPieceRotate(pieces.constFirst(), rotationOrigin, rotateOn, m_rotationSum,
|
||||
allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
layout->UndoStack()->push(
|
||||
new VPUndoPieceRotate(pieces.constFirst(), rotationOrigin, rotateOn, allowChangeMerge));
|
||||
}
|
||||
else if (pieces.size() > 1)
|
||||
{
|
||||
auto *command =
|
||||
new VPUndoPiecesRotate(pieces, rotationOrigin, rotateOn, m_rotationSum, allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
layout->UndoStack()->push(new VPUndoPiecesRotate(pieces, rotationOrigin, rotateOn, allowChangeMerge));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -490,6 +488,19 @@ void VPGraphicsPieceControls::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
VPLayoutPtr const layout = m_layout.toStrongRef();
|
||||
|
||||
if (not layout.isNull() && layout->LayoutSettings().GetFollowGrainline())
|
||||
{
|
||||
VPTransformationOrigon const rotationOrigin = TransformationOrigin(m_layout, m_pieceRect);
|
||||
QList<VPPiecePtr> const pieces = SelectedPieces();
|
||||
for (const auto &piece : qAsConst(pieces))
|
||||
{
|
||||
piece->RotateToGrainline(rotationOrigin);
|
||||
emit layout->PieceTransformationChanged(piece);
|
||||
}
|
||||
}
|
||||
|
||||
m_controlsVisible = true;
|
||||
m_ignorePieceTransformation = false;
|
||||
|
||||
|
@ -505,22 +516,19 @@ void VPGraphicsPieceControls::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
if (m_originSaved)
|
||||
if (m_originSaved && not layout.isNull())
|
||||
{
|
||||
if (VPLayoutPtr const layout = m_layout.toStrongRef(); not layout.isNull())
|
||||
if (VPSheetPtr const sheet = layout->GetFocusedSheet(); not sheet.isNull())
|
||||
{
|
||||
if (VPSheetPtr const sheet = layout->GetFocusedSheet(); not sheet.isNull())
|
||||
if (not m_savedOrigin.custom)
|
||||
{
|
||||
if (not m_savedOrigin.custom)
|
||||
{
|
||||
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
|
||||
m_savedOrigin.origin = m_pieceRect.center();
|
||||
}
|
||||
sheet->SetTransformationOrigin(m_savedOrigin);
|
||||
emit TransformationOriginChanged();
|
||||
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
|
||||
m_savedOrigin.origin = m_pieceRect.center();
|
||||
}
|
||||
m_originSaved = false;
|
||||
sheet->SetTransformationOrigin(m_savedOrigin);
|
||||
emit TransformationOriginChanged();
|
||||
}
|
||||
m_originSaved = false;
|
||||
}
|
||||
|
||||
on_UpdateControls();
|
||||
|
@ -853,32 +861,6 @@ void VPGraphicsPieceControls::PrepareTransformationOrigin(bool shiftPressed)
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPGraphicsPieceControls::CorrectRotationSum(const VPLayoutPtr &layout,
|
||||
const VPTransformationOrigon &rotationOrigin, qreal rotateOn)
|
||||
{
|
||||
if (layout.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (layout->LayoutSettings().GetFollowGrainline() && not rotationOrigin.custom)
|
||||
{
|
||||
if (m_rotationSum > 90 || m_rotationSum < -90)
|
||||
{
|
||||
m_rotationSum = rotateOn;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum += rotateOn;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum = rotateOn;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPGraphicsPieceControls::SelectedHandleCorner(const QPointF &pos) const -> VPHandleCorner
|
||||
{
|
||||
|
|
|
@ -143,7 +143,6 @@ private:
|
|||
|
||||
QRectF m_pieceRect{};
|
||||
QPointF m_rotationStartPoint{};
|
||||
qreal m_rotationSum{0};
|
||||
bool m_controlsVisible{false};
|
||||
VPLayoutWeakPtr m_layout{};
|
||||
VPHandleCorner m_handleCorner{VPHandleCorner::Invalid};
|
||||
|
@ -185,7 +184,6 @@ private:
|
|||
void UpdateCursor(VPHandleCorner corner);
|
||||
|
||||
void PrepareTransformationOrigin(bool shiftPressed);
|
||||
void CorrectRotationSum(const VPLayoutPtr &layout, const VPTransformationOrigon &rotationOrigin, qreal rotateOn);
|
||||
};
|
||||
|
||||
#endif // VPGRAPHICSPIECECONTROLS_H
|
||||
|
|
|
@ -320,8 +320,6 @@ void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event)
|
|||
sheet->SceneData()->RotationControls()->on_UpdateControls();
|
||||
sheet->SceneData()->RotationControls()->on_HideHandles(false);
|
||||
}
|
||||
|
||||
m_rotationSum = 0;
|
||||
}
|
||||
}
|
||||
VMainGraphicsView::keyReleaseEvent(event);
|
||||
|
@ -439,31 +437,34 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle)
|
|||
return pieces;
|
||||
};
|
||||
|
||||
if (layout->LayoutSettings().GetFollowGrainline() && not origin.custom)
|
||||
{
|
||||
if (m_rotationSum > 90 || m_rotationSum < -90)
|
||||
{
|
||||
m_rotationSum = angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum += angle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum = angle;
|
||||
}
|
||||
QList<VPPiecePtr> const pieces = PreparePieces();
|
||||
|
||||
if (QList<VPPiecePtr> const pieces = PreparePieces(); pieces.size() == 1)
|
||||
if (pieces.size() == 1)
|
||||
{
|
||||
auto *command = new VPUndoPieceRotate(pieces.constFirst(), origin, angle, m_rotationSum, m_allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
layout->UndoStack()->push(new VPUndoPieceRotate(pieces.constFirst(), origin, angle, m_allowChangeMerge));
|
||||
}
|
||||
else if (pieces.size() > 1)
|
||||
{
|
||||
auto *command = new VPUndoPiecesRotate(pieces, origin, angle, m_rotationSum, m_allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
layout->UndoStack()->push(new VPUndoPiecesRotate(pieces, origin, angle, m_allowChangeMerge));
|
||||
}
|
||||
|
||||
QTime const dieTime = QTime::currentTime().addMSecs(150);
|
||||
while (QTime::currentTime() < dieTime)
|
||||
{
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
|
||||
}
|
||||
|
||||
for (const auto &piece : qAsConst(pieces))
|
||||
{
|
||||
if (not piece.isNull())
|
||||
{
|
||||
if (layout->LayoutSettings().GetFollowGrainline() || piece->IsFollowGrainline())
|
||||
{
|
||||
piece->RotateToGrainline(origin);
|
||||
}
|
||||
|
||||
emit layout->PieceTransformationChanged(piece);
|
||||
}
|
||||
}
|
||||
|
||||
m_allowChangeMerge = true;
|
||||
|
@ -516,7 +517,7 @@ void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy)
|
|||
auto *command = new VPUndoPieceMove(p, dx, dy, m_allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
|
||||
if (layout->LayoutSettings().GetStickyEdges())
|
||||
if (layout->LayoutSettings().IsStickyEdges())
|
||||
{
|
||||
QVector<QPointF> path;
|
||||
if (not p.isNull() && p->StickyPosition(m_stickyTranslateX, m_stickyTranslateY))
|
||||
|
@ -677,7 +678,7 @@ void VPMainGraphicsView::MovePiece(QKeyEvent *event)
|
|||
if (const QList<VPGraphicsPiece *> &graphicsPieces = sheet->SceneData()->GraphicsPieces();
|
||||
m_hasStickyPosition && not graphicsPieces.isEmpty())
|
||||
{
|
||||
if (layout->LayoutSettings().GetStickyEdges())
|
||||
if (layout->LayoutSettings().IsStickyEdges())
|
||||
{
|
||||
auto PreparePieces = [layout]()
|
||||
{
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
#ifndef VPMAINGRAPHICSVIEW_H
|
||||
#define VPMAINGRAPHICSVIEW_H
|
||||
|
||||
#include "../vwidgets/vmaingraphicsview.h"
|
||||
#include "../layout/layoutdef.h"
|
||||
#include "../vwidgets/vmaingraphicsview.h"
|
||||
|
||||
class VMainGraphicsScene;
|
||||
class VPGraphicsPieceControls;
|
||||
|
@ -45,6 +45,7 @@ class VPPiece;
|
|||
class VPMainGraphicsView : public VMainGraphicsView
|
||||
{
|
||||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
VPMainGraphicsView(const VPLayoutPtr &layout, QWidget *parent);
|
||||
~VPMainGraphicsView() override = default;
|
||||
|
@ -98,8 +99,6 @@ private:
|
|||
|
||||
bool m_allowChangeMerge{false};
|
||||
|
||||
qreal m_rotationSum{0};
|
||||
|
||||
bool m_hasStickyPosition{false};
|
||||
qreal m_stickyTranslateX{0};
|
||||
qreal m_stickyTranslateY{0};
|
||||
|
|
|
@ -41,12 +41,11 @@ auto RoundAngle(qreal angle) -> qreal
|
|||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPUndoPieceRotate::VPUndoPieceRotate(const VPPiecePtr &piece, const VPTransformationOrigon &origin, qreal angle,
|
||||
qreal angleSum, bool allowMerge, QUndoCommand *parent)
|
||||
bool allowMerge, QUndoCommand *parent)
|
||||
: VPUndoCommand(allowMerge, parent),
|
||||
m_piece(piece),
|
||||
m_origin(origin),
|
||||
m_angle(angle),
|
||||
m_angleSum(angleSum)
|
||||
m_angle(angle)
|
||||
{
|
||||
SCASSERT(not piece.isNull())
|
||||
|
||||
|
@ -81,6 +80,10 @@ void VPUndoPieceRotate::undo()
|
|||
}
|
||||
|
||||
piece->SetMatrix(m_oldTransform);
|
||||
if (m_followGrainline || piece->IsFollowGrainline())
|
||||
{
|
||||
piece->RotateToGrainline(m_origin);
|
||||
}
|
||||
emit layout->PieceTransformationChanged(piece);
|
||||
}
|
||||
|
||||
|
@ -104,23 +107,9 @@ void VPUndoPieceRotate::redo()
|
|||
layout->SetFocusedSheet(piece->Sheet());
|
||||
}
|
||||
|
||||
if (m_firstCall)
|
||||
{
|
||||
if ((m_followGrainline || piece->IsFollowGrainline()) && piece->IsGrainlineEnabled())
|
||||
{
|
||||
piece->Rotate(m_origin.origin, m_angleSum);
|
||||
}
|
||||
else
|
||||
{
|
||||
piece->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
piece->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
piece->Rotate(m_origin.origin, m_angle);
|
||||
|
||||
if (m_followGrainline || piece->IsFollowGrainline())
|
||||
if (!m_firstCall && (m_followGrainline || piece->IsFollowGrainline()))
|
||||
{
|
||||
piece->RotateToGrainline(m_origin);
|
||||
}
|
||||
|
@ -168,11 +157,10 @@ auto VPUndoPieceRotate::id() const -> int
|
|||
// rotate pieces
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPUndoPiecesRotate::VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const VPTransformationOrigon &origin,
|
||||
qreal angle, qreal angleSum, bool allowMerge, QUndoCommand *parent)
|
||||
qreal angle, bool allowMerge, QUndoCommand *parent)
|
||||
: VPUndoCommand(allowMerge, parent),
|
||||
m_origin(origin),
|
||||
m_angle(angle),
|
||||
m_angleSum(angleSum)
|
||||
m_angle(angle)
|
||||
{
|
||||
setText(QObject::tr("rotate pieces"));
|
||||
|
||||
|
@ -219,6 +207,10 @@ void VPUndoPiecesRotate::undo()
|
|||
if (m_oldTransforms.contains(p->GetUniqueID()))
|
||||
{
|
||||
p->SetMatrix(m_oldTransforms.value(p->GetUniqueID()));
|
||||
if (m_followGrainline || p->IsFollowGrainline())
|
||||
{
|
||||
p->RotateToGrainline(m_origin);
|
||||
}
|
||||
emit layout->PieceTransformationChanged(p);
|
||||
}
|
||||
}
|
||||
|
@ -249,23 +241,9 @@ void VPUndoPiecesRotate::redo()
|
|||
VPPiecePtr const p = piece.toStrongRef();
|
||||
if (not p.isNull())
|
||||
{
|
||||
if (m_firstCall)
|
||||
{
|
||||
if ((m_followGrainline || p->IsFollowGrainline()) && p->IsGrainlineEnabled())
|
||||
{
|
||||
p->Rotate(m_origin.origin, m_angleSum);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
p->Rotate(m_origin.origin, m_angle);
|
||||
|
||||
if (m_followGrainline || p->IsFollowGrainline())
|
||||
if (!m_firstCall && (m_followGrainline || p->IsFollowGrainline()))
|
||||
{
|
||||
p->RotateToGrainline(m_origin);
|
||||
}
|
||||
|
|
|
@ -37,11 +37,12 @@
|
|||
class VPUndoPieceRotate : public VPUndoCommand
|
||||
{
|
||||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
VPUndoPieceRotate(const VPPiecePtr &piece, const VPTransformationOrigon &origin, qreal angle, qreal angleSum,
|
||||
VPUndoPieceRotate(const VPPiecePtr &piece, const VPTransformationOrigon &origin, qreal angle,
|
||||
bool allowMerge = false, QUndoCommand *parent = nullptr);
|
||||
|
||||
~VPUndoPieceRotate() override =default;
|
||||
~VPUndoPieceRotate() override = default;
|
||||
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
@ -58,13 +59,12 @@ public:
|
|||
private:
|
||||
Q_DISABLE_COPY_MOVE(VPUndoPieceRotate) // NOLINT
|
||||
|
||||
bool m_firstCall{true};
|
||||
bool m_firstCall{true};
|
||||
VPPieceWeakPtr m_piece;
|
||||
QTransform m_oldTransform{};
|
||||
QTransform m_oldTransform{};
|
||||
VPTransformationOrigon m_origin;
|
||||
qreal m_angle;
|
||||
qreal m_angleSum;
|
||||
bool m_followGrainline{false};
|
||||
qreal m_angle;
|
||||
bool m_followGrainline{false};
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -95,10 +95,11 @@ inline auto VPUndoPieceRotate::FollowGrainline() const -> bool
|
|||
class VPUndoPiecesRotate : public VPUndoCommand
|
||||
{
|
||||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
explicit VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const VPTransformationOrigon &origin, qreal angle,
|
||||
qreal angleSum, bool allowMerge = false, QUndoCommand *parent = nullptr);
|
||||
~VPUndoPiecesRotate() override =default;
|
||||
bool allowMerge = false, QUndoCommand *parent = nullptr);
|
||||
~VPUndoPiecesRotate() override = default;
|
||||
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
@ -114,13 +115,12 @@ public:
|
|||
private:
|
||||
Q_DISABLE_COPY_MOVE(VPUndoPiecesRotate) // NOLINT
|
||||
|
||||
bool m_firstCall{true};
|
||||
QVector<VPPieceWeakPtr> m_pieces{};
|
||||
bool m_firstCall{true};
|
||||
QVector<VPPieceWeakPtr> m_pieces{};
|
||||
QMap<QString, QTransform> m_oldTransforms{};
|
||||
VPTransformationOrigon m_origin;
|
||||
qreal m_angle;
|
||||
qreal m_angleSum;
|
||||
bool m_followGrainline{false};
|
||||
VPTransformationOrigon m_origin;
|
||||
qreal m_angle;
|
||||
bool m_followGrainline{false};
|
||||
|
||||
auto Layout() const -> VPLayoutPtr;
|
||||
auto Sheet() const -> VPSheetPtr;
|
||||
|
|
|
@ -160,40 +160,41 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
|||
|
||||
{
|
||||
QString debugdate = "["_L1 + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
|
||||
QString const file = VAbstractApplication::ReduceLogContextFilePath(context.file);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
debugdate += QStringLiteral(":DEBUG:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, msg);
|
||||
vStdOut() << QApplication::translate("mNoisyHandler", "DEBUG:") << msg << "\n";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
debugdate += QStringLiteral(":WARNING:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, msg);
|
||||
vStdErr() << QApplication::translate("mNoisyHandler", "WARNING:") << msg << "\n";
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
debugdate += QStringLiteral(":CRITICAL:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, msg);
|
||||
vStdErr() << QApplication::translate("mNoisyHandler", "CRITICAL:") << msg << "\n";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
debugdate += QStringLiteral(":FATAL:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, msg);
|
||||
vStdErr() << QApplication::translate("mNoisyHandler", "FATAL:") << msg << "\n";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
debugdate += QStringLiteral(":INFO:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, msg);
|
||||
vStdOut() << QApplication::translate("mNoisyHandler", "INFO:") << msg << "\n";
|
||||
|
@ -491,6 +492,13 @@ auto VPApplication::TrVars() -> const VTranslateVars *
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPApplication::OpenSettings()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
QString const docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (!docPath.isEmpty())
|
||||
{
|
||||
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, docPath);
|
||||
}
|
||||
#endif
|
||||
settings = new VPSettings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(),
|
||||
QCoreApplication::applicationName(), this);
|
||||
connect(settings, &VPSettings::SVGFontsPathChanged, this, &VPApplication::SVGFontsPathChanged);
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <QtMath>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include "../ifc/exception/vexception.h"
|
||||
#include "../ifc/xml/vlayoutconverter.h"
|
||||
|
@ -323,10 +324,10 @@ struct VPExportData
|
|||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent)
|
||||
VPMainWindow::VPMainWindow(VPCommandLinePtr cmd, QWidget *parent)
|
||||
: VAbstractMainWindow(parent),
|
||||
ui(std::make_unique<Ui::VPMainWindow>()),
|
||||
m_cmd(cmd),
|
||||
m_cmd(std::move(cmd)),
|
||||
m_undoStack(new QUndoStack(this)),
|
||||
m_layout{VPLayout::CreateLayout(m_undoStack)},
|
||||
m_statusLabel(new QLabel(this)),
|
||||
|
@ -686,7 +687,14 @@ void VPMainWindow::SetupMenu()
|
|||
const QString filePath = senderAction->data().toString();
|
||||
if (not filePath.isEmpty())
|
||||
{
|
||||
LoadFile(filePath);
|
||||
if (curFile.isEmpty() && !this->isWindowModified())
|
||||
{
|
||||
VPApplication::VApp()->MainWindow()->LoadFile(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
VPApplication::VApp()->NewMainWindow()->LoadFile(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -769,101 +777,111 @@ void VPMainWindow::InitProperties()
|
|||
InitPropertyTabLayout();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::CurrentPieceShowSeamLineToggled(bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
selectedPiece->SetHideMainPath(not checked);
|
||||
LayoutWasSaved(false);
|
||||
// nothing changed, but will force redraw
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::ShowFullPieceToggled(bool checked)
|
||||
{
|
||||
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsShowFullPiece() != checked)
|
||||
{
|
||||
selectedPiece->SetShowFullPiece(checked);
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::ShowMirrorLineToggled(bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsShowMirrorLine() != checked)
|
||||
{
|
||||
selectedPiece->SetShowMirrorLine(checked);
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::CurrentPieceVerticallyFlippedToggled(bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsVerticallyFlipped() != checked)
|
||||
{
|
||||
selectedPiece->FlipVertically();
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::CurrentPieceHorizontallyFlippedToggled(bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsHorizontallyFlipped() != checked)
|
||||
{
|
||||
selectedPiece->FlipHorizontally();
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::InitPropertyTabCurrentPiece()
|
||||
{
|
||||
connect(ui->checkBoxCurrentPieceShowSeamline, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
selectedPiece->SetHideMainPath(not checked);
|
||||
LayoutWasSaved(false);
|
||||
// nothing changed, but will force redraw
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->checkBoxShowFullPiece, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsShowFullPiece() != checked)
|
||||
{
|
||||
selectedPiece->SetShowFullPiece(checked);
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->checkBoxShowMirrorLine, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsShowMirrorLine() != checked)
|
||||
{
|
||||
selectedPiece->SetShowMirrorLine(checked);
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
&VPMainWindow::CurrentPieceShowSeamLineToggled);
|
||||
connect(ui->checkBoxShowFullPiece, &QCheckBox::toggled, this, &VPMainWindow::ShowFullPieceToggled);
|
||||
connect(ui->checkBoxShowMirrorLine, &QCheckBox::toggled, this, &VPMainWindow::ShowMirrorLineToggled);
|
||||
connect(ui->checkBoxCurrentPieceVerticallyFlipped, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsVerticallyFlipped() != checked)
|
||||
{
|
||||
selectedPiece->FlipVertically();
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
&VPMainWindow::CurrentPieceVerticallyFlippedToggled);
|
||||
connect(ui->checkBoxCurrentPieceHorizontallyFlipped, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
|
||||
if (selectedPieces.size() == 1)
|
||||
{
|
||||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
if (not selectedPiece.isNull())
|
||||
{
|
||||
if (selectedPiece->IsHorizontallyFlipped() != checked)
|
||||
{
|
||||
selectedPiece->FlipHorizontally();
|
||||
LayoutWasSaved(false);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
&VPMainWindow::CurrentPieceHorizontallyFlippedToggled);
|
||||
|
||||
// Translate
|
||||
ui->comboBoxTranslateUnit->addItem(tr("Millimiters"), QVariant(UnitsToStr(Unit::Mm)));
|
||||
|
@ -1101,8 +1119,7 @@ void VPMainWindow::InitMarginsData(const QString &suffix)
|
|||
LayoutWasSaved(false);
|
||||
m_layout->TileFactory()->RefreshTileInfos();
|
||||
m_graphicsView->RefreshLayout();
|
||||
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
m_layout->CheckPiecesPositionValidity(sheet);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1239,6 +1256,8 @@ void VPMainWindow::InitPropertyTabLayout()
|
|||
|
||||
connect(ui->checkBoxLayoutWarningPiecesSuperposition, &QCheckBox::toggled, this,
|
||||
&VPMainWindow::LayoutWarningPiecesSuperposition_toggled);
|
||||
connect(ui->checkBoxLayoutWarningPieceGapePosition, &QCheckBox::toggled, this,
|
||||
&VPMainWindow::LayoutWarningPieceGapePosition_toggled);
|
||||
connect(ui->checkBoxLayoutWarningPiecesOutOfBound, &QCheckBox::toggled, this,
|
||||
&VPMainWindow::LayoutWarningPiecesOutOfBound_toggled);
|
||||
connect(ui->checkBoxCutOnFold, &QCheckBox::toggled, this, &VPMainWindow::LayoutCutOnFold_toggled);
|
||||
|
@ -1246,6 +1265,8 @@ void VPMainWindow::InitPropertyTabLayout()
|
|||
connect(ui->checkBoxSheetStickyEdges, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
ui->doubleSpinBoxSheetPiecesGap->setEnabled(checked);
|
||||
|
||||
if (not m_layout.isNull())
|
||||
{
|
||||
m_layout->LayoutSettings().SetStickyEdges(checked);
|
||||
|
@ -1256,6 +1277,9 @@ void VPMainWindow::InitPropertyTabLayout()
|
|||
connect(ui->checkBoxFollowGainline, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
ui->toolButtonGrainlineHorizontalOrientation->setEnabled(ui->checkBoxFollowGainline->isChecked());
|
||||
ui->toolButtonGrainlineVerticalOrientation->setEnabled(ui->checkBoxFollowGainline->isChecked());
|
||||
|
||||
if (not m_layout.isNull())
|
||||
{
|
||||
m_layout->LayoutSettings().SetFollowGrainline(checked);
|
||||
|
@ -1347,6 +1371,7 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
|
|||
SetLineEditValue(ui->lineEditCurrentPieceName, selectedPiece->GetName());
|
||||
SetPlainTextEditValue(ui->plainTextEditCurrentPieceUUID, selectedPiece->GetUUID().toString());
|
||||
SetLineEditValue(ui->lineEditCurrentPieceGradationId, selectedPiece->GetGradationId());
|
||||
SetLineEditValue(ui->lineEditCopyNumber, QString::number(selectedPiece->CopyNumber()));
|
||||
|
||||
SetCheckBoxValue(ui->checkBoxCurrentPieceShowSeamline, not selectedPiece->IsHideMainPath());
|
||||
SetCheckBoxValue(ui->checkBoxCurrentPieceVerticallyFlipped, selectedPiece->IsVerticallyFlipped());
|
||||
|
@ -1454,7 +1479,9 @@ void VPMainWindow::SetPropertyTabSheetData()
|
|||
|
||||
GrainlineType const type = sheet->GetGrainlineType();
|
||||
ui->toolButtonGrainlineHorizontalOrientation->setChecked(type == GrainlineType::Horizontal);
|
||||
ui->toolButtonGrainlineHorizontalOrientation->setEnabled(ui->checkBoxFollowGainline->isChecked());
|
||||
ui->toolButtonGrainlineVerticalOrientation->setChecked(type == GrainlineType::Vertical);
|
||||
ui->toolButtonGrainlineVerticalOrientation->setEnabled(ui->checkBoxFollowGainline->isChecked());
|
||||
|
||||
// set placement grid
|
||||
ui->groupBoxSheetGrid->setDisabled(false);
|
||||
|
@ -1593,7 +1620,9 @@ void VPMainWindow::SetPropertyTabLayoutData()
|
|||
m_layout->LayoutSettings().GetWarningPiecesOutOfBound());
|
||||
SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition,
|
||||
m_layout->LayoutSettings().GetWarningSuperpositionOfPieces());
|
||||
SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().GetStickyEdges());
|
||||
SetCheckBoxValue(ui->checkBoxLayoutWarningPieceGapePosition,
|
||||
m_layout->LayoutSettings().GetWarningPieceGapePosition());
|
||||
SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().IsStickyEdges());
|
||||
SetCheckBoxValue(ui->checkBoxFollowGainline, m_layout->LayoutSettings().GetFollowGrainline());
|
||||
SetCheckBoxValue(ui->checkBoxTogetherWithNotches, m_layout->LayoutSettings().IsBoundaryTogetherWithNotches());
|
||||
SetCheckBoxValue(ui->checkBoxCutOnFold, m_layout->LayoutSettings().IsCutOnFold());
|
||||
|
@ -1602,6 +1631,7 @@ void VPMainWindow::SetPropertyTabLayoutData()
|
|||
SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, m_layout->LayoutSettings().GetPiecesGapConverted());
|
||||
|
||||
ui->doubleSpinBoxSheetPiecesGap->setSuffix(" " + UnitsToStr(LayoutUnit(), true));
|
||||
ui->doubleSpinBoxSheetPiecesGap->setEnabled(ui->checkBoxSheetStickyEdges->isChecked());
|
||||
|
||||
ui->groupBoxLayoutScale->setDisabled(false);
|
||||
|
||||
|
@ -2108,11 +2138,9 @@ void VPMainWindow::SheetPaperSizeChanged()
|
|||
{
|
||||
RotatePiecesToGrainline();
|
||||
}
|
||||
|
||||
VPSheetPtr const sheet = m_layout->GetFocusedSheet();
|
||||
if (not sheet.isNull())
|
||||
else
|
||||
{
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2166,6 +2194,7 @@ void VPMainWindow::FindTemplate(QComboBox *box, qreal width, qreal height)
|
|||
const QSizeF tmplSize =
|
||||
VAbstractLayoutDialog::GetTemplateSize(static_cast<VAbstractLayoutDialog::PaperSizeTemplate>(i), paperUnit);
|
||||
if (VAbstractLayoutDialog::RoundTemplateSize(width, height, paperUnit) == tmplSize ||
|
||||
// NOLINTNEXTLINE(readability-suspicious-call-argument)
|
||||
VAbstractLayoutDialog::RoundTemplateSize(height, width, paperUnit) == tmplSize)
|
||||
{
|
||||
box->blockSignals(true);
|
||||
|
@ -2915,7 +2944,8 @@ auto VPMainWindow::DrawTilesScheme(QPrinter *printer, QPainter *painter, const V
|
|||
auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool
|
||||
{
|
||||
if (not m_layout->LayoutSettings().GetWarningPiecesOutOfBound() &&
|
||||
not m_layout->LayoutSettings().GetWarningSuperpositionOfPieces())
|
||||
not m_layout->LayoutSettings().GetWarningSuperpositionOfPieces() &&
|
||||
not m_layout->LayoutSettings().GetWarningPieceGapePosition())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -2924,6 +2954,7 @@ auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool
|
|||
{
|
||||
bool outOfBoundChecked = false;
|
||||
bool pieceSuperpositionChecked = false;
|
||||
bool pieceGapePositionChecked = false;
|
||||
|
||||
QList<VPPiecePtr> const pieces = sheet->GetPieces();
|
||||
for (const auto &piece : pieces)
|
||||
|
@ -2937,6 +2968,11 @@ auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not CheckPieceGapePosition(piece, pieceGapePositionChecked))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3003,6 +3039,37 @@ auto VPMainWindow::CheckSuperpositionOfPieces(const VPPiecePtr &piece, bool &pie
|
|||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPMainWindow::CheckPieceGapePosition(const VPPiecePtr &piece, bool &pieceGapePositionChecked) -> bool
|
||||
{
|
||||
if (m_layout->LayoutSettings().GetWarningPieceGapePosition())
|
||||
{
|
||||
if (not pieceGapePositionChecked && not piece.isNull() && piece->HasInvalidPieceGapPosition())
|
||||
{
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setIcon(QMessageBox::Question);
|
||||
msgBox.setWindowTitle(tr("The layout is invalid."));
|
||||
msgBox.setText(tr("The layout is invalid. One or several pieces are closer than minimally allowed. Do you "
|
||||
"want to continue export?"));
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
const int width = 500;
|
||||
auto *horizontalSpacer = new QSpacerItem(width, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
auto *layout = qobject_cast<QGridLayout *>(msgBox.layout());
|
||||
SCASSERT(layout != nullptr)
|
||||
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pieceGapePositionChecked = true; // no need to ask more
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::PrintLayoutSheets(QPrinter *printer, const QList<VPSheetPtr> &sheets)
|
||||
{
|
||||
|
@ -3417,18 +3484,22 @@ void VPMainWindow::TranslatePieceRelatively(const VPPiecePtr &piece, const QRect
|
|||
pieceDy += dy * ((pieceRect.topLeft().y() - rect.topLeft().y()) / rect.height()) * 2.;
|
||||
}
|
||||
|
||||
auto *command = new VPUndoPieceMove(piece, pieceDx, pieceDy);
|
||||
m_layout->UndoStack()->push(command);
|
||||
m_layout->UndoStack()->push(new VPUndoPieceMove(piece, pieceDx, pieceDy));
|
||||
|
||||
if (m_layout->LayoutSettings().GetStickyEdges())
|
||||
if (m_layout->LayoutSettings().IsStickyEdges())
|
||||
{
|
||||
qreal stickyTranslateX = 0;
|
||||
qreal stickyTranslateY = 0;
|
||||
if (piece->StickyPosition(stickyTranslateX, stickyTranslateY))
|
||||
{
|
||||
QTime const dieTime = QTime::currentTime().addMSecs(150);
|
||||
while (QTime::currentTime() < dieTime)
|
||||
{
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
|
||||
}
|
||||
|
||||
bool const allowMerge = selectedPiecesCount == 1;
|
||||
auto *stickyCommand = new VPUndoPieceMove(piece, stickyTranslateX, stickyTranslateY, allowMerge);
|
||||
m_layout->UndoStack()->push(stickyCommand);
|
||||
m_layout->UndoStack()->push(new VPUndoPieceMove(piece, stickyTranslateX, stickyTranslateY, allowMerge));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3450,6 +3521,25 @@ void VPMainWindow::RotatePieces()
|
|||
return;
|
||||
}
|
||||
|
||||
auto StickyRotateToGrainline = [this](const VPPiecePtr &piece, const VPTransformationOrigon &origin)
|
||||
{
|
||||
QTime const dieTime = QTime::currentTime().addMSecs(150);
|
||||
while (QTime::currentTime() < dieTime)
|
||||
{
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
|
||||
}
|
||||
|
||||
if (not piece.isNull())
|
||||
{
|
||||
if (m_layout->LayoutSettings().GetFollowGrainline() || piece->IsFollowGrainline())
|
||||
{
|
||||
piece->RotateToGrainline(origin);
|
||||
}
|
||||
|
||||
emit m_layout->PieceTransformationChanged(piece);
|
||||
}
|
||||
};
|
||||
|
||||
if (ui->checkBoxTransformSeparately->isChecked())
|
||||
{
|
||||
m_layout->UndoStack()->beginMacro(tr("rotate pieces"));
|
||||
|
@ -3463,8 +3553,9 @@ void VPMainWindow::RotatePieces()
|
|||
origin.origin = rect.center();
|
||||
origin.custom = true;
|
||||
|
||||
auto *command = new VPUndoPieceRotate(piece, origin, angle, angle);
|
||||
m_layout->UndoStack()->push(command);
|
||||
m_layout->UndoStack()->push(new VPUndoPieceRotate(piece, origin, angle));
|
||||
|
||||
StickyRotateToGrainline(piece, origin);
|
||||
}
|
||||
}
|
||||
m_layout->UndoStack()->endMacro();
|
||||
|
@ -3478,8 +3569,12 @@ void VPMainWindow::RotatePieces()
|
|||
}
|
||||
|
||||
VPTransformationOrigon const origin = sheet->TransformationOrigin();
|
||||
auto *command = new VPUndoPiecesRotate(selectedPieces, origin, angle, angle);
|
||||
m_layout->UndoStack()->push(command);
|
||||
m_layout->UndoStack()->push(new VPUndoPiecesRotate(selectedPieces, origin, angle));
|
||||
|
||||
for (const auto &piece : qAsConst(selectedPieces))
|
||||
{
|
||||
StickyRotateToGrainline(piece, origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3813,7 +3908,7 @@ void VPMainWindow::on_SheetMarginChanged()
|
|||
|
||||
LayoutWasSaved(false);
|
||||
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
m_layout->CheckPiecesPositionValidity(sheet);
|
||||
}
|
||||
|
||||
m_graphicsView->RefreshLayout();
|
||||
|
@ -4806,6 +4901,21 @@ void VPMainWindow::VerticalScaleChanged(double value)
|
|||
VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::LayoutWarningPieceGapePosition_toggled(bool checked)
|
||||
{
|
||||
if (not m_layout.isNull())
|
||||
{
|
||||
m_layout->LayoutSettings().SetWarningPieceGapePosition(checked);
|
||||
LayoutWasSaved(false);
|
||||
if (checked)
|
||||
{
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
}
|
||||
m_graphicsView->RefreshPieces();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::LayoutWarningPiecesSuperposition_toggled(bool checked)
|
||||
{
|
||||
|
@ -4815,11 +4925,7 @@ void VPMainWindow::LayoutWarningPiecesSuperposition_toggled(bool checked)
|
|||
LayoutWasSaved(false);
|
||||
if (checked)
|
||||
{
|
||||
VPSheetPtr const sheet = m_layout->GetFocusedSheet();
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
sheet->ValidateSuperpositionOfPieces();
|
||||
}
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
}
|
||||
m_graphicsView->RefreshPieces();
|
||||
}
|
||||
|
@ -4835,11 +4941,7 @@ void VPMainWindow::LayoutWarningPiecesOutOfBound_toggled(bool checked)
|
|||
|
||||
if (checked)
|
||||
{
|
||||
VPSheetPtr const sheet = m_layout->GetFocusedSheet();
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
}
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
}
|
||||
m_graphicsView->RefreshPieces();
|
||||
}
|
||||
|
@ -4852,15 +4954,7 @@ void VPMainWindow::LayoutCutOnFold_toggled(bool checked)
|
|||
{
|
||||
m_layout->LayoutSettings().SetCutOnFold(checked);
|
||||
LayoutWasSaved(false);
|
||||
|
||||
if (checked)
|
||||
{
|
||||
VPSheetPtr const sheet = m_layout->GetFocusedSheet();
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
}
|
||||
}
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
m_graphicsView->RefreshLayout();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class VPMainWindow : public VAbstractMainWindow
|
|||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
explicit VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent = nullptr);
|
||||
explicit VPMainWindow(VPCommandLinePtr cmd, QWidget *parent = nullptr);
|
||||
~VPMainWindow() override;
|
||||
|
||||
auto CurrentFile() const -> QString;
|
||||
|
@ -293,6 +293,7 @@ private slots:
|
|||
void HorizontalScaleChanged(double value);
|
||||
void VerticalScaleChanged(double value);
|
||||
|
||||
void LayoutWarningPieceGapePosition_toggled(bool checked);
|
||||
void LayoutWarningPiecesSuperposition_toggled(bool checked);
|
||||
void LayoutWarningPiecesOutOfBound_toggled(bool checked);
|
||||
void LayoutCutOnFold_toggled(bool checked);
|
||||
|
@ -300,6 +301,11 @@ private slots:
|
|||
void UpdateShortcuts();
|
||||
|
||||
void TogetherWithNotchesChanged(bool checked);
|
||||
void CurrentPieceShowSeamLineToggled(bool checked);
|
||||
void ShowFullPieceToggled(bool checked);
|
||||
void ShowMirrorLineToggled(bool checked);
|
||||
void CurrentPieceVerticallyFlippedToggled(bool checked);
|
||||
void CurrentPieceHorizontallyFlippedToggled(bool checked);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(VPMainWindow) // NOLINT
|
||||
|
@ -501,6 +507,7 @@ private:
|
|||
auto AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool;
|
||||
auto CheckPiecesOutOfBound(const VPPiecePtr &piece, bool &outOfBoundChecked) -> bool;
|
||||
auto CheckSuperpositionOfPieces(const VPPiecePtr &piece, bool &pieceSuperpositionChecked) -> bool;
|
||||
auto CheckPieceGapePosition(const VPPiecePtr &piece, bool &pieceGapePositionChecked) -> bool;
|
||||
|
||||
void PrintLayoutSheets(QPrinter *printer, const QList<VPSheetPtr> &sheets);
|
||||
static auto PrintLayoutSheetPage(QPrinter *printer, QPainter &painter, const VPSheetPtr &sheet) -> bool;
|
||||
|
|
|
@ -280,7 +280,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>378</width>
|
||||
<height>721</height>
|
||||
<height>752</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_23">
|
||||
|
@ -378,6 +378,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Copy number:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEditCopyNumber">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -1645,8 +1659,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>392</width>
|
||||
<height>700</height>
|
||||
<width>378</width>
|
||||
<height>710</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_27">
|
||||
|
@ -1720,6 +1734,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxLayoutWarningPieceGapePosition">
|
||||
<property name="text">
|
||||
<string>Warning piece gape position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxSheetStickyEdges">
|
||||
<property name="text">
|
||||
|
@ -2434,8 +2455,8 @@
|
|||
</resources>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="buttonGroupRotationDirection"/>
|
||||
<buttongroup name="buttonGroupSheetOrientation"/>
|
||||
<buttongroup name="buttonGroupTileOrientation"/>
|
||||
<buttongroup name="buttonGroupSheetOrientation"/>
|
||||
<buttongroup name="buttonGroupRotationDirection"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
|
@ -63,6 +63,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTileShowWatermark, ("layou
|
|||
// NOLINTNEXTLINE
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesSuperposition,
|
||||
("layout/warningPiecesSuperposition"_L1))
|
||||
// NOLINTNEXTLINE
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPieceGapePosition, ("layout/warningPieceGapePosition"_L1))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutStickyEdges, ("layout/stickyEdges"_L1)) // NOLINT
|
||||
// NOLINTNEXTLINE
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesOutOfBound, ("layout/warningPiecesOutOfBound"_L1))
|
||||
|
@ -292,6 +294,18 @@ auto VPSettings::GetLayoutWarningPiecesSuperposition() const -> bool
|
|||
return value(*settingLayoutWarningPiecesSuperposition, true).toBool();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSettings::SetLayoutWarningPieceGapePosition(bool value)
|
||||
{
|
||||
setValue(*settingLayoutWarningPieceGapePosition, value);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPSettings::GetLayoutWarningPieceGapePosition() const -> bool
|
||||
{
|
||||
return value(*settingLayoutWarningPieceGapePosition, true).toBool();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSettings::SetLayoutStickyEdges(bool value)
|
||||
{
|
||||
|
|
|
@ -89,6 +89,9 @@ public:
|
|||
void SetLayoutWarningPiecesSuperposition(bool value);
|
||||
auto GetLayoutWarningPiecesSuperposition() const -> bool;
|
||||
|
||||
void SetLayoutWarningPieceGapePosition(bool value);
|
||||
auto GetLayoutWarningPieceGapePosition() const -> bool;
|
||||
|
||||
void SetLayoutStickyEdges(bool value);
|
||||
auto GetLayoutStickyEdges() const -> bool;
|
||||
|
||||
|
|
|
@ -333,6 +333,7 @@ void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout)
|
|||
QXmlStreamAttributes const attribs = attributes();
|
||||
layout->LayoutSettings().SetWarningSuperpositionOfPieces(
|
||||
ReadAttributeBool(attribs, ML::AttrWarningSuperposition, trueStr));
|
||||
layout->LayoutSettings().SetWarningPieceGapePosition(ReadAttributeBool(attribs, ML::AttrWarningPieceGape, trueStr));
|
||||
layout->LayoutSettings().SetWarningPiecesOutOfBound(ReadAttributeBool(attribs, ML::AttrWarningOutOfBound, trueStr));
|
||||
layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr));
|
||||
layout->LayoutSettings().SetPiecesGap(qMax(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')), 0.0));
|
||||
|
|
|
@ -172,7 +172,8 @@ void VPLayoutFileWriter::WriteLayoutProperties(const VPLayoutPtr &layout)
|
|||
writeStartElement(ML::TagControl);
|
||||
SetAttribute(ML::AttrWarningSuperposition, layout->LayoutSettings().GetWarningSuperpositionOfPieces());
|
||||
SetAttribute(ML::AttrWarningOutOfBound, layout->LayoutSettings().GetWarningPiecesOutOfBound());
|
||||
SetAttribute(ML::AttrStickyEdges, layout->LayoutSettings().GetStickyEdges());
|
||||
SetAttribute(ML::AttrWarningPieceGape, layout->LayoutSettings().GetWarningPieceGapePosition());
|
||||
SetAttribute(ML::AttrStickyEdges, layout->LayoutSettings().IsStickyEdges());
|
||||
SetAttribute(ML::AttrPiecesGap, layout->LayoutSettings().GetPiecesGap());
|
||||
SetAttribute(ML::AttrFollowGrainline, layout->LayoutSettings().GetFollowGrainline());
|
||||
SetAttribute(ML::AttrBoundaryTogetherWithNotches, layout->LayoutSettings().IsBoundaryTogetherWithNotches());
|
||||
|
|
|
@ -71,6 +71,7 @@ const QString TagMirrorLine = QStringLiteral("mirrorLine"); // NOLINT(ce
|
|||
|
||||
const QString AttrWarningSuperposition = QStringLiteral("warningSuperposition"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrWarningOutOfBound = QStringLiteral("warningOutOfBound"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrWarningPieceGape = QStringLiteral("warningPieceGape"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrStickyEdges = QStringLiteral("stickyEdges"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrPiecesGap = QStringLiteral("piecesGap"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrVisible = QStringLiteral("visible"); // NOLINT(cert-err58-cpp)
|
||||
|
|
|
@ -70,6 +70,7 @@ extern const QString TagMirrorLine;
|
|||
|
||||
extern const QString AttrWarningSuperposition;
|
||||
extern const QString AttrWarningOutOfBound;
|
||||
extern const QString AttrWarningPieceGape;
|
||||
extern const QString AttrStickyEdges;
|
||||
extern const QString AttrPiecesGap;
|
||||
extern const QString AttrVisible;
|
||||
|
|
|
@ -118,8 +118,9 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
|
|||
|
||||
#if !defined(CRASH_REPORTING)
|
||||
ui->groupBoxCrashReports->setDisabled(true);
|
||||
#endif
|
||||
|
||||
ui->checkBoxSendCrashReports->setChecked(false);
|
||||
ui->lineEditCrashUserEmail->setText(QString());
|
||||
#else
|
||||
ui->checkBoxSendCrashReports->setChecked(settings->IsSendCrashReport());
|
||||
connect(ui->checkBoxSendCrashReports, &QCheckBox::stateChanged, this,
|
||||
[this]() { m_sendCrashReportsChanged = true; });
|
||||
|
@ -130,6 +131,7 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
|
|||
ui->lineEditCrashUserEmail->setText(settings->GetCrashEmail());
|
||||
connect(ui->lineEditCrashUserEmail, &QLineEdit::editingFinished, this,
|
||||
[this]() { m_crashUserEmailChanged = true; });
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -196,40 +196,41 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
|||
|
||||
{
|
||||
QString debugdate = "["_L1 + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
|
||||
QString const file = VAbstractApplication::ReduceLogContextFilePath(context.file);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
debugdate += QStringLiteral(":DEBUG:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdOut() << QApplication::translate("mNoisyHandler", "DEBUG:") << logMsg << "\n";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
debugdate += QStringLiteral(":WARNING:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdErr() << QApplication::translate("mNoisyHandler", "WARNING:") << logMsg << "\n";
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
debugdate += QStringLiteral(":CRITICAL:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdErr() << QApplication::translate("mNoisyHandler", "CRITICAL:") << logMsg << "\n";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
debugdate += QStringLiteral(":FATAL:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdErr() << QApplication::translate("mNoisyHandler", "FATAL:") << logMsg << "\n";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
debugdate += QStringLiteral(":INFO:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdOut() << QApplication::translate("mNoisyHandler", "INFO:") << logMsg << "\n";
|
||||
|
@ -613,6 +614,13 @@ void MApplication::AboutToQuit()
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void MApplication::OpenSettings()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
QString const docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (!docPath.isEmpty())
|
||||
{
|
||||
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, docPath);
|
||||
}
|
||||
#endif
|
||||
settings = new VTapeSettings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(),
|
||||
QCoreApplication::applicationName(), this);
|
||||
connect(settings, &VTapeSettings::SVGFontsPathChanged, this, &MApplication::SVGFontsPathChanged);
|
||||
|
|
|
@ -225,12 +225,13 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
|||
|
||||
{
|
||||
QString debugdate = "["_L1 + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
|
||||
QString const file = VAbstractApplication::ReduceLogContextFilePath(context.file);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
debugdate += QStringLiteral(":DEBUG:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdOut() << QApplication::translate("vNoisyHandler", "DEBUG:") << logMsg << "\n";
|
||||
|
@ -241,7 +242,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
|||
VAbstractValApplication::VApp()->PostWarningMessage(logMsg, type);
|
||||
}
|
||||
debugdate += QStringLiteral(":WARNING:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdErr() << QApplication::translate("vNoisyHandler", "WARNING:") << logMsg << "\n";
|
||||
|
@ -252,14 +253,14 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
|||
VAbstractValApplication::VApp()->PostWarningMessage(logMsg, type);
|
||||
}
|
||||
debugdate += QStringLiteral(":CRITICAL:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdErr() << QApplication::translate("vNoisyHandler", "CRITICAL:") << logMsg << "\n";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
debugdate += QStringLiteral(":FATAL:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdErr() << QApplication::translate("vNoisyHandler", "FATAL:") << logMsg << "\n";
|
||||
|
@ -270,7 +271,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
|||
VAbstractValApplication::VApp()->PostWarningMessage(logMsg, type);
|
||||
}
|
||||
debugdate += QStringLiteral(":INFO:%1(%2)] %3: %4: %5")
|
||||
.arg(context.file)
|
||||
.arg(file)
|
||||
.arg(context.line)
|
||||
.arg(context.function, context.category, logMsg);
|
||||
vStdOut() << QApplication::translate("vNoisyHandler", "INFO:") << logMsg << "\n";
|
||||
|
|
|
@ -180,8 +180,9 @@ PreferencesConfigurationPage::PreferencesConfigurationPage(QWidget *parent)
|
|||
|
||||
#if !defined(CRASH_REPORTING)
|
||||
ui->groupBoxCrashReports->setDisabled(true);
|
||||
#endif
|
||||
|
||||
ui->checkBoxSendCrashReports->setChecked(false);
|
||||
ui->lineEditCrashUserEmail->setText(QString());
|
||||
#else
|
||||
ui->checkBoxSendCrashReports->setChecked(settings->IsSendCrashReport());
|
||||
connect(ui->checkBoxSendCrashReports, &QCheckBox::stateChanged, this,
|
||||
[this]() { m_sendCrashReportsChanged = true; });
|
||||
|
@ -192,6 +193,7 @@ PreferencesConfigurationPage::PreferencesConfigurationPage(QWidget *parent)
|
|||
ui->lineEditCrashUserEmail->setText(settings->GetCrashEmail());
|
||||
connect(ui->lineEditCrashUserEmail, &QLineEdit::editingFinished, this,
|
||||
[this]() { m_crashUserEmailChanged = true; });
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<xs:complexType>
|
||||
<xs:attribute type="xs:boolean" name="warningSuperposition"/>
|
||||
<xs:attribute type="xs:boolean" name="warningOutOfBound"/>
|
||||
<xs:attribute type="xs:boolean" name="warningPieceGape"/>
|
||||
<xs:attribute type="xs:boolean" name="stickyEdges"/>
|
||||
<xs:attribute type="xs:boolean" name="followGrainline"/>
|
||||
<xs:attribute type="xs:boolean" name="boundaryTogetherWithNotches"/>
|
||||
|
|
|
@ -153,42 +153,6 @@ inline auto LineAlign(const TextLine &tl, const QString &text, const QFontMetric
|
|||
|
||||
return dX;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
|
||||
int maxLineWidth) -> QTransform
|
||||
{
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(topLeft.x(), topLeft.y());
|
||||
|
||||
if ((piece.IsVerticallyFlipped() && piece.IsHorizontallyFlipped()) ||
|
||||
(!piece.IsVerticallyFlipped() && !piece.IsHorizontallyFlipped()))
|
||||
{
|
||||
labelMatrix.rotate(-angle);
|
||||
}
|
||||
else if (piece.IsVerticallyFlipped() || piece.IsHorizontallyFlipped())
|
||||
{
|
||||
if (piece.IsVerticallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
|
||||
if (piece.IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
|
||||
|
||||
labelMatrix *= piece.GetMatrix();
|
||||
|
||||
return labelMatrix;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1159,7 +1123,6 @@ void VDxfEngine::ExportPieceText(const QSharedPointer<dx_ifaceBlock> &detailBloc
|
|||
|
||||
VTextManager const tm = detail.GetPieceLabelData();
|
||||
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont());
|
||||
const int maxLineWidth = tm.MaxLineWidthOutlineFont(static_cast<int>(dW));
|
||||
|
||||
for (const auto &tl : labelLines)
|
||||
{
|
||||
|
@ -1174,7 +1137,7 @@ void VDxfEngine::ExportPieceText(const QSharedPointer<dx_ifaceBlock> &detailBloc
|
|||
dY += fm.height() * scale / 2;
|
||||
|
||||
const qreal dX = LineAlign(tl, tl.m_qsText, fm, dW);
|
||||
QTransform const lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
|
||||
QTransform const lineMatrix = detail.LineMatrix(labelShape.at(0), angle, QPointF(dX, dY), dW);
|
||||
|
||||
QPointF const pos = lineMatrix.map(QPointF());
|
||||
|
||||
|
|
|
@ -158,41 +158,6 @@ inline auto LineAlign(const TextLine &tl, const QString &text, const QFontMetric
|
|||
return dX;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
|
||||
int maxLineWidth) -> QTransform
|
||||
{
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(topLeft.x(), topLeft.y());
|
||||
|
||||
if ((piece.IsVerticallyFlipped() && piece.IsHorizontallyFlipped()) ||
|
||||
(!piece.IsVerticallyFlipped() && !piece.IsHorizontallyFlipped()))
|
||||
{
|
||||
labelMatrix.rotate(angle);
|
||||
}
|
||||
else if (piece.IsVerticallyFlipped() || piece.IsHorizontallyFlipped())
|
||||
{
|
||||
if (piece.IsVerticallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
|
||||
if (piece.IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
|
||||
labelMatrix *= piece.GetMatrix();
|
||||
|
||||
return labelMatrix;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto OptimizePattern(QVector<int> pattern) -> QVector<int>
|
||||
{
|
||||
|
@ -751,7 +716,6 @@ void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail,
|
|||
const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length();
|
||||
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
|
||||
const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle();
|
||||
const int maxLineWidth = tm.MaxLineWidthSVGFont(static_cast<int>(dW), m_penWidthPx);
|
||||
|
||||
qreal dY = m_penWidthPx;
|
||||
|
||||
|
@ -770,7 +734,7 @@ void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail,
|
|||
const QString qsText = tl.m_qsText;
|
||||
const qreal dX = LineAlign(tl, qsText, engine, dW, m_penWidthPx);
|
||||
// set up the rotation around top-left corner matrix
|
||||
const QTransform lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
|
||||
const QTransform lineMatrix = detail.LineMatrix(labelShape.at(0), angle, QPointF(dX, dY), dW);
|
||||
|
||||
QPainterPath const path = lineMatrix.map(engine.DrawPath(QPointF(), qsText));
|
||||
PlotPainterPath(out, path, Qt::SolidLine);
|
||||
|
@ -791,7 +755,6 @@ void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &det
|
|||
const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length();
|
||||
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
|
||||
const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle();
|
||||
const int maxLineWidth = tm.MaxLineWidthOutlineFont(static_cast<int>(dW));
|
||||
|
||||
qreal dY = 0;
|
||||
|
||||
|
@ -824,7 +787,7 @@ void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &det
|
|||
const QString qsText = tl.m_qsText;
|
||||
const qreal dX = LineAlign(tl, qsText, fm, dW);
|
||||
// set up the rotation around top-left corner matrix
|
||||
const QTransform lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
|
||||
const QTransform lineMatrix = detail.LineMatrix(labelShape.at(0), angle, QPointF(dX, dY), dW);
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
|
|
|
@ -1856,6 +1856,40 @@ auto VLayoutPiece::MapPassmark(VLayoutPassmark passmark, const QTransform &matri
|
|||
return passmark;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VLayoutPiece::LineMatrix(const QPointF &topLeft, qreal angle, const QPointF &linePos, qreal maxLineWidth) const
|
||||
-> QTransform
|
||||
{
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(topLeft.x(), topLeft.y());
|
||||
|
||||
if ((IsVerticallyFlipped() && IsHorizontallyFlipped()) || (!IsVerticallyFlipped() && !IsHorizontallyFlipped()))
|
||||
{
|
||||
labelMatrix.rotate(angle);
|
||||
}
|
||||
else if (IsVerticallyFlipped() || IsHorizontallyFlipped())
|
||||
{
|
||||
if (IsVerticallyFlipped() && !IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
|
||||
if (IsHorizontallyFlipped() && !IsVerticallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
|
||||
labelMatrix *= GetMatrix();
|
||||
|
||||
return labelMatrix;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VLayoutPiece::BoundingRect(QVector<QPointF> points) -> QRectF
|
||||
{
|
||||
|
@ -2046,7 +2080,7 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
|
|||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-tm.MaxLineWidthOutlineFont(static_cast<int>(dW)), 0);
|
||||
labelMatrix.translate(-qRound(dW), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -240,6 +240,9 @@ public:
|
|||
|
||||
static auto MapPassmark(VLayoutPassmark passmark, const QTransform &matrix, bool mirror) -> VLayoutPassmark;
|
||||
|
||||
auto LineMatrix(const QPointF &topLeft, qreal angle, const QPointF &linePos, qreal maxLineWidth) const
|
||||
-> QTransform;
|
||||
|
||||
protected:
|
||||
void SetGrainline(const VPieceGrainline &grainline);
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ QT_WARNING_POP
|
|||
*/
|
||||
inline auto VPosition::FabricGrainline() const -> QLineF
|
||||
{
|
||||
return m_data.isOriginPaperOrientationPortrait ? QLineF(10, 10, 10, 100) : QLineF(10, 10, 100, 10);
|
||||
return m_data.isOriginPaperOrientationPortrait ? QLineF(10, 10, 10, -100) : QLineF(10, 10, -100, 10);
|
||||
}
|
||||
|
||||
#endif // VPOSITION_H
|
||||
|
|
|
@ -786,67 +786,6 @@ auto VTextManager::GetLabelSourceLines(int width, const VSvgFont &font, qreal pe
|
|||
return lines;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VTextManager::MaxLineWidthOutlineFont(int width) const -> int
|
||||
{
|
||||
int maxWidth = 0;
|
||||
for (int i = 0; i < m_liLines.count(); ++i)
|
||||
{
|
||||
const TextLine &tl = m_liLines.at(i);
|
||||
|
||||
QFont fnt = m_font;
|
||||
fnt.setPointSize(qMax(fnt.pointSize() + tl.m_iFontSize, 1));
|
||||
fnt.setBold(tl.m_bold);
|
||||
fnt.setItalic(tl.m_italic);
|
||||
|
||||
QFontMetrics const fm(fnt);
|
||||
|
||||
QString qsText = tl.m_qsText;
|
||||
|
||||
if (fm.horizontalAdvance(qsText) > width)
|
||||
{
|
||||
qsText = fm.elidedText(qsText, Qt::ElideMiddle, width);
|
||||
}
|
||||
|
||||
maxWidth = qMax(fm.horizontalAdvance(qsText), maxWidth);
|
||||
}
|
||||
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VTextManager::MaxLineWidthSVGFont(int width, qreal penWidth) const -> int
|
||||
{
|
||||
VSvgFontDatabase *db = VAbstractApplication::VApp()->SVGFontDatabase();
|
||||
VSvgFontEngine engine =
|
||||
db->FontEngine(m_svgFontFamily, SVGFontStyle::Normal, SVGFontWeight::Normal, m_svgFontPointSize);
|
||||
VSvgFont const svgFont = engine.Font();
|
||||
|
||||
int maxWidth = 0;
|
||||
for (int i = 0; i < m_liLines.count(); ++i)
|
||||
{
|
||||
const TextLine &tl = m_liLines.at(i);
|
||||
|
||||
VSvgFont fnt = svgFont;
|
||||
fnt.SetPointSize(fnt.PointSize() + tl.m_iFontSize);
|
||||
fnt.SetBold(tl.m_bold);
|
||||
fnt.SetItalic(tl.m_italic);
|
||||
|
||||
engine = db->FontEngine(fnt);
|
||||
|
||||
QString qsText = tl.m_qsText;
|
||||
|
||||
if (engine.TextWidth(qsText, penWidth) > width)
|
||||
{
|
||||
qsText = engine.ElidedText(qsText, SVGTextElideMode::ElideMiddle, width);
|
||||
}
|
||||
|
||||
maxWidth = qMax(qRound(engine.TextWidth(qsText, penWidth)), maxWidth);
|
||||
}
|
||||
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief VTextManager::Update updates the text lines with detail data
|
||||
|
|
|
@ -104,9 +104,6 @@ public:
|
|||
auto GetLabelSourceLines(int width, const QFont &font) const -> QVector<TextLine>;
|
||||
auto GetLabelSourceLines(int width, const VSvgFont &font, qreal penWidth) const -> QVector<TextLine>;
|
||||
|
||||
auto MaxLineWidthOutlineFont(int width) const -> int;
|
||||
auto MaxLineWidthSVGFont(int width, qreal penWidth) const -> int;
|
||||
|
||||
void Update(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern);
|
||||
void Update(VAbstractPattern *pDoc, const VContainer *pattern);
|
||||
|
||||
|
|
|
@ -92,7 +92,13 @@ auto AppCrashVersion() -> QString
|
|||
QString const platform = QStringLiteral("unknown");
|
||||
#endif
|
||||
|
||||
return QStringLiteral("%1-%2-%3-%4%5").arg(version, VCS_REPO_STATE_REVISION, qtVersion, platform, multibundle);
|
||||
QString revision = QStringLiteral(VCS_REPO_STATE_REVISION);
|
||||
if (!revision.startsWith('g'))
|
||||
{ // assume always git
|
||||
revision.prepend('g');
|
||||
}
|
||||
|
||||
return QStringLiteral("%1-%2-%3-%4%5").arg(version, revision, qtVersion, platform, multibundle);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -33,6 +33,36 @@
|
|||
#include "../projectversion.h"
|
||||
#include "vcrashpaths.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
|
||||
#include "../compatibility.h"
|
||||
#endif
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
namespace
|
||||
{
|
||||
auto LogDirPath(const QString &appName) -> QString
|
||||
{
|
||||
const QString logs = QStringLiteral("Logs");
|
||||
|
||||
QString logDirPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
|
||||
if (logDirPath.isEmpty())
|
||||
{
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
return QStringList{QCoreApplication::applicationDirPath(), logs, appName}.join(QDir::separator());
|
||||
#else
|
||||
return QStringList{QDir::homePath(), VER_COMPANYNAME_STR, logs, appName}.join(QDir::separator());
|
||||
#endif
|
||||
}
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
QString path = QStringList{logDirPath, logs}.join(QDir::separator());
|
||||
#else
|
||||
QString path = QStringList{logDirPath, VER_COMPANYNAME_STR, logs, appName}.join(QDir::separator());
|
||||
#endif
|
||||
return path;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VCrashPaths::VCrashPaths(QString exeDir)
|
||||
: m_exeDir(std::move(exeDir))
|
||||
|
@ -42,10 +72,9 @@ VCrashPaths::VCrashPaths(QString exeDir)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCrashPaths::GetAttachmentPath(const QString &appName) -> QString
|
||||
{
|
||||
const QString logDirPath =
|
||||
QStandardPaths::locate(QStandardPaths::ConfigLocation, QString(), QStandardPaths::LocateDirectory) +
|
||||
QStringLiteral(VER_COMPANYNAME_STR);
|
||||
return QStringLiteral("%1/%2-pid%3.log").arg(logDirPath, appName.toLower()).arg(QCoreApplication::applicationPid());
|
||||
return QStringLiteral("%1/%2-pid%3.log")
|
||||
.arg(LogDirPath(appName), appName.toLower())
|
||||
.arg(QCoreApplication::applicationPid());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -64,15 +93,25 @@ auto VCrashPaths::GetHandlerPath() const -> QString
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCrashPaths::GetReportsPath() -> QString
|
||||
{
|
||||
return QStandardPaths::locate(QStandardPaths::AppConfigLocation, QString(), QStandardPaths::LocateDirectory) +
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QDir::separator() +
|
||||
QStringList{"User Data", "Crashpad", "Reports"}.join(QDir::separator());
|
||||
#else
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QDir::separator() +
|
||||
QStringList{VER_COMPANYNAME_STR, "User Data", "Crashpad", "Reports"}.join(QDir::separator());
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCrashPaths::GetMetricsPath() -> QString
|
||||
{
|
||||
return QStandardPaths::locate(QStandardPaths::AppConfigLocation, QString(), QStandardPaths::LocateDirectory) +
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QDir::separator() +
|
||||
QStringList{"User Data", "Crashpad", "Metrics"}.join(QDir::separator());
|
||||
#else
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QDir::separator() +
|
||||
QStringList{VER_COMPANYNAME_STR, "User Data", "Crashpad", "Metrics"}.join(QDir::separator());
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionValidator>
|
||||
|
||||
#if defined(CRASH_REPORTING)
|
||||
#include "../vabstractapplication.h"
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
DialogAskCollectStatistic::DialogAskCollectStatistic(QWidget *parent)
|
||||
|
@ -42,14 +44,16 @@ DialogAskCollectStatistic::DialogAskCollectStatistic(QWidget *parent)
|
|||
|
||||
#if !defined(CRASH_REPORTING)
|
||||
ui->groupBoxCrashReports->setDisabled(true);
|
||||
#endif
|
||||
|
||||
ui->checkBoxSendCrashReports->setChecked(false);
|
||||
ui->lineEditCrashUserEmail->setText(QString());
|
||||
#else
|
||||
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
|
||||
|
||||
QRegularExpression const rx(QStringLiteral("\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b"),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
ui->lineEditCrashUserEmail->setValidator(new QRegularExpressionValidator(rx, this));
|
||||
ui->lineEditCrashUserEmail->setText(settings->GetCrashEmail());
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"PointColor": "#d9d9d9",
|
||||
"LabelColor": "#d9d9d9",
|
||||
"LabelHoverColor": "#ffd900",
|
||||
"LabelLineColor": "#80ffd900",
|
||||
"LabelLineColor": [255, 217, 0, 32],
|
||||
"AccuracyRadiusColor": "#ffd900",
|
||||
"ControlLineColor": "#80ffd900",
|
||||
"ControlPointColor": "#ffd900",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"PointColor": "black",
|
||||
"LabelColor": "black",
|
||||
"LabelHoverColor": "green",
|
||||
"LabelLineColor": [0, 0, 0],
|
||||
"LabelLineColor": [0, 0, 0, 16],
|
||||
"AccuracyRadiusColor": "blue",
|
||||
"ControlLineColor": [0, 0, 0],
|
||||
"ControlPointColor": "red",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "QtConcurrent/qtconcurrentrun.h"
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QFuture>
|
||||
#include <QLibraryInfo>
|
||||
|
@ -286,6 +287,20 @@ auto VAbstractApplication::QtTranslationsPath(const QString &locale) -> QString
|
|||
#endif // defined(Q_OS_LINUX)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VAbstractApplication::ReduceLogContextFilePath(QString path) -> QString
|
||||
{
|
||||
// Find the position of the 'src' folder in the path
|
||||
vsizetype const srcIndex = path.indexOf(QDir::toNativeSeparators(QStringLiteral("/src/")));
|
||||
if (srcIndex != -1)
|
||||
{
|
||||
// Extract the substring starting from 'src' folder
|
||||
path = path.mid(srcIndex);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VAbstractApplication::getUndoStack() const -> QUndoStack *
|
||||
{
|
||||
|
@ -554,7 +569,7 @@ void VAbstractApplication::CheckSystemLocale()
|
|||
|
||||
auto CheckLanguage = [](QStandardPaths::StandardLocation type, const QStringList &test)
|
||||
{
|
||||
const QString path = QStandardPaths::locate(type, QString(), QStandardPaths::LocateDirectory);
|
||||
const QString path = QStandardPaths::writableLocation(type);
|
||||
return std::any_of(test.begin(), test.end(), [path](const QString &t) { return path.contains(t); });
|
||||
};
|
||||
|
||||
|
@ -634,10 +649,28 @@ void VAbstractApplication::InitHighDpiScaling(int argc, char *argv[])
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VAbstractApplication::LogDirPath() -> QString
|
||||
{
|
||||
const QString logDirPath =
|
||||
QStandardPaths::locate(QStandardPaths::ConfigLocation, QString(), QStandardPaths::LocateDirectory) +
|
||||
QCoreApplication::organizationName();
|
||||
return logDirPath;
|
||||
const QString logs = QStringLiteral("Logs");
|
||||
|
||||
QString const logDirPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
|
||||
if (logDirPath.isEmpty())
|
||||
{
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
return QStringList{QCoreApplication::applicationDirPath(), logs, QCoreApplication::applicationName()}.join(
|
||||
QDir::separator());
|
||||
#else
|
||||
return QStringList{QDir::homePath(), QCoreApplication::organizationName(), logs,
|
||||
QCoreApplication::applicationName()}
|
||||
.join(QDir::separator());
|
||||
#endif
|
||||
}
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
QString path = QStringList{logDirPath, logs}.join(QDir::separator());
|
||||
#else
|
||||
QString path =
|
||||
QStringList{logDirPath, QCoreApplication::organizationName(), logs, QCoreApplication::applicationName()}.join(
|
||||
QDir::separator());
|
||||
#endif
|
||||
return path;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -669,7 +702,13 @@ void VAbstractApplication::ClearOldLogs()
|
|||
// Restore working directory
|
||||
auto restore = qScopeGuard([workingDirectory] { QDir::setCurrent(workingDirectory); });
|
||||
|
||||
const QStringList allFiles = logsDir.entryList(QDir::NoDotAndDotDot | QDir::Files);
|
||||
QDirIterator it(logsDir.absolutePath(), QDir::Files | QDir::NoDotAndDotDot, QDirIterator::NoIteratorFlags);
|
||||
QStringList allFiles;
|
||||
while (it.hasNext())
|
||||
{
|
||||
allFiles << it.next();
|
||||
}
|
||||
|
||||
if (allFiles.isEmpty())
|
||||
{
|
||||
qDebug("There are no old logs.");
|
||||
|
|
|
@ -78,6 +78,8 @@ public:
|
|||
static auto translationsPath(const QString &locale = QString()) -> QString;
|
||||
static auto QtTranslationsPath(const QString &locale = QString()) -> QString;
|
||||
|
||||
static auto ReduceLogContextFilePath(QString path) -> QString;
|
||||
|
||||
void LoadTranslation(QString locale);
|
||||
|
||||
virtual void OpenSettings() = 0;
|
||||
|
|
|
@ -71,6 +71,13 @@ void VAbstractValApplication::PostWarningMessage(const QString &message, QtMsgTy
|
|||
*/
|
||||
void VAbstractValApplication::OpenSettings()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
QString const docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (!docPath.isEmpty())
|
||||
{
|
||||
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, docPath);
|
||||
}
|
||||
#endif
|
||||
settings = new VValentinaSettings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(),
|
||||
QCoreApplication::applicationName(), this);
|
||||
connect(settings, &VValentinaSettings::SVGFontsPathChanged, this, &VAbstractValApplication::SVGFontsPathChanged);
|
||||
|
|
|
@ -347,7 +347,19 @@ void VCommonSettings::SetPathCustomImage(const QString &value)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::GetDefPathSVGFonts() -> QString
|
||||
{
|
||||
return QDir::homePath() + QStringLiteral("/valentina/svg fonts");
|
||||
QString const defPath = QStringList{QDir::homePath(), "Valentina"_L1, "Svg fonts"_L1}.join(QDir::separator());
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QString const docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (docPath.isEmpty())
|
||||
{
|
||||
return defPath;
|
||||
}
|
||||
|
||||
return QStringList{docPath, "Valentina"_L1, "Svg fonts"_L1}.join(QDir::separator());
|
||||
#else
|
||||
return defPath;
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -375,7 +387,20 @@ void VCommonSettings::SetPathSVGFonts(const QString &value)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::GetDefPathFontCorrections() -> QString
|
||||
{
|
||||
return QDir::homePath() + "/valentina/font corrections"_L1;
|
||||
QString const defPath =
|
||||
QStringList{QDir::homePath(), "Valentina"_L1, "Font corrections"_L1}.join(QDir::separator());
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QString const docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (docPath.isEmpty())
|
||||
{
|
||||
return defPath;
|
||||
}
|
||||
|
||||
return QStringList{docPath, "Valentina"_L1, "Font corrections"_L1}.join(QDir::separator());
|
||||
#else
|
||||
return defPath;
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -396,7 +421,20 @@ void VCommonSettings::SetPathFontCorrections(const QString &value)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::GetDefPathKnownMeasurements() -> QString
|
||||
{
|
||||
return QDir::homePath() + "/valentina/known measurements"_L1;
|
||||
QString const defPath =
|
||||
QStringList{QDir::homePath(), "Valentina"_L1, "Known measurements"_L1}.join(QDir::separator());
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QString const docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (docPath.isEmpty())
|
||||
{
|
||||
return defPath;
|
||||
}
|
||||
|
||||
return QStringList{docPath, "Valentina"_L1, "Known measurements"_L1}.join(QDir::separator());
|
||||
#else
|
||||
return defPath;
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -2298,11 +2298,11 @@ auto VToolSeamAllowance::FindGrainlineGeometry(const VGrainlineData &geom, const
|
|||
const auto centerPinPoint = VAbstractTool::data.GeometricObject<VPointF>(centerPin);
|
||||
|
||||
const qreal cLength = ToPixel(length, *VDataTool::data.GetPatternUnit());
|
||||
QLineF grainline(centerPinPoint->x(), centerPinPoint->y(), centerPinPoint->x() + cLength / 2.0,
|
||||
QLineF grainline(centerPinPoint->x(), centerPinPoint->y(), centerPinPoint->x() - cLength / 2.0,
|
||||
centerPinPoint->y());
|
||||
|
||||
grainline.setAngle(rotationAngle);
|
||||
grainline = QLineF(grainline.p2(), grainline.p1());
|
||||
Swap(grainline);
|
||||
grainline.setLength(cLength);
|
||||
|
||||
pos = grainline.p2();
|
||||
|
|
Loading…
Reference in New Issue