Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3129ae4296 | |||
| 0572853dbd | |||
| 2f0c3a79fa | |||
| 0f29891a98 | |||
| 3eaf87b2dc | |||
| 60fd668d5c | |||
| 4351058504 | |||
| f2f4b44792 | |||
| 90ff921ef7 | |||
| 662aebd881 | |||
| d2f0c4f33d | |||
| b80d000aff | |||
| 627ae70a53 | |||
| a261a55adf | |||
| dbb4cc6415 | |||
| e25cd6c71b | |||
| 1fb7ed43cf | |||
| ebca0c9836 | |||
| 476b4d5f97 | |||
| 3450cf9860 | |||
| 0dc75267fe | |||
| f7dccfaa90 | |||
| 76542ae729 | |||
| 55698377f9 | |||
| f21cbce8cd | |||
| 9152703516 | |||
| c264c76d8f | |||
| d8f5560cac | |||
| 442e411cf0 | |||
| 55080952a8 | |||
| f185504b4e | |||
| 2bc3daedcc | |||
| 2cef63f8a3 | |||
| 81a7d937bd | |||
| 64f3424cab | |||
| 64cb745ddc | |||
| 228876f8f2 | |||
| 8ece48c70b |
@@ -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);
|
||||
|
||||
@@ -3031,7 +3031,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+24
-12
@@ -1092,9 +1092,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 +1177,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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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 <ping@lfw.org></font>'''\n"
|
||||
"htmldocument=pydoc.html.page(title,contents)\n";
|
||||
|
||||
@@ -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;
|
||||
|
||||
+58
-19
@@ -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";
|
||||
|
||||
@@ -577,14 +577,18 @@ class UpdateWorker(QtCore.QThread):
|
||||
name = re.findall("title=\"(.*?) @",l)[0]
|
||||
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 = "https://github.com/" + re.findall("href=\"\/(.*?)\/tree",l)[0]
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
state = 1
|
||||
repos.append([name,url,state])
|
||||
addondir = moddir + os.sep + name
|
||||
#print ("found:",name," at ",url)
|
||||
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:
|
||||
|
||||
@@ -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"))
|
||||
@@ -259,7 +260,8 @@ class _ArchMaterial:
|
||||
obj.addProperty("App::PropertyColor","Color","Arch",QT_TRANSLATE_NOOP("App::Property","The color of this material"))
|
||||
|
||||
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(",")])
|
||||
@@ -283,52 +285,51 @@ 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
|
||||
val = str(obj.Color[:3])
|
||||
if "DiffuseColor" in d:
|
||||
if d["DiffuseColor"] == val:
|
||||
return
|
||||
d["DiffuseColor"] = val
|
||||
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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -62,7 +62,7 @@ def importFCMat(fileName):
|
||||
|
||||
Config = configparser.RawConfigParser()
|
||||
Config.optionxform = str
|
||||
Config.read(fileName)
|
||||
Config.read(fileName, encoding='utf-8') # respect unicode filenames
|
||||
dict1 = {}
|
||||
for section in Config.sections():
|
||||
options = Config.options(section)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 << "]";
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
+2
-2
@@ -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>
|
||||
Reference in New Issue
Block a user