From c4b5c3dccb7779b43db6fbe99e4a4f9b309ffc72 Mon Sep 17 00:00:00 2001 From: Patrick Proy Date: Wed, 28 May 2014 21:16:41 +0200 Subject: [PATCH] Apply changes to DOM tree. No validation yet. --HG-- branch : XML Editor --- src/app/dialogs/app/dialogpatternxmledit.cpp | 169 +++++++++++++++++-- src/app/dialogs/app/dialogpatternxmledit.h | 74 ++++++++ src/app/dialogs/app/dialogpatternxmledit.ui | 10 ++ 3 files changed, 236 insertions(+), 17 deletions(-) diff --git a/src/app/dialogs/app/dialogpatternxmledit.cpp b/src/app/dialogs/app/dialogpatternxmledit.cpp index dc1211f7a..21044fd26 100644 --- a/src/app/dialogs/app/dialogpatternxmledit.cpp +++ b/src/app/dialogs/app/dialogpatternxmledit.cpp @@ -45,22 +45,20 @@ DialogPatternXmlEdit::DialogPatternXmlEdit(QWidget *parent, VPattern *xmldoc) { ui->setupUi(this); - xmlmodel = new VXMLTreeView(); - - doc=xmldoc; - root = doc->documentElement(); - // disable edit trigers : - //ui->treeView_main->editTriggers(QTreeView::NoEditTriggers); + this->xmlmodel = new VXMLTreeView(); + this->doc=xmldoc; + this->root = this->doc->documentElement(); + // disable edit trigers (no edition directly on tree) ui->treeView_main->setEditTriggers(QTreeView::NoEditTriggers); ui->treeView_main->setWindowTitle("XML"); - rootNode = xmlmodel->invisibleRootItem(); + this->rootNode = this->xmlmodel->invisibleRootItem(); int drawnum=xmldoc->elementsByTagName("draw").size(); - rootBases = new VXMLTreeElement*[drawnum+1]; - rootBasesNum=1; - rootBases[0]=new VXMLTreeElement("Valentina", VXMLTreeElement::TypeRoot, root, false); + this->rootBases = new VXMLTreeElement*[drawnum+1]; + this->rootBasesNum=1; + this->rootBases[0]=new VXMLTreeElement("Valentina", VXMLTreeElement::TypeRoot, root, false); // TODO : OOM exception. @@ -68,9 +66,9 @@ DialogPatternXmlEdit::DialogPatternXmlEdit(QWidget *parent, VPattern *xmldoc) ui->comboBox_Base_Selection->addItem(tr("All pattern pieces"), QVariant(0)); //rootBases[0]=(QDomNode) doc->DocumentNode; - rootNode->appendRow(standard_base); + this->rootNode->appendRow(standard_base); - ReadNodes(root, standard_base, xmlmodel, false); + this->ReadNodes(this->root, standard_base, this->xmlmodel, false); ui->treeView_main->setModel(xmlmodel); @@ -95,6 +93,64 @@ DialogPatternXmlEdit::DialogPatternXmlEdit(QWidget *parent, VPattern *xmldoc) connect(ui->pushButton_Remove_Node, &QPushButton::clicked, this, &DialogPatternXmlEdit::ButtonDeleteNode); } +bool DialogPatternXmlEdit::CheckChanges(QString &message, QDomNode testRoot) +{ + message="OK"; + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogPatternXmlEdit::ApplyAttributeChange(QDomNode domElement, QString name, QString value) +{ + if (domElement.isElement() == false) + { + return false; + } + domElement.toElement().setAttribute(name,value); + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogPatternXmlEdit::ApplyNodeChange(QDomNode domElement, QString name, QString value) +{ + if (domElement.isElement() == false) + { + return false; + } + domElement.toElement().setNodeValue(value); + domElement.toElement().setTagName(name); + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogPatternXmlEdit::ApplyNodeAdd(QDomNode domElement, VXMLTreeElement* treeElement, QString name, QString value) +{ + QDomElement newnode = domElement.ownerDocument().createElement(name); + //Q_ASSERT(newnode != nullptr); + newnode.setNodeValue(value); + domElement.appendChild(newnode); + treeElement->SetDocNode(newnode); + return true; +} + +bool DialogPatternXmlEdit::ApplyAttributeDelete(QDomNode domElement, QString name) +{ + if (domElement.isElement() == false) + { + return false; + } + domElement.toElement().removeAttribute(name); + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogPatternXmlEdit::ApplyNodeDelete(QDomNode domElement) +{ + QDomNode mother=domElement.parentNode(); + mother.removeChild(domElement); + return true; +} + //--------------------------------------------------------------------------------------------------------------------- void DialogPatternXmlEdit::ButtonDeleteNode() { @@ -431,6 +487,83 @@ void DialogPatternXmlEdit::ButtonApplyChangesClicked() } QMessageBox::information(this, "Changes (not REALLY applied for now)", Changes); // TODO : clear stack and apply + + currentChange=this->changeStackRoot; + // copy DOM + QDomNode newroot = root.cloneNode(true); + + QString name, value; + while (currentChange != nullptr) + { + if (currentChange->type == DialogPatternXmlEdit::ChangeTypeModify) + { + name=(currentChange->changedText == false) ? currentChange->element->GettreeNodeName() + : *currentChange->newText; + value=(currentChange->changedValue == false) ? currentChange->element->GettreeNodeValue() + : *currentChange->newValue; + if (currentChange->element->GetelementType() == VXMLTreeElement::TypeAttr) + { + + this->ApplyAttributeChange(currentChange->element->GetDocNode(), name, value); + } + else if (currentChange->element->GetelementType() == VXMLTreeElement::TypeNode) + { + this->ApplyNodeChange(currentChange->element->GetDocNode(), name, value); + } + else + { + QMessageBox::warning(this, "Error in changes", "Invalid node type"); + return; + } + } + else if (currentChange->type == DialogPatternXmlEdit::ChangeTypeAdd) + { + name=(currentChange->changedText == false) ? currentChange->element->GettreeNodeName() + : *currentChange->newText; + value=(currentChange->changedValue == false) ? currentChange->element->GettreeNodeValue() + : *currentChange->newValue; + if (currentChange->element->GetelementType() == VXMLTreeElement::TypeAttr) + { + this->ApplyAttributeChange(currentChange->element->GetFatherElement()->GetDocNode(), name, value); + } + else if (currentChange->element->GetelementType() == VXMLTreeElement::TypeNode) + { + this->ApplyNodeAdd(currentChange->element->GetFatherElement()->GetDocNode(), currentChange->element, + name, value); + } + else + { + QMessageBox::warning(this, "Error in changes", "Invalid node type"); + return; + } + } + else if (currentChange->type == DialogPatternXmlEdit::ChangeTypeDelete) + { + if (currentChange->element->GetelementType() == VXMLTreeElement::TypeAttr) + { + name=(currentChange->changedText == false) ? currentChange->element->GettreeNodeName() + : *currentChange->newText; + this->ApplyAttributeDelete(currentChange->element->GetDocNode(), name); + } + else if (currentChange->element->GetelementType() == VXMLTreeElement::TypeNode) + { + this->ApplyNodeDelete(currentChange->element->GetDocNode().parentNode()); + } + else + { + QMessageBox::warning(this, "Error in changes", "Invalid node type"); + return; + } + } + currentChange=currentChange->next; + } + QString message; + if (this->CheckChanges(message,newroot) == false) + { + QMessageBox::warning(this, "Error in changes", message); + return; + } + this->doc->FullUpdateTree(); } //--------------------------------------------------------------------------------------------------------------------- @@ -586,17 +719,17 @@ void DialogPatternXmlEdit::ButtonAddSonClicked() { return; } - QString value = QInputDialog::getText(this, tr("Node Value (may be empty)"), - tr("Value:"), QLineEdit::Normal, - "", &ok); + QString value = QInputDialog::getText(this, tr("Node Value (may be empty)"),tr("Value:"), + QLineEdit::Normal,"", &ok); if (ok==false) { return; } - // create element tree but do not add attribute in DOM (will be done in apply). + // create element tree and put father tree element to catch up with DOM tree. QDomNode empty; VXMLTreeElement* tElement = new VXMLTreeElement(name, VXMLTreeElement::TypeNode, empty, true); + tElement->SetFatherElement(this->currentNodeEdited); if (value.isEmpty() == false) { @@ -656,6 +789,8 @@ void DialogPatternXmlEdit::ButtonAddAttributeClicked() // create element tree but do not add attribute in DOM (will be done in apply). VXMLTreeElement* tElement = new VXMLTreeElement(name, VXMLTreeElement::TypeAttr, empty, true); + // set parent node. + tElement->SetFatherElement(this->currentNodeEdited); tElement->SetTreeNodeValue(value); currentNodeEdited->appendRow(tElement); @@ -1063,7 +1198,7 @@ const short int VXMLTreeElement::TypeRoot=3; // ^ VXMLTreeElement::VXMLTreeElement(QString name, int nodetype, QDomNode source, bool editor) : QStandardItem(name), DocNode(source), addedNode(editor), elementType(nodetype), treeNodeValue(""), - treeNodeValueSet(false), treeNodeName(name), selectable(true) + treeNodeValueSet(false), treeNodeName(name), selectable(true), parentnode(nullptr) { if (editor == false) { diff --git a/src/app/dialogs/app/dialogpatternxmledit.h b/src/app/dialogs/app/dialogpatternxmledit.h index 4a8fccdc7..51e3e316f 100644 --- a/src/app/dialogs/app/dialogpatternxmledit.h +++ b/src/app/dialogs/app/dialogpatternxmledit.h @@ -74,8 +74,23 @@ public: * @return current document node */ QDomNode GetDocNode(); + /** + * @brief SetDocNode set tree element DomNode + * @param node + */ + inline void SetDocNode(QDomNode node) + { + this->DocNode=node; + } + inline void SetAddedNode(bool state) {this->addedNode=state;} + inline bool GetAddedNode() {return this->addedNode;} + QString GettreeNodeName(); QString GettreeNodeValue(); + /** + * @brief GettreeNodeValueSet check if value has been set + * @return true if value is set + */ bool GettreeNodeValueSet(); void SetTreeNodeName(QString value); /** @@ -86,12 +101,26 @@ public: bool IsSelectable(); void SetSetlectable(bool value); + inline void SetFatherElement(VXMLTreeElement* parent) + { + this->parentnode=parent; + } + inline VXMLTreeElement* GetFatherElement() + { + return this->parentnode; + } + private: /** * @brief DocNode : link to current document node */ QDomNode DocNode; + /** + * @brief parentnode parent node of this element. If null then the DocNode must be valid + */ + VXMLTreeElement* parentnode; + /** * @brief addedNode : true if node is added by editor (implies empty DocNode) */ @@ -280,6 +309,51 @@ public: */ bool DeleteNodeAndSons(VXMLTreeElement *currentNode, bool onlydeactivate); + /** + * @brief ApplyAttributeChange change or add attribute for node + * @param domElement : node containing attribute + * @param name + * @param value + * @return true on success + */ + bool ApplyAttributeChange(QDomNode domElement, QString name, QString value); + /** + * @brief ApplyNodeChange Change name or text content of node + * @param domElement node + * @param name + * @param value text content of node + * @return true on success + */ + bool ApplyNodeChange(QDomNode domElement, QString name, QString value); + /** + * @brief ApplyNodeAdd add node as child of domElement and set DocNode of treeElement + * @param domElement + * @param treeElement the XMLTreeElement of added node + * @param name + * @param value + * @return true on success + */ + bool ApplyNodeAdd(QDomNode domElement, VXMLTreeElement* treeElement, QString name, QString value); + /** + * @brief ApplyAttributeDelete delete attribute for node + * @param domElement + * @param name attribute name + * @return true on success + */ + bool ApplyAttributeDelete(QDomNode domElement, QString name); + /** + * @brief ApplyNodeDelete delete node domElement + * @param domElement + * @return true on success + */ + bool ApplyNodeDelete(QDomNode domElement); + /** + * @brief CheckChanges Check if changes made are OK + * @param message error message returned if false + * @param testRoot root of DOM to test + * @return true if validated, false otherwise + */ + bool CheckChanges(QString &message, QDomNode testRoot); private slots: void BaseSelectionChanged(int value); void ElementClicked ( const QModelIndex & index ); diff --git a/src/app/dialogs/app/dialogpatternxmledit.ui b/src/app/dialogs/app/dialogpatternxmledit.ui index f6ce6432d..2b4c4a83a 100644 --- a/src/app/dialogs/app/dialogpatternxmledit.ui +++ b/src/app/dialogs/app/dialogpatternxmledit.ui @@ -287,6 +287,16 @@ + + + + Immediate apply + + + false + + +