diff --git a/src/Mod/TechDraw/App/DrawViewSymbol.cpp b/src/Mod/TechDraw/App/DrawViewSymbol.cpp index d31f763720..8680b81129 100644 --- a/src/Mod/TechDraw/App/DrawViewSymbol.cpp +++ b/src/Mod/TechDraw/App/DrawViewSymbol.cpp @@ -25,23 +25,17 @@ #ifndef _PreComp_ # include -#include #endif -#include -#include - -#include - +#include #include -#include +#include "QDomNodeModel.h" #include #include #include #include -#include "QDomNodeModel.h" #include "DrawUtil.h" #include "DrawPage.h" #include "DrawViewSymbol.h" @@ -51,7 +45,6 @@ using namespace TechDraw; using namespace std; - //=========================================================================== // DrawViewSymbol //=========================================================================== @@ -75,58 +68,16 @@ DrawViewSymbol::~DrawViewSymbol() void DrawViewSymbol::onChanged(const App::Property* prop) { -// Base::Console().Message("DVS::onChanged(%s) \n",prop->getName()); if (prop == &Symbol) { - if (!isRestoring() && Symbol.getValue()[0]) { - //this pulls the initial values from svg into editabletexts - // should only happen first time?? extra loop onChanged->execute->onChanged - - std::vector editables; - QDomDocument symbolDocument; - - const char* symbol = Symbol.getValue(); - QByteArray qba(symbol); - QString errorMsg; - int errorLine; - int errorCol; - bool nsProcess = false; - bool rc = symbolDocument.setContent(qba, nsProcess, &errorMsg, &errorLine, &errorCol); - if (rc) { - QDomElement symbolDocElem = symbolDocument.documentElement(); - - QXmlQuery query(QXmlQuery::XQuery10); - QDomNodeModel model(query.namePool(), symbolDocument); - query.setFocus(QXmlItem(model.fromDomNode(symbolDocElem))); - - // 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); - - while (!queryResult.next().isNull()) - { - QDomElement tspanElement = model.toDomNode(queryResult.current().toNodeModelIndex()).toElement(); - editables.push_back(tspanElement.text().toStdString()); - } - } - else { - Base::Console().Warning("DVS::onChanged - %s - SVG for Symbol is not valid. See log.\n"); - Base::Console().Log( - "Warning: DVS::onChanged(Symbol) for %s - len: %d rc: %d error: %s line: %d col: %d\n", - getNameInDocument(), strlen(symbol), rc, - qPrintable(errorMsg), errorLine, errorCol); - - - } - + if (!isRestoring() && !Symbol.isEmpty()) { + std::vector editables = getEditableFields(); EditableTexts.setValues(editables); -// requestPaint(); } + } else if (prop == &EditableTexts) { + //this will change Symbol, which will call onChanged(Symbol), + //which will change EditableTexts, but the loop stops after + //1 cycle + updateFieldsInSymbol(); } TechDraw::DrawView::onChanged(prop); @@ -134,76 +85,8 @@ void DrawViewSymbol::onChanged(const App::Property* prop) App::DocumentObjectExecReturn *DrawViewSymbol::execute(void) { -// Base::Console().Message("DVS::execute() \n"); -// //dvs::execute is pretty fast. doesn't need to be blocked? -// if (!keepUpdated()) { -// return App::DocumentObject::StdReturn; -// } - - std::string svg = Symbol.getValue(); - if (svg.empty()) { - return App::DocumentObject::StdReturn; - } - - const std::vector& editText = EditableTexts.getValues(); - - if (!editText.empty()) { - QDomDocument symbolDocument; - const char* symbol = Symbol.getValue(); - QByteArray qba(symbol); - QString errorMsg; - int errorLine; - int errorCol; - bool nsProcess = false; - bool rc = symbolDocument.setContent(qba, nsProcess, &errorMsg, &errorLine, &errorCol); - if (rc) { - QDomElement symbolDocElem = symbolDocument.documentElement(); - - QXmlQuery query(QXmlQuery::XQuery10); - QDomNodeModel model(query.namePool(), symbolDocument); - query.setFocus(QXmlItem(model.fromDomNode(symbolDocElem))); - - // 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); - - unsigned int count = 0; - while (!queryResult.next().isNull()) - { - QDomElement tspanElement = model.toDomNode(queryResult.current().toNodeModelIndex()).toElement(); - - // Keep all spaces in the text node - tspanElement.setAttribute(QString::fromUtf8("xml:space"), QString::fromUtf8("preserve")); - - // Remove all child nodes (if any) - while (!tspanElement.lastChild().isNull()) { - tspanElement.removeChild(tspanElement.lastChild()); - } - - // Finally append text node with editable replacement as the only descendant - tspanElement.appendChild(symbolDocument.createTextNode( - QString::fromUtf8(editText[count].c_str()))); - ++count; - } - - Symbol.setValue(symbolDocument.toString(1).toStdString()); - } - else { - Base::Console().Warning("DVS::execute - %s - SVG for Symbol is not valid. See log.\n"); - Base::Console().Log( - "Warning: DVS::execute() - %s - len: %d rc: %d error: %s line: %d col: %d\n", - getNameInDocument(), strlen(symbol), rc, - qPrintable(errorMsg), errorLine, errorCol); - } - } - -// requestPaint(); + //nothing to do. DVS is just a container for properties. + //the action takes place on the Gui side. return DrawView::execute(); } @@ -212,32 +95,9 @@ QRectF DrawViewSymbol::getRect() const double w = 64.0; //must default to something double h = 64.0; return (QRectF(0,0,w,h)); -// std::string svg = Symbol.getValue(); -// string::const_iterator begin, end; -// begin = svg.begin(); -// end = svg.end(); -// boost::match_results what; - -// boost::regex e1 ("width=\"([0-9.]*?)[a-zA-Z]*?\""); -// if (boost::regex_search(begin, end, what, e1)) { -// //std::string wText = what[0].str(); //this is the whole match 'width="100"' -// std::string wNum = what[1].str(); //this is just the number 100 -// w = std::stod(wNum); -// } -// -// boost::regex e2 ("height=\"([0-9.]*?)[a-zA-Z]*?\""); -// if (boost::regex_search(begin, end, what, e2)) { -// //std::string hText = what[0].str(); -// std::string hNum = what[1].str(); -// h = std::stod(hNum); -// } -// return (QRectF(0,0,getScale() * w,getScale() * h)); -//we now have a w x h, but we don't really know what it means - px,mm,in,... - } //!Assume all svg files fit the page and/or the user will scale manually -//see getRect() above bool DrawViewSymbol::checkFit(TechDraw::DrawPage* p) const { (void)p; @@ -245,19 +105,105 @@ bool DrawViewSymbol::checkFit(TechDraw::DrawPage* p) const return result; } -short DrawViewSymbol::mustExecute() const +//get editable fields from symbol +std::vector DrawViewSymbol::getEditableFields() { - short result = 0; - if (!isRestoring()) { - result = (Scale.isTouched() || - EditableTexts.isTouched()); + QDomDocument symbolDocument; + QXmlResultItems queryResult; + std::vector editables; + + bool rc = loadQDomDocument(symbolDocument); + if (rc) { + QDomElement symbolDocElem = symbolDocument.documentElement(); + QXmlQuery query(QXmlQuery::XQuery10); + QDomNodeModel model(query.namePool(), symbolDocument); + query.setFocus(QXmlItem(model.fromDomNode(symbolDocument.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")); + + query.evaluateTo(&queryResult); + + while (!queryResult.next().isNull()) { + QDomElement tspan = model.toDomNode(queryResult.current().toNodeModelIndex()).toElement(); + QString editableValue = tspan.firstChild().nodeValue(); + editables.push_back(std::string(editableValue.toUtf8().constData())); + } } - if ((bool) result) { - return result; - } - return DrawView::mustExecute(); + return editables; } +//replace editable field in symbol with values from property +void DrawViewSymbol::updateFieldsInSymbol() +{ + const std::vector& editText = EditableTexts.getValues(); + if (editText.empty()) { + return; + } + + QDomDocument symbolDocument; + QXmlResultItems queryResult; + + bool rc = loadQDomDocument(symbolDocument); + if (rc) { + QDomElement symbolDocElem = symbolDocument.documentElement(); + QXmlQuery query(QXmlQuery::XQuery10); + QDomNodeModel model(query.namePool(), symbolDocument); + query.setFocus(QXmlItem(model.fromDomNode(symbolDocElem))); + + // 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")); + query.evaluateTo(&queryResult); + + unsigned int count = 0; + while (!queryResult.next().isNull()) + { + QDomElement tspanElement = model.toDomNode(queryResult.current().toNodeModelIndex()).toElement(); + + // Keep all spaces in the text node + tspanElement.setAttribute(QString::fromUtf8("xml:space"), QString::fromUtf8("preserve")); + + // Remove all child nodes (if any) + while (!tspanElement.lastChild().isNull()) { + tspanElement.removeChild(tspanElement.lastChild()); + } + + // Finally append text node with editable replacement as the only descendant + tspanElement.appendChild(symbolDocument.createTextNode( + QString::fromUtf8(editText[count].c_str()))); + ++count; + } + Symbol.setValue(symbolDocument.toString(1).toStdString()); + } +} + +//load QDomDocument +bool DrawViewSymbol::loadQDomDocument(QDomDocument& symbolDocument) +{ + const char* symbol = Symbol.getValue(); + QByteArray qba(symbol); + QString errorMsg; + int errorLine; + int errorCol; + bool nsProcess = false; + bool rc = symbolDocument.setContent(qba, nsProcess, &errorMsg, &errorLine, &errorCol); + if (!rc) { + //invalid SVG message + Base::Console().Warning("DrawViewSymbol - %s - SVG for Symbol is not valid. See log.\n"); + Base::Console().Log("DrawViewSymbol - %s - len: %d rc: %d error: %s line: %d col: %d\n", + getNameInDocument(), strlen(symbol), rc, + qPrintable(errorMsg), errorLine, errorCol); + } + return rc; +} PyObject *DrawViewSymbol::getPyObject(void) { diff --git a/src/Mod/TechDraw/App/DrawViewSymbol.h b/src/Mod/TechDraw/App/DrawViewSymbol.h index e2fe910671..830a7f2162 100644 --- a/src/Mod/TechDraw/App/DrawViewSymbol.h +++ b/src/Mod/TechDraw/App/DrawViewSymbol.h @@ -23,18 +23,21 @@ #ifndef _DrawViewSymbol_h_ #define _DrawViewSymbol_h_ +#include + +#include +#include + #include #include #include #include "DrawView.h" - namespace TechDraw { class DrawPage; - class TechDrawExport DrawViewSymbol : public TechDraw::DrawView { PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawViewSymbol); @@ -63,12 +66,13 @@ public: //return PyObject as DrawViewSymbolPy virtual PyObject *getPyObject(void) override; - virtual short mustExecute() const override; - - protected: virtual void onChanged(const App::Property* prop) override; Base::BoundBox3d bbox; + + std::vector getEditableFields(); + void updateFieldsInSymbol(); + bool loadQDomDocument(QDomDocument& symbolDocument); }; typedef App::FeaturePythonT DrawViewSymbolPython; diff --git a/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp b/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp index b9f3f25c90..d07597bef4 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp @@ -67,6 +67,15 @@ std::vector ViewProviderSymbol::getDisplayModes(void) const void ViewProviderSymbol::updateData(const App::Property* prop) { + if (prop == &getViewObject()->Scale) { + onGuiRepaint(getViewObject()); + } else if (prop == &getViewObject()->Rotation) { + onGuiRepaint(getViewObject()); + } else if (prop == &getViewObject()->Symbol) { + onGuiRepaint(getViewObject()); + } else if (prop == &getViewObject()->EditableTexts) { + onGuiRepaint(getViewObject()); + } ViewProviderDrawingView::updateData(prop); } diff --git a/src/Mod/TechDraw/Gui/ViewProviderSymbol.h b/src/Mod/TechDraw/Gui/ViewProviderSymbol.h index ed634c41ff..4d31d378c0 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderSymbol.h +++ b/src/Mod/TechDraw/Gui/ViewProviderSymbol.h @@ -24,6 +24,8 @@ #ifndef DRAWINGGUI_VIEWPROVIDERSYMBOL_H #define DRAWINGGUI_VIEWPROVIDERSYMBOL_H +#include + #include #include "ViewProviderDrawingView.h"