Commit dda0e6dd authored by Emmanuel Promayon's avatar Emmanuel Promayon
Browse files

UPDATED Save History with no memory leak + indentation + XML prolog + proper default filename

parent f0714295
......@@ -41,6 +41,7 @@
#include <QFileDialog>
#include <QDomDocument>
#include <QTextStream>
#include <QDateTime>
// -- VTK stuff (only for updating progress bar via vtk filters)
#include <vtkAlgorithm.h>
......@@ -942,36 +943,38 @@ void Application::saveHistoryAsSXML() {
}
// Create the XML document
QDomDocument* doc = new QDomDocument();
QDomDocument doc;
QDomNode xmlProlog = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(xmlProlog);
// root element
QDomElement root = doc->createElement("scxml");
QDomElement root = doc.createElement("scxml");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.setAttribute("xmlns", "http://camitk.imag.fr/3/smallScxml");
root.setAttribute("xmlns:camitk", "http://camitk.imag.fr/3/asm");
root.setAttribute("xsi:schemaLocation", "http://camitk.imag.fr/3/smallScxml/../resources/smallScxml.xsd");
root.setAttribute("initial", "Initialize");
doc->appendChild(root);
doc.appendChild(root);
// SXML always contains an Initialize element which describe the pipeline
QDomElement initializeElt = doc->createElement("state");
QDomElement initializeElt = doc.createElement("state");
root.appendChild(initializeElt);
initializeElt.setAttribute("id", "Initialize");
QDomElement initializeElt_onEntry = doc->createElement("onentry");
QDomElement initializeElt_onEntry = doc.createElement("onentry");
initializeElt.appendChild(initializeElt_onEntry);
QDomElement initializeElt_onState = doc->createElement("camitk:onState");
QDomElement initializeElt_onState = doc.createElement("camitk:onState");
initializeElt_onEntry.appendChild(initializeElt_onState);
// Description of the pipeline
QDomElement initializeElt_desc = doc->createElement("camitk:description");
QDomElement initializeElt_desc = doc.createElement("camitk:description");
initializeElt_onState.appendChild(initializeElt_desc);
// create the pipeline description that will be filled whilel processing the history items.
QString pipelineDescription = "This pipeline will process several actions on the input component(s): <br /> <ul>";
// Transition
QDomElement initializeElt_transition = doc->createElement("transition");
QDomElement initializeElt_transition = doc.createElement("transition");
initializeElt_transition.setAttribute("event", "Next");
initializeElt_transition.setAttribute("target", "Action 1");
initializeElt.appendChild(initializeElt_transition);
QDomElement initializeElt_transition2 = doc->createElement("transition");
QDomElement initializeElt_transition2 = doc.createElement("transition");
// Create a list of all components created during the pipeline, to know which ones to delete once pipeline is reset
// by the action state machine
......@@ -983,38 +986,38 @@ void Application::saveHistoryAsSXML() {
HistoryItem historyItem = Application::getHistory().at(i);
Action* action = Application::getAction(historyItem.getName());
// state
QDomElement stateElement = doc->createElement("state");
QDomElement stateElement = doc.createElement("state");
root.appendChild(stateElement);
stateElement.setAttribute("id", "Action " + QString::number(i + 1));
// onEntry
QDomElement onentryElement = doc->createElement("onentry");
QDomElement onentryElement = doc.createElement("onentry");
stateElement.appendChild(onentryElement);
QDomElement onStateElement = doc->createElement("camitk:onState");
QDomElement onStateElement = doc.createElement("camitk:onState");
onentryElement.appendChild(onStateElement);
// action description
QDomElement descriptionElement = doc->createElement("camitk:description");
QDomText descriptionText = doc->createTextNode(action->getDescription());
QDomElement descriptionElement = doc.createElement("camitk:description");
QDomText descriptionText = doc.createTextNode(action->getDescription());
descriptionElement.appendChild(descriptionText);
onStateElement.appendChild(descriptionElement);
// action name & parameters
QDomElement actionElement = doc->createElement("camitk:action");
QDomElement actionElement = doc.createElement("camitk:action");
onStateElement.appendChild(actionElement);
// action name
QDomElement actionElementName = doc->createElement("camitk:name");
QDomElement actionElementName = doc.createElement("camitk:name");
actionElement.appendChild(actionElementName);
pipelineDescription.append("<li>" + action->getName() + "</li>");
QDomText actionElementNameText = doc->createTextNode(action->getName());
QDomText actionElementNameText = doc.createTextNode(action->getName());
actionElementName.appendChild(actionElementNameText);
// action parameters
QDomElement parametersElement = doc->createElement("camitk:parameters");
QDomElement parametersElement = doc.createElement("camitk:parameters");
actionElement.appendChild(parametersElement);
if (!action->dynamicPropertyNames().isEmpty()) {
foreach (QByteArray actionParameter, action->dynamicPropertyNames()) {
QDomElement parameterElement = doc->createElement("camitk:parameter");
QDomElement parameterElement = doc.createElement("camitk:parameter");
parameterElement.setAttribute("name", QString(actionParameter));
parameterElement.setAttribute("type", QVariant::typeToName(action->property(actionParameter).type()));
parameterElement.setAttribute("value", action->property(actionParameter.data()).toString());
......@@ -1024,11 +1027,11 @@ void Application::saveHistoryAsSXML() {
// action input components
if (!historyItem.getInputHistoryComponents().isEmpty()) {
QDomElement actionElementInputComp = doc->createElement("camitk:inputs");
QDomElement actionElementInputComp = doc.createElement("camitk:inputs");
actionElement.appendChild(actionElementInputComp);
for (int j = 0; j < historyItem.getInputHistoryComponents().size(); j++) {
QDomElement componentElement = doc->createElement("camitk:component");
QDomElement componentElement = doc.createElement("camitk:component");
// determine the type of each input component (image, meshes or other)
HistoryComponent inputHistoryComponents = historyItem.getInputHistoryComponents().at(j);
......@@ -1057,11 +1060,11 @@ void Application::saveHistoryAsSXML() {
// action output components
if (!historyItem.getOutputHistoryComponents().isEmpty()) {
QDomElement outputsElement = doc->createElement("camitk:outputs");
QDomElement outputsElement = doc.createElement("camitk:outputs");
actionElement.appendChild(outputsElement);
for (int j = 0; j < historyItem.getOutputHistoryComponents().size(); j++) {
QDomElement componentElement = doc->createElement("camitk:component");
QDomElement componentElement = doc.createElement("camitk:component");
// determine the type of each input component (image, meshes or other)
HistoryComponent outputHistoryComponents = historyItem.getOutputHistoryComponents().at(j);
allCreatedComponents.append(outputHistoryComponents); // note the component created
......@@ -1092,7 +1095,7 @@ void Application::saveHistoryAsSXML() {
// Transitions
if (Application::getHistory().size() >= 1) { // else, no transition at all
// Next transition
QDomElement nextTransitionElement = doc->createElement("transition");
QDomElement nextTransitionElement = doc.createElement("transition");
if (i == Application::getHistory().size() - 1) { // Last action element => next element = Bye element.
nextTransitionElement.setAttribute("target", "Bye");
......@@ -1104,7 +1107,7 @@ void Application::saveHistoryAsSXML() {
nextTransitionElement.setAttribute("event", "Next");
// Back transition
QDomElement backTransitionElement = doc->createElement("transition");
QDomElement backTransitionElement = doc.createElement("transition");
backTransitionElement.setAttribute("event", "Back");
if (i == 0) { // Back to Initialize state
......@@ -1117,13 +1120,13 @@ void Application::saveHistoryAsSXML() {
if (!previousItem.getOutputHistoryComponents().isEmpty()) {
// Ask for deletion of each component created at the previous element
QDomElement onTransitionElement = doc->createElement("onTransition");
QDomElement onTransitionElement = doc.createElement("onTransition");
backTransitionElement.appendChild(onTransitionElement);
QDomElement closeElement = doc->createElement("camitk:close");
QDomElement closeElement = doc.createElement("camitk:close");
onTransitionElement.appendChild(closeElement);
foreach (HistoryComponent outputHistoryComponent, previousItem.getOutputHistoryComponents()) {
QDomElement backTransitionComponentElement = doc->createElement("camitk:component");
QDomElement backTransitionComponentElement = doc.createElement("camitk:component");
closeElement.appendChild(backTransitionComponentElement);
switch (outputHistoryComponent.getType()) {
......@@ -1155,37 +1158,37 @@ void Application::saveHistoryAsSXML() {
}
// Update description of the pipeline, now that we have filled the it!
initializeElt_desc.appendChild(doc->createCDATASection(pipelineDescription));
initializeElt_desc.appendChild(doc.createCDATASection(pipelineDescription));
// Last element : Bye
QDomElement finalElt = doc->createElement("state");
QDomElement finalElt = doc.createElement("state");
root.appendChild(finalElt);
finalElt.setAttribute("id", "Bye");
finalElt.setAttribute("final", "true");
QDomElement finalElt_onEntry = doc->createElement("onentry");
QDomElement finalElt_onEntry = doc.createElement("onentry");
finalElt.appendChild(finalElt_onEntry);
QDomElement finalElt_onState = doc->createElement("camitk:onState");
QDomElement finalElt_onState = doc.createElement("camitk:onState");
finalElt_onEntry.appendChild(finalElt_onState);
// Thanks !
QDomElement finalElt_desc = doc->createElement("camitk:description");
QDomElement finalElt_desc = doc.createElement("camitk:description");
finalElt_onState.appendChild(finalElt_desc);
QDomCDATASection finalEltDesc;
finalElt_desc.appendChild(doc->createCDATASection("Thanks you for using the CamiTK Action State Machine !"));
finalElt_desc.appendChild(doc.createCDATASection("Thanks you for using the CamiTK Action State Machine !"));
// Transition
QDomElement finalElt_transition = doc->createElement("transition");
QDomElement finalElt_transition = doc.createElement("transition");
finalElt_transition.setAttribute("event", "Back to the beginning");
finalElt_transition.setAttribute("target", "Initialize");
finalElt.appendChild(finalElt_transition);
// Ask for deletion of all components created in the pipeline
if (!allCreatedComponents.isEmpty()) {
QDomElement finalEltTransition_onTransition = doc->createElement("onTransition");
QDomElement finalEltTransition_onTransition = doc.createElement("onTransition");
finalElt_transition.appendChild(finalEltTransition_onTransition);
QDomElement finalEltTransition_close = doc->createElement("camitk:close");
QDomElement finalEltTransition_close = doc.createElement("camitk:close");
finalEltTransition_onTransition.appendChild(finalEltTransition_close);
foreach (HistoryComponent createdComponent, allCreatedComponents) {
QDomElement finalEltTransition_comp = doc->createElement("camitk:component");
QDomElement finalEltTransition_comp = doc.createElement("camitk:component");
finalEltTransition_close.appendChild(finalEltTransition_comp);
switch (createdComponent.getType()) {
......@@ -1207,20 +1210,17 @@ void Application::saveHistoryAsSXML() {
}
}
// note, final element will automatically have a "Quit" transition, added by the action state machine.
// Get the xml of the tree node
QString xml = doc->toString();
// note: final element will automatically have a "Quit" transition, added by the action state machine.
// Write the xml to a file
QString outputFileName = QFileDialog::getSaveFileName(NULL, tr("Save history of actions ..."), Core::getCurrentWorkingDir() + "/actions_history.xml", tr("XML Files (*.xml)"));
QString outputFileName = QFileDialog::getSaveFileName(NULL, tr("Save history of actions ..."), Core::getCurrentWorkingDir() + "/camitk-history-" + QDateTime::currentDateTime().toString("yyyyMMdd-HHmmss") + ".scxml", tr("SCXML Files (*.scxml)"));
QFile* outputFile = new QFile(outputFileName);
QFile outputFile(outputFileName);
if (outputFile->open(QFile::WriteOnly)) {
QTextStream out(outputFile);
out << xml;
if (outputFile.open(QFile::WriteOnly | QFile::Text)) {
QTextStream out(&outputFile);
// automatically indent XML output
doc.save(out, 4);
}
else {
CAMITK_ERROR_ALT(tr("Cannot open file \"%1\" for writing. No history saved.").arg(outputFileName))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment