Compare commits

...

70 Commits

Author SHA1 Message Date
Abdullah Tahiri b7b014ce43 App/Gui: New restoreError Document status and Gui pop-up
========================================================

If the restore of Document.xml results in invalid Document.xml (because unhandled exceptions occurred), the
document status Document::restoreError is set. The GUI or Mod/Web if a link was clicked, show a pop-up indicating
this situation.

This commit also shows an appropriate pop-up for the partialRestore when opening from the menu, that before only
appeared when opening by clicking a link.
2021-01-30 20:07:55 +01:00
Yorik van Havre 5e51288bf6 New fix for Addon Manager: Use gitmodules instead of parsing github html page 2020-12-04 14:58:41 +01:00
Yorik van Havre 734202bc81 Fixed typo in last commit 2020-10-29 13:13:01 +01:00
Yorik van Havre b7ab01e6de Better fix for failing addon-manager 2020-10-29 13:10:20 +01:00
lorenz 258f9f1577 fix for failing addon-manager
https://forum.freecadweb.org/viewtopic.php?f=13&t=51346
2020-10-20 16:30:30 +02:00
wmayer 783e1346c7 Fem: fix segmentation fault when opening contraint transform panel
Fix Python code
2020-02-26 01:15:21 +01:00
wmayer 5fd5d40d8f Part: the number of domains returned by TopoShape::getDomains must match with number of faces 2020-02-26 01:13:52 +01:00
wmayer d13e777b28 apply fixes from master when building with occt 7.4 2020-02-06 22:25:00 +01:00
wmayer 9ae1297056 fixes #0004182: Segfault when clicking constraints from a different viewport [skip ci] 2020-01-11 17:37:49 +01:00
Syres916 9f2401dd4e [Draft] ImportDXF 0.18 Bug upgrading from 0.16
See discussion https://forum.freecadweb.org/viewtopic.php?f=3&t=41879
2019-12-26 15:52:12 -03:00
wmayer 04641657d0 fixes #0004233: Access violation and file corruption on undo duplicate sketch 2019-12-24 12:52:16 +01:00
Bernd Hahnebach 061439ee3b FEM: py3 fix in selection widget 2019-12-20 13:39:42 +01:00
Bernd Hahnebach 7479df7303 FEM: selection widgets, add some error prints 2019-12-20 13:39:25 +01:00
Bernd Hahnebach e8bd919ff8 FEM: equations, fix reset edit mode 2019-12-20 13:39:10 +01:00
Syres916 6f0d9c21f3 [AddonManager] 0.18 Improve Non GitPython Error..
...Handling. Previous output when clicking Macros tab caused errors in Report View with no Macros loaded at all.
2019-12-17 15:11:46 -03:00
wmayer 9c2cf7283b fix encoding problem when clicking a link on StartPage if application is installed into a directory with non-ASCII characters 2019-11-05 13:34:21 +01:00
Syres916 44f6e86d19 [Arch] ArchMaterial 0.18 Fix Crash
As per discussion  https://forum.freecadweb.org/viewtopic.php?t=36806
2019-11-05 09:27:20 -03:00
wmayer 980bf9060e pre-select name filter in import/export file dialog 2019-10-22 18:53:35 +02:00
wandererfan f972b010bb [TD]Fix slow GC of QGIPrimPath 2019-10-15 19:43:51 -04:00
sliptonic 5a1527f954 Merge pull request #2489 from Jantek/patch-1
[Path] Correction of drill speed calculation for grbl_G1 of 18.3
2019-10-07 16:02:43 -05:00
Syres916 dea7d2080b [Spreadsheet] Excel File Import fix Py3 bug
Please see discussion https://forum.freecadweb.org/viewtopic.php?f=3&t=39653
2019-09-28 12:18:33 +02:00
sliptonic a4a42b36e4 Merge pull request #2541 from Syres916/patch-4
[Path] Fix xrange bug with Py3
2019-09-24 15:36:52 -05:00
Syres916 7fa0eea88a Fix xrange bug in PathSurface.py 2019-09-20 15:28:57 +01:00
Syres916 2b28c50525 Fix xrange bug in PathCircularHoleBaseGui.py 2019-09-20 15:22:29 +01:00
wmayer 31d9283325 fix print preview function for >= Qt 5.9 2019-09-07 13:23:39 +02:00
luz.paz f07b6e3e17 Follow-up: Fixed thumbnail for problematic FEM example file
This updated FEM example has the thumbnail updated  to remove the artifacts present in the previous commit.
2019-09-06 07:38:54 -04:00
sliptonic 38e0e99579 Merge pull request #2490 from Jantek/patch-2
[Path] Fixed problems with 'pythonopen' in grbl_G81 of release 18.3
2019-09-05 17:00:29 -05:00
luz.paz 2483c467bb Backport: startwb files restored in 0.18.3 to display thumbs correctly
0.18.x displays the example files within in the Start WB without their respective thumbs. This PR restores that functionality:  Forum thread: https://forum.freecadweb.org/viewtopic.php?f=8&t=39038  

Props to kisolre  to the assistance :)
2019-09-04 17:22:35 -04:00
Jan Phillip Willmann d9b8faf8bf Fixed problems with 'pythonopen' 2019-09-04 10:21:15 +02:00
Jan Phillip Willmann 102b97aca7 Correction of drill speed calculation
The multiplier was missing, so the calculated drill speed was to low.
2019-09-04 10:08:49 +02:00
Bernd Hahnebach 1e9f9faa24 Material: py2 fix in depreciated mat file parser (back port from 0.19) 2019-08-26 08:31:49 +02:00
wandererfan 7320c4c448 [TD]Fix #4017 Crash on bad hatch scale 2019-07-20 11:14:23 -04:00
Yorik van Havre 3129ae4296 AddonManager: Skip non-github addons 2019-07-12 18:08:08 -03:00
Abdullah Tahiri 0572853dbd Sketcher: Fix Carbon copy leads to unsolvable sketch
====================================================

fixes #3973

https://forum.freecadweb.org/viewtopic.php?p=316251#p316198

This commit disables an old "axis orientation correction mode", which tried to
solve a problem with orientation of the axis. It never worked fine and it should
have never been introduced, as everything it intends to do should be done by
setting the appropriate placement offset.
2019-06-28 10:49:05 +02:00
Abdullah Tahiri 2f0c3a79fa Sketcher: Fix carbon copy construction points
=============================================

fixes #3926

Points made of construction type are special non-constrainable points, such as (current) bspline knots.

This was not intended in Carbon Copy.
2019-06-28 10:48:56 +02:00
wmayer 0f29891a98 fixes #0003993: Memory leak with Python3 2019-06-24 14:32:42 +02:00
wmayer 3eaf87b2dc code simplification in PythonWrapper 2019-06-22 14:38:49 +02:00
wmayer 60fd668d5c issue #0003984: Creating a Path Job object fails with 'PySide2.QtWidgets.QDialog' object has no attribute 'templateGroup' 2019-06-22 14:38:20 +02:00
Russell Johnson 4351058504 Fixes bug #4008: removes phantom path cause
Job object was base of transformations, rather than Job base(clone).
2019-06-22 14:34:51 +02:00
wmayer f2f4b44792 Fix crash in case encoding of Python paths fails 2019-06-21 16:33:18 +02:00
luz.paz 90ff921ef7 [Material] Respect unicode filenames
Fixes #4027
2019-06-21 16:27:41 +02:00
Zheng, Lei 662aebd881 BrowserView: fix QWebEngine crash 2019-06-21 16:27:12 +02:00
wmayer d2f0c4f33d Py3: no __builtin__ module available 2019-06-17 17:11:14 +02:00
wmayer b80d000aff fixes 0004010: Box Selection + Part -> MakeCompound will crash FreeCAD 2019-06-12 11:26:21 +02:00
Bernd Hahnebach 627ae70a53 FEM: solver elmer tasks, Py3 decode fix 2019-06-11 15:49:12 +02:00
wmayer a261a55adf make OpenSCAD utilities working again with Py2 2019-06-07 13:09:41 +02:00
wmayer dbb4cc6415 replace insecure use of eval() with proper use of units 2019-05-11 13:02:55 +02:00
wmayer e25cd6c71b py3/py2: use exec as function 2019-05-10 19:26:12 +02:00
Yorik van Havre 1fb7ed43cf Arch: Fixed error in roof - Fixes #3864 2019-05-07 22:49:19 -03:00
Yorik van Havre ebca0c9836 Draft: Fixed 0.18.1 bug in DXF importer 2019-05-02 16:10:12 -03:00
wmayer 476b4d5f97 Py3 fix: correctly convert a Python str to const char* 2019-04-21 10:15:13 +02:00
wmayer 3450cf9860 Py3: fix reading/writing from/to OBJ file 2019-04-21 10:14:45 +02:00
wmayer 0dc75267fe fixes 0003913: libspnav crash on linux wayland during startup 2019-04-05 17:43:53 +02:00
Bernd Hahnebach f7dccfaa90 FEM: ccx tools, set back the assignment of linux and osx ccx binary path 2019-04-04 15:42:43 +02:00
lorenz 76542ae729 FEM: osx: try to fix default ccx detection 2019-04-04 15:42:24 +02:00
wmayer 55698377f9 fix crash when checking an empty error message of an exception 2019-04-04 15:37:55 +02:00
wmayer f21cbce8cd fix crash when checking an empty error message of an exception 2019-04-04 15:37:40 +02:00
Bernd Hahnebach 9152703516 FEM: Py3 fix in result reader 2019-04-04 15:37:25 +02:00
Peter Eszlari c264c76d8f Linux/appdata: generate release info 2019-04-04 15:37:09 +02:00
sliptonic d8f5560cac Path: per Werner, fixing bug for function removed from string module
in py3
2019-04-04 15:36:53 +02:00
wmayer 442e411cf0 Py3: make string concatenation to work with Py2 and Py3 2019-04-04 15:36:39 +02:00
wmayer 55080952a8 reset expressions of a property when removing it 2019-04-04 15:36:25 +02:00
wmayer f185504b4e in case object deletion fails then make sure to re-enable updates of the main window 2019-04-04 15:36:11 +02:00
wmayer 2bc3daedcc Document::breakDependency should handle exceptions to avoid to leave document in an inconsistent state 2019-04-04 15:35:57 +02:00
Craig Marshall 2cef63f8a3 Fix #2034 with more precision attempt 2 2019-04-04 15:35:43 +02:00
triplus 81a7d937bd Fix for build failure on Ubuntu 16.04 2019-04-04 15:35:12 +02:00
wmayer 64f3424cab fix mouse selection for high DPI screens 2019-04-04 15:33:10 +02:00
wmayer 64cb745ddc fixes 0003130: FreeCAD 0.17 Qt5 bugs with external display 2019-04-04 15:32:54 +02:00
wmayer 228876f8f2 improve drawing of overlay pixmaps for high DPI screens 2019-04-04 15:32:34 +02:00
Yorik van Havre 8ece48c70b Arch: Fixed materials not updating their dicts 2019-03-20 10:01:27 -03:00
68 changed files with 613 additions and 307 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -180,12 +180,12 @@ class R4: public R3
{
friend std::ostream& operator <<(std::ostream& f, const R4 & P )
{ f << P.x << ' ' << P.y << ' ' << P.z << ' ' << P.omega; return f; }
friend istream& operator >>(istream& f, R4 & P)
friend std::istream& operator >>(std::istream& f, R4 & P)
{ f >> P.x >> P.y >> P.z >> P.omega ; return f; }
friend std::ostream& operator <<(std::ostream& f, const R4 * P )
{ f << P->x << ' ' << P->y << ' ' << P->z << ' ' << P->omega; return f; }
friend istream& operator >>(istream& f, R4 * P)
friend std::istream& operator >>(std::istream& f, R4 * P)
{ f >> P->x >> P->y >> P->z >> P->omega ; return f; }
public:
+5 -1
View File
@@ -1529,7 +1529,11 @@ void Application::initConfig(int argc, char ** argv)
PyImport_AppendInittab ("FreeCAD", init_freecad_module);
PyImport_AppendInittab ("__FreeCADBase__", init_freecad_base_module);
#endif
mConfig["PythonSearchPath"] = Interpreter().init(argc,argv);
const char* pythonpath = Interpreter().init(argc,argv);
if (pythonpath)
mConfig["PythonSearchPath"] = pythonpath;
else
Base::Console().Warning("Encoding of Python paths failed\n");
// Parse the options that have impact on the init process
ParseOptions(argc,argv);
+8 -1
View File
@@ -1861,6 +1861,7 @@ void Document::restore (void)
}
catch (const Base::Exception& e) {
Base::Console().Error("Invalid Document.xml: %s\n", e.what());
setStatus(Document::RestoreError, true);
}
// Special handling for Gui document, the view representations must already
@@ -3031,7 +3032,13 @@ void Document::breakDependency(DocumentObject* pcObject, bool clear)
std::vector<App::ObjectIdentifier> paths;
pcObject->ExpressionEngine.getPathsToDocumentObject(it->second, paths);
for (std::vector<App::ObjectIdentifier>::iterator jt = paths.begin(); jt != paths.end(); ++jt) {
pcObject->ExpressionEngine.setValue(*jt, nullptr);
// When nullifying the expression handle case where an identifier lacks of the property
try {
pcObject->ExpressionEngine.setValue(*jt, nullptr);
}
catch (const Base::Exception& e) {
e.ReportException();
}
}
}
}
+2 -1
View File
@@ -69,7 +69,8 @@ public:
Closable = 2,
Restoring = 3,
Recomputing = 4,
PartialRestore = 5
PartialRestore = 5,
RestoreError = 10
};
/** @name Properties */
+20 -3
View File
@@ -496,10 +496,27 @@ void DocumentObject::setDocument(App::Document* doc)
onSettingDocument();
}
void DocumentObject::onAboutToRemoveProperty(const char* prop)
void DocumentObject::onAboutToRemoveProperty(const char* name)
{
if (_pDoc)
_pDoc->removePropertyOfObject(this, prop);
if (_pDoc) {
_pDoc->removePropertyOfObject(this, name);
Property* prop = getDynamicPropertyByName(name);
if (prop) {
auto expressions = ExpressionEngine.getExpressions();
std::vector<App::ObjectIdentifier> removeExpr;
for (auto it : expressions) {
if (it.first.getProperty() == prop) {
removeExpr.push_back(it.first);
}
}
for (auto it : removeExpr) {
ExpressionEngine.setValue(it, boost::shared_ptr<Expression>());
}
}
}
}
void DocumentObject::onBeforeChange(const Property* prop)
+4 -3
View File
@@ -1062,6 +1062,7 @@ boost::any ObjectIdentifier::getValue() const
destructor d1(pyvalue);
Base::PyGILStateLocker locker;
if (!pyvalue)
throw Base::RuntimeError("Failed to get property value.");
#if PY_MAJOR_VERSION < 3
@@ -1078,12 +1079,12 @@ boost::any ObjectIdentifier::getValue() const
return boost::any(PyString_AsString(pyvalue));
#endif
else if (PyUnicode_Check(pyvalue)) {
#if PY_MAJOR_VERSION >= 3
return boost::any(PyUnicode_AsUTF8(pyvalue));
#else
PyObject * s = PyUnicode_AsUTF8String(pyvalue);
destructor d2(s);
#if PY_MAJOR_VERSION >= 3
return boost::any(PyUnicode_AsUTF8(s));
#else
return boost::any(PyString_AsString(s));
#endif
}
+6 -4
View File
@@ -354,13 +354,15 @@ void InterpreterSingleton::runInteractiveString(const char *sCmd)
PyErr_Fetch(&errobj, &errdata, &errtraceback);
RuntimeError exc(""); // do not use PyException since this clears the error indicator
if (errdata) {
#if PY_MAJOR_VERSION >= 3
if (PyUnicode_Check(errdata))
exc.setMessage(PyUnicode_AsUTF8(errdata));
if (PyUnicode_Check(errdata))
exc.setMessage(PyUnicode_AsUTF8(errdata));
#else
if (PyString_Check(errdata))
exc.setMessage(PyString_AsString(errdata));
if (PyString_Check(errdata))
exc.setMessage(PyString_AsString(errdata));
#endif
}
PyErr_Restore(errobj, errdata, errtraceback);
if (PyErr_Occurred())
PyErr_Print();
+4 -4
View File
@@ -2033,25 +2033,25 @@ namespace Py
}
String()
: SeqBase<Char>( PyUnicode_FromString( "" ) )
: SeqBase<Char>( PyUnicode_FromString( "" ), true )
{
validate();
}
String( const char *latin1 )
: SeqBase<Char>( PyUnicode_FromString( latin1 ) )
: SeqBase<Char>( PyUnicode_FromString( latin1 ), true )
{
validate();
}
String( const std::string &latin1 )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ) )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ), true )
{
validate();
}
String( const char *latin1, Py_ssize_t size )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ) )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ), true )
{
validate();
}
+11 -4
View File
@@ -571,20 +571,27 @@ QPixmap BitmapFactoryInst::merge(const QPixmap& p1, const QPixmap& p2, Position
{
// does the similar as the method above except that this method does not resize the resulting pixmap
int x = 0, y = 0;
#if QT_VERSION >= 0x050000
qreal dpr1 = p1.devicePixelRatio();
qreal dpr2 = p2.devicePixelRatio();
#else
qreal dpr1 = 1;
qreal dpr2 = 1;
#endif
switch (pos)
{
case TopLeft:
break;
case TopRight:
x = p1.width () - p2.width ();
x = p1.width ()/dpr1 - p2.width ()/dpr2;
break;
case BottomLeft:
y = p1.height() - p2.height();
y = p1.height()/dpr1 - p2.height()/dpr2;
break;
case BottomRight:
x = p1.width () - p2.width ();
y = p1.height() - p2.height();
x = p1.width ()/dpr1 - p2.width ()/dpr2;
y = p1.height()/dpr1 - p2.height()/dpr2;
break;
}
+32 -12
View File
@@ -151,6 +151,14 @@ void StdCmdOpen::activated(int iMsg)
else {
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
getGuiApplication()->open(it.key().toUtf8(), it.value().toLatin1());
App::Document *doc = App::GetApplication().getActiveDocument();
if(doc && doc->testStatus(App::Document::PartialRestore))
QMessageBox::critical(getMainWindow(), QObject::tr("Error"), QObject::tr("There were errors while loading the file. Some data might have been modified or not recovered at all. Look in the report view for more specific information about the objects involved."));
if(doc && doc->testStatus(App::Document::RestoreError))
QMessageBox::critical(getMainWindow(), QObject::tr("Error"), QObject::tr("There were serious errors while loading the file. Some data might have been modified or not recovered at all. Saving the project will most likely result in loss of data."));
}
}
}
@@ -1092,9 +1100,15 @@ void StdCmdDelete::activated(int iMsg)
// handle the view provider
Gui::getMainWindow()->setUpdatesEnabled(false);
(*it)->openTransaction("Delete");
vpedit->onDelete(ft->getSubNames());
(*it)->commitTransaction();
try {
(*it)->openTransaction("Delete");
vpedit->onDelete(ft->getSubNames());
(*it)->commitTransaction();
}
catch (const Base::Exception& e) {
(*it)->abortTransaction();
e.ReportException();
}
Gui::getMainWindow()->setUpdatesEnabled(true);
Gui::getMainWindow()->update();
@@ -1171,18 +1185,24 @@ void StdCmdDelete::activated(int iMsg)
if (autoDeletion) {
Gui::getMainWindow()->setUpdatesEnabled(false);
(*it)->openTransaction("Delete");
for (std::vector<Gui::SelectionObject>::iterator ft = sel.begin(); ft != sel.end(); ++ft) {
Gui::ViewProvider* vp = pGuiDoc->getViewProvider(ft->getObject());
if (vp) {
// ask the ViewProvider if it wants to do some clean up
if (vp->onDelete(ft->getSubNames())) {
doCommand(Doc,"App.getDocument(\"%s\").removeObject(\"%s\")"
,(*it)->getName(), ft->getFeatName());
try {
(*it)->openTransaction("Delete");
for (std::vector<Gui::SelectionObject>::iterator ft = sel.begin(); ft != sel.end(); ++ft) {
Gui::ViewProvider* vp = pGuiDoc->getViewProvider(ft->getObject());
if (vp) {
// ask the ViewProvider if it wants to do some clean up
if (vp->onDelete(ft->getSubNames())) {
doCommand(Doc,"App.getDocument(\"%s\").removeObject(\"%s\")"
,(*it)->getName(), ft->getFeatName());
}
}
}
(*it)->commitTransaction();
}
catch (const Base::Exception& e) {
(*it)->abortTransaction();
e.ReportException();
}
(*it)->commitTransaction();
Gui::getMainWindow()->setUpdatesEnabled(true);
Gui::getMainWindow()->update();
+6
View File
@@ -199,6 +199,8 @@ QString FileDialog::getSaveFileName (QWidget * parent, const QString & caption,
dlg.setDirectory(dirName);
dlg.setOptions(options);
dlg.setNameFilters(filter.split(QLatin1String(";;")));
if (selectedFilter && !selectedFilter->isEmpty())
dlg.selectNameFilter(*selectedFilter);
dlg.onSelectedFilter(dlg.selectedNameFilter());
dlg.setNameFilterDetailsVisible(true);
dlg.setConfirmOverwrite(true);
@@ -295,6 +297,8 @@ QString FileDialog::getOpenFileName(QWidget * parent, const QString & caption, c
dlg.setOptions(options);
dlg.setNameFilters(filter.split(QLatin1String(";;")));
dlg.setNameFilterDetailsVisible(true);
if (selectedFilter && !selectedFilter->isEmpty())
dlg.selectNameFilter(*selectedFilter);
if (dlg.exec() == QDialog::Accepted) {
if (selectedFilter)
*selectedFilter = dlg.selectedNameFilter();
@@ -369,6 +373,8 @@ QStringList FileDialog::getOpenFileNames (QWidget * parent, const QString & capt
dlg.setOptions(options);
dlg.setNameFilters(filter.split(QLatin1String(";;")));
dlg.setNameFilterDetailsVisible(true);
if (selectedFilter && !selectedFilter->isEmpty())
dlg.selectNameFilter(*selectedFilter);
if (dlg.exec() == QDialog::Accepted) {
if (selectedFilter)
*selectedFilter = dlg.selectedNameFilter();
@@ -98,6 +98,12 @@ void Gui::GUIApplicationNativeEventAware::initSpaceball(QMainWindow *window)
mainWindow = window;
#if defined(Q_OS_LINUX) && defined(SPNAV_FOUND)
#if QT_VERSION >= 0x050200
if (!QX11Info::isPlatformX11()) {
Base::Console().Log("Application is not running on X11\n");
return;
}
#endif
if (spnav_x11_open(QX11Info::display(), window->winId()) == -1) {
Base::Console().Log("Couldn't connect to spacenav daemon\n");
} else {
+18
View File
@@ -390,7 +390,16 @@ int PolyPickerSelection::locationEvent(const SoLocation2Event* const, const QPoi
if (polyline.isWorking()) {
// check the position
#if QT_VERSION >= 0x050600
qreal dpr = _pcView3D->getGLWidget()->devicePixelRatioF();
#else
qreal dpr = 1.0;
#endif
QRect r = _pcView3D->getGLWidget()->rect();
if (dpr != 1.0) {
r.setHeight(r.height()*dpr);
r.setWidth(r.width()*dpr);
}
if (!r.contains(clPoint)) {
if (clPoint.x() < r.left())
@@ -599,7 +608,16 @@ int FreehandSelection::locationEvent(const SoLocation2Event* const e, const QPoi
if (polyline.isWorking()) {
// check the position
#if QT_VERSION >= 0x050600
qreal dpr = _pcView3D->getGLWidget()->devicePixelRatioF();
#else
qreal dpr = 1.0;
#endif
QRect r = _pcView3D->getGLWidget()->rect();
if (dpr != 1.0) {
r.setHeight(r.height()*dpr);
r.setWidth(r.width()*dpr);
}
if (!r.contains(clPoint)) {
if (clPoint.x() < r.left())
+2 -2
View File
@@ -116,7 +116,7 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const
dict = PyDict_Copy(dict);
QByteArray cmd =
"import string, os, sys, pydoc, pkgutil\n"
"import os, sys, pydoc, pkgutil\n"
"\n"
"class FreeCADDoc(pydoc.HTMLDoc):\n"
" def index(self, dir, shadowed=None):\n"
@@ -160,7 +160,7 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const
" ret = pydoc.html.index(dir, seen)\n"
" if ret != None:\n"
" indices.append(ret)\n"
"contents = heading + string.join(indices) + '''<p align=right>\n"
"contents = heading + ' '.join(indices) + '''<p align=right>\n"
"<font color=\"#909090\" face=\"helvetica, arial\"><strong>\n"
"pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''\n"
"htmldocument=pydoc.html.page(title,contents)\n";
+2 -1
View File
@@ -323,7 +323,8 @@ void InteractiveInterpreter::runCode(PyCodeObject* code) const
if (PyErr_Occurred()) { /* get latest python exception information */
PyObject *errobj, *errdata, *errtraceback;
PyErr_Fetch(&errobj, &errdata, &errtraceback);
if (PyDict_Check(errdata)) {
// the error message can be empty so errdata will be null
if (errdata && PyDict_Check(errdata)) {
PyObject* value = PyDict_GetItemString(errdata, "swhat");
if (value) {
Base::RuntimeError e;
+3 -1
View File
@@ -477,7 +477,9 @@ void View3DInventor::printPreview()
{
QPrinter printer(QPrinter::ScreenResolution);
printer.setFullPage(true);
//printer.setPageSize(QPrinter::A3);
#if (QT_VERSION > QT_VERSION_CHECK(5, 9, 0))
printer.setPageSize(QPrinter::A4);
#endif
printer.setOrientation(QPrinter::Landscape);
QPrintPreviewDialog dlg(&printer, this);
+58 -19
View File
@@ -232,6 +232,28 @@ Py::Object qt_wrapInstance(qttype object, const char* className,
return func.apply(arguments);
}
const char* qt_identifyType(QObject* ptr, const char* pyside)
{
PyObject* module = PyImport_ImportModule(pyside);
if (!module) {
std::string error = "Cannot load ";
error += pyside;
error += " module";
throw Py::Exception(PyExc_ImportError, error);
}
Py::Module qtmod(module);
const QMetaObject* metaObject = ptr->metaObject();
while (metaObject) {
const char* className = metaObject->className();
if (qtmod.getDict().hasKey(className))
return className;
metaObject = metaObject->superClass();
}
return nullptr;
}
void* qt_getCppPointer(const Py::Object& pyobject, const char* shiboken, const char* unwrap)
{
// https://github.com/PySide/Shiboken/blob/master/shibokenmodule/typesystem_shiboken.xml
@@ -475,39 +497,50 @@ bool PythonWrapper::loadWidgetsModule()
void PythonWrapper::createChildrenNameAttributes(PyObject* root, QObject* object)
{
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
Q_FOREACH (QObject* child, object->children()) {
const QByteArray name = child->objectName().toLocal8Bit();
if (!name.isEmpty() && !name.startsWith("_") && !name.startsWith("qt_")) {
bool hasAttr = PyObject_HasAttrString(root, name.constData());
if (!hasAttr) {
#if defined (HAVE_SHIBOKEN2) && defined(HAVE_PYSIDE2)
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide2_QtCoreTypes[SBK_QOBJECT_IDX], child));
#else
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide_QtCoreTypes[SBK_QOBJECT_IDX], child));
#endif
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython(reinterpret_cast<SbkObjectType*>(Shiboken::SbkType<QObject>()), child));
PyObject_SetAttrString(root, name.constData(), pyChild);
#elif QT_VERSION >= 0x050000
const char* className = qt_identifyType(child, "PySide2.QtWidgets");
if (!className) {
if (qobject_cast<QWidget*>(child))
className = "QWidget";
else
className = "QObject";
}
Py::Object pyChild(qt_wrapInstance<QObject*>(child, className, "shiboken2", "PySide2.QtWidgets", "wrapInstance"));
PyObject_SetAttrString(root, name.constData(), pyChild.ptr());
#else
const char* className = qt_identifyType(child, "PySide.QtGui");
if (!className) {
if (qobject_cast<QWidget*>(child))
className = "QWidget";
else
className = "QObject";
}
Py::Object pyChild(qt_wrapInstance<QObject*>(child, className, "shiboken", "PySide.QtGui", "wrapInstance"));
PyObject_SetAttrString(root, name.constData(), pyChild.ptr());
#endif
}
createChildrenNameAttributes(root, child);
}
createChildrenNameAttributes(root, child);
}
#else
Q_UNUSED(root);
Q_UNUSED(object);
#endif
}
void PythonWrapper::setParent(PyObject* pyWdg, QObject* parent)
{
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
if (parent) {
#if defined (HAVE_SHIBOKEN2) && defined(HAVE_PYSIDE2)
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide2_QtGuiTypes[SBK_QWIDGET_IDX], parent));
#else
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide_QtGuiTypes[SBK_QWIDGET_IDX], parent));
#endif
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython(reinterpret_cast<SbkObjectType*>(Shiboken::SbkType<QWidget>()), parent));
Shiboken::Object::setParent(pyParent, pyWdg);
}
#else
@@ -680,7 +713,10 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
str << "import pyside2uic\n"
<< "from PySide2 import QtCore, QtGui, QtWidgets\n"
<< "import xml.etree.ElementTree as xml\n"
<< "from cStringIO import StringIO\n"
<< "try:\n"
<< " from cStringIO import StringIO\n"
<< "except:\n"
<< " from io import StringIO\n"
<< "\n"
<< "uiFile = \"" << file.c_str() << "\"\n"
<< "parsed = xml.parse(uiFile)\n"
@@ -691,7 +727,7 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
<< " frame = {}\n"
<< " pyside2uic.compileUi(f, o, indent=0)\n"
<< " pyc = compile(o.getvalue(), '<string>', 'exec')\n"
<< " exec pyc in frame\n"
<< " exec(pyc, frame)\n"
<< " #Fetch the base_class and form class based on their type in the xml from designer\n"
<< " form_class = frame['Ui_%s'%form_class]\n"
<< " base_class = eval('QtWidgets.%s'%widget_class)\n";
@@ -699,7 +735,10 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
str << "import pysideuic\n"
<< "from PySide import QtCore, QtGui\n"
<< "import xml.etree.ElementTree as xml\n"
<< "from cStringIO import StringIO\n"
<< "try:\n"
<< " from cStringIO import StringIO\n"
<< "except:\n"
<< " from io import StringIO\n"
<< "\n"
<< "uiFile = \"" << file.c_str() << "\"\n"
<< "parsed = xml.parse(uiFile)\n"
@@ -710,7 +749,7 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
<< " frame = {}\n"
<< " pysideuic.compileUi(f, o, indent=0)\n"
<< " pyc = compile(o.getvalue(), '<string>', 'exec')\n"
<< " exec pyc in frame\n"
<< " exec(pyc, frame)\n"
<< " #Fetch the base_class and form class based on their type in the xml from designer\n"
<< " form_class = frame['Ui_%s'%form_class]\n"
<< " base_class = eval('QtGui.%s'%widget_class)\n";
+39 -25
View File
@@ -298,7 +298,10 @@ class AddonsInstaller(QtGui.QDialog):
if oktoclose:
if hasattr(self,"install_worker"):
QtGui.QMessageBox.information(self, translate("AddonsInstaller","Addon manager"), translate("AddonsInstaller","Please restart FreeCAD for changes to take effect."))
shutil.rmtree(self.macro_repo_dir,onerror=self.remove_readonly)
try:
shutil.rmtree(self.macro_repo_dir,onerror=self.remove_readonly)
except:
FreeCAD.Console.PrintMessage(translate("AddonsInstaller", 'AddonManager - Macros, there was nothing to clean up'))
QtGui.QDialog.reject(self)
def retranslateUi(self):
@@ -562,29 +565,36 @@ class UpdateWorker(QtCore.QThread):
def run(self):
"populates the list of addons"
self.progressbar_show.emit(True)
u = urlopen("https://github.com/FreeCAD/FreeCAD-addons")
u = urlopen("https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/.gitmodules")
p = u.read()
if sys.version_info.major >= 3 and isinstance(p, bytes):
p = p.decode("utf-8")
u.close()
p = p.replace("\n"," ")
p = re.findall("octicon-file-submodule(.*?)message",p)
p1 = re.findall("url = (http.*?)\n",p)
names = re.findall("path = (.*?)\n",p)
links = []
for l in p1:
if l.endswith(".git"):
links.append(l[:-4])
else:
links.append(l)
basedir = FreeCAD.getUserAppDataDir()
moddir = basedir + os.sep + "Mod"
repos = []
for l in p:
#name = re.findall("data-skip-pjax=\"true\">(.*?)<",l)[0]
name = re.findall("title=\"(.*?) @",l)[0]
for i in range(len(links)):
name = names[i]
self.info_label.emit(name)
#url = re.findall("title=\"(.*?) @",l)[0]
url = "https://github.com/" + re.findall("href=\"\/(.*?)\/tree",l)[0]
addondir = moddir + os.sep + name
#print ("found:",name," at ",url)
if not os.path.exists(addondir):
state = 0
try:
url = links[i]
except:
pass
else:
state = 1
repos.append([name,url,state])
addondir = moddir + os.sep + name
if not os.path.exists(addondir):
state = 0
else:
state = 1
repos.append([name,url,state])
if not repos:
self.info_label.emit(translate("AddonsInstaller", "Unable to download addon list."))
else:
@@ -715,16 +725,20 @@ class FillMacroListWorker(QtCore.QThread):
return
self.info_label_signal.emit('Downloading list of macros for git...')
git.Repo.clone_from('https://github.com/FreeCAD/FreeCAD-macros.git', self.repo_dir)
for dirpath, _, filenames in os.walk(self.repo_dir):
if '.git' in dirpath:
continue
for filename in filenames:
if filename.lower().endswith('.fcmacro'):
macro = Macro(filename[:-8]) # Remove ".FCMacro".
macro.on_git = True
macro.src_filename = os.path.join(dirpath, filename)
self.macros.append(macro)
try:
git.Repo.clone_from('https://github.com/FreeCAD/FreeCAD-macros.git', self.repo_dir)
for dirpath, _, filenames in os.walk(self.repo_dir):
if '.git' in dirpath:
continue
for filename in filenames:
if filename.lower().endswith('.fcmacro'):
macro = Macro(filename[:-8]) # Remove ".FCMacro".
macro.on_git = True
macro.src_filename = os.path.join(dirpath, filename)
self.macros.append(macro)
except:
FreeCAD.Console.PrintWarning(translate('AddonsInstaller', 'Something went wrong with the Git Macro Retieval, possibly the Git executable is not in the path')+"\n")
def retrieve_macros_from_wiki(self):
"""Retrieve macros from the wiki
+52 -38
View File
@@ -250,6 +250,7 @@ class _ArchMaterial:
"The Material object"
def __init__(self,obj):
self.Type = "Material"
obj.Proxy = self
obj.addProperty("App::PropertyString","Description","Arch",QT_TRANSLATE_NOOP("App::Property","A description for this material"))
@@ -258,13 +259,23 @@ class _ArchMaterial:
obj.addProperty("App::PropertyPercent","Transparency","Arch",QT_TRANSLATE_NOOP("App::Property","The transparency value of this material"))
obj.addProperty("App::PropertyColor","Color","Arch",QT_TRANSLATE_NOOP("App::Property","The color of this material"))
def isSameColor(self,c1,c2):
r = 4
if round(c1[0],r) == round(c2[0],r):
if round(c1[1],r) == round(c2[1],r):
if round(c1[2],r) == round(c2[2],r):
return True
return False
def onChanged(self,obj,prop):
d = None
d = obj.Material
if prop == "Material":
if "DiffuseColor" in obj.Material:
c = tuple([float(f) for f in obj.Material['DiffuseColor'].strip("()").split(",")])
if hasattr(obj,"Color"):
if obj.Color != c:
if not self.isSameColor(obj.Color,c):
obj.Color = c
if "Transparency" in obj.Material:
t = int(obj.Material['Transparency'])
@@ -283,52 +294,50 @@ class _ArchMaterial:
if hasattr(obj,"Description"):
if obj.Description != obj.Material["Description"]:
obj.Description = obj.Material["Description"]
if "Name" in obj.Material:
if hasattr(obj,"Label"):
if obj.Label != obj.Material["Name"]:
obj.Label = obj.Material["Name"]
elif prop == "Label":
if "Name" in d:
if d["Name"] == obj.Label:
return
d["Name"] = obj.Label
elif prop == "Color":
if hasattr(obj,"Color"):
if obj.Material:
d = obj.Material
val = str(obj.Color[:3])
if "DiffuseColor" in d:
if d["DiffuseColor"] == val:
return
d["DiffuseColor"] = val
if "DiffuseColor" in d:
if self.isSameColor(tuple([float(f) for f in d['DiffuseColor'].strip("()").split(",")]),obj.Color[:3]):
return
d["DiffuseColor"] = str(obj.Color[:3])
elif prop == "Transparency":
if hasattr(obj,"Transparency"):
if obj.Material:
d = obj.Material
val = str(obj.Transparency)
if "Transparency" in d:
if d["Transparency"] == val:
return
d["Transparency"] = val
val = str(obj.Transparency)
if "Transparency" in d:
if d["Transparency"] == val:
return
d["Transparency"] = val
elif prop == "ProductURL":
if hasattr(obj,"ProductURL"):
if obj.Material:
d = obj.Material
val = obj.ProductURL
if "ProductURL" in d:
if d["ProductURL"] == val:
return
obj.Material["ProductURL"] = val
val = obj.ProductURL
if "ProductURL" in d:
if d["ProductURL"] == val:
return
obj.Material["ProductURL"] = val
elif prop == "StandardCode":
if hasattr(obj,"StandardCode"):
if obj.Material:
d = obj.Material
val = obj.StandardCode
if "StandardCode" in d:
if d["StandardCode"] == val:
return
d["StandardCode"] = val
val = obj.StandardCode
if "StandardCode" in d:
if d["StandardCode"] == val:
return
d["StandardCode"] = val
elif prop == "Description":
if hasattr(obj,"Description"):
if obj.Material:
d = obj.Material
val = obj.Description
if "Description" in d:
if d["Description"] == val:
return
d["Description"] = val
if d:
val = obj.Description
if "Description" in d:
if d["Description"] == val:
return
d["Description"] = val
if d and (d != obj.Material):
obj.Material = d
if FreeCAD.GuiUp:
import FreeCADGui
@@ -516,6 +525,11 @@ class _ArchMaterialTaskPanel:
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def reject(self):
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def chooseMat(self, card):
"sets self.material from a card"
if card in self.cards:
+6 -2
View File
@@ -674,8 +674,12 @@ class _Roof(ArchComponent.Component):
if obj.Base.Shape.Solids:
return obj.Shape
else :
if self.sub:
return self.sub
if hasattr(self,"sub"):
if self.sub:
return self.sub
else :
self.execute(obj)
return self.sub
else :
self.execute(obj)
return self.sub
+17 -17
View File
@@ -195,7 +195,7 @@ def export(exportList,filename):
outfile.close()
FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + " " + decode(filename) + "\n")
if materials:
outfile = pythonopen(filenamemtl,"wb")
outfile = pythonopen(filenamemtl,"w")
outfile.write("# FreeCAD v" + ver[0] + "." + ver[1] + " build" + ver[2] + " Arch module\n")
outfile.write("# http://www.freecadweb.org\n")
kinds = {"AmbientColor":"Ka ","DiffuseColor":"Kd ","SpecularColor":"Ks ","EmissiveColor":"Ke ","Transparency":"d "}
@@ -219,23 +219,23 @@ def export(exportList,filename):
FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + ' ' + decode(filenamemtl) + "\n")
def decode(name):
"decodes encoded strings"
try:
decodedName = (name.decode("utf8"))
except UnicodeDecodeError:
try:
decodedName = (name.decode("latin1"))
except UnicodeDecodeError:
FreeCAD.Console.PrintError(translate("Arch","Error: Couldn't determine character encoding"))
decodedName = name
return decodedName
#def decode(name):
# "decodes encoded strings"
# try:
# decodedName = (name.decode("utf8"))
# except UnicodeDecodeError:
# try:
# decodedName = (name.decode("latin1"))
# except UnicodeDecodeError:
# FreeCAD.Console.PrintError(translate("Arch","Error: Couldn't determine character encoding"))
# decodedName = name
# return decodedName
def open(filename):
"called when freecad wants to open a file"
docname = (os.path.splitext(os.path.basename(filename))[0]).encode("utf8")
doc = FreeCAD.newDocument(docname)
doc.Label = decode(docname)
docname = (os.path.splitext(os.path.basename(filename))[0])
doc = FreeCAD.newDocument(docname.encode("utf8"))
doc.Label = docname
return insert(filename,doc.Name)
def insert(filename,docname):
@@ -246,7 +246,7 @@ def insert(filename,docname):
doc = FreeCAD.newDocument(docname)
FreeCAD.ActiveDocument = doc
with pythonopen(filename,"rb") as infile:
with pythonopen(filename,"r") as infile:
verts = []
facets = []
activeobject = None
@@ -257,7 +257,7 @@ def insert(filename,docname):
if line[:7] == "mtllib ":
matlib = os.path.join(os.path.dirname(filename),line[7:])
if os.path.exists(matlib):
with pythonopen(matlib,"rb") as matfile:
with pythonopen(matlib,"r") as matfile:
mname = None
color = None
trans = None
+7 -23
View File
@@ -87,22 +87,13 @@ def errorDXFLib(gui):
if gui:
from PySide import QtGui, QtCore
from DraftTools import translate
if float(FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]) >= 0.17:
message = translate("Draft","""Download of dxf libraries failed.
message = translate("Draft","""Download of dxf libraries failed.
Please install the dxf Library addon manually
from menu Tools -> Addon Manager""")
else:
message = translate("Draft","""Download of dxf libraries failed.
Please download and install them manually.
See complete instructions at
http://www.freecadweb.org/wiki/Dxf_Importer_Install""")
QtGui.QMessageBox.information(None,"",message)
else:
FreeCAD.Console.PrintWarning("The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n")
if float(FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]) >= 0.17:
FreeCAD.Console.PrintWarning("Please install the dxf Library addon from Tools -> Addons Manager\n")
else:
FreeCAD.Console.PrintWarning("Please check https://github.com/yorikvanhavre/Draft-dxf-importer\n")
FreeCAD.Console.PrintWarning("Please install the dxf Library addon from Tools -> Addons Manager\n")
break
progressbar.stop()
sys.path.append(FreeCAD.ConfigGet("UserAppData"))
@@ -110,17 +101,7 @@ http://www.freecadweb.org/wiki/Dxf_Importer_Install""")
if gui:
from PySide import QtGui, QtCore
from DraftTools import translate
if float(FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]) >= 0.17:
message = translate('draft',"""The DXF import/export libraries needed by FreeCAD to handle
the DXF format were not found on this system.
Please either enable FreeCAD to download these libraries:
1 - Load Draft workbench
2 - Menu Edit > Preferences > Import-Export > DXF > Enable downloads
Or install the libraries manually by installing the dxf-Library addon
from menu Tools -> Addon Manager.
To enabled FreeCAD to download these libraries, answer Yes.""")
else:
message = translate('draft',"""The DXF import/export libraries needed by FreeCAD to handle
message = translate('draft',"""The DXF import/export libraries needed by FreeCAD to handle
the DXF format were not found on this system.
Please either enable FreeCAD to download these libraries:
1 - Load Draft workbench
@@ -154,7 +135,10 @@ def getDXFlibs():
global dxfLibrary,dxfColorMap,dxfReader
import dxfLibrary
import dxfColorMap
import dxfReader
try:
import dxfReader
except:
libsok = False
except ImportError:
libsok = False
FreeCAD.Console.PrintWarning("DXF libraries not found. Trying to download...\n")
+1
View File
@@ -81,6 +81,7 @@
#include <Base/Vector3D.h>
using namespace Drawing;
using namespace std;
TopoDS_Edge DrawingOutput::asCircle(const BRepAdaptor_Curve& c) const
{
@@ -117,12 +117,15 @@ TaskFemConstraintTransform::TaskFemConstraintTransform(ViewProviderFemConstraint
//Transformable surfaces
Gui::Command::doCommand(Gui::Command::Doc,TaskFemConstraintTransform::getSurfaceReferences((static_cast<Fem::Constraint*>(ConstraintView->getObject()))->getNameInDocument()).c_str());
std::vector<App::DocumentObject*> ObjDispl = pcConstraint->RefDispl.getValues();
std::vector<App::DocumentObject*> nDispl = pcConstraint->NameDispl.getValues();
std::vector<std::string> SubElemDispl = pcConstraint->RefDispl.getSubValues();
for (std::size_t i = 0; i < ObjDispl.size(); i++) {
ui->lw_displobj_rect->addItem(makeRefText(ObjDispl[i], SubElemDispl[i]));
ui->lw_displobj_cylin->addItem(makeRefText(ObjDispl[i], SubElemDispl[i]));
}
std::vector<App::DocumentObject*> nDispl = pcConstraint->NameDispl.getValues();
for (std::size_t i = 0; i < nDispl.size(); i++) {
ui->lw_dis_rect->addItem(makeText(nDispl[i]));
ui->lw_dis_cylin->addItem(makeText(nDispl[i]));
}
@@ -447,7 +450,7 @@ A = []\n\
i = 0\n\
ss = []\n\
for member in members:\n\
if (member.isDerivedFrom(\"Fem::ConstraintDisplacement\")) or (member.isDerivedFrom(\"Fem::ConstraintForce\")):\n\
if ((member.isDerivedFrom(\"Fem::ConstraintDisplacement\")) or (member.isDerivedFrom(\"Fem::ConstraintForce\"))) and len(member.References) > 0:\n\
m = member.References\n\
A.append(m)\n\
if i >0:\n\
@@ -463,7 +466,10 @@ for member in members:\n\
i = i+1\n\
if i>0:\n\
App.ActiveDocument."+showConstr+".RefDispl = [x]\n\
App.ActiveDocument."+showConstr+".NameDispl = ss\n";
App.ActiveDocument."+showConstr+".NameDispl = ss\n\
else:\n\
App.ActiveDocument."+showConstr+".RefDispl = None\n\
App.ActiveDocument."+showConstr+".NameDispl = []\n";
}
/* Note: */
@@ -29,6 +29,8 @@ __url__ = "http://www.freecadweb.org"
# \ingroup FEM
# \brief FreeCAD FEM FemSelectWidget
import sys
import FreeCAD
import FreeCADGui
import femmesh.meshtools as FemMeshTools
@@ -160,10 +162,19 @@ class SolidSelector(_Selector):
if solids:
item = (selObj.Object, tuple(solids))
selection.append(item)
if len(selection) == 0:
FreeCAD.Console.PrintMessage(
"Object with no Shape selected or nothing selected at all.\n"
)
return selection
def _getObjects(self, obj, names):
objects = []
if not hasattr(obj, "Shape"):
FreeCAD.Console.PrintMessage(
"Selected object has no Shape.\n"
)
return objects
shape = obj.Shape
for n in names:
if n.startswith("Face"):
@@ -195,7 +206,11 @@ class SolidSelector(_Selector):
if(self._findSub(sub, solid.Vertexes)):
foundSolids.add("Solid" + str(solidId + 1))
if len(foundSolids) == 1:
return iter(foundSolids).next()
it = iter(foundSolids)
if sys.version_info.major >= 3:
return next(it)
else:
return it.next()
return None
def _findSub(self, sub, subList):
+3 -3
View File
@@ -295,14 +295,14 @@ def fill_femresult_mechanical(res_obj, result_set):
if len(Peeq) > 0:
if len(Peeq.values()) != len(disp.values()):
Pe = []
Pe_extra_nodes = Peeq.values()
Pe_extra_nodes = list(Peeq.values())
nodes = len(disp.values())
for i in range(nodes):
Pe_value = Pe_extra_nodes[i]
Pe.append(Pe_value)
res_obj.Peeq = Pe
else:
res_obj.Peeq = Peeq.values()
res_obj.Peeq = list(Peeq.values())
# fill res_obj.Temperature if they exist
# TODO, check if it is possible to have Temperature without disp, we would need to set NodeNumbers than
@@ -311,7 +311,7 @@ def fill_femresult_mechanical(res_obj, result_set):
if len(Temperature) > 0:
if len(Temperature.values()) != len(disp.values()):
Temp = []
Temp_extra_nodes = Temperature.values()
Temp_extra_nodes = list(Temperature.values())
nodes = len(disp.values())
for i in range(nodes):
Temp_value = Temp_extra_nodes[i]
@@ -89,14 +89,13 @@ class _TaskPanel(object):
self._part.ViewObject.show()
def reject(self):
self._restoreVisibility()
self._recomputeAndRestore()
return True
def accept(self):
if self._obj.References != self._refWidget.references():
self._obj.References = self._refWidget.references()
self._obj.Document.recompute()
self._restoreVisibility()
self._recomputeAndRestore()
return True
def _restoreVisibility(self):
@@ -110,4 +109,13 @@ class _TaskPanel(object):
else:
self._part.ViewObject.hide()
def _recomputeAndRestore(self):
doc = Gui.getDocument(self._obj.Document)
doc.Document.recompute()
self._restoreVisibility()
# TODO: test if there is an active selection observer
# if yes Gui.Selection.removeObserver is your friend
doc.resetEdit()
## @}
+6 -1
View File
@@ -28,6 +28,8 @@ __url__ = "http://www.freecadweb.org"
import subprocess
import os.path
import sys
import femtools.femutils as femutils
from .. import run
@@ -112,7 +114,10 @@ class Solve(run.Solve):
def _updateOutput(self, output):
if self.solver.ElmerOutput is None:
self._createOutput()
self.solver.ElmerOutput.Text = output.decode("utf-8")
if sys.version_info.major >= 3:
self.solver.ElmerOutput.Text = output
else:
self.solver.ElmerOutput.Text = output.decode("utf-8")
def _createOutput(self):
self.solver.ElmerOutput = self.analysis.Document.addObject(
+2 -2
View File
@@ -536,11 +536,11 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
ccx_path = FreeCAD.getHomePath() + "bin/ccx.exe"
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx").SetString("ccxBinaryPath", ccx_path)
self.ccx_binary = ccx_path
elif system() == "Linux":
elif system() in ("Linux", "Darwin"):
p1 = subprocess.Popen(['which', 'ccx'], stdout=subprocess.PIPE)
if p1.wait() == 0:
if sys.version_info.major >= 3:
ccx_path = str(p1.stdout.read()).split('\n')[0]
ccx_path = p1.stdout.read().decode("utf8").split('\n')[0]
else:
ccx_path = p1.stdout.read().split('\n')[0]
elif p1.wait() == 1:
+5 -3
View File
@@ -22,11 +22,15 @@
#* Milos Koutny 2010 *
#***************************************************************************/
import FreeCAD, Part, os, FreeCADGui, __builtin__
import FreeCAD, Part, os, FreeCADGui
from FreeCAD import Base
from math import *
import ImportGui
# to distinguish python built-in open function from the one declared here
if open.__module__ in ['__builtin__','io']:
pythonopen = open
##########################################################
# Script version dated 19-Jan-2012 #
##########################################################
@@ -54,8 +58,6 @@ IDF_diag_path="/tmp" # path for output of footprint.lst and missing_models.lst
# End config section do not touch code below #
########################################################################################
pythonopen = __builtin__.open # to distinguish python built-in open function from the one declared here
def open(filename):
"""called when freecad opens an Emn file"""
docname = os.path.splitext(os.path.basename(filename))[0]
@@ -138,8 +138,15 @@ def cmdCreateImageScaling(name):
def accept(self):
sel = FreeCADGui.Selection.getSelection()
try:
locale=QtCore.QLocale.system()
d, ok = locale.toFloat(str(eval(self.lineEdit.text())))
try:
q = FreeCAD.Units.parseQuantity(self.lineEdit.text())
d = q.Value
if q.Unit == FreeCAD.Units.Unit(): # plain number
ok = True
elif q.Unit == FreeCAD.Units.Length:
ok = True
except:
ok = False
if not ok:
raise ValueError
s=d/self.distance
+6 -1
View File
@@ -20,6 +20,8 @@
# * *
# ***************************************************************************
import sys
# here the usage description if you use this tool from the command line ("__main__")
CommandlineUsage = """Material - Tool to work with FreeCAD Material definition cards
@@ -62,7 +64,10 @@ def importFCMat(fileName):
Config = configparser.RawConfigParser()
Config.optionxform = str
Config.read(fileName)
if sys.version_info.major >= 3:
Config.read(fileName, encoding='utf-8') # respect unicode filenames
else:
Config.read(fileName)
dict1 = {}
for section in Config.sections():
options = Config.options(section)
+19 -9
View File
@@ -42,6 +42,8 @@ except AttributeError:
return QtGui.QApplication.translate(context, text, None)
import io
import sys
PY2 = sys.version_info.major == 2
try:
import FreeCAD
@@ -144,18 +146,23 @@ def callopenscad(inputfilename,outputfilename=None,outputext='csg',keepname=Fals
import FreeCAD,os,subprocess,tempfile,time
def check_output2(*args,**kwargs):
kwargs.update({'stdout':subprocess.PIPE,'stderr':subprocess.PIPE})
p=subprocess.Popen(*args,**kwargs)
if PY2:
p=subprocess.Popen(*args)
else:
p=subprocess.Popen(*args,**kwargs)
stdoutd,stderrd = p.communicate()
stdoutd = stdoutd.decode("utf8")
stderrd = stderrd.decode("utf8")
if not PY2:
stdoutd = stdoutd.decode("utf8")
stderrd = stderrd.decode("utf8")
if p.returncode != 0:
raise OpenSCADError('%s %s\n' % (stdoutd.strip(),stderrd.strip()))
#raise Exception,'stdout %s\n stderr%s' %(stdoutd,stderrd)
if stderrd.strip():
FreeCAD.Console.PrintWarning(stderrd+u'\n')
if stdoutd.strip():
FreeCAD.Console.PrintMessage(stdoutd+u'\n')
return stdoutd
if not PY2:
if stderrd.strip():
FreeCAD.Console.PrintWarning(stderrd+u'\n')
if stdoutd.strip():
FreeCAD.Console.PrintMessage(stdoutd+u'\n')
return stdoutd
osfilename = FreeCAD.ParamGet(\
"User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
@@ -182,7 +189,10 @@ def callopenscadstring(scadstr,outputext='csg'):
dir1=tempfile.gettempdir()
inputfilename=os.path.join(dir1,'%s.scad' % next(tempfilenamegen))
inputfile = io.open(inputfilename,'w', encoding="utf8")
inputfile.write(scadstr)
if PY2:
inputfile.write(scadstr.decode('utf8'))
else:
inputfile.write(scadstr)
inputfile.close()
outputfilename = callopenscad(inputfilename,outputext=outputext,\
keepname=True)
+18 -10
View File
@@ -66,21 +66,29 @@ App::DocumentObjectExecReturn *Compound::execute(void)
TopoDS_Compound comp;
builder.MakeCompound(comp);
// avoid duplicates without changing the order
// See also ViewProviderCompound::updateData
std::set<DocumentObject*> tempLinks;
const std::vector<DocumentObject*>& links = Links.getValues();
for (std::vector<DocumentObject*>::const_iterator it = links.begin(); it != links.end(); ++it) {
if (*it && (*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
Part::Feature* fea = static_cast<Part::Feature*>(*it);
const TopoDS_Shape& sh = fea->Shape.getValue();
if (!sh.IsNull()) {
builder.Add(comp, sh);
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(sh, TopAbs_FACE, faceMap);
ShapeHistory hist;
hist.type = TopAbs_FACE;
for (int i=1; i<=faceMap.Extent(); i++) {
hist.shapeMap[i-1].push_back(countFaces++);
auto pos = tempLinks.insert(fea);
if (pos.second) {
const TopoDS_Shape& sh = fea->Shape.getValue();
if (!sh.IsNull()) {
builder.Add(comp, sh);
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(sh, TopAbs_FACE, faceMap);
ShapeHistory hist;
hist.type = TopAbs_FACE;
for (int i=1; i<=faceMap.Extent(); i++) {
hist.shapeMap[i-1].push_back(countFaces++);
}
history.push_back(hist);
}
history.push_back(hist);
}
}
}
+19 -19
View File
@@ -203,7 +203,7 @@ unsigned int Geometry::getMemSize (void) const
void Geometry::Save(Base::Writer &writer) const
{
const char c = Construction?'1':'0';
writer.Stream() << writer.ind() << "<Construction value=\"" << c << "\"/>" << endl;
writer.Stream() << writer.ind() << "<Construction value=\"" << c << "\"/>" << std::endl;
}
void Geometry::Restore(Base::XMLReader &reader)
@@ -323,7 +323,7 @@ void GeomPoint::Save(Base::Writer &writer) const
<< "X=\"" << Point.x <<
"\" Y=\"" << Point.y <<
"\" Z=\"" << Point.z <<
"\"/>" << endl;
"\"/>" << std::endl;
}
void GeomPoint::Restore(Base::XMLReader &reader)
@@ -793,7 +793,7 @@ void GeomBezierCurve::Save(Base::Writer& writer) const
<< writer.ind()
<< "<BezierCurve "
<< "PolesCount=\"" << poles.size() <<
"\">" << endl;
"\">" << std::endl;
writer.incInd();
@@ -808,11 +808,11 @@ void GeomBezierCurve::Save(Base::Writer& writer) const
"\" Y=\"" << (*itp).y <<
"\" Z=\"" << (*itp).z <<
"\" Weight=\"" << (*itw) <<
"\"/>" << endl;
"\"/>" << std::endl;
}
writer.decInd();
writer.Stream() << writer.ind() << "</BezierCurve>" << endl ;
writer.Stream() << writer.ind() << "</BezierCurve>" << std::endl;
}
void GeomBezierCurve::Restore(Base::XMLReader& reader)
@@ -1270,7 +1270,7 @@ void GeomBSplineCurve::Save(Base::Writer& writer) const
"\" KnotsCount=\"" << knots.size() <<
"\" Degree=\"" << degree <<
"\" IsPeriodic=\"" << (int) isperiodic <<
"\">" << endl;
"\">" << std::endl;
writer.incInd();
@@ -1285,7 +1285,7 @@ void GeomBSplineCurve::Save(Base::Writer& writer) const
"\" Y=\"" << (*itp).y <<
"\" Z=\"" << (*itp).z <<
"\" Weight=\"" << (*itw) <<
"\"/>" << endl;
"\"/>" << std::endl;
}
std::vector<double>::const_iterator itk;
@@ -1297,11 +1297,11 @@ void GeomBSplineCurve::Save(Base::Writer& writer) const
<< "<Knot "
<< "Value=\"" << (*itk)
<< "\" Mult=\"" << (*itm) <<
"\"/>" << endl;
"\"/>" << std::endl;
}
writer.decInd();
writer.Stream() << writer.ind() << "</BSplineCurve>" << endl ;
writer.Stream() << writer.ind() << "</BSplineCurve>" << std::endl;
}
void GeomBSplineCurve::Restore(Base::XMLReader& reader)
@@ -1903,7 +1903,7 @@ void GeomCircle::Save(Base::Writer& writer) const
"\" NormalZ=\"" << normal.Z() <<
"\" AngleXU=\"" << AngleXU <<
"\" Radius=\"" << this->myCurve->Radius() <<
"\"/>" << endl;
"\"/>" << std::endl;
}
void GeomCircle::Restore(Base::XMLReader& reader)
@@ -2132,7 +2132,7 @@ void GeomArcOfCircle::Save(Base::Writer &writer) const
"\" Radius=\"" << circle->Radius() <<
"\" StartAngle=\"" << this->myCurve->FirstParameter() <<
"\" EndAngle=\"" << this->myCurve->LastParameter() <<
"\"/>" << endl;
"\"/>" << std::endl;
}
void GeomArcOfCircle::Restore(Base::XMLReader &reader)
@@ -2383,7 +2383,7 @@ void GeomEllipse::Save(Base::Writer& writer) const
<< "MajorRadius=\"" << this->myCurve->MajorRadius() << "\" "
<< "MinorRadius=\"" << this->myCurve->MinorRadius() << "\" "
<< "AngleXU=\"" << AngleXU << "\" "
<< "/>" << endl;
<< "/>" << std::endl;
}
void GeomEllipse::Restore(Base::XMLReader& reader)
@@ -2653,7 +2653,7 @@ void GeomArcOfEllipse::Save(Base::Writer &writer) const
<< "AngleXU=\"" << AngleXU << "\" "
<< "StartAngle=\"" << this->myCurve->FirstParameter() << "\" "
<< "EndAngle=\"" << this->myCurve->LastParameter() << "\" "
<< "/>" << endl;
<< "/>" << std::endl;
}
void GeomArcOfEllipse::Restore(Base::XMLReader &reader)
@@ -2826,7 +2826,7 @@ void GeomHyperbola::Save(Base::Writer& writer) const
<< "MajorRadius=\"" << this->myCurve->MajorRadius() << "\" "
<< "MinorRadius=\"" << this->myCurve->MinorRadius() << "\" "
<< "AngleXU=\"" << AngleXU << "\" "
<< "/>" << endl;
<< "/>" << std::endl;
}
void GeomHyperbola::Restore(Base::XMLReader& reader)
@@ -3083,7 +3083,7 @@ void GeomArcOfHyperbola::Save(Base::Writer &writer) const
<< "AngleXU=\"" << AngleXU << "\" "
<< "StartAngle=\"" << this->myCurve->FirstParameter() << "\" "
<< "EndAngle=\"" << this->myCurve->LastParameter() << "\" "
<< "/>" << endl;
<< "/>" << std::endl;
}
void GeomArcOfHyperbola::Restore(Base::XMLReader &reader)
@@ -3236,7 +3236,7 @@ void GeomParabola::Save(Base::Writer& writer) const
<< "NormalZ=\"" << normal.Z() << "\" "
<< "Focal=\"" << this->myCurve->Focal() << "\" "
<< "AngleXU=\"" << AngleXU << "\" "
<< "/>" << endl;
<< "/>" << std::endl;
}
void GeomParabola::Restore(Base::XMLReader& reader)
@@ -3436,7 +3436,7 @@ void GeomArcOfParabola::Save(Base::Writer &writer) const
<< "AngleXU=\"" << AngleXU << "\" "
<< "StartAngle=\"" << this->myCurve->FirstParameter() << "\" "
<< "EndAngle=\"" << this->myCurve->LastParameter() << "\" "
<< "/>" << endl;
<< "/>" << std::endl;
}
void GeomArcOfParabola::Restore(Base::XMLReader &reader)
@@ -3581,7 +3581,7 @@ void GeomLine::Save(Base::Writer &writer) const
"\" DirX=\"" << Dir.x <<
"\" DirY=\"" << Dir.y <<
"\" DirZ=\"" << Dir.z <<
"\"/>" << endl;
"\"/>" << std::endl;
}
void GeomLine::Restore(Base::XMLReader &reader)
{
@@ -3722,7 +3722,7 @@ void GeomLineSegment::Save (Base::Writer &writer) const
"\" EndX=\"" << End.x <<
"\" EndY=\"" << End.y <<
"\" EndZ=\"" << End.z <<
"\"/>" << endl;
"\"/>" << std::endl;
}
void GeomLineSegment::Restore (Base::XMLReader &reader)
+1
View File
@@ -83,6 +83,7 @@
#include <Mod/Part/App/Geom2d/OffsetCurve2dPy.h>
using namespace Part;
using namespace std;
extern const char* gce_ErrorStatusText(gce_ErrorType et);
+3 -3
View File
@@ -281,11 +281,11 @@ static void BRepTools_Write(const TopoDS_Shape& Sh, Standard_OStream& S) {
static Standard_Boolean BRepTools_Write(const TopoDS_Shape& Sh,
const Standard_CString File)
{
ofstream os;
std::ofstream os;
#if OCC_VERSION_HEX >= 0x060800
OSD_OpenStream(os, File, ios::out);
OSD_OpenStream(os, File, std::ios::out);
#else
os.open(File, ios::out);
os.open(File, std::ios::out);
#endif
if (!os.rdbuf()->is_open()) return Standard_False;
+7 -1
View File
@@ -3084,8 +3084,14 @@ void TopoShape::getDomains(std::vector<Domain>& domains) const
TopLoc_Location loc;
Handle(Poly_Triangulation) theTriangulation = BRep_Tool::Triangulation(face, loc);
if (theTriangulation.IsNull())
if (theTriangulation.IsNull()) {
// For a face that cannot be meshed append an empty domain.
// It's important for some algorithms (e.g. color mapping) that the numbers of
// faces and domains match
Domain domain;
domains.push_back(domain);
continue;
}
Domain domain;
// copy the points
+8 -4
View File
@@ -908,11 +908,15 @@ void CmdPartCompound::activated(int iMsg)
std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection();
std::stringstream str;
std::vector<std::string> tempSelNames;
// avoid duplicates without changing the order
std::set<std::string> tempSelNames;
str << "App.activeDocument()." << FeatName << ".Links = [";
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it){
str << "App.activeDocument()." << it->FeatName << ",";
tempSelNames.push_back(it->FeatName);
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it) {
auto pos = tempSelNames.insert(it->FeatName);
if (pos.second) {
str << "App.activeDocument()." << it->FeatName << ",";
}
}
str << "]";
+7 -7
View File
@@ -383,8 +383,8 @@ void PartGui::DimensionLinear::setupDimension()
//dimension arrows
float dimLength = (point2.getValue()-point1.getValue()).length();
float coneHeight = dimLength * .05;
float coneRadius = coneHeight / 2;
float coneHeight = dimLength * 0.05;
float coneRadius = coneHeight * 0.5;
SoCone *cone = new SoCone();
cone->bottomRadius.setValue(coneRadius);
@@ -392,8 +392,8 @@ void PartGui::DimensionLinear::setupDimension()
char lStr[100];
char rStr[100];
snprintf(lStr, sizeof(lStr), "translation %.2f 0.0 0.0", coneHeight*0.5);
snprintf(rStr, sizeof(rStr), "translation 0.0 -%.2f 0.0", coneHeight*0.5);
snprintf(lStr, sizeof(lStr), "translation %.6f 0.0 0.0", coneHeight * 0.5);
snprintf(rStr, sizeof(rStr), "translation 0.0 -%.6f 0.0", coneHeight * 0.5);
setPart("leftArrow.shape", cone);
set("leftArrow.transform", "rotation 0.0 0.0 1.0 1.5707963");
@@ -1072,7 +1072,7 @@ void PartGui::DimensionAngular::setupDimension()
//dimension arrows
float coneHeight = radius.getValue() * 0.1;
float coneRadius = coneHeight / 2;
float coneRadius = coneHeight * 0.5;
SoCone *cone = new SoCone();
cone->bottomRadius.setValue(coneRadius);
@@ -1080,8 +1080,8 @@ void PartGui::DimensionAngular::setupDimension()
char str1[100];
char str2[100];
snprintf(str1, sizeof(str1), "translation 0.0 %.2f 0.0", coneHeight*0.5);
snprintf(str2, sizeof(str2), "translation 0.0 -%.2f 0.0", coneHeight*0.5);
snprintf(str1, sizeof(str1), "translation 0.0 %.6f 0.0", coneHeight * 0.5);
snprintf(str2, sizeof(str2), "translation 0.0 -%.6f 0.0", coneHeight * 0.5);
setPart("arrow1.shape", cone);
set("arrow1.localTransform", "rotation 0.0 0.0 1.0 3.1415927");
+18
View File
@@ -72,6 +72,24 @@ void ViewProviderCompound::updateData(const App::Property* prop)
(prop)->getValues();
Part::Compound* objComp = static_cast<Part::Compound*>(getObject());
std::vector<App::DocumentObject*> sources = objComp->Links.getValues();
if (hist.size() != sources.size()) {
// avoid duplicates without changing the order
// See also Compound::execute
std::set<App::DocumentObject*> tempSources;
std::vector<App::DocumentObject*> filter;
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it) {
Part::Feature* objBase = dynamic_cast<Part::Feature*>(*it);
if (objBase) {
auto pos = tempSources.insert(objBase);
if (pos.second) {
filter.push_back(objBase);
}
}
}
sources = filter;
}
if (hist.size() != sources.size())
return;
+3 -1
View File
@@ -643,9 +643,11 @@ void CmdPartDesignDuplicateSelection::activated(int iMsg)
std::vector<App::DocumentObject*> beforeFeatures = getDocument()->getObjects();
openCommand("Duplicate a PartDesign object");
doCommand(Doc,"FreeCADGui.runCommand('Std_DuplicateSelection')");
// This transaction must be opened after using the core duplication function.
// See https://forum.freecadweb.org/viewtopic.php?f=19&t=41918&p=355939#p355939
openCommand("Duplicate a PartDesign object");
if (pcActiveBody) {
// Find the features that were added
std::vector<App::DocumentObject*> afterFeatures = getDocument()->getObjects();
@@ -89,7 +89,7 @@ class ObjectOp(PathOp.ObjectOp):
Obviously this is as fragile as can be, but currently the best we can do while the panel sheets
hide the actual features from Path and they can't be referenced directly.
'''
ids = string.split(sub, '.')
ids = sub.split(".")
holeId = int(ids[0])
wireId = int(ids[1])
edgeId = int(ids[2])
@@ -29,6 +29,10 @@ import PathScripts.PathOpGui as PathOpGui
from PySide import QtCore, QtGui
import sys
if sys.version_info.major >= 3:
xrange = range
__title__ = "Base for Circular Hole based operations' UI"
__author__ = "sliptonic (Brad Collette)"
__url__ = "http://www.freecadweb.org"
+4
View File
@@ -1019,6 +1019,10 @@ class TaskPanel:
Draft.move(sel.Object, by)
def updateSelection(self):
# Remove Job object if present in Selection: source of phantom paths
if self.obj in FreeCADGui.Selection.getSelection():
FreeCADGui.Selection.removeSelection(self.obj)
sel = FreeCADGui.Selection.getSelectionEx()
if len(sel) == 1 and len(sel[0].SubObjects) == 1:
+4
View File
@@ -35,6 +35,10 @@ import PathScripts.PathOp as PathOp
from PySide import QtCore
import sys
if sys.version_info.major >= 3:
xrange = range
__title__ = "Path Surface Operation"
__author__ = "sliptonic (Brad Collette)"
__url__ = "http://www.freecadweb.org"
@@ -101,7 +101,7 @@ CURRENT_Z = 0
# to distinguish python built-in open function from the one declared below
if open.__module__ == '__builtin__':
if open.__module__ in ['__builtin__','io']:
pythonopen = open
@@ -393,7 +393,7 @@ def drill_translate(outstring, cmd, params):
RETRACT_Z = CURRENT_Z
# Recupere les valeurs des autres parametres
drill_Speed = params['F']
drill_Speed = params['F'] * SPEED_MULTIPLIER
if cmd == 'G83':
drill_Step = params['Q']
elif cmd == 'G82':
@@ -40,6 +40,7 @@
#include <Mod/Part/App/TopoShapePy.h>
#include <App/Application.h>
using namespace std;
namespace Raytracing {
class Module : public Py::ExtensionModule<Module>
+1
View File
@@ -38,6 +38,7 @@
using namespace Raytracing;
using namespace std;
PROPERTY_SOURCE(Raytracing::LuxFeature, Raytracing::RaySegment)
+8 -44
View File
@@ -5140,7 +5140,7 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction)
for (std::vector<Part::Geometry *>::const_iterator it=svals.begin(); it != svals.end(); ++it){
Part::Geometry *geoNew = (*it)->copy();
if(construction) {
if(construction && geoNew->getTypeId() != Part::GeomPoint::getClassTypeId()) {
geoNew->Construction = true;
}
newVals.push_back(geoNew);
@@ -5174,11 +5174,13 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction)
int sourceid = 0;
for (std::vector< Sketcher::Constraint * >::const_iterator it= scvals.begin(); it != scvals.end(); ++it,nextcid++,sourceid++) {
if ((*it)->Type == Sketcher::Distance ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Diameter ||
(*it)->Type == Sketcher::Angle ||
(*it)->Type == Sketcher::SnellsLaw) {
if ((*it)->Type == Sketcher::Distance ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Diameter ||
(*it)->Type == Sketcher::Angle ||
(*it)->Type == Sketcher::SnellsLaw ||
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ) {
// then we link its value to the parent
// (there is a plausible alternative for a slightly different use case to copy the expression of the parent if one is existing)
if ((*it)->isDriving) {
@@ -5191,45 +5193,7 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction)
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
}
else if ((*it)->Type == Sketcher::DistanceX) {
// then we link its value to the parent
// (there is a plausible alternative for a slightly different use case to copy the expression of the parent if one is existing)
if ((*it)->isDriving) {
App::ObjectIdentifier spath = psObj->Constraints.createPath(sourceid);
if(xinv) {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, std::string(1,'-') + spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
else {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
}
}
else if ((*it)->Type == Sketcher::DistanceY ) {
// then we link its value to the parent
// (there is a plausible alternative for a slightly different use case to copy the expression of the parent if one is existing)
if ((*it)->isDriving) {
App::ObjectIdentifier spath = psObj->Constraints.createPath(sourceid);
if(yinv) {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, std::string(1,'-') + spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
else {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
}
}
}
+1 -3
View File
@@ -82,9 +82,7 @@ void EditDatumDialog::exec(bool atCursor)
}
Gui::MDIView *mdi = Gui::Application::Instance->activeDocument()->getActiveView();
Gui::View3DInventorViewer *viewer = static_cast<Gui::View3DInventor *>(mdi)->getViewer();
QDialog dlg(viewer->getGLWidget());
QDialog dlg(mdi);
Ui::InsertDatum ui_ins_datum;
ui_ins_datum.setupUi(&dlg);
+8 -2
View File
@@ -1195,11 +1195,17 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
return true;
}
case STATUS_SKETCH_UseRubberBand: {
// Here we must use the device-pixel-ratio to compute the correct y coordinate (#0003130)
#if QT_VERSION >= 0x050600
qreal dpr = viewer->getGLWidget()->devicePixelRatioF();
#else
qreal dpr = 1;
#endif
newCursorPos = cursorPos;
rubberband->setCoords(prvCursorPos.getValue()[0],
viewer->getGLWidget()->height() - prvCursorPos.getValue()[1],
viewer->getGLWidget()->height()*dpr - prvCursorPos.getValue()[1],
newCursorPos.getValue()[0],
viewer->getGLWidget()->height() - newCursorPos.getValue()[1]);
viewer->getGLWidget()->height()*dpr - newCursorPos.getValue()[1]);
viewer->redraw();
return true;
}
+5 -1
View File
@@ -57,6 +57,7 @@ known issues:
import zipfile
import xml.dom.minidom
import FreeCAD as App
import sys
try: import FreeCADGui
except ValueError: gui = False
@@ -371,7 +372,10 @@ def handleCells(cellList, actCellSheet, sList):
if cellType == 'n':
actCellSheet.set(ref, theValue)
if cellType == 's':
actCellSheet.set(ref, (sList[int(theValue)]).encode('utf8'))
if sys.version_info.major >= 3:
actCellSheet.set(ref, (sList[int(theValue)]))
else:
actCellSheet.set(ref, (sList[int(theValue)]).encode('utf8'))
def handleWorkBook(theBook, sheetDict, Doc):
+13
View File
@@ -517,6 +517,7 @@ void QGIFace::buildSvgHatch()
before.append(QString::fromStdString(SVGCOLPREFIX + SVGCOLDEFAULT));
after.append(QString::fromStdString(SVGCOLPREFIX + m_svgCol));
QByteArray colorXML = m_svgXML.replace(before,after);
long int tileCount = 0;
for (int iw = 0; iw < int(nw); iw++) {
for (int ih = 0; ih < int(nh); ih++) {
QGCustomSvg* tile = new QGCustomSvg();
@@ -525,6 +526,14 @@ void QGIFace::buildSvgHatch()
tile->setParentItem(m_rect);
tile->setPos(iw*wTile,-h + ih*hTile);
}
tileCount++;
if (tileCount > m_maxTile) {
Base::Console().Warning("SVG tile count exceeded: %ld\n",tileCount);
break;
}
}
if (tileCount > m_maxTile) {
break;
}
}
}
@@ -611,6 +620,10 @@ void QGIFace::getParameters(void)
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
m_maxSeg = hGrp->GetInt("MaxSeg",10000l);
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Decorations");
m_maxTile = hGrp->GetInt("MaxSVGTile",10000l);
}
+1
View File
@@ -147,6 +147,7 @@ protected:
std::vector<DashSpec> m_dashSpecs;
long int m_segCount;
long int m_maxSeg;
long int m_maxTile;
private:
+14 -5
View File
@@ -374,7 +374,10 @@ void QGIViewPart::drawViewPart()
}
newFace->isHatched(true);
newFace->setFillMode(QGIFace::GeomHatchFill);
newFace->setHatchScale(fGeom->ScalePattern.getValue());
double hatchScale = fGeom->ScalePattern.getValue();
if (hatchScale > 0.0) {
newFace->setHatchScale(fGeom->ScalePattern.getValue());
}
newFace->setHatchFile(fGeom->FilePattern.getValue());
Gui::ViewProvider* gvp = QGIView::getViewProvider(fGeom);
ViewProviderGeomHatch* geomVp = dynamic_cast<ViewProviderGeomHatch*>(gvp);
@@ -392,7 +395,10 @@ void QGIViewPart::drawViewPart()
Gui::ViewProvider* gvp = QGIView::getViewProvider(fHatch);
ViewProviderHatch* hatchVp = dynamic_cast<ViewProviderHatch*>(gvp);
if (hatchVp != nullptr) {
newFace->setHatchScale(hatchVp->HatchScale.getValue());
double hatchScale = hatchVp->HatchScale.getValue();
if (hatchScale > 0.0) {
newFace->setHatchScale(hatchVp->HatchScale.getValue());
}
newFace->setHatchColor(hatchVp->HatchColor.getValue());
}
}
@@ -541,7 +547,8 @@ void QGIViewPart::removePrimitives()
for (auto& c:children) {
QGIPrimPath* prim = dynamic_cast<QGIPrimPath*>(c);
if (prim) {
removeFromGroup(prim);
prim->hide();
// removeFromGroup(prim);
scene()->removeItem(prim);
delete prim;
}
@@ -559,11 +566,13 @@ void QGIViewPart::removeDecorations()
QGIDecoration* decor = dynamic_cast<QGIDecoration*>(c);
QGIMatting* mat = dynamic_cast<QGIMatting*>(c);
if (decor) {
removeFromGroup(decor);
decor->hide();
// removeFromGroup(decor);
scene()->removeItem(decor);
delete decor;
} else if (mat) {
removeFromGroup(mat);
mat->hide();
// removeFromGroup(mat);
scene()->removeItem(mat);
delete mat;
}
+12 -5
View File
@@ -47,8 +47,13 @@
using namespace TechDrawGui;
App::PropertyFloatConstraint::Constraints ViewProviderHatch::scaleRange = {Precision::Confusion(),
std::numeric_limits<double>::max(),
//scaleRange = {lowerLimit, upperLimit, stepSize}
//original range is far too broad for drawing. causes massive loop counts.
//App::PropertyFloatConstraint::Constraints ViewProviderHatch::scaleRange = {Precision::Confusion(),
// std::numeric_limits<double>::max(),
// pow(10,- Base::UnitsApi::getDecimals())};
App::PropertyFloatConstraint::Constraints ViewProviderHatch::scaleRange = {pow(10,- Base::UnitsApi::getDecimals()),
1000.0,
pow(10,- Base::UnitsApi::getDecimals())};
@@ -99,9 +104,11 @@ void ViewProviderHatch::onChanged(const App::Property* prop)
{
if ((prop == &HatchScale) ||
(prop == &HatchColor)) {
TechDraw::DrawViewPart* parent = getViewObject()->getSourceView();
if (parent) {
parent->requestPaint();
if (HatchScale.getValue() > 0.0) {
TechDraw::DrawViewPart* parent = getViewObject()->getSourceView();
if (parent) {
parent->requestPaint();
}
}
}
}
+15 -2
View File
@@ -126,7 +126,7 @@ Py::Object BrowserViewPy::setHtml(const Py::Tuple& args)
PyMem_Free(HtmlCode);
if (myWebView)
myWebView->setHtml(QString::fromUtf8(EncodedHtml.c_str()), QUrl(QString::fromLatin1(BaseUrl)));
myWebView->setHtml(QString::fromUtf8(EncodedHtml.c_str()), QUrl(QString::fromUtf8(BaseUrl)));
return Py::None();
}
}
@@ -227,6 +227,11 @@ BrowserView::BrowserView(QWidget* parent)
isLoading(false),
textSizeMultiplier(1.0)
{
#if defined(QTWEBENGINE)
// Otherwise cause crash on exit, probably due to double deletion
setAttribute(Qt::WA_DeleteOnClose,false);
#endif
view = new WebView(this);
setCentralWidget(view);
@@ -322,7 +327,12 @@ void BrowserView::onLinkClicked (const QUrl & url)
Gui::Command::doCommand(Gui::Command::Gui,q.toStdString().c_str());
}
// Gui::Command::doCommand(Gui::Command::Gui,"execfile('%s')",(const char*) fi.absoluteFilePath(). toLocal8Bit());
Gui::Command::doCommand(Gui::Command::Gui,"exec(open('%s').read())",(const char*) fi.absoluteFilePath() .toLocal8Bit());
QString filename = fi.absoluteFilePath();
#if PY_MAJOR_VERSION < 3
Gui::Command::doCommand(Gui::Command::Gui,"exec(open(unicode('%s', 'utf-8')).read())",(const char*) filename.toUtf8());
#else
Gui::Command::doCommand(Gui::Command::Gui,"exec(open('%s').read())",(const char*) filename.toUtf8());
#endif
}
catch (const Base::Exception& e) {
QMessageBox::critical(this, tr("Error"), QString::fromUtf8(e.what()));
@@ -331,6 +341,9 @@ void BrowserView::onLinkClicked (const QUrl & url)
App::Document *doc = BaseView::getAppDocument();
if(doc && doc->testStatus(App::Document::PartialRestore))
QMessageBox::critical(this, tr("Error"), tr("There were errors while loading the file. Some data might have been modified or not recovered at all. Look in the report view for more specific information about the objects involved."));
if(doc && doc->testStatus(App::Document::RestoreError))
QMessageBox::critical(this, tr("Error"), tr("There were serious errors while loading the file. Some data might have been modified or not recovered at all. Saving the project will most likely result in loss of data."));
}
}
else {
+36 -4
View File
@@ -1,4 +1,36 @@
install(FILES org.freecadweb.FreeCAD.appdata.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
install(FILES org.freecadweb.FreeCAD.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES org.freecadweb.FreeCAD.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps)
install(FILES org.freecadweb.FreeCAD.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages)
include(GNUInstallDirs)
if(NOT DEFINED APPDATA_RELEASE_DATE)
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(COMMAND git log -1 --pretty=%cd --date=short
OUTPUT_VARIABLE APPDATA_RELEASE_DATE
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
file(TIMESTAMP "${CMAKE_SOURCE_DIR}/CMakeLists.txt" APPDATA_RELEASE_DATE "%Y-%m-%d")
endif()
endif()
configure_file(
org.freecadweb.FreeCAD.appdata.xml.in
${CMAKE_BINARY_DIR}/org.freecadweb.FreeCAD.appdata.xml
)
install(
FILES ${CMAKE_BINARY_DIR}/org.freecadweb.FreeCAD.appdata.xml
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo
)
install(
FILES org.freecadweb.FreeCAD.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications
)
install(
FILES org.freecadweb.FreeCAD.svg
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps
)
install(
FILES org.freecadweb.FreeCAD.xml
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mime/packages
)
@@ -29,8 +29,8 @@
<url type="help">https://forum.freecadweb.org</url>
<url type="donation">https://www.freecadweb.org/wiki/Donate</url>
<update_contact>yorik_AT_uncreated.net</update_contact>
<content_rating type="oars-1.1" />
<content_rating type="oars-1.1"/>
<releases>
<release version="0.17" date="2018-04-06"></release>
<release version="@PACKAGE_VERSION@" date="@APPDATA_RELEASE_DATE@"/>
</releases>
</component>