[TD]fix embedded template file handling

This commit is contained in:
wandererfan
2022-11-07 21:43:45 -05:00
committed by WandererFan
parent 74d85eeeaa
commit 1cf51ec1c3
7 changed files with 104 additions and 181 deletions

View File

@@ -33,11 +33,14 @@
#endif
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h> //TODO: should be in DrawTemplate.h??
#include <Base/Console.h>
#include <Base/FileInfo.h>
#include <Base/Quantity.h>
#include <Base/Tools.h>
#include "DrawPage.h"
#include "DrawSVGTemplate.h"
#include "DrawSVGTemplatePy.h"
#include "DrawUtil.h"
@@ -51,12 +54,8 @@ DrawSVGTemplate::DrawSVGTemplate()
{
static const char *group = "Template";
//TODO: Do we need PageResult anymore? -wf Yes!
// PageResult points to a temporary file in tmp/FreeCAD-AB-CD-EF-.../myTemplate.svg
// which is really copy of original Template with EditableFields replaced
// When restoring saved document, Template is redundant/incorrect/not present - PageResult is the correct info. -wf-
ADD_PROPERTY_TYPE(PageResult, (nullptr), group, App::Prop_Output, "Current SVG code for template");
ADD_PROPERTY_TYPE(Template, (""), group, App::Prop_Transient, "Template for the page"); //sb TemplateFileName???
ADD_PROPERTY_TYPE(PageResult, (nullptr), group, App::Prop_Output, "Embedded SVG code for template. For system use."); //n/a for users
ADD_PROPERTY_TYPE(Template, (""), group, App::Prop_None, "Template file name.");
// Width and Height properties shouldn't be set by the user
Height.setStatus(App::Property::ReadOnly, true);
@@ -80,103 +79,44 @@ PyObject *DrawSVGTemplate::getPyObject()
return Py::new_reference_to(PythonObject);
}
unsigned int DrawSVGTemplate::getMemSize() const
{
return 0;
}
short DrawSVGTemplate::mustExecute() const
{
return TechDraw::DrawTemplate::mustExecute();
}
void DrawSVGTemplate::onChanged(const App::Property* prop)
{
bool updatePage = false;
if (prop == &PageResult) {
if (isRestoring()) {
//original template has been stored in fcstd file
Template.setValue(PageResult.getValue());
}
} else if (prop == &Template) { //fileName has changed
if (!isRestoring()) {
EditableTexts.setValues(getEditableTextsFromTemplate());
updatePage = true;
}
if (prop == &Template && !isRestoring()) {
//if we are restoring an existing file we just want the properties set as they were save,
//but if we are not restoring, we need to replace the embedded file and extract the new
//EditableTexts.
//We could try to find matching field names are preserve the values from
//the old template, but there is no guarantee that the same fields will be present.
replaceFileIncluded(Template.getValue());
EditableTexts.setValues(getEditableTextsFromTemplate());
} else if (prop == &EditableTexts) {
if (!isRestoring()) {
updatePage = true;
}
}
if (updatePage) {
execute();
//handled by ViewProvider
}
TechDraw::DrawTemplate::onChanged(prop);
}
App::DocumentObjectExecReturn * DrawSVGTemplate::execute()
//parse the Svg code, inserting current EditableTexts values, and return the result as a QString.
//While parsing, not the Orientation, Width and Height values in the Svg code.
QString DrawSVGTemplate::processTemplate()
{
std::string templateFilename = Template.getValue();
if (templateFilename.empty())
return App::DocumentObject::StdReturn;
// Base::Console().Message("DSVGT::processTemplate() - isRestoring: %d\n", isRestoring());
if (isRestoring()) {
//until everything is fully restored, the embedded file is not available, so we
//can't do anything
return QString();
}
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
std::string tempName = PageResult.getExchangeTempFile();
std::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();
}
QString DrawSVGTemplate::processTemplate(QString fileSpec)
{
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();
}
QFile templateFile(Base::Tools::fromStdString(PageResult.getValue()));
if (!templateFile.open(QIODevice::ReadOnly)) {
Base::Console().Error("DrawSVGTemplate::processTemplate can't read embedded template %s!\n", PageResult.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();
Base::Console().Error("DrawSVGTemplate::processTemplate - failed to parse file: %s\n",
PageResult.getValue());
return QString();
}
@@ -251,8 +191,24 @@ double DrawSVGTemplate::getHeight() const
return Height.getValue();
}
void DrawSVGTemplate::replaceFileIncluded(std::string newTemplateFileName)
{
// Base::Console().Message("DSVGT::replaceFileIncluded(%s)\n", newTemplateFileName.c_str());
if (newTemplateFileName.empty()) {
return;
}
Base::FileInfo tfi(newTemplateFileName);
if (tfi.isReadable()) {
PageResult.setValue(newTemplateFileName.c_str());
} else {
throw Base::RuntimeError("Could not read the new template file");
}
}
std::map<std::string, std::string> DrawSVGTemplate::getEditableTextsFromTemplate()
{
// Base::Console().Message("DSVGT::getEditableTextsFromTemplate()\n");
std::map<std::string, std::string> editables;
std::string templateFilename = Template.getValue();