Apply changes to DOM tree. No validation yet.

--HG--
branch : XML Editor
This commit is contained in:
Patrick Proy 2014-05-28 21:16:41 +02:00
parent 2afc195a87
commit c4b5c3dccb
3 changed files with 236 additions and 17 deletions

View File

@ -45,22 +45,20 @@ DialogPatternXmlEdit::DialogPatternXmlEdit(QWidget *parent, VPattern *xmldoc)
{ {
ui->setupUi(this); ui->setupUi(this);
xmlmodel = new VXMLTreeView(); this->xmlmodel = new VXMLTreeView();
this->doc=xmldoc;
doc=xmldoc; this->root = this->doc->documentElement();
root = doc->documentElement(); // disable edit trigers (no edition directly on tree)
// disable edit trigers :
//ui->treeView_main->editTriggers(QTreeView::NoEditTriggers);
ui->treeView_main->setEditTriggers(QTreeView::NoEditTriggers); ui->treeView_main->setEditTriggers(QTreeView::NoEditTriggers);
ui->treeView_main->setWindowTitle("XML"); ui->treeView_main->setWindowTitle("XML");
rootNode = xmlmodel->invisibleRootItem(); this->rootNode = this->xmlmodel->invisibleRootItem();
int drawnum=xmldoc->elementsByTagName("draw").size(); int drawnum=xmldoc->elementsByTagName("draw").size();
rootBases = new VXMLTreeElement*[drawnum+1]; this->rootBases = new VXMLTreeElement*[drawnum+1];
rootBasesNum=1; this->rootBasesNum=1;
rootBases[0]=new VXMLTreeElement("Valentina", VXMLTreeElement::TypeRoot, root, false); this->rootBases[0]=new VXMLTreeElement("Valentina", VXMLTreeElement::TypeRoot, root, false);
// TODO : OOM exception. // TODO : OOM exception.
@ -68,9 +66,9 @@ DialogPatternXmlEdit::DialogPatternXmlEdit(QWidget *parent, VPattern *xmldoc)
ui->comboBox_Base_Selection->addItem(tr("All pattern pieces"), QVariant(0)); ui->comboBox_Base_Selection->addItem(tr("All pattern pieces"), QVariant(0));
//rootBases[0]=(QDomNode) doc->DocumentNode; //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); 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); 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() void DialogPatternXmlEdit::ButtonDeleteNode()
{ {
@ -431,6 +487,83 @@ void DialogPatternXmlEdit::ButtonApplyChangesClicked()
} }
QMessageBox::information(this, "Changes (not REALLY applied for now)", Changes); QMessageBox::information(this, "Changes (not REALLY applied for now)", Changes);
// TODO : clear stack and apply // 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; return;
} }
QString value = QInputDialog::getText(this, tr("Node Value (may be empty)"), QString value = QInputDialog::getText(this, tr("Node Value (may be empty)"),tr("Value:"),
tr("Value:"), QLineEdit::Normal, QLineEdit::Normal,"", &ok);
"", &ok);
if (ok==false) if (ok==false)
{ {
return; 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; QDomNode empty;
VXMLTreeElement* tElement = new VXMLTreeElement(name, VXMLTreeElement::TypeNode, empty, true); VXMLTreeElement* tElement = new VXMLTreeElement(name, VXMLTreeElement::TypeNode, empty, true);
tElement->SetFatherElement(this->currentNodeEdited);
if (value.isEmpty() == false) 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). // create element tree but do not add attribute in DOM (will be done in apply).
VXMLTreeElement* tElement = new VXMLTreeElement(name, VXMLTreeElement::TypeAttr, empty, true); VXMLTreeElement* tElement = new VXMLTreeElement(name, VXMLTreeElement::TypeAttr, empty, true);
// set parent node.
tElement->SetFatherElement(this->currentNodeEdited);
tElement->SetTreeNodeValue(value); tElement->SetTreeNodeValue(value);
currentNodeEdited->appendRow(tElement); currentNodeEdited->appendRow(tElement);
@ -1063,7 +1198,7 @@ const short int VXMLTreeElement::TypeRoot=3;
// ^ // ^
VXMLTreeElement::VXMLTreeElement(QString name, int nodetype, QDomNode source, bool editor) VXMLTreeElement::VXMLTreeElement(QString name, int nodetype, QDomNode source, bool editor)
: QStandardItem(name), DocNode(source), addedNode(editor), elementType(nodetype), treeNodeValue("<empty>"), : QStandardItem(name), DocNode(source), addedNode(editor), elementType(nodetype), treeNodeValue("<empty>"),
treeNodeValueSet(false), treeNodeName(name), selectable(true) treeNodeValueSet(false), treeNodeName(name), selectable(true), parentnode(nullptr)
{ {
if (editor == false) if (editor == false)
{ {

View File

@ -74,8 +74,23 @@ public:
* @return current document node * @return current document node
*/ */
QDomNode GetDocNode(); 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 GettreeNodeName();
QString GettreeNodeValue(); QString GettreeNodeValue();
/**
* @brief GettreeNodeValueSet check if value has been set
* @return true if value is set
*/
bool GettreeNodeValueSet(); bool GettreeNodeValueSet();
void SetTreeNodeName(QString value); void SetTreeNodeName(QString value);
/** /**
@ -86,12 +101,26 @@ public:
bool IsSelectable(); bool IsSelectable();
void SetSetlectable(bool value); void SetSetlectable(bool value);
inline void SetFatherElement(VXMLTreeElement* parent)
{
this->parentnode=parent;
}
inline VXMLTreeElement* GetFatherElement()
{
return this->parentnode;
}
private: private:
/** /**
* @brief DocNode : link to current document node * @brief DocNode : link to current document node
*/ */
QDomNode DocNode; 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) * @brief addedNode : true if node is added by editor (implies empty DocNode)
*/ */
@ -280,6 +309,51 @@ public:
*/ */
bool DeleteNodeAndSons(VXMLTreeElement *currentNode, bool onlydeactivate); 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: private slots:
void BaseSelectionChanged(int value); void BaseSelectionChanged(int value);
void ElementClicked ( const QModelIndex & index ); void ElementClicked ( const QModelIndex & index );

View File

@ -287,6 +287,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_Apply_Changes">
<property name="text">
<string>Immediate apply</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">