Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 980bf9060e | |||
| f972b010bb | |||
| 5a1527f954 | |||
| dea7d2080b | |||
| a4a42b36e4 | |||
| 7fa0eea88a | |||
| 2b28c50525 | |||
| 31d9283325 | |||
| f07b6e3e17 | |||
| 38e0e99579 | |||
| 2483c467bb | |||
| d9b8faf8bf | |||
| 102b97aca7 | |||
| 1e9f9faa24 | |||
| 7320c4c448 | |||
| 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 |
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.
Binary file not shown.
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ protected:
|
||||
std::vector<DashSpec> m_dashSpecs;
|
||||
long int m_segCount;
|
||||
long int m_maxSeg;
|
||||
long int m_maxTile;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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