diff --git a/src/Mod/TechDraw/App/DrawSVGTemplate.cpp b/src/Mod/TechDraw/App/DrawSVGTemplate.cpp index f1c83922dc..3a7b51286b 100644 --- a/src/Mod/TechDraw/App/DrawSVGTemplate.cpp +++ b/src/Mod/TechDraw/App/DrawSVGTemplate.cpp @@ -33,11 +33,14 @@ #endif #include +#include +#include //TODO: should be in DrawTemplate.h?? #include #include #include #include +#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 DrawSVGTemplate::getEditableTextsFromTemplate() { +// Base::Console().Message("DSVGT::getEditableTextsFromTemplate()\n"); std::map editables; std::string templateFilename = Template.getValue(); diff --git a/src/Mod/TechDraw/App/DrawSVGTemplate.h b/src/Mod/TechDraw/App/DrawSVGTemplate.h index ec95415e43..c010bb80ee 100644 --- a/src/Mod/TechDraw/App/DrawSVGTemplate.h +++ b/src/Mod/TechDraw/App/DrawSVGTemplate.h @@ -35,45 +35,32 @@ namespace TechDraw class TechDrawExport DrawSVGTemplate: public TechDraw::DrawTemplate { - PROPERTY_HEADER(TechDraw::DrawSVGTemplate); + PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawSVGTemplate); public: DrawSVGTemplate(); - ~DrawSVGTemplate(); + ~DrawSVGTemplate() override; App::PropertyFileIncluded PageResult; App::PropertyFile Template; - /** @name methods override Feature */ - //@{ - /// recalculate the Feature - virtual App::DocumentObjectExecReturn *execute(void); - //@} - - short mustExecute() const; - - /// returns the type name of the ViewProvider - virtual const char* getViewProviderName(void) const { + void onChanged(const App::Property* prop) override; + /// returns the type name of the ViewProvider + const char* getViewProviderName(void) const override { return "TechDrawGui::ViewProviderTemplate"; } - virtual PyObject *getPyObject(void); - virtual unsigned int getMemSize(void) const; + PyObject *getPyObject(void) override; - double getWidth() const; - double getHeight() const; + double getWidth() const override; + double getHeight() const override; + + QString processTemplate(); protected: - void onChanged(const App::Property* prop); - - /// Returns map with - /*! - * Also populates editableSvgIds - */ + void replaceFileIncluded(std::string newTemplateFileName); std::map getEditableTextsFromTemplate(); - QString processTemplate(QString fileSpec); - }; using DrawSVGTemplatePython = App::FeaturePythonT; diff --git a/src/Mod/TechDraw/App/DrawTemplate.cpp b/src/Mod/TechDraw/App/DrawTemplate.cpp index 9f73dadc79..43d190496f 100644 --- a/src/Mod/TechDraw/App/DrawTemplate.cpp +++ b/src/Mod/TechDraw/App/DrawTemplate.cpp @@ -47,23 +47,20 @@ DrawTemplate::DrawTemplate() const char *group = "Page Properties"; Orientation.setEnums(OrientationEnums); - ADD_PROPERTY(Orientation, ((long)0)); + ADD_PROPERTY(Orientation, (0l)); // Physical Properties inherent to every template class - ADD_PROPERTY_TYPE(Width, (0), group, (App::PropertyType)(App::Prop_None), "Width of page"); - ADD_PROPERTY_TYPE(Height, (0), group, (App::PropertyType)(App::Prop_None), "Height of page"); - //ADD_PROPERTY_TYPE(PaperSize, (""), group, (App::PropertyType)(App::Prop_None), "Paper Format"); //obs? + ADD_PROPERTY_TYPE(Width, (0), group, App::PropertyType::Prop_None, "Width of page"); + ADD_PROPERTY_TYPE(Height, (0), group, App::PropertyType::Prop_None, "Height of page"); - ADD_PROPERTY_TYPE(EditableTexts, (), group, (App::PropertyType)(App::Prop_None), + ADD_PROPERTY_TYPE(EditableTexts, (), group, App::PropertyType::Prop_None, "Editable strings in the template"); } DrawTemplate::~DrawTemplate() { - Base::Console().Log("template destroyed"); } - PyObject *DrawTemplate::getPyObject() { if (PythonObject.is(Py::_None())) { @@ -73,11 +70,6 @@ PyObject *DrawTemplate::getPyObject() return Py::new_reference_to(PythonObject); } -unsigned int DrawTemplate::getMemSize() const -{ - return 0; -} - double DrawTemplate::getWidth() const { return Width.getValue(); @@ -88,41 +80,30 @@ double DrawTemplate::getHeight() const return Height.getValue(); } -short DrawTemplate::mustExecute() const -{ - return App::DocumentObject::mustExecute(); -} - -/// get called by the container when a Property was changed -void DrawTemplate::onChanged(const App::Property* prop) -{ - App::DocumentObject::onChanged(prop); -} - App::DocumentObjectExecReturn *DrawTemplate::execute() { - DrawPage *page = nullptr; - std::vector parent = getInList(); - for (std::vector::iterator it = parent.begin(); it != parent.end(); ++it) { - if ((*it)->getTypeId().isDerivedFrom(DrawPage::getClassTypeId())) { - page = dynamic_cast(*it); - } - } +// DrawPage *page = nullptr; +// std::vector parent = getInList(); +// for (std::vector::iterator it = parent.begin(); it != parent.end(); ++it) { +// if ((*it)->getTypeId().isDerivedFrom(DrawPage::getClassTypeId())) { +// page = dynamic_cast(*it); +// } +// } - if(page) { - page->Template.touch(); //if you are on a page, execute yourself??? - } +// if(page) { +// page->Template.touch(); +// } return App::DocumentObject::execute(); } DrawPage* DrawTemplate::getParentPage() const { - TechDraw::DrawPage* page = nullptr; - std::vector parent = getInList(); - for (std::vector::iterator it = parent.begin(); it != parent.end(); ++it) { - if ((*it)->getTypeId().isDerivedFrom(DrawPage::getClassTypeId())) { - page = static_cast(*it); + TechDraw::DrawPage* page(nullptr); + std::vector parents = getInList(); + for (auto& obj : parents) { + if (obj->getTypeId().isDerivedFrom(DrawPage::getClassTypeId())) { + page = static_cast(obj); } } return page; diff --git a/src/Mod/TechDraw/App/DrawTemplate.h b/src/Mod/TechDraw/App/DrawTemplate.h index d55b24fd58..f031c6987b 100644 --- a/src/Mod/TechDraw/App/DrawTemplate.h +++ b/src/Mod/TechDraw/App/DrawTemplate.h @@ -36,17 +36,16 @@ class DrawPage; class TechDrawExport DrawTemplate : public App::DocumentObject { - PROPERTY_HEADER(TechDraw::DrawTemplate); + PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawTemplate); public: DrawTemplate(); /// Constructor - ~DrawTemplate(); + ~DrawTemplate() override; // Page Physical Properties App::PropertyLength Width; App::PropertyLength Height; App::PropertyEnumeration Orientation; - //App::PropertyString PaperSize; App::PropertyMap EditableTexts; @@ -62,23 +61,17 @@ public: /** @name methods override Feature */ //@{ /// recalculate the Feature - virtual App::DocumentObjectExecReturn *execute(void); + App::DocumentObjectExecReturn *execute(void) override; //@} - virtual short mustExecute() const; - /// returns the type name of the ViewProvider - virtual const char* getViewProviderName(void) const { + const char* getViewProviderName(void) const override{ return "TechDrawGui::ViewProviderTemplate"; } // from base class - virtual PyObject *getPyObject(void); - virtual unsigned int getMemSize(void) const; - -protected: - void onChanged(const App::Property* prop); + virtual PyObject *getPyObject(void) override; private: static const char* OrientationEnums[]; diff --git a/src/Mod/TechDraw/Gui/QGISVGTemplate.cpp b/src/Mod/TechDraw/Gui/QGISVGTemplate.cpp index 27b6a19b57..f6329ef93c 100644 --- a/src/Mod/TechDraw/Gui/QGISVGTemplate.cpp +++ b/src/Mod/TechDraw/Gui/QGISVGTemplate.cpp @@ -84,17 +84,9 @@ void QGISVGTemplate::openFile(const QFile &file) Q_UNUSED(file); } -void QGISVGTemplate::load(const QString &fileName) +void QGISVGTemplate::load(const QByteArray &svgCode) { - if (fileName.isEmpty()){ - return; - } - - QFile file(fileName); - if (!file.exists()) { - return; - } - m_svgRender->load(file.fileName()); + m_svgRender->load(svgCode); QSize size = m_svgRender->defaultSize(); m_svgItem->setSharedRenderer(m_svgRender); @@ -107,11 +99,11 @@ void QGISVGTemplate::load(const QString &fileName) //convert from pixels or mm or inches in svg file to mm page size TechDraw::DrawSVGTemplate *tmplte = getSVGTemplate(); double xaspect, yaspect; - xaspect = tmplte->getWidth() / (double) size.width(); - yaspect = tmplte->getHeight() / (double) size.height(); + xaspect = tmplte->getWidth() / static_cast(size.width()); + yaspect = tmplte->getHeight() / static_cast(size.height()); QTransform qtrans; - qtrans.translate(0.f, Rez::guiX(-tmplte->getHeight())); + qtrans.translate(0.0, Rez::guiX(-tmplte->getHeight())); qtrans.scale(Rez::guiX(xaspect) , Rez::guiX(yaspect)); m_svgItem->setTransform(qtrans); } @@ -129,7 +121,7 @@ void QGISVGTemplate::draw() TechDraw::DrawSVGTemplate *tmplte = getSVGTemplate(); if(!tmplte) throw Base::RuntimeError("Template Feature not set for QGISVGTemplate"); - load(QString::fromUtf8(tmplte->PageResult.getValue())); + load(tmplte->processTemplate().toUtf8()); } void QGISVGTemplate::updateView(bool update) @@ -141,6 +133,11 @@ void QGISVGTemplate::updateView(bool update) void QGISVGTemplate::createClickHandles() { TechDraw::DrawSVGTemplate *svgTemplate = getSVGTemplate(); + if (svgTemplate->isRestoring()) { + //the embedded file is not available yet, so just return + return; + } + QString templateFilename(QString::fromUtf8(svgTemplate->PageResult.getValue())); if (templateFilename.isEmpty()) { diff --git a/src/Mod/TechDraw/Gui/QGISVGTemplate.h b/src/Mod/TechDraw/Gui/QGISVGTemplate.h index f0a3999fe3..0bd6284b73 100644 --- a/src/Mod/TechDraw/Gui/QGISVGTemplate.h +++ b/src/Mod/TechDraw/Gui/QGISVGTemplate.h @@ -25,13 +25,13 @@ #include -QT_BEGIN_NAMESPACE +#include + class QGraphicsScene; class QGraphicsSvgItem; class QSvgRenderer; class QFile; class QString; -QT_END_NAMESPACE namespace TechDraw { class DrawSVGTemplate; @@ -61,7 +61,7 @@ public: protected: void openFile(const QFile &file); - void load (const QString & fileName); + void load (const QByteArray& svgCode); void createClickHandles(void); protected: diff --git a/src/Mod/TechDraw/Gui/ViewProviderTemplate.cpp b/src/Mod/TechDraw/Gui/ViewProviderTemplate.cpp index 182af361aa..62d88bdd68 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderTemplate.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderTemplate.cpp @@ -69,6 +69,7 @@ ViewProviderTemplate::~ViewProviderTemplate() void ViewProviderTemplate::updateData(const App::Property* prop) { + //This doesn't belong here. Should be in attach? if (getTemplate()->isDerivedFrom(TechDraw::DrawSVGTemplate::getClassTypeId())) { auto t = static_cast(getTemplate()); if (prop == &(t->Template)) { @@ -80,6 +81,14 @@ void ViewProviderTemplate::updateData(const App::Property* prop) } } } + + if (prop == &(getTemplate()->EditableTexts)) { + QGITemplate* qgiv = getQTemplate(); + if (qgiv) { + qgiv->updateView(true); + } + } + Gui::ViewProviderDocumentObject::updateData(prop); }