Skip to content

Commit

Permalink
Merge branch 'master' into feature/Path-BoundBox
Browse files Browse the repository at this point in the history
  • Loading branch information
mlampert committed Oct 1, 2019
2 parents e1e095d + ff5a978 commit a3c8957
Show file tree
Hide file tree
Showing 19 changed files with 1,981 additions and 760 deletions.
6 changes: 4 additions & 2 deletions src/Gui/Application.cpp
Expand Up @@ -720,15 +720,17 @@ void Application::slotDeleteDocument(const App::Document& Doc)
return;
}

// Inside beforeDelete() a view provider may finish editing mode
// and therefore can alter the selection.
doc->second->beforeDelete();

// We must clear the selection here to notify all observers.
// And because of possible cross document link, better clear all selection
// to be safe
Gui::Selection().clearCompleteSelection();
doc->second->signalDeleteDocument(*doc->second);
signalDeleteDocument(*doc->second);

doc->second->beforeDelete();

// If the active document gets destructed we must set it to 0. If there are further existing documents then the
// view that becomes active sets the active document again. So, we needn't worry about this.
if (d->activeDocument == doc->second)
Expand Down
13 changes: 12 additions & 1 deletion src/Gui/Document.cpp
Expand Up @@ -1627,6 +1627,13 @@ Gui::MDIView* Document::cloneView(Gui::MDIView* oldview)
view3D->setWindowIcon(oldview->windowIcon());
view3D->resize(oldview->size());

// FIXME: Add parameter to define behaviour by the calling instance
// View provider editing
if (d->_editViewProvider) {
firstView->getViewer()->resetEditingViewProvider();
view3D->getViewer()->setEditingViewProvider(d->_editViewProvider, d->_editMode);
}

return view3D;
}

Expand Down Expand Up @@ -1787,7 +1794,11 @@ bool Document::canClose (bool checkModify, bool checkLink)
if (!Gui::Control().isAllowedAlterDocument()) {
std::string name = Gui::Control().activeDialog()->getDocumentName();
if (name == this->getDocument()->getName()) {
if (this->getInEdit())
// getInEdit() only checks if the currently active MDI view is
// a 3D view and that it is in edit mode. However, when closing a
// document then the edit mode must be reset independent of the
// active view.
if (d->_editViewProvider)
this->_resetEdit();
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/Gui/View3DInventorViewer.cpp
Expand Up @@ -608,6 +608,14 @@ View3DInventorViewer::~View3DInventorViewer()
// to prevent following OpenGL error message: "Texture is not valid in the current context. Texture has not been destroyed"
aboutToDestroyGLContext();

// It can happen that a document has several MDI views and when the about to be
// closed 3D view is in edit mode the corresponding view provider must be restored
// because otherwise it might be left in a broken state
// See https://forum.freecadweb.org/viewtopic.php?f=3&t=39720
if (restoreEditingRoot) {
resetEditingRoot(false);
}

// cleanup
this->backgroundroot->unref();
this->backgroundroot = 0;
Expand Down
237 changes: 117 additions & 120 deletions src/Mod/TechDraw/App/DrawSVGTemplate.cpp
Expand Up @@ -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 <tspan> nodes whose <text> 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<std::string, std::string> 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<std::string, std::string>::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 <tspan> nodes whose <text> 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<std::string, std::string> 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<std::string, std::string>::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
Expand Down Expand Up @@ -308,7 +305,7 @@ std::map<std::string, std::string> DrawSVGTemplate::getEditableTextsFromTemplate
// XPath query to select all <tspan> nodes whose <text> 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"));

Expand Down
4 changes: 2 additions & 2 deletions src/Mod/TechDraw/App/DrawSVGTemplate.h
Expand Up @@ -73,8 +73,8 @@ class TechDrawExport DrawSVGTemplate: public TechDraw::DrawTemplate
* Also populates editableSvgIds
*/
std::map<std::string, std::string> getEditableTextsFromTemplate();
bool writeExchangeFile(QString exchangeName, QString fileContent);

QString processTemplate(QString fileSpec);

};

Expand Down
13 changes: 13 additions & 0 deletions src/Mod/TechDraw/App/DrawUtil.cpp
Expand Up @@ -1060,4 +1060,17 @@ QString DrawUtil::qbaToDebug(const QByteArray & line)
return s;
}

void DrawUtil::dumpCS(const char* text,
gp_Ax2 CS)
{
gp_Dir baseAxis = CS.Direction();
gp_Dir baseX = CS.XDirection();
gp_Dir baseY = CS.YDirection();
Base::Console().Message("DU::dumpCSDVS - %s Axis: %s X: %s Y: %s\n", text,
DrawUtil::formatVector(baseAxis).c_str(),
DrawUtil::formatVector(baseX).c_str(),
DrawUtil::formatVector(baseY).c_str());
}


//==================================
2 changes: 2 additions & 0 deletions src/Mod/TechDraw/App/DrawUtil.h
Expand Up @@ -158,6 +158,8 @@ class TechDrawExport DrawUtil {
static void countEdges(const char* label, const TopoDS_Shape& s);
static const char* printBool(bool b);
static QString qbaToDebug(const QByteArray& line);
static void dumpCS(const char* text, gp_Ax2 CS);

};

} //end namespace TechDraw
Expand Down

0 comments on commit a3c8957

Please sign in to comment.