Adding removing nodes of curved path.

This commit is contained in:
Roman Telezhynskyi 2023-11-17 09:30:48 +02:00
parent 111d8950fd
commit 8b402dc1d9
10 changed files with 710 additions and 169 deletions

View file

@ -55,6 +55,7 @@
- Allow negative values.
- Tape app. New feature: Always keep on top.
- [smart-pattern/valentina#188] Label %mFileName% file name punctuation.
- Adding removing nodes of curved path.
# Valentina 0.7.52 September 12, 2022
- Fix crash when default locale is ru.

View file

@ -72,6 +72,7 @@ DialogCubicBezierPath::DialogCubicBezierPath(const VContainer *data, VAbstractPa
InitOkCancelApply(ui);
bOk->setEnabled(false);
FillComboBoxPoints(ui->comboBoxNewPoint);
FillComboBoxPoints(ui->comboBoxPoint);
FillComboBoxLineColors(ui->comboBoxColor);
FillComboBoxTypeLine(ui->comboBoxPenStyle,
@ -83,6 +84,16 @@ DialogCubicBezierPath::DialogCubicBezierPath(const VContainer *data, VAbstractPa
connect(ui->listWidget, &QListWidget::currentRowChanged, this, &DialogCubicBezierPath::PointChanged);
connect(ui->comboBoxPoint, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&DialogCubicBezierPath::currentPointChanged);
connect(ui->comboBoxNewPoint, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&DialogCubicBezierPath::NewPointChanged);
connect(ui->toolButtonAddPoint, &QToolButton::clicked, this, &DialogCubicBezierPath::AddPoint);
connect(ui->toolButtonRemovePoint, &QToolButton::clicked, this, &DialogCubicBezierPath::RemovePoint);
connect(ui->toolButtonTop, &QToolButton::clicked, this, &DialogCubicBezierPath::MoveTop);
connect(ui->toolButtonUp, &QToolButton::clicked, this, &DialogCubicBezierPath::MoveUp);
connect(ui->toolButtonDown, &QToolButton::clicked, this, &DialogCubicBezierPath::MoveDown);
connect(ui->toolButtonBottom, &QToolButton::clicked, this, &DialogCubicBezierPath::MoveBottom);
connect(ui->lineEditAlias, &QLineEdit::textEdited, this, &DialogCubicBezierPath::ValidateAlias);
@ -136,6 +147,9 @@ void DialogCubicBezierPath::SetPath(const VCubicBezierPath &value)
}
ValidatePath();
ui->toolButtonRemovePoint->setEnabled(ui->listWidget->count() > 7);
MoveControls();
}
//---------------------------------------------------------------------------------------------------------------------
@ -175,22 +189,24 @@ void DialogCubicBezierPath::ChosenObject(quint32 id, const SceneObject &type)
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::ShowDialog(bool click)
{
if (click == false)
if (click)
{
const auto size = path.CountPoints();
if (size >= 7)
{
if (size - VCubicBezierPath::SubSplPointsCount(path.CountSubSpl()) == 0)
{ // Accept only if all subpaths are completed
emit ToolTip(QString());
return;
}
if (not data->IsUnique(path.name()))
{
path.SetDuplicate(DNumber(path.name()));
}
const auto size = path.CountPoints();
if (size >= 7)
{
if (size - VCubicBezierPath::SubSplPointsCount(path.CountSubSpl()) == 0)
{ // Accept only if all subpaths are completed
emit ToolTip(QString());
DialogAccepted();
if (not data->IsUnique(path.name()))
{
path.SetDuplicate(DNumber(path.name()));
}
DialogAccepted();
}
}
}
@ -225,9 +241,15 @@ void DialogCubicBezierPath::PointChanged(int row)
{
if (ui->listWidget->count() == 0)
{
ui->toolButtonTop->setEnabled(false);
ui->toolButtonUp->setEnabled(false);
ui->toolButtonDown->setEnabled(false);
ui->toolButtonBottom->setEnabled(false);
return;
}
MoveControls();
const auto p = qvariant_cast<VPointF>(ui->listWidget->item(row)->data(Qt::UserRole));
DataPoint(p);
}
@ -279,6 +301,88 @@ void DialogCubicBezierPath::ValidateAlias()
CheckState();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::NewPointChanged()
{
ui->toolButtonAddPoint->setEnabled(ui->comboBoxNewPoint->currentIndex() != -1);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::AddPoint()
{
const auto id = qvariant_cast<quint32>(ui->comboBoxNewPoint->currentData());
const auto point = data->GeometricObject<VPointF>(id);
NewItem(*point);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
ui->comboBoxNewPoint->blockSignals(true);
ui->comboBoxNewPoint->setCurrentIndex(-1);
ui->comboBoxNewPoint->blockSignals(false);
ui->toolButtonAddPoint->setDisabled(true);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::RemovePoint()
{
if (ui->listWidget->count() <= 7)
{
ui->toolButtonRemovePoint->setDisabled(true);
return;
}
QListWidgetItem *selectedItem = ui->listWidget->currentItem();
if (selectedItem)
{
delete ui->listWidget->takeItem(ui->listWidget->row(selectedItem));
ui->listWidget->setCurrentRow(0);
ui->toolButtonRemovePoint->setDisabled(ui->listWidget->count() <= 7);
}
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::MoveTop()
{
MoveListRowTop(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::MoveUp()
{
MoveListRowUp(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::MoveDown()
{
MoveListRowDown(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::MoveBottom()
{
MoveListRowBottom(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::NewItem(const VPointF &point)
{
@ -316,6 +420,7 @@ void DialogCubicBezierPath::SavePath()
auto DialogCubicBezierPath::AllPathBackboneIds() const -> QSet<quint32>
{
QVector<quint32> points;
points.reserve(ui->listWidget->count());
for (qint32 i = 0; i < ui->listWidget->count(); ++i)
{
points.append(qvariant_cast<VPointF>(ui->listWidget->item(i)->data(Qt::UserRole)).id());
@ -348,6 +453,7 @@ auto DialogCubicBezierPath::IsPathValid() const -> bool
auto DialogCubicBezierPath::ExtractPath() const -> VCubicBezierPath
{
QVector<VPointF> points;
points.reserve(ui->listWidget->count());
for (qint32 i = 0; i < ui->listWidget->count(); ++i)
{
points.append(qvariant_cast<VPointF>(ui->listWidget->item(i)->data(Qt::UserRole)));
@ -398,6 +504,17 @@ void DialogCubicBezierPath::ValidatePath()
ChangeColor(ui->labelPoint, color);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::MoveControls()
{
const int index = ui->listWidget->currentRow();
ui->toolButtonTop->setEnabled(index > 0);
ui->toolButtonUp->setEnabled(index > 0);
ui->toolButtonDown->setEnabled(index != -1 && index < ui->listWidget->count() - 1);
ui->toolButtonBottom->setEnabled(index != -1 && index < ui->listWidget->count() - 1);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezierPath::SetNotes(const QString &notes)
{

View file

@ -50,7 +50,8 @@ class DialogCubicBezierPath : public DialogTool
Q_OBJECT // NOLINT
public:
explicit DialogCubicBezierPath(const VContainer *data, VAbstractPattern *doc, quint32 toolId, QWidget *parent = nullptr);
explicit DialogCubicBezierPath(const VContainer *data, VAbstractPattern *doc, quint32 toolId,
QWidget *parent = nullptr);
~DialogCubicBezierPath() override;
auto GetPath() const -> VCubicBezierPath;
@ -72,6 +73,15 @@ private slots:
void PointChanged(int row);
void currentPointChanged(int index);
void ValidateAlias();
void NewPointChanged();
void AddPoint();
void RemovePoint();
void MoveTop();
void MoveUp();
void MoveDown();
void MoveBottom();
private:
Q_DISABLE_COPY_MOVE(DialogCubicBezierPath) // NOLINT
@ -94,6 +104,7 @@ private:
auto IsPathValid() const -> bool;
auto ExtractPath() const -> VCubicBezierPath;
void ValidatePath();
void MoveControls();
};
//---------------------------------------------------------------------------------------------------------------------

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>375</width>
<height>439</height>
<width>374</width>
<height>511</height>
</rect>
</property>
<property name="windowTitle">
@ -27,7 +27,62 @@
<attribute name="title">
<string>Tool</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>New point:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxNewPoint"/>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="toolButtonAddPoint">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonRemovePoint">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@ -46,14 +101,116 @@
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="listWidget">
<property name="toolTip">
<string>List of points</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QListWidget" name="listWidget">
<property name="toolTip">
<string>List of points</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonTop">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move on top</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-top">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonUp">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move up</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonDown">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move down</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonBottom">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move on bottom</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-bottom">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5000</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>

View file

@ -80,18 +80,7 @@ using namespace Qt::Literals::StringLiterals;
*/
DialogSplinePath::DialogSplinePath(const VContainer *data, VAbstractPattern *doc, quint32 toolId, QWidget *parent)
: DialogTool(data, doc, toolId, parent),
ui(new Ui::DialogSplinePath),
path(),
newDuplicate(-1),
formulaBaseHeightAngle1(0),
formulaBaseHeightAngle2(0),
formulaBaseHeightLength1(0),
formulaBaseHeightLength2(0),
flagAngle1(),
flagAngle2(),
flagLength1(),
flagLength2(),
flagError(false)
ui(new Ui::DialogSplinePath)
{
ui->setupUi(this);
@ -110,6 +99,7 @@ DialogSplinePath::DialogSplinePath(const VContainer *data, VAbstractPattern *doc
InitOkCancelApply(ui);
bOk->setEnabled(false);
FillComboBoxPoints(ui->comboBoxNewPoint);
FillComboBoxPoints(ui->comboBoxPoint);
FillComboBoxLineColors(ui->comboBoxColor);
FillComboBoxTypeLine(ui->comboBoxPenStyle,
@ -121,6 +111,16 @@ DialogSplinePath::DialogSplinePath(const VContainer *data, VAbstractPattern *doc
connect(ui->listWidget, &QListWidget::currentRowChanged, this, &DialogSplinePath::PointChanged);
connect(ui->comboBoxPoint, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&DialogSplinePath::currentPointChanged);
connect(ui->comboBoxNewPoint, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&DialogSplinePath::NewPointChanged);
connect(ui->toolButtonAddPoint, &QToolButton::clicked, this, &DialogSplinePath::AddPoint);
connect(ui->toolButtonRemovePoint, &QToolButton::clicked, this, &DialogSplinePath::RemovePoint);
connect(ui->toolButtonTop, &QToolButton::clicked, this, &DialogSplinePath::MoveTop);
connect(ui->toolButtonUp, &QToolButton::clicked, this, &DialogSplinePath::MoveUp);
connect(ui->toolButtonDown, &QToolButton::clicked, this, &DialogSplinePath::MoveDown);
connect(ui->toolButtonBottom, &QToolButton::clicked, this, &DialogSplinePath::MoveBottom);
connect(ui->toolButtonExprAngle1, &QPushButton::clicked, this, &DialogSplinePath::FXAngle1);
connect(ui->toolButtonExprAngle2, &QPushButton::clicked, this, &DialogSplinePath::FXAngle2);
@ -194,6 +194,9 @@ void DialogSplinePath::SetPath(const VSplinePath &value)
ui->listWidget->blockSignals(false);
flagError = IsPathValid();
ui->toolButtonRemovePoint->setEnabled(ui->listWidget->count() > 3);
MoveControls();
}
//---------------------------------------------------------------------------------------------------------------------
@ -226,8 +229,7 @@ void DialogSplinePath::ChosenObject(quint32 id, const SceneObject &type)
if (path.CountPoints() == 1)
{
visPath->VisualMode(NULL_ID);
VAbstractMainWindow *window =
qobject_cast<VAbstractMainWindow *>(VAbstractValApplication::VApp()->getMainWindow());
auto *window = qobject_cast<VAbstractMainWindow *>(VAbstractValApplication::VApp()->getMainWindow());
SCASSERT(window != nullptr)
connect(visPath, &VisToolSplinePath::ToolTip, window, &VAbstractMainWindow::ShowToolTip);
@ -322,7 +324,7 @@ void DialogSplinePath::Angle1Changed()
{
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
const QString angle1F = ui->plainTextEditAngle1F->toPlainText();
const qreal angle1 = Visualization::FindValFromUser(angle1F, data->DataVariables());
@ -357,7 +359,7 @@ void DialogSplinePath::Angle2Changed()
{
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
const QString angle2F = ui->plainTextEditAngle2F->toPlainText();
const qreal angle2 = Visualization::FindValFromUser(angle2F, data->DataVariables());
@ -392,7 +394,7 @@ void DialogSplinePath::Length1Changed()
{
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
const QString length1F = ui->plainTextEditLength1F->toPlainText();
const qreal length1 = Visualization::FindLengthFromUser(length1F, data->DataVariables());
@ -418,7 +420,7 @@ void DialogSplinePath::Length2Changed()
{
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
const QString length2F = ui->plainTextEditLength2F->toPlainText();
const qreal length2 = Visualization::FindLengthFromUser(length2F, data->DataVariables());
@ -579,7 +581,7 @@ void DialogSplinePath::EvalAngle1()
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
ShowPointIssue(p.P().name());
}
@ -604,7 +606,7 @@ void DialogSplinePath::EvalAngle2()
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
ShowPointIssue(p.P().name());
}
@ -630,7 +632,7 @@ void DialogSplinePath::EvalLength1()
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
ShowPointIssue(p.P().name());
}
@ -656,7 +658,7 @@ void DialogSplinePath::EvalLength2()
QListWidgetItem *item = ui->listWidget->item(row);
SCASSERT(item != nullptr)
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
ShowPointIssue(p.P().name());
}
@ -670,9 +672,15 @@ void DialogSplinePath::PointChanged(int row)
{
if (ui->listWidget->count() == 0)
{
ui->toolButtonTop->setEnabled(false);
ui->toolButtonUp->setEnabled(false);
ui->toolButtonDown->setEnabled(false);
ui->toolButtonBottom->setEnabled(false);
return;
}
MoveControls();
const auto p = qvariant_cast<VSplinePoint>(ui->listWidget->item(row)->data(Qt::UserRole));
DataPoint(p);
}
@ -684,13 +692,13 @@ void DialogSplinePath::PointChanged(int row)
*/
void DialogSplinePath::currentPointChanged(int index)
{
const quint32 id = qvariant_cast<quint32>(ui->comboBoxPoint->itemData(index));
const auto id = qvariant_cast<quint32>(ui->comboBoxPoint->itemData(index));
QColor color;
try
{
QListWidgetItem *item = ui->listWidget->item(ui->listWidget->currentRow());
VSplinePoint p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
auto p = qvariant_cast<VSplinePoint>(item->data(Qt::UserRole));
const auto point = data->GeometricObject<VPointF>(id);
p.SetP(*point);
@ -747,22 +755,108 @@ void DialogSplinePath::currentPointChanged(int index)
CheckState();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::NewPointChanged()
{
ui->toolButtonAddPoint->setEnabled(ui->comboBoxNewPoint->currentIndex() != -1);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::AddPoint()
{
const auto id = qvariant_cast<quint32>(ui->comboBoxNewPoint->currentData());
const auto point = data->GeometricObject<VPointF>(id);
VSplinePoint p;
p.SetP(*point);
NewItem(p);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
ui->comboBoxNewPoint->blockSignals(true);
ui->comboBoxNewPoint->setCurrentIndex(-1);
ui->comboBoxNewPoint->blockSignals(false);
ui->toolButtonAddPoint->setDisabled(true);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::RemovePoint()
{
if (ui->listWidget->count() <= 3)
{
ui->toolButtonRemovePoint->setDisabled(true);
return;
}
QListWidgetItem *selectedItem = ui->listWidget->currentItem();
if (selectedItem)
{
delete ui->listWidget->takeItem(ui->listWidget->row(selectedItem));
ui->listWidget->setCurrentRow(0);
ui->toolButtonRemovePoint->setDisabled(ui->listWidget->count() <= 3);
}
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::MoveTop()
{
MoveListRowTop(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::MoveUp()
{
MoveListRowUp(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::MoveDown()
{
MoveListRowDown(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::MoveBottom()
{
MoveListRowBottom(ui->listWidget);
SavePath();
flagError = IsPathValid();
CheckState(); // Disable Ok and Apply buttons if something wrong.
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::ShowDialog(bool click)
{
if (click == false)
if (click)
{
if (path.CountPoints() >= 3)
return;
}
if (path.CountPoints() >= 3)
{
emit ToolTip(QString());
if (not data->IsUnique(path.name()))
{
emit ToolTip(QString());
if (not data->IsUnique(path.name()))
{
path.SetDuplicate(DNumber(path.name()));
}
DialogAccepted();
path.SetDuplicate(DNumber(path.name()));
}
DialogAccepted();
}
}
@ -800,6 +894,7 @@ void DialogSplinePath::NewItem(const VSplinePoint &point)
{
bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
bOk->setEnabled(true);
ui->toolButtonRemovePoint->setEnabled(true);
}
DataPoint(point);
@ -970,6 +1065,7 @@ auto DialogSplinePath::IsPathValid() const -> bool
auto DialogSplinePath::ExtractPath() const -> VSplinePath
{
QVector<VSplinePoint> points;
points.reserve(ui->listWidget->count());
for (qint32 i = 0; i < ui->listWidget->count(); ++i)
{
points.append(qvariant_cast<VSplinePoint>(ui->listWidget->item(i)->data(Qt::UserRole)));
@ -1017,6 +1113,17 @@ void DialogSplinePath::InitIcons()
ui->label_11->setPixmap(VTheme::GetPixmapResource(resource, equalIcon));
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSplinePath::MoveControls()
{
const int index = ui->listWidget->currentRow();
ui->toolButtonTop->setEnabled(index > 0);
ui->toolButtonUp->setEnabled(index > 0);
ui->toolButtonDown->setEnabled(index != -1 && index < ui->listWidget->count() - 1);
ui->toolButtonBottom->setEnabled(index != -1 && index < ui->listWidget->count() - 1);
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSplinePath::IsValid() const -> bool
{

View file

@ -79,6 +79,15 @@ protected:
private slots:
void PointChanged(int row);
void currentPointChanged(int index);
void NewPointChanged();
void AddPoint();
void RemovePoint();
void MoveTop();
void MoveUp();
void MoveDown();
void MoveBottom();
void DeployAngle1TextEdit();
void DeployAngle2TextEdit();
@ -104,22 +113,22 @@ private:
Ui::DialogSplinePath *ui;
/** @brief path spline path */
VSplinePath path;
VSplinePath path{};
qint32 newDuplicate;
qint32 newDuplicate{-1};
/** @brief formulaBaseHeight base height defined by dialogui */
int formulaBaseHeightAngle1;
int formulaBaseHeightAngle2;
int formulaBaseHeightLength1;
int formulaBaseHeightLength2;
int formulaBaseHeightAngle1{0};
int formulaBaseHeightAngle2{0};
int formulaBaseHeightLength1{0};
int formulaBaseHeightLength2{0};
/** @brief flagAngle1 true if value of first angle is correct */
QVector<bool> flagAngle1;
QVector<bool> flagAngle2;
QVector<bool> flagLength1;
QVector<bool> flagLength2;
bool flagError;
QVector<bool> flagAngle1{};
QVector<bool> flagAngle2{};
QVector<bool> flagLength1{};
QVector<bool> flagLength2{};
bool flagError{false};
bool flagAlias{true};
QString originAliasSuffix{};
@ -138,6 +147,8 @@ private:
void ShowPointIssue(const QString &pName);
void InitIcons();
void MoveControls();
};
//---------------------------------------------------------------------------------------------------------------------

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>576</width>
<height>707</height>
<width>553</width>
<height>743</height>
</rect>
</property>
<property name="windowTitle">
@ -31,8 +31,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>656</height>
<width>533</width>
<height>692</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
@ -45,7 +45,62 @@
<attribute name="title">
<string>Tool</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>New point:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxNewPoint"/>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="toolButtonAddPoint">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonRemovePoint">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@ -143,7 +198,7 @@
<string>Formula wizard</string>
</property>
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
@ -323,7 +378,7 @@
<string>Formula wizard</string>
</property>
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
@ -516,7 +571,7 @@
<string>Formula wizard</string>
</property>
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
@ -696,7 +751,7 @@
<string>Formula wizard</string>
</property>
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
@ -813,11 +868,100 @@
</layout>
</item>
<item>
<widget class="QListWidget" name="listWidget">
<property name="toolTip">
<string>List of points</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QListWidget" name="listWidget">
<property name="toolTip">
<string>List of points</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonTop">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move on top</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-top">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonUp">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move up</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonDown">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move down</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QToolButton" name="toolButtonBottom">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move on bottom</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-bottom">
<normaloff>../../../../app/tape</normaloff>../../../../app/tape</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5000</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>

View file

@ -86,65 +86,8 @@ VToolSplinePath::VToolSplinePath(const VToolSplinePathInitData &initData, QGraph
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true); // For keyboard input focus
auto InitControlPoint = [this](VControlPointSpline *cPoint)
{
connect(cPoint, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSplinePath::ControlPointChangePosition);
connect(this, &VToolSplinePath::setEnabledPoint, cPoint, &VControlPointSpline::setEnabledPoint);
connect(cPoint, &VControlPointSpline::ShowContextMenu, this, &VToolSplinePath::contextMenuEvent);
connect(cPoint, &VControlPointSpline::Released, this, &VToolSplinePath::CurveReleased);
connect(cPoint, &VControlPointSpline::Selected, this, &VToolSplinePath::CurveSelected);
controlPoints.append(cPoint);
};
const QSharedPointer<VSplinePath> splPath = initData.data->GeometricObject<VSplinePath>(initData.id);
for (qint32 i = 1; i <= splPath->CountSubSpl(); ++i)
{
const VSpline spl = splPath->GetSpline(i);
bool freeAngle1 = true;
if (i > 1)
{
const VSpline prevSpl = splPath->GetSpline(i - 1);
freeAngle1 = qmu::QmuTokenParser::IsSingle(spl.GetStartAngleFormula()) &&
qmu::QmuTokenParser::IsSingle(prevSpl.GetEndAngleFormula());
}
else
{
freeAngle1 = qmu::QmuTokenParser::IsSingle(spl.GetStartAngleFormula());
}
const bool freeLength1 = qmu::QmuTokenParser::IsSingle(spl.GetC1LengthFormula());
auto *controlPoint = new VControlPointSpline(i, SplinePointPosition::FirstPoint,
static_cast<QPointF>(spl.GetP2()), freeAngle1, freeLength1, this);
InitControlPoint(controlPoint);
bool freeAngle2 = true;
if (i < splPath->CountSubSpl())
{
const VSpline nextSpl = splPath->GetSpline(i + 1);
freeAngle2 = qmu::QmuTokenParser::IsSingle(nextSpl.GetStartAngleFormula()) &&
qmu::QmuTokenParser::IsSingle(spl.GetEndAngleFormula());
}
else
{
freeAngle2 = qmu::QmuTokenParser::IsSingle(spl.GetEndAngleFormula());
}
const bool freeLength2 = qmu::QmuTokenParser::IsSingle(spl.GetC2LengthFormula());
controlPoint = new VControlPointSpline(i, SplinePointPosition::LastPoint, static_cast<QPointF>(spl.GetP3()),
freeAngle2, freeLength2, this);
InitControlPoint(controlPoint);
}
VToolSplinePath::RefreshCtrlPoints();
ShowHandles(IsDetailsMode());
InitControlPoints(splPath.data());
ToolCreation(initData.typeCreation);
}
@ -442,11 +385,72 @@ void VToolSplinePath::SetSplinePathAttributes(QDomElement &domElement, const VSp
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::UndoCommandMove(const VSplinePath &oldPath, const VSplinePath &newPath)
{
MoveSplinePath *moveSplPath = new MoveSplinePath(doc, oldPath, newPath, m_id);
auto *moveSplPath = new MoveSplinePath(doc, oldPath, newPath, m_id);
connect(moveSplPath, &VUndoCommand::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
VAbstractApplication::VApp()->getUndoStack()->push(moveSplPath);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::InitControlPoints(const VSplinePath *splPath)
{
auto InitControlPoint = [this](VControlPointSpline *cPoint)
{
connect(cPoint, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSplinePath::ControlPointChangePosition);
connect(this, &VToolSplinePath::setEnabledPoint, cPoint, &VControlPointSpline::setEnabledPoint);
connect(cPoint, &VControlPointSpline::ShowContextMenu, this, &VToolSplinePath::contextMenuEvent);
connect(cPoint, &VControlPointSpline::Released, this, &VToolSplinePath::CurveReleased);
connect(cPoint, &VControlPointSpline::Selected, this, &VToolSplinePath::CurveSelected);
controlPoints.append(cPoint);
};
for (qint32 i = 1; i <= splPath->CountSubSpl(); ++i)
{
const VSpline spl = splPath->GetSpline(i);
bool freeAngle1 = true;
if (i > 1)
{
const VSpline prevSpl = splPath->GetSpline(i - 1);
freeAngle1 = qmu::QmuTokenParser::IsSingle(spl.GetStartAngleFormula()) &&
qmu::QmuTokenParser::IsSingle(prevSpl.GetEndAngleFormula());
}
else
{
freeAngle1 = qmu::QmuTokenParser::IsSingle(spl.GetStartAngleFormula());
}
const bool freeLength1 = qmu::QmuTokenParser::IsSingle(spl.GetC1LengthFormula());
auto *controlPoint = new VControlPointSpline(i, SplinePointPosition::FirstPoint,
static_cast<QPointF>(spl.GetP2()), freeAngle1, freeLength1, this);
InitControlPoint(controlPoint);
bool freeAngle2 = true;
if (i < splPath->CountSubSpl())
{
const VSpline nextSpl = splPath->GetSpline(i + 1);
freeAngle2 = qmu::QmuTokenParser::IsSingle(nextSpl.GetStartAngleFormula()) &&
qmu::QmuTokenParser::IsSingle(spl.GetEndAngleFormula());
}
else
{
freeAngle2 = qmu::QmuTokenParser::IsSingle(spl.GetEndAngleFormula());
}
const bool freeLength2 = qmu::QmuTokenParser::IsSingle(spl.GetC2LengthFormula());
controlPoint = new VControlPointSpline(i, SplinePointPosition::LastPoint, static_cast<QPointF>(spl.GetP3()),
freeAngle2, freeLength2, this);
InitControlPoint(controlPoint);
}
VToolSplinePath::RefreshCtrlPoints();
VToolSplinePath::ShowHandles(IsDetailsMode());
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief UpdatePathPoints update spline path in pattern file.
@ -566,20 +570,9 @@ void VToolSplinePath::SaveDialog(QDomElement &domElement, QList<quint32> &oldDep
AddDependence(newDependencies, splPath.at(i).P().id());
}
for (qint32 i = 1; i <= splPath.CountSubSpl(); ++i)
{
VSpline spl = splPath.GetSpline(i);
qint32 j = i * 2;
controlPoints[j - 2]->blockSignals(true);
controlPoints[j - 1]->blockSignals(true);
controlPoints[j - 2]->setPos(static_cast<QPointF>(spl.GetP2()));
controlPoints[j - 1]->setPos(static_cast<QPointF>(spl.GetP3()));
controlPoints[j - 2]->blockSignals(false);
controlPoints[j - 1]->blockSignals(false);
}
qDeleteAll(controlPoints);
controlPoints.clear();
InitControlPoints(&splPath);
doc->SetAttributeOrRemoveIf<QString>(domElement, AttrNotes, dialogTool->GetNotes(),
[](const QString &notes) noexcept { return notes.isEmpty(); });
@ -721,9 +714,9 @@ void VToolSplinePath::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
const QList<QGraphicsView *> viewList = scene()->views();
if (not viewList.isEmpty())
{
if (VMainGraphicsView *view = qobject_cast<VMainGraphicsView *>(viewList.at(0)))
if (auto *view = qobject_cast<VMainGraphicsView *>(viewList.at(0)))
{
VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
auto *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
SCASSERT(currentScene)
const QPointF cursorPosition = currentScene->getScenePos();
const qreal scale = SceneScale(scene());
@ -825,6 +818,11 @@ void VToolSplinePath::RefreshCtrlPoints()
{
const qint32 j = i * 2;
if (j - 2 >= controlPoints.size())
{
break;
}
controlPoints[j - 2]->blockSignals(true);
controlPoints[j - 1]->blockSignals(true);

View file

@ -142,6 +142,8 @@ private:
void SetSplinePathAttributes(QDomElement &domElement, const VSplinePath &path);
void UndoCommandMove(const VSplinePath &oldPath, const VSplinePath &newPath);
void InitControlPoints(const VSplinePath *splPath);
};
#endif // VTOOLSPLINEPATH_H

View file

@ -245,20 +245,13 @@ void VControlPointSpline::SetCtrlLine(const QPointF &controlPoint, const QPointF
QLineF circleLine(QPointF(), splinePoint - controlPoint);
const qreal radius = ScaledRadius(SceneScale(scene()));
if (circleLine.length() > radius)
{
QPointF p1, p2;
VGObject::LineIntersectCircle(QPointF(), radius, circleLine, p1, p2);
QLineF line(splinePoint - controlPoint, p1);
controlLine->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
controlLine->setLine(line);
controlLine->setVisible(not line.isNull());
controlLine->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
}
else
{
controlLine->setVisible(false);
}
QPointF p1, p2;
VGObject::LineIntersectCircle(QPointF(), radius, circleLine, p1, p2);
QLineF line(splinePoint - controlPoint, p1);
controlLine->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
controlLine->setLine(line);
controlLine->setVisible(not line.isNull());
controlLine->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
}
//---------------------------------------------------------------------------------------------------------------------