Allow insertion of multiple nodes. Closes #80

This commit is contained in:
Roman Telezhynskyi 2020-11-21 19:04:31 +02:00
parent c31966145e
commit 28d2358825
9 changed files with 172 additions and 112 deletions

View File

@ -1,5 +1,6 @@
# Version 0.7.40 (unreleased)
- New function Warning.
- [smart-pattern/valentina#80] Allow insertion of multiple nodes.
# Version 0.7.39 Nov 17, 2020
- Fix crash for Line tool notes.

View File

@ -1336,7 +1336,7 @@ void MainWindow::ClosedDialogInsertNode(int result)
{
const QPointer<DialogInsertNode> dTool = qobject_cast<DialogInsertNode *>(dialogTool);
SCASSERT(not dTool.isNull())
VToolSeamAllowance::InsertNode(dTool->GetNode(), dTool->GetPieceId(), sceneDetails, pattern, doc);
VToolSeamAllowance::InsertNode(dTool->GetNodes(), dTool->GetPieceId(), sceneDetails, pattern, doc);
}
ArrowTool(true);
doc->LiteParseTree(Document::LiteParse);
@ -1493,9 +1493,12 @@ void MainWindow::ToolTrueDarts(bool checked)
//---------------------------------------------------------------------------------------------------------------------
void MainWindow::ToolInsertNode(bool checked)
{
ToolSelectAllDrawObjects();
ToolSelectOperationObjects();
const QString tooltip = tr("Select one or more objects, hold <b>%1</b> - for multiple selection, "
"<b>%2</b> - finish creation")
.arg(VModifierKey::Control(), VModifierKey::EnterKey());
SetToolButton<DialogInsertNode>(checked, Tool::InsertNode, "://cursor/insert_node_cursor.png",
tr("Select an item to insert"), &MainWindow::ClosedDialogInsertNode);
tooltip, &MainWindow::ClosedDialogInsertNode);
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -449,7 +449,7 @@ QString DialogTool::GetNodeName(const VPieceNode &node, bool showPassmarkDetails
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::NewNodeItem(QListWidget *listWidget, const VPieceNode &node, bool showPassmark)
void DialogTool::NewNodeItem(QListWidget *listWidget, const VPieceNode &node, bool showPassmark, bool showExclusion)
{
SCASSERT(listWidget != nullptr);
SCASSERT(node.GetId() > NULL_ID);
@ -485,7 +485,7 @@ void DialogTool::NewNodeItem(QListWidget *listWidget, const VPieceNode &node, bo
if(canAddNewPoint)
{
QListWidgetItem *item = new QListWidgetItem(name);
item->setFont(NodeFont(item->font(), node.IsExcluded()));
item->setFont(NodeFont(item->font(), showExclusion ? node.IsExcluded() : false));
item->setData(Qt::UserRole, QVariant::fromValue(node));
listWidget->addItem(item);
listWidget->setCurrentRow(listWidget->count()-1);

View File

@ -214,7 +214,8 @@ protected:
virtual void SaveData() {}
quint32 DNumber(const QString &baseName) const;
QString GetNodeName(const VPieceNode &node, bool showPassmarkDetails = false) const;
void NewNodeItem(QListWidget *listWidget, const VPieceNode &node, bool showPassmark = true);
void NewNodeItem(QListWidget *listWidget, const VPieceNode &node, bool showPassmark = true,
bool showExclusion = true);
void InitNodeAngles(QComboBox *box);
private:

View File

@ -30,24 +30,24 @@
#include "ui_dialoginsertnode.h"
#include "../vpatterndb/vcontainer.h"
#include <QMenu>
//---------------------------------------------------------------------------------------------------------------------
DialogInsertNode::DialogInsertNode(const VContainer *data, quint32 toolId, QWidget *parent)
: DialogTool(data, toolId, parent),
ui(new Ui::DialogInsertNode),
m_node(),
m_flagItem(false),
m_flagError(false)
ui(new Ui::DialogInsertNode)
{
ui->setupUi(this);
InitOkCancel(ui);
CheckPieces();
CheckItem();
connect(ui->comboBoxPiece, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]()
{
CheckPieces();
});
connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogInsertNode::ShowContextMenu);
}
//---------------------------------------------------------------------------------------------------------------------
@ -96,73 +96,134 @@ void DialogInsertNode::SetPieceId(quint32 id)
}
//---------------------------------------------------------------------------------------------------------------------
VPieceNode DialogInsertNode::GetNode() const
QVector<VPieceNode> DialogInsertNode::GetNodes() const
{
return m_node;
QVector<VPieceNode> nodes;
for (qint32 i = 0; i < ui->listWidget->count(); ++i)
{
nodes.append(qvariant_cast<VPieceNode>(ui->listWidget->item(i)->data(Qt::UserRole)));
}
return nodes;
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::SetNode(const VPieceNode &node)
void DialogInsertNode::ShowDialog(bool click)
{
m_node = node;
m_flagItem = true;
QString name = tr("Uknown");
try
if (not click)
{
name = data->GetGObject(m_node.GetId())->ObjectName();
}
catch (const VExceptionBadId &)
{
m_flagItem = false;
// Broken id
}
ui->labelItemName->setText(name);
ui->labelItemName->setToolTip(name);
CheckItem();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::ChosenObject(quint32 id, const SceneObject &type)
{
if (not prepare)
{
VPieceNode node;
switch (type)
if (m_nodes.isEmpty())
{
case SceneObject::Arc:
node = VPieceNode(id, Tool::NodeArc);
break;
case SceneObject::ElArc:
node = VPieceNode(id, Tool::NodeElArc);
break;
case SceneObject::Point:
node = VPieceNode(id, Tool::NodePoint);
break;
case SceneObject::Spline:
node = VPieceNode(id, Tool::NodeSpline);
break;
case SceneObject::SplinePath:
node = VPieceNode(id, Tool::NodeSplinePath);
break;
case (SceneObject::Line):
case (SceneObject::Detail):
case (SceneObject::Unknown):
default:
qDebug() << "Got wrong scene object. Ignore.";
return;
return;
}
node.SetExcluded(true);
SetNode(node);
for (auto &node : m_nodes)
{
NewNodeItem(ui->listWidget, node, false, false);
}
m_nodes.clear();
CheckNodes();
prepare = true;
this->setModal(true);
this->show();
setModal(true);
emit ToolTip(QString());
show();
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::SelectedObject(bool selected, quint32 object, quint32 tool)
{
Q_UNUSED(tool)
if (prepare)
{
return;
}
auto nodeIterator = std::find_if(m_nodes.begin(), m_nodes.end(),
[object](const VPieceNode &node) { return node.GetId() == object; });
if (selected)
{
if (nodeIterator == m_nodes.cend())
{
GOType type = GOType::Unknown;
try
{
type = data->GetGObject(object)->getType();
}
catch (const VExceptionBadId &)
{
qDebug() << "Cannot find an object with id" << object;
return;
}
VPieceNode node;
switch (type)
{
case GOType::Arc:
node = VPieceNode(object, Tool::NodeArc);
break;
case GOType::EllipticalArc:
node = VPieceNode(object, Tool::NodeElArc);
break;
case GOType::Point:
node = VPieceNode(object, Tool::NodePoint);
break;
case GOType::Spline:
case GOType::CubicBezier:
node = VPieceNode(object, Tool::NodeSpline);
break;
case GOType::SplinePath:
case GOType::CubicBezierPath:
node = VPieceNode(object, Tool::NodeSplinePath);
break;
case GOType::Unknown:
case GOType::PlaceLabel:
default:
qDebug() << "Got unexpected object type. Ignore.";
return;
}
node.SetExcluded(true);
m_nodes.append(node);
}
}
else
{
if (nodeIterator != m_nodes.end())
{
m_nodes.erase(nodeIterator);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::ShowContextMenu(const QPoint &pos)
{
const int row = ui->listWidget->currentRow();
if (ui->listWidget->count() == 0 || row == -1 || row >= ui->listWidget->count())
{
return;
}
QScopedPointer<QMenu> menu(new QMenu());
QListWidgetItem *rowItem = ui->listWidget->item(row);
SCASSERT(rowItem != nullptr);
QAction *actionDelete = menu->addAction(QIcon::fromTheme(editDeleteIcon), tr("Delete"));
QAction *selectedAction = menu->exec(ui->listWidget->viewport()->mapToGlobal(pos));
if (selectedAction == actionDelete)
{
delete rowItem;
}
CheckNodes();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::CheckPieces()
{
@ -182,10 +243,8 @@ void DialogInsertNode::CheckPieces()
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::CheckItem()
void DialogInsertNode::CheckNodes()
{
QColor color;
m_flagItem ? color = OkColor(this) : color = errorColor;
ChangeColor(ui->labelItem, color);
m_flagNodes = ui->listWidget->count() > 0;
CheckState();
}

View File

@ -50,31 +50,35 @@ public:
quint32 GetPieceId() const;
void SetPieceId(quint32 id);
VPieceNode GetNode() const;
void SetNode(const VPieceNode &node);
QVector<VPieceNode> GetNodes() const;
virtual void ShowDialog(bool click) override;
public slots:
virtual void ChosenObject(quint32 id, const SceneObject &type) override;
virtual void SelectedObject(bool selected, quint32 object, quint32 tool) override;
protected:
virtual bool IsValid() const final;
private slots:
void ShowContextMenu(const QPoint &pos);
private:
Q_DISABLE_COPY(DialogInsertNode)
Ui::DialogInsertNode *ui;
VPieceNode m_node;
bool m_flagItem;
bool m_flagError;
QVector<VPieceNode> m_nodes{};
bool m_flagNodes{false};
bool m_flagError{false};
void CheckPieces();
void CheckItem();
void CheckNodes();
};
//---------------------------------------------------------------------------------------------------------------------
inline bool DialogInsertNode::IsValid() const
{
return m_flagItem && m_flagError;
return m_flagNodes && m_flagError;
}
#endif // DIALOGINSERTNODE_H

View File

@ -6,45 +6,34 @@
<rect>
<x>0</x>
<y>0</y>
<width>244</width>
<height>103</height>
<width>411</width>
<height>399</height>
</rect>
</property>
<property name="windowTitle">
<string>Insert node</string>
<string>Insert nodes</string>
</property>
<property name="windowIcon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
<iconset resource="../../../../vmisc/share/resources/icon.qrc">
<normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelItem">
<property name="text">
<string>Item:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelItemName">
<property name="text">
<string notr="true">item name</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelPiece">
<property name="text">
<string>Piece:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxPiece"/>
</item>
</layout>
@ -62,7 +51,7 @@
</layout>
</widget>
<resources>
<include location="../../../vmisc/share/resources/icon.qrc"/>
<include location="../../../../vmisc/share/resources/icon.qrc"/>
</resources>
<connections>
<connection>

View File

@ -223,14 +223,14 @@ void VToolSeamAllowance::RemoveWithConfirm(bool ask)
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSeamAllowance::InsertNode(VPieceNode node, quint32 pieceId, VMainGraphicsScene *scene,
void VToolSeamAllowance::InsertNode(const QVector<VPieceNode> &nodes, quint32 pieceId, VMainGraphicsScene *scene,
VContainer *data, VAbstractPattern *doc)
{
SCASSERT(scene != nullptr)
SCASSERT(data != nullptr)
SCASSERT(doc != nullptr)
if (pieceId > NULL_ID)
if (pieceId > NULL_ID && not nodes.isEmpty())
{
VPiece oldDet;
try
@ -244,21 +244,24 @@ void VToolSeamAllowance::InsertNode(VPieceNode node, quint32 pieceId, VMainGraph
VPiece newDet = oldDet;
const quint32 id = PrepareNode(node, scene, doc, data);
if (id == NULL_ID)
for (auto node : nodes)
{
return;
const quint32 id = PrepareNode(node, scene, doc, data);
if (id == NULL_ID)
{
return;
}
node.SetId(id);
newDet.GetPath().Append(node);
// Seam allowance tool already initializated and can't init the node
VToolSeamAllowance *saTool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(pieceId));
SCASSERT(saTool != nullptr);
InitNode(node, scene, data, doc, saTool);
}
node.SetId(id);
newDet.GetPath().Append(node);
// Seam allowance tool already initializated and can't init the node
VToolSeamAllowance *saTool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(pieceId));
SCASSERT(saTool != nullptr);
InitNode(node, scene, data, doc, saTool);
qApp->getUndoStack()->push(new SavePieceOptions(oldDet, newDet, doc, pieceId));
}
}

View File

@ -91,8 +91,8 @@ public:
void RemoveWithConfirm(bool ask);
static void InsertNode(VPieceNode node, quint32 pieceId, VMainGraphicsScene *scene, VContainer *data,
VAbstractPattern *doc);
static void InsertNode(const QVector<VPieceNode> &nodes, quint32 pieceId, VMainGraphicsScene *scene,
VContainer *data, VAbstractPattern *doc);
static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece);
static void AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, CustomSARecord record);