[TechDraw] Issue #5903 - Autofill template information

This commit is contained in:
pavltom
2024-03-16 10:50:35 +01:00
committed by WandererFan
parent 2a1120429b
commit 2f04fce75e
13 changed files with 236 additions and 156 deletions

View File

@@ -53,6 +53,7 @@
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawSVGTemplate.h>
#include <Mod/TechDraw/App/DrawViewArch.h>
#include <Mod/TechDraw/App/DrawViewClip.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
@@ -105,40 +106,33 @@ void CmdTechDrawPageDefault::activated(int iMsg)
Q_UNUSED(iMsg);
QString templateFileName = Preferences::defaultTemplate();
std::string PageName = getUniqueObjectName("Page");
std::string TemplateName = getUniqueObjectName("Template");
QFileInfo tfi(templateFileName);
if (tfi.isReadable()) {
Gui::WaitCursor wc;
openCommand(QT_TRANSLATE_NOOP("Command", "Drawing create page"));
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawPage', '%s')",
PageName.c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawPage', 'Page', '%s')",
PageName.c_str(), PageName.c_str());
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawSVGTemplate', '%s')",
TemplateName.c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawSVGTemplate', 'Template', '%s')",
TemplateName.c_str(), TemplateName.c_str());
auto page = dynamic_cast<TechDraw::DrawPage *>
(getDocument()->addObject("TechDraw::DrawPage", "Page"));
if (!page) {
throw Base::TypeError("CmdTechDrawPageDefault - page not created");
}
page->translateLabel("DrawPage", "Page", page->getNameInDocument());
doCommand(Doc, "App.activeDocument().%s.Template = '%s'", TemplateName.c_str(),
templateFileName.toStdString().c_str());
doCommand(Doc, "App.activeDocument().%s.Template = App.activeDocument().%s",
PageName.c_str(), TemplateName.c_str());
auto svgTemplate = dynamic_cast<TechDraw::DrawSVGTemplate *>
(getDocument()->addObject("TechDraw::DrawSVGTemplate", "Template"));
if (!svgTemplate) {
throw Base::TypeError("CmdTechDrawPageDefault - template not created");
}
svgTemplate->translateLabel("DrawSVGTemplate", "Template", svgTemplate->getNameInDocument());
page->Template.setValue(svgTemplate);
svgTemplate->Template.setValue(templateFileName.toStdString());
updateActive();
commitCommand();
TechDraw::DrawPage* fp =
dynamic_cast<TechDraw::DrawPage*>(getDocument()->getObject(PageName.c_str()));
if (!fp) {
throw Base::TypeError("CmdTechDrawPageDefault fp not found\n");
}
Gui::ViewProvider* vp =
Gui::Application::Instance->getDocument(getDocument())->getViewProvider(fp);
TechDrawGui::ViewProviderPage* dvp = dynamic_cast<TechDrawGui::ViewProviderPage*>(vp);
TechDrawGui::ViewProviderPage *dvp = dynamic_cast<TechDrawGui::ViewProviderPage *>
(Gui::Application::Instance->getViewProvider(page));
if (dvp) {
dvp->show();
}
@@ -182,44 +176,33 @@ void CmdTechDrawPageTemplate::activated(int iMsg)
return;
}
std::string PageName = getUniqueObjectName("Page");
std::string TemplateName = getUniqueObjectName("Template");
QFileInfo tfi(templateFileName);
if (tfi.isReadable()) {
Gui::WaitCursor wc;
openCommand(QT_TRANSLATE_NOOP("Command", "Drawing create page"));
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawPage', '%s')",
PageName.c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawPage', 'Page', '%s')",
PageName.c_str(), PageName.c_str());
// Create the Template Object to attach to the page
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawSVGTemplate', '%s')",
TemplateName.c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawSVGTemplate', 'Template', '%s')",
TemplateName.c_str(), TemplateName.c_str());
auto page = dynamic_cast<TechDraw::DrawPage *>
(getDocument()->addObject("TechDraw::DrawPage", "Page"));
if (!page) {
throw Base::TypeError("CmdTechDrawPageTemplate - page not created");
}
page->translateLabel("DrawPage", "Page", page->getNameInDocument());
//why is "Template" property set twice? -wf
// once to set DrawSVGTemplate.Template to OS template file name
templateFileName = Base::Tools::escapeEncodeFilename(templateFileName);
doCommand(Doc, "App.activeDocument().%s.Template = \"%s\"", TemplateName.c_str(),
templateFileName.toUtf8().constData());
// once to set Page.Template to DrawSVGTemplate.Name
doCommand(Doc, "App.activeDocument().%s.Template = App.activeDocument().%s",
PageName.c_str(), TemplateName.c_str());
// consider renaming DrawSVGTemplate.Template property?
auto svgTemplate = dynamic_cast<TechDraw::DrawSVGTemplate *>
(getDocument()->addObject("TechDraw::DrawSVGTemplate", "Template"));
if (!svgTemplate) {
throw Base::TypeError("CmdTechDrawPageTemplate - template not created");
}
svgTemplate->translateLabel("DrawSVGTemplate", "Template", svgTemplate->getNameInDocument());
page->Template.setValue(svgTemplate);
svgTemplate->Template.setValue(templateFileName.toStdString());
updateActive();
commitCommand();
TechDraw::DrawPage* fp =
dynamic_cast<TechDraw::DrawPage*>(getDocument()->getObject(PageName.c_str()));
if (!fp) {
throw Base::TypeError("CmdTechDrawNewPagePick fp not found\n");
}
Gui::ViewProvider* vp =
Gui::Application::Instance->getDocument(getDocument())->getViewProvider(fp);
TechDrawGui::ViewProviderPage* dvp = dynamic_cast<TechDrawGui::ViewProviderPage*>(vp);
TechDrawGui::ViewProviderPage *dvp = dynamic_cast<TechDrawGui::ViewProviderPage *>
(Gui::Application::Instance->getViewProvider(page));
if (dvp) {
dvp->show();
}

View File

@@ -178,9 +178,9 @@ void QGISVGTemplate::createClickHandles()
// XPath query to select all <text> nodes with "freecad:editable" attribute
query.processItems(QString::fromUtf8("declare default element namespace \"" SVG_NS_URI "\"; "
"declare namespace freecad=\"" FREECAD_SVG_NS_URI "\"; "
"//text[@freecad:editable]"),
"//text[@" FREECAD_ATTR_EDITABLE "]"),
[&](QDomElement& textElement) -> bool {
QString name = textElement.attribute(QString::fromUtf8("freecad:editable"));
QString name = textElement.attribute(QString::fromUtf8(FREECAD_ATTR_EDITABLE));
double x = Rez::guiX(
textElement.attribute(QString::fromUtf8("x"), QString::fromUtf8("0.0")).toDouble());
double y = Rez::guiX(

View File

@@ -38,6 +38,7 @@
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawProjGroupItem.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include "TaskProjGroup.h"
#include "ui_TaskProjGroup.h"
@@ -306,81 +307,6 @@ void TaskProjGroup::spacingChanged()
multiView->recomputeFeature();
}
std::pair<int, int> TaskProjGroup::nearestFraction(const double val, const long int maxDenom) const
{
/*
** find rational approximation to given real number
** David Eppstein / UC Irvine / 8 Aug 1993
**
** With corrections from Arno Formella, May 2008
** and additional fiddles by WF 2017
** usage: a.out r d
** r is real number to approx
** d is the maximum denominator allowed
**
** based on the theory of continued fractions
** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
** then best approximation is found by truncating this series
** (with some adjustments in the last term).
**
** Note the fraction can be recovered as the first column of the matrix
** ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
** ( 1 0 ) ( 1 0 ) ( 1 0 )
** Instead of keeping the sequence of continued fraction terms,
** we just keep the last partial product of these matrices.
*/
std::pair<int, int> result;
long m[2][2];
long maxden = maxDenom;
long ai;
double x = val;
double startx = x;
/* initialize matrix */
m[0][0] = m[1][1] = 1;
m[0][1] = m[1][0] = 0;
/* loop finding terms until denom gets too big */
while (m[1][0] * ( ai = (long)x ) + m[1][1] <= maxden) {
long t;
t = m[0][0] * ai + m[0][1];
m[0][1] = m[0][0];
m[0][0] = t;
t = m[1][0] * ai + m[1][1];
m[1][1] = m[1][0];
m[1][0] = t;
if(x == (double) ai)
break; // AF: division by zero
x = 1/(x - (double) ai);
if(x > (double) std::numeric_limits<int>::max())
break; // AF: representation failure
}
/* now remaining x is between 0 and 1/ai */
/* approx as either 0 or 1/m where m is max that will fit in maxden */
/* first try zero */
double error1 = startx - ((double) m[0][0] / (double) m[1][0]);
int n1 = m[0][0];
int d1 = m[1][0];
/* now try other possibility */
ai = (maxden - m[1][1]) / m[1][0];
m[0][0] = m[0][0] * ai + m[0][1];
m[1][0] = m[1][0] * ai + m[1][1];
double error2 = startx - ((double) m[0][0] / (double) m[1][0]);
int n2 = m[0][0];
int d2 = m[1][0];
if (std::fabs(error1) <= std::fabs(error2)) {
result.first = n1;
result.second = d1;
} else {
result.first = n2;
result.second = d2;
}
return result;
}
void TaskProjGroup::updateTask()
{
// Update the scale type
@@ -398,7 +324,7 @@ void TaskProjGroup::setFractionalScale(double newScale)
{
blockUpdate = true;
std::pair<int, int> fraction = nearestFraction(newScale);
std::pair<int, int> fraction = DrawUtil::nearestFraction(newScale);
ui->sbScaleNum->setValue(fraction.first);
ui->sbScaleDen->setValue(fraction.second);

View File

@@ -60,7 +60,6 @@ public:
QPushButton* btnApply);
void updateTask();
std::pair<int, int> nearestFraction(double val, long int maxDenom = 999) const;
// Sets the numerator and denominator widgets to match newScale
void setFractionalScale(double newScale);
void setCreateMode(bool mode) { m_createMode = mode;}