From ff5a9783d415bc9d49f8a1a7b20c8770353a1840 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 1 Oct 2019 15:00:23 -0400 Subject: [PATCH] [TD]Fix #4085 Win File Rename Fail --- src/Mod/TechDraw/App/DrawSVGTemplate.cpp | 237 +++++++++++------------ src/Mod/TechDraw/App/DrawSVGTemplate.h | 4 +- 2 files changed, 119 insertions(+), 122 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawSVGTemplate.cpp b/src/Mod/TechDraw/App/DrawSVGTemplate.cpp index 4466e5d1784d..71c6498b7630 100644 --- a/src/Mod/TechDraw/App/DrawSVGTemplate.cpp +++ b/src/Mod/TechDraw/App/DrawSVGTemplate.cpp @@ -133,128 +133,125 @@ void DrawSVGTemplate::onChanged(const App::Property* prop) App::DocumentObjectExecReturn * DrawSVGTemplate::execute(void) { - std::string templateFilename = Template.getValue(); - if (templateFilename.empty()) - return App::DocumentObject::StdReturn; - - Base::FileInfo fi(templateFilename); - if (!fi.isReadable()) { - // non-empty template value, but can't read file - // if there is a old absolute template file set use a redirect - fi.setFile(App::Application::getResourceDir() + "Mod/Drawing/Templates/" + fi.fileName()); - // try the redirect - if (!fi.isReadable()) { - Base::Console().Log("DrawSVGTemplate::execute() not able to open %s!\n", Template.getValue()); - std::string error = std::string("Cannot open file ") + Template.getValue(); - return new App::DocumentObjectExecReturn(error); - } - } - - if (std::string(PageResult.getValue()).empty()) //first time through? - PageResult.setValue(fi.filePath().c_str()); - - QFile templateFile(QString::fromUtf8(fi.filePath().c_str())); - if (!templateFile.open(QIODevice::ReadOnly)) { - Base::Console().Log("DrawSVGTemplate::execute() can't read template %s!\n", Template.getValue()); - std::string error = std::string("Cannot read file ") + Template.getValue(); - return new App::DocumentObjectExecReturn(error); - } - - QDomDocument templateDocument; - if (!templateDocument.setContent(&templateFile)) { - Base::Console().Message("DrawSVGTemplate::execute() - failed to parse file: %s\n", - Template.getValue()); - std::string error = std::string("Cannot parse file ") + Template.getValue(); - return new App::DocumentObjectExecReturn(error); - } - - QXmlQuery query(QXmlQuery::XQuery10); - QDomNodeModel model(query.namePool(), templateDocument); - query.setFocus(QXmlItem(model.fromDomNode(templateDocument.documentElement()))); - - // XPath query to select all nodes whose parent - // has "freecad:editable" attribute - query.setQuery(QString::fromUtf8( - "declare default element namespace \"" SVG_NS_URI "\"; " - "declare namespace freecad=\"" FREECAD_SVG_NS_URI "\"; " - "//text[@freecad:editable]/tspan")); - - QXmlResultItems queryResult; - query.evaluateTo(&queryResult); - - std::map substitutions = EditableTexts.getValues(); - while (!queryResult.next().isNull()) - { - QDomElement tspan = model.toDomNode(queryResult.current().toNodeModelIndex()).toElement(); - - // Replace the editable text spans with new nodes holding actual values - QString editableName = tspan.parentNode().toElement().attribute(QString::fromUtf8("freecad:editable")); - std::map::iterator item = - substitutions.find(std::string(editableName.toUtf8().constData())); - if (item != substitutions.end()) { - // Keep all spaces in the text node - tspan.setAttribute(QString::fromUtf8("xml:space"), QString::fromUtf8("preserve")); - - // Remove all child nodes and append text node with editable replacement as the only descendant - while (!tspan.lastChild().isNull()) { - tspan.removeChild(tspan.lastChild()); - } - tspan.appendChild(templateDocument.createTextNode(QString::fromUtf8(item->second.c_str()))); - } - } - - //re #4085 - - std::string ssExchangeName = PageResult.getExchangeTempFile(); - QString qExchangeName = Base::Tools::fromStdString(ssExchangeName); - bool rc = writeExchangeFile(qExchangeName, templateDocument.toString()); - if (rc) { - PageResult.setValue(ssExchangeName.c_str()); - } else { - Base::Console().Error("DrawSVGTemplate::execute - failed to exchange temp file: %s\n", - ssExchangeName.c_str()); - } - - // Calculate the dimensions of the page and store for retrieval - // Obtain the size of the SVG document by reading the document attributes - QDomElement docElement = templateDocument.documentElement(); - Base::Quantity quantity; - - // Obtain the width - QString str = docElement.attribute(QString::fromLatin1("width")); - quantity = Base::Quantity::parse(str); - quantity.setUnit(Base::Unit::Length); - - Width.setValue(quantity.getValue()); - - str = docElement.attribute(QString::fromLatin1("height")); - quantity = Base::Quantity::parse(str); - quantity.setUnit(Base::Unit::Length); - - Height.setValue(quantity.getValue()); - - bool isLandscape = getWidth() / getHeight() >= 1.; - - Orientation.setValue(isLandscape ? 1 : 0); - - return TechDraw::DrawTemplate::execute(); + std::string templateFilename = Template.getValue(); + if (templateFilename.empty()) + return App::DocumentObject::StdReturn; + + Base::FileInfo fi(templateFilename); + if (!fi.isReadable()) { + // non-empty template value, but can't read file + // if there is a old absolute template file set use a redirect + fi.setFile(App::Application::getResourceDir() + "Mod/Drawing/Templates/" + fi.fileName()); + // try the redirect + if (!fi.isReadable()) { + Base::Console().Log("DrawSVGTemplate::execute() not able to open %s!\n", Template.getValue()); + std::string error = std::string("Cannot open file ") + Template.getValue(); + return new App::DocumentObjectExecReturn(error); + } + } + + if (std::string(PageResult.getValue()).empty()) //first time through? + PageResult.setValue(fi.filePath().c_str()); + + std::string templateFileSpec = fi.filePath(); + QString qSpec = Base::Tools::fromStdString(templateFileSpec); + std::string documentImage; + QString qDocImage; + + qDocImage = processTemplate(qSpec); + + if (!qDocImage.isEmpty()) { + // make a temp file for FileIncluded Property + string tempName = PageResult.getExchangeTempFile(); + ofstream outfinal(tempName.c_str()); + std::string result = Base::Tools::toStdString(qDocImage); + outfinal << result; + outfinal.close(); + PageResult.setValue(tempName.c_str()); + } + else { + Base::Console().Error("QSVGT::execute - failed to process Template\n"); + } + + return TechDraw::DrawTemplate::execute(); } -bool DrawSVGTemplate::writeExchangeFile(QString exchangeName, QString fileContent) +QString DrawSVGTemplate::processTemplate(QString fileSpec) { -// Base::Console().Message("DSVGT::writeExchangeFile(%s)\n", qPrintable(exchangeName)); - bool rc = true; - QFile newTempFile(exchangeName); - if (newTempFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - QTextStream stream(&newTempFile); - stream << fileContent; - newTempFile.close(); - } - else { - Base::Console().Message("DrawSVGT:writeExchangeFile - failed to open temp file for writing: %s\n", - qPrintable(exchangeName)); - rc = false; - } - return rc; + QFile templateFile(fileSpec); + if (!templateFile.open(QIODevice::ReadOnly)) { + Base::Console().Log("DrawSVGTemplate::execute() can't read template %s!\n", Template.getValue()); + std::string error = std::string("Cannot read file ") + Template.getValue(); + return QString(); + } + + QDomDocument templateDocument; + if (!templateDocument.setContent(&templateFile)) { + Base::Console().Message("DrawSVGTemplate::execute() - failed to parse file: %s\n", + Template.getValue()); + std::string error = std::string("Cannot parse file ") + Template.getValue(); + return QString(); + } + + QXmlQuery query(QXmlQuery::XQuery10); + QDomNodeModel model(query.namePool(), templateDocument); + query.setFocus(QXmlItem(model.fromDomNode(templateDocument.documentElement()))); + + // XPath query to select all nodes whose parent + // has "freecad:editable" attribute + query.setQuery(QString::fromUtf8( + "declare default element namespace \"" SVG_NS_URI "\"; " + "declare namespace freecad=\"" FREECAD_SVG_NS_URI "\"; " + "//text[@freecad:editable]/tspan")); + + QXmlResultItems queryResult; + query.evaluateTo(&queryResult); + + std::map substitutions = EditableTexts.getValues(); + while (!queryResult.next().isNull()) + { + QDomElement tspan = model.toDomNode(queryResult.current().toNodeModelIndex()).toElement(); + + // Replace the editable text spans with new nodes holding actual values + QString editableName = tspan.parentNode().toElement().attribute(QString::fromUtf8("freecad:editable")); + std::map::iterator item = + substitutions.find(std::string(editableName.toUtf8().constData())); + if (item != substitutions.end()) { + // Keep all spaces in the text node + tspan.setAttribute(QString::fromUtf8("xml:space"), QString::fromUtf8("preserve")); + + // Remove all child nodes and append text node with editable replacement as the only descendant + while (!tspan.lastChild().isNull()) { + tspan.removeChild(tspan.lastChild()); + } + tspan.appendChild(templateDocument.createTextNode(QString::fromUtf8(item->second.c_str()))); + } + } + + // Calculate the dimensions of the page and store for retrieval + // Obtain the size of the SVG document by reading the document attributes + QDomElement docElement = templateDocument.documentElement(); + Base::Quantity quantity; + + // Obtain the width + QString str = docElement.attribute(QString::fromLatin1("width")); + quantity = Base::Quantity::parse(str); + quantity.setUnit(Base::Unit::Length); + + Width.setValue(quantity.getValue()); + + str = docElement.attribute(QString::fromLatin1("height")); + quantity = Base::Quantity::parse(str); + quantity.setUnit(Base::Unit::Length); + + Height.setValue(quantity.getValue()); + + bool isLandscape = getWidth() / getHeight() >= 1.; + + Orientation.setValue(isLandscape ? 1 : 0); + + //all Qt holds on files should be released on exit #4085 + return templateDocument.toString(); } double DrawSVGTemplate::getWidth() const @@ -308,7 +305,7 @@ std::map DrawSVGTemplate::getEditableTextsFromTemplate // XPath query to select all nodes whose parent // has "freecad:editable" attribute query.setQuery(QString::fromUtf8( - "declare default element namespace \"" SVG_NS_URI "\"; " + "declare default element namespace \"" SVG_NS_URI "\"; " "declare namespace freecad=\"" FREECAD_SVG_NS_URI "\"; " "//text[@freecad:editable]/tspan")); diff --git a/src/Mod/TechDraw/App/DrawSVGTemplate.h b/src/Mod/TechDraw/App/DrawSVGTemplate.h index eaa10dec59be..c8a11eb42e61 100644 --- a/src/Mod/TechDraw/App/DrawSVGTemplate.h +++ b/src/Mod/TechDraw/App/DrawSVGTemplate.h @@ -73,8 +73,8 @@ class TechDrawExport DrawSVGTemplate: public TechDraw::DrawTemplate * Also populates editableSvgIds */ std::map getEditableTextsFromTemplate(); - - bool writeExchangeFile(QString exchangeName, QString fileContent); + + QString processTemplate(QString fileSpec); };