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) # Version 0.7.40 (unreleased)
- New function Warning. - New function Warning.
- [smart-pattern/valentina#80] Allow insertion of multiple nodes.
# Version 0.7.39 Nov 17, 2020 # Version 0.7.39 Nov 17, 2020
- Fix crash for Line tool notes. - 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); const QPointer<DialogInsertNode> dTool = qobject_cast<DialogInsertNode *>(dialogTool);
SCASSERT(not dTool.isNull()) SCASSERT(not dTool.isNull())
VToolSeamAllowance::InsertNode(dTool->GetNode(), dTool->GetPieceId(), sceneDetails, pattern, doc); VToolSeamAllowance::InsertNode(dTool->GetNodes(), dTool->GetPieceId(), sceneDetails, pattern, doc);
} }
ArrowTool(true); ArrowTool(true);
doc->LiteParseTree(Document::LiteParse); doc->LiteParseTree(Document::LiteParse);
@ -1493,9 +1493,12 @@ void MainWindow::ToolTrueDarts(bool checked)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void MainWindow::ToolInsertNode(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", 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(listWidget != nullptr);
SCASSERT(node.GetId() > NULL_ID); SCASSERT(node.GetId() > NULL_ID);
@ -485,7 +485,7 @@ void DialogTool::NewNodeItem(QListWidget *listWidget, const VPieceNode &node, bo
if(canAddNewPoint) if(canAddNewPoint)
{ {
QListWidgetItem *item = new QListWidgetItem(name); 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)); item->setData(Qt::UserRole, QVariant::fromValue(node));
listWidget->addItem(item); listWidget->addItem(item);
listWidget->setCurrentRow(listWidget->count()-1); listWidget->setCurrentRow(listWidget->count()-1);

View File

@ -214,7 +214,8 @@ protected:
virtual void SaveData() {} virtual void SaveData() {}
quint32 DNumber(const QString &baseName) const; quint32 DNumber(const QString &baseName) const;
QString GetNodeName(const VPieceNode &node, bool showPassmarkDetails = false) 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); void InitNodeAngles(QComboBox *box);
private: private:

View File

@ -30,24 +30,24 @@
#include "ui_dialoginsertnode.h" #include "ui_dialoginsertnode.h"
#include "../vpatterndb/vcontainer.h" #include "../vpatterndb/vcontainer.h"
#include <QMenu>
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
DialogInsertNode::DialogInsertNode(const VContainer *data, quint32 toolId, QWidget *parent) DialogInsertNode::DialogInsertNode(const VContainer *data, quint32 toolId, QWidget *parent)
: DialogTool(data, toolId, parent), : DialogTool(data, toolId, parent),
ui(new Ui::DialogInsertNode), ui(new Ui::DialogInsertNode)
m_node(),
m_flagItem(false),
m_flagError(false)
{ {
ui->setupUi(this); ui->setupUi(this);
InitOkCancel(ui); InitOkCancel(ui);
CheckPieces(); CheckPieces();
CheckItem();
connect(ui->comboBoxPiece, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]() connect(ui->comboBoxPiece, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]()
{ {
CheckPieces(); CheckPieces();
}); });
connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogInsertNode::ShowContextMenu);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -96,72 +96,133 @@ 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; if (not click)
m_flagItem = true; {
QString name = tr("Uknown"); if (m_nodes.isEmpty())
{
return;
}
for (auto &node : m_nodes)
{
NewNodeItem(ui->listWidget, node, false, false);
}
m_nodes.clear();
CheckNodes();
prepare = true;
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 try
{ {
name = data->GetGObject(m_node.GetId())->ObjectName(); type = data->GetGObject(object)->getType();
} }
catch (const VExceptionBadId &) catch (const VExceptionBadId &)
{ {
m_flagItem = false; qDebug() << "Cannot find an object with id" << object;
// Broken id return;
} }
ui->labelItemName->setText(name);
ui->labelItemName->setToolTip(name);
CheckItem();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::ChosenObject(quint32 id, const SceneObject &type)
{
if (not prepare)
{
VPieceNode node; VPieceNode node;
switch (type) switch (type)
{ {
case SceneObject::Arc: case GOType::Arc:
node = VPieceNode(id, Tool::NodeArc); node = VPieceNode(object, Tool::NodeArc);
break; break;
case SceneObject::ElArc: case GOType::EllipticalArc:
node = VPieceNode(id, Tool::NodeElArc); node = VPieceNode(object, Tool::NodeElArc);
break; break;
case SceneObject::Point: case GOType::Point:
node = VPieceNode(id, Tool::NodePoint); node = VPieceNode(object, Tool::NodePoint);
break; break;
case SceneObject::Spline: case GOType::Spline:
node = VPieceNode(id, Tool::NodeSpline); case GOType::CubicBezier:
node = VPieceNode(object, Tool::NodeSpline);
break; break;
case SceneObject::SplinePath: case GOType::SplinePath:
node = VPieceNode(id, Tool::NodeSplinePath); case GOType::CubicBezierPath:
node = VPieceNode(object, Tool::NodeSplinePath);
break; break;
case (SceneObject::Line): case GOType::Unknown:
case (SceneObject::Detail): case GOType::PlaceLabel:
case (SceneObject::Unknown):
default: default:
qDebug() << "Got wrong scene object. Ignore."; qDebug() << "Got unexpected object type. Ignore.";
return; return;
} }
node.SetExcluded(true); node.SetExcluded(true);
SetNode(node); m_nodes.append(node);
prepare = true;
this->setModal(true);
this->show();
} }
} }
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() void DialogInsertNode::CheckPieces()
@ -182,10 +243,8 @@ void DialogInsertNode::CheckPieces()
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void DialogInsertNode::CheckItem() void DialogInsertNode::CheckNodes()
{ {
QColor color; m_flagNodes = ui->listWidget->count() > 0;
m_flagItem ? color = OkColor(this) : color = errorColor;
ChangeColor(ui->labelItem, color);
CheckState(); CheckState();
} }

View File

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

View File

@ -6,45 +6,34 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>244</width> <width>411</width>
<height>103</height> <height>399</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Insert node</string> <string>Insert nodes</string>
</property> </property>
<property name="windowIcon"> <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> <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy"> <property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum> <enum>QFormLayout::ExpandingFieldsGrow</enum>
</property> </property>
<item row="0" column="0"> <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"> <widget class="QLabel" name="labelPiece">
<property name="text"> <property name="text">
<string>Piece:</string> <string>Piece:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="comboBoxPiece"/> <widget class="QComboBox" name="comboBoxPiece"/>
</item> </item>
</layout> </layout>
@ -62,7 +51,7 @@
</layout> </layout>
</widget> </widget>
<resources> <resources>
<include location="../../../vmisc/share/resources/icon.qrc"/> <include location="../../../../vmisc/share/resources/icon.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <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) VContainer *data, VAbstractPattern *doc)
{ {
SCASSERT(scene != nullptr) SCASSERT(scene != nullptr)
SCASSERT(data != nullptr) SCASSERT(data != nullptr)
SCASSERT(doc != nullptr) SCASSERT(doc != nullptr)
if (pieceId > NULL_ID) if (pieceId > NULL_ID && not nodes.isEmpty())
{ {
VPiece oldDet; VPiece oldDet;
try try
@ -244,6 +244,8 @@ void VToolSeamAllowance::InsertNode(VPieceNode node, quint32 pieceId, VMainGraph
VPiece newDet = oldDet; VPiece newDet = oldDet;
for (auto node : nodes)
{
const quint32 id = PrepareNode(node, scene, doc, data); const quint32 id = PrepareNode(node, scene, doc, data);
if (id == NULL_ID) if (id == NULL_ID)
{ {
@ -258,6 +260,7 @@ void VToolSeamAllowance::InsertNode(VPieceNode node, quint32 pieceId, VMainGraph
SCASSERT(saTool != nullptr); SCASSERT(saTool != nullptr);
InitNode(node, scene, data, doc, saTool); InitNode(node, scene, data, doc, saTool);
}
qApp->getUndoStack()->push(new SavePieceOptions(oldDet, newDet, doc, pieceId)); qApp->getUndoStack()->push(new SavePieceOptions(oldDet, newDet, doc, pieceId));
} }

View File

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