Compare commits

...

38 Commits

Author SHA1 Message Date
Yorik van Havre 3129ae4296 AddonManager: Skip non-github addons 2019-07-12 18:08:08 -03:00
Abdullah Tahiri 0572853dbd Sketcher: Fix Carbon copy leads to unsolvable sketch
====================================================

fixes #3973

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

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

fixes #3926

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

This was not intended in Carbon Copy.
2019-06-28 10:48:56 +02:00
wmayer 0f29891a98 fixes #0003993: Memory leak with Python3 2019-06-24 14:32:42 +02:00
wmayer 3eaf87b2dc code simplification in PythonWrapper 2019-06-22 14:38:49 +02:00
wmayer 60fd668d5c issue #0003984: Creating a Path Job object fails with 'PySide2.QtWidgets.QDialog' object has no attribute 'templateGroup' 2019-06-22 14:38:20 +02:00
Russell Johnson 4351058504 Fixes bug #4008: removes phantom path cause
Job object was base of transformations, rather than Job base(clone).
2019-06-22 14:34:51 +02:00
wmayer f2f4b44792 Fix crash in case encoding of Python paths fails 2019-06-21 16:33:18 +02:00
luz.paz 90ff921ef7 [Material] Respect unicode filenames
Fixes #4027
2019-06-21 16:27:41 +02:00
Zheng, Lei 662aebd881 BrowserView: fix QWebEngine crash 2019-06-21 16:27:12 +02:00
wmayer d2f0c4f33d Py3: no __builtin__ module available 2019-06-17 17:11:14 +02:00
wmayer b80d000aff fixes 0004010: Box Selection + Part -> MakeCompound will crash FreeCAD 2019-06-12 11:26:21 +02:00
Bernd Hahnebach 627ae70a53 FEM: solver elmer tasks, Py3 decode fix 2019-06-11 15:49:12 +02:00
wmayer a261a55adf make OpenSCAD utilities working again with Py2 2019-06-07 13:09:41 +02:00
wmayer dbb4cc6415 replace insecure use of eval() with proper use of units 2019-05-11 13:02:55 +02:00
wmayer e25cd6c71b py3/py2: use exec as function 2019-05-10 19:26:12 +02:00
Yorik van Havre 1fb7ed43cf Arch: Fixed error in roof - Fixes #3864 2019-05-07 22:49:19 -03:00
Yorik van Havre ebca0c9836 Draft: Fixed 0.18.1 bug in DXF importer 2019-05-02 16:10:12 -03:00
wmayer 476b4d5f97 Py3 fix: correctly convert a Python str to const char* 2019-04-21 10:15:13 +02:00
wmayer 3450cf9860 Py3: fix reading/writing from/to OBJ file 2019-04-21 10:14:45 +02:00
wmayer 0dc75267fe fixes 0003913: libspnav crash on linux wayland during startup 2019-04-05 17:43:53 +02:00
Bernd Hahnebach f7dccfaa90 FEM: ccx tools, set back the assignment of linux and osx ccx binary path 2019-04-04 15:42:43 +02:00
lorenz 76542ae729 FEM: osx: try to fix default ccx detection 2019-04-04 15:42:24 +02:00
wmayer 55698377f9 fix crash when checking an empty error message of an exception 2019-04-04 15:37:55 +02:00
wmayer f21cbce8cd fix crash when checking an empty error message of an exception 2019-04-04 15:37:40 +02:00
Bernd Hahnebach 9152703516 FEM: Py3 fix in result reader 2019-04-04 15:37:25 +02:00
Peter Eszlari c264c76d8f Linux/appdata: generate release info 2019-04-04 15:37:09 +02:00
sliptonic d8f5560cac Path: per Werner, fixing bug for function removed from string module
in py3
2019-04-04 15:36:53 +02:00
wmayer 442e411cf0 Py3: make string concatenation to work with Py2 and Py3 2019-04-04 15:36:39 +02:00
wmayer 55080952a8 reset expressions of a property when removing it 2019-04-04 15:36:25 +02:00
wmayer f185504b4e in case object deletion fails then make sure to re-enable updates of the main window 2019-04-04 15:36:11 +02:00
wmayer 2bc3daedcc Document::breakDependency should handle exceptions to avoid to leave document in an inconsistent state 2019-04-04 15:35:57 +02:00
Craig Marshall 2cef63f8a3 Fix #2034 with more precision attempt 2 2019-04-04 15:35:43 +02:00
triplus 81a7d937bd Fix for build failure on Ubuntu 16.04 2019-04-04 15:35:12 +02:00
wmayer 64f3424cab fix mouse selection for high DPI screens 2019-04-04 15:33:10 +02:00
wmayer 64cb745ddc fixes 0003130: FreeCAD 0.17 Qt5 bugs with external display 2019-04-04 15:32:54 +02:00
wmayer 228876f8f2 improve drawing of overlay pixmaps for high DPI screens 2019-04-04 15:32:34 +02:00
Yorik van Havre 8ece48c70b Arch: Fixed materials not updating their dicts 2019-03-20 10:01:27 -03:00
36 changed files with 402 additions and 234 deletions
+5 -1
View File
@@ -1529,7 +1529,11 @@ void Application::initConfig(int argc, char ** argv)
PyImport_AppendInittab ("FreeCAD", init_freecad_module);
PyImport_AppendInittab ("__FreeCADBase__", init_freecad_base_module);
#endif
mConfig["PythonSearchPath"] = Interpreter().init(argc,argv);
const char* pythonpath = Interpreter().init(argc,argv);
if (pythonpath)
mConfig["PythonSearchPath"] = pythonpath;
else
Base::Console().Warning("Encoding of Python paths failed\n");
// Parse the options that have impact on the init process
ParseOptions(argc,argv);
+7 -1
View File
@@ -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();
}
}
}
}
+20 -3
View File
@@ -496,10 +496,27 @@ void DocumentObject::setDocument(App::Document* doc)
onSettingDocument();
}
void DocumentObject::onAboutToRemoveProperty(const char* prop)
void DocumentObject::onAboutToRemoveProperty(const char* name)
{
if (_pDoc)
_pDoc->removePropertyOfObject(this, prop);
if (_pDoc) {
_pDoc->removePropertyOfObject(this, name);
Property* prop = getDynamicPropertyByName(name);
if (prop) {
auto expressions = ExpressionEngine.getExpressions();
std::vector<App::ObjectIdentifier> removeExpr;
for (auto it : expressions) {
if (it.first.getProperty() == prop) {
removeExpr.push_back(it.first);
}
}
for (auto it : removeExpr) {
ExpressionEngine.setValue(it, boost::shared_ptr<Expression>());
}
}
}
}
void DocumentObject::onBeforeChange(const Property* prop)
+4 -3
View File
@@ -1062,6 +1062,7 @@ boost::any ObjectIdentifier::getValue() const
destructor d1(pyvalue);
Base::PyGILStateLocker locker;
if (!pyvalue)
throw Base::RuntimeError("Failed to get property value.");
#if PY_MAJOR_VERSION < 3
@@ -1078,12 +1079,12 @@ boost::any ObjectIdentifier::getValue() const
return boost::any(PyString_AsString(pyvalue));
#endif
else if (PyUnicode_Check(pyvalue)) {
#if PY_MAJOR_VERSION >= 3
return boost::any(PyUnicode_AsUTF8(pyvalue));
#else
PyObject * s = PyUnicode_AsUTF8String(pyvalue);
destructor d2(s);
#if PY_MAJOR_VERSION >= 3
return boost::any(PyUnicode_AsUTF8(s));
#else
return boost::any(PyString_AsString(s));
#endif
}
+6 -4
View File
@@ -354,13 +354,15 @@ void InterpreterSingleton::runInteractiveString(const char *sCmd)
PyErr_Fetch(&errobj, &errdata, &errtraceback);
RuntimeError exc(""); // do not use PyException since this clears the error indicator
if (errdata) {
#if PY_MAJOR_VERSION >= 3
if (PyUnicode_Check(errdata))
exc.setMessage(PyUnicode_AsUTF8(errdata));
if (PyUnicode_Check(errdata))
exc.setMessage(PyUnicode_AsUTF8(errdata));
#else
if (PyString_Check(errdata))
exc.setMessage(PyString_AsString(errdata));
if (PyString_Check(errdata))
exc.setMessage(PyString_AsString(errdata));
#endif
}
PyErr_Restore(errobj, errdata, errtraceback);
if (PyErr_Occurred())
PyErr_Print();
+4 -4
View File
@@ -2033,25 +2033,25 @@ namespace Py
}
String()
: SeqBase<Char>( PyUnicode_FromString( "" ) )
: SeqBase<Char>( PyUnicode_FromString( "" ), true )
{
validate();
}
String( const char *latin1 )
: SeqBase<Char>( PyUnicode_FromString( latin1 ) )
: SeqBase<Char>( PyUnicode_FromString( latin1 ), true )
{
validate();
}
String( const std::string &latin1 )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ) )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ), true )
{
validate();
}
String( const char *latin1, Py_ssize_t size )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ) )
: SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ), true )
{
validate();
}
+11 -4
View File
@@ -571,20 +571,27 @@ QPixmap BitmapFactoryInst::merge(const QPixmap& p1, const QPixmap& p2, Position
{
// does the similar as the method above except that this method does not resize the resulting pixmap
int x = 0, y = 0;
#if QT_VERSION >= 0x050000
qreal dpr1 = p1.devicePixelRatio();
qreal dpr2 = p2.devicePixelRatio();
#else
qreal dpr1 = 1;
qreal dpr2 = 1;
#endif
switch (pos)
{
case TopLeft:
break;
case TopRight:
x = p1.width () - p2.width ();
x = p1.width ()/dpr1 - p2.width ()/dpr2;
break;
case BottomLeft:
y = p1.height() - p2.height();
y = p1.height()/dpr1 - p2.height()/dpr2;
break;
case BottomRight:
x = p1.width () - p2.width ();
y = p1.height() - p2.height();
x = p1.width ()/dpr1 - p2.width ()/dpr2;
y = p1.height()/dpr1 - p2.height()/dpr2;
break;
}
+24 -12
View File
@@ -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 {
+18
View File
@@ -390,7 +390,16 @@ int PolyPickerSelection::locationEvent(const SoLocation2Event* const, const QPoi
if (polyline.isWorking()) {
// check the position
#if QT_VERSION >= 0x050600
qreal dpr = _pcView3D->getGLWidget()->devicePixelRatioF();
#else
qreal dpr = 1.0;
#endif
QRect r = _pcView3D->getGLWidget()->rect();
if (dpr != 1.0) {
r.setHeight(r.height()*dpr);
r.setWidth(r.width()*dpr);
}
if (!r.contains(clPoint)) {
if (clPoint.x() < r.left())
@@ -599,7 +608,16 @@ int FreehandSelection::locationEvent(const SoLocation2Event* const e, const QPoi
if (polyline.isWorking()) {
// check the position
#if QT_VERSION >= 0x050600
qreal dpr = _pcView3D->getGLWidget()->devicePixelRatioF();
#else
qreal dpr = 1.0;
#endif
QRect r = _pcView3D->getGLWidget()->rect();
if (dpr != 1.0) {
r.setHeight(r.height()*dpr);
r.setWidth(r.width()*dpr);
}
if (!r.contains(clPoint)) {
if (clPoint.x() < r.left())
+2 -2
View File
@@ -116,7 +116,7 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const
dict = PyDict_Copy(dict);
QByteArray cmd =
"import string, os, sys, pydoc, pkgutil\n"
"import os, sys, pydoc, pkgutil\n"
"\n"
"class FreeCADDoc(pydoc.HTMLDoc):\n"
" def index(self, dir, shadowed=None):\n"
@@ -160,7 +160,7 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const
" ret = pydoc.html.index(dir, seen)\n"
" if ret != None:\n"
" indices.append(ret)\n"
"contents = heading + string.join(indices) + '''<p align=right>\n"
"contents = heading + ' '.join(indices) + '''<p align=right>\n"
"<font color=\"#909090\" face=\"helvetica, arial\"><strong>\n"
"pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''\n"
"htmldocument=pydoc.html.page(title,contents)\n";
+2 -1
View File
@@ -323,7 +323,8 @@ void InteractiveInterpreter::runCode(PyCodeObject* code) const
if (PyErr_Occurred()) { /* get latest python exception information */
PyObject *errobj, *errdata, *errtraceback;
PyErr_Fetch(&errobj, &errdata, &errtraceback);
if (PyDict_Check(errdata)) {
// the error message can be empty so errdata will be null
if (errdata && PyDict_Check(errdata)) {
PyObject* value = PyDict_GetItemString(errdata, "swhat");
if (value) {
Base::RuntimeError e;
+58 -19
View File
@@ -232,6 +232,28 @@ Py::Object qt_wrapInstance(qttype object, const char* className,
return func.apply(arguments);
}
const char* qt_identifyType(QObject* ptr, const char* pyside)
{
PyObject* module = PyImport_ImportModule(pyside);
if (!module) {
std::string error = "Cannot load ";
error += pyside;
error += " module";
throw Py::Exception(PyExc_ImportError, error);
}
Py::Module qtmod(module);
const QMetaObject* metaObject = ptr->metaObject();
while (metaObject) {
const char* className = metaObject->className();
if (qtmod.getDict().hasKey(className))
return className;
metaObject = metaObject->superClass();
}
return nullptr;
}
void* qt_getCppPointer(const Py::Object& pyobject, const char* shiboken, const char* unwrap)
{
// https://github.com/PySide/Shiboken/blob/master/shibokenmodule/typesystem_shiboken.xml
@@ -475,39 +497,50 @@ bool PythonWrapper::loadWidgetsModule()
void PythonWrapper::createChildrenNameAttributes(PyObject* root, QObject* object)
{
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
Q_FOREACH (QObject* child, object->children()) {
const QByteArray name = child->objectName().toLocal8Bit();
if (!name.isEmpty() && !name.startsWith("_") && !name.startsWith("qt_")) {
bool hasAttr = PyObject_HasAttrString(root, name.constData());
if (!hasAttr) {
#if defined (HAVE_SHIBOKEN2) && defined(HAVE_PYSIDE2)
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide2_QtCoreTypes[SBK_QOBJECT_IDX], child));
#else
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide_QtCoreTypes[SBK_QOBJECT_IDX], child));
#endif
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython(reinterpret_cast<SbkObjectType*>(Shiboken::SbkType<QObject>()), child));
PyObject_SetAttrString(root, name.constData(), pyChild);
#elif QT_VERSION >= 0x050000
const char* className = qt_identifyType(child, "PySide2.QtWidgets");
if (!className) {
if (qobject_cast<QWidget*>(child))
className = "QWidget";
else
className = "QObject";
}
Py::Object pyChild(qt_wrapInstance<QObject*>(child, className, "shiboken2", "PySide2.QtWidgets", "wrapInstance"));
PyObject_SetAttrString(root, name.constData(), pyChild.ptr());
#else
const char* className = qt_identifyType(child, "PySide.QtGui");
if (!className) {
if (qobject_cast<QWidget*>(child))
className = "QWidget";
else
className = "QObject";
}
Py::Object pyChild(qt_wrapInstance<QObject*>(child, className, "shiboken", "PySide.QtGui", "wrapInstance"));
PyObject_SetAttrString(root, name.constData(), pyChild.ptr());
#endif
}
createChildrenNameAttributes(root, child);
}
createChildrenNameAttributes(root, child);
}
#else
Q_UNUSED(root);
Q_UNUSED(object);
#endif
}
void PythonWrapper::setParent(PyObject* pyWdg, QObject* parent)
{
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
if (parent) {
#if defined (HAVE_SHIBOKEN2) && defined(HAVE_PYSIDE2)
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide2_QtGuiTypes[SBK_QWIDGET_IDX], parent));
#else
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython((SbkObjectType*)SbkPySide_QtGuiTypes[SBK_QWIDGET_IDX], parent));
#endif
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython(reinterpret_cast<SbkObjectType*>(Shiboken::SbkType<QWidget>()), parent));
Shiboken::Object::setParent(pyParent, pyWdg);
}
#else
@@ -680,7 +713,10 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
str << "import pyside2uic\n"
<< "from PySide2 import QtCore, QtGui, QtWidgets\n"
<< "import xml.etree.ElementTree as xml\n"
<< "from cStringIO import StringIO\n"
<< "try:\n"
<< " from cStringIO import StringIO\n"
<< "except:\n"
<< " from io import StringIO\n"
<< "\n"
<< "uiFile = \"" << file.c_str() << "\"\n"
<< "parsed = xml.parse(uiFile)\n"
@@ -691,7 +727,7 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
<< " frame = {}\n"
<< " pyside2uic.compileUi(f, o, indent=0)\n"
<< " pyc = compile(o.getvalue(), '<string>', 'exec')\n"
<< " exec pyc in frame\n"
<< " exec(pyc, frame)\n"
<< " #Fetch the base_class and form class based on their type in the xml from designer\n"
<< " form_class = frame['Ui_%s'%form_class]\n"
<< " base_class = eval('QtWidgets.%s'%widget_class)\n";
@@ -699,7 +735,10 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
str << "import pysideuic\n"
<< "from PySide import QtCore, QtGui\n"
<< "import xml.etree.ElementTree as xml\n"
<< "from cStringIO import StringIO\n"
<< "try:\n"
<< " from cStringIO import StringIO\n"
<< "except:\n"
<< " from io import StringIO\n"
<< "\n"
<< "uiFile = \"" << file.c_str() << "\"\n"
<< "parsed = xml.parse(uiFile)\n"
@@ -710,7 +749,7 @@ Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
<< " frame = {}\n"
<< " pysideuic.compileUi(f, o, indent=0)\n"
<< " pyc = compile(o.getvalue(), '<string>', 'exec')\n"
<< " exec pyc in frame\n"
<< " exec(pyc, frame)\n"
<< " #Fetch the base_class and form class based on their type in the xml from designer\n"
<< " form_class = frame['Ui_%s'%form_class]\n"
<< " base_class = eval('QtGui.%s'%widget_class)\n";
+11 -7
View File
@@ -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:
+38 -37
View File
@@ -250,6 +250,7 @@ class _ArchMaterial:
"The Material object"
def __init__(self,obj):
self.Type = "Material"
obj.Proxy = self
obj.addProperty("App::PropertyString","Description","Arch",QT_TRANSLATE_NOOP("App::Property","A description for this material"))
@@ -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
+6 -2
View File
@@ -674,8 +674,12 @@ class _Roof(ArchComponent.Component):
if obj.Base.Shape.Solids:
return obj.Shape
else :
if self.sub:
return self.sub
if hasattr(self,"sub"):
if self.sub:
return self.sub
else :
self.execute(obj)
return self.sub
else :
self.execute(obj)
return self.sub
+17 -17
View File
@@ -195,7 +195,7 @@ def export(exportList,filename):
outfile.close()
FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + " " + decode(filename) + "\n")
if materials:
outfile = pythonopen(filenamemtl,"wb")
outfile = pythonopen(filenamemtl,"w")
outfile.write("# FreeCAD v" + ver[0] + "." + ver[1] + " build" + ver[2] + " Arch module\n")
outfile.write("# http://www.freecadweb.org\n")
kinds = {"AmbientColor":"Ka ","DiffuseColor":"Kd ","SpecularColor":"Ks ","EmissiveColor":"Ke ","Transparency":"d "}
@@ -219,23 +219,23 @@ def export(exportList,filename):
FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + ' ' + decode(filenamemtl) + "\n")
def decode(name):
"decodes encoded strings"
try:
decodedName = (name.decode("utf8"))
except UnicodeDecodeError:
try:
decodedName = (name.decode("latin1"))
except UnicodeDecodeError:
FreeCAD.Console.PrintError(translate("Arch","Error: Couldn't determine character encoding"))
decodedName = name
return decodedName
#def decode(name):
# "decodes encoded strings"
# try:
# decodedName = (name.decode("utf8"))
# except UnicodeDecodeError:
# try:
# decodedName = (name.decode("latin1"))
# except UnicodeDecodeError:
# FreeCAD.Console.PrintError(translate("Arch","Error: Couldn't determine character encoding"))
# decodedName = name
# return decodedName
def open(filename):
"called when freecad wants to open a file"
docname = (os.path.splitext(os.path.basename(filename))[0]).encode("utf8")
doc = FreeCAD.newDocument(docname)
doc.Label = decode(docname)
docname = (os.path.splitext(os.path.basename(filename))[0])
doc = FreeCAD.newDocument(docname.encode("utf8"))
doc.Label = docname
return insert(filename,doc.Name)
def insert(filename,docname):
@@ -246,7 +246,7 @@ def insert(filename,docname):
doc = FreeCAD.newDocument(docname)
FreeCAD.ActiveDocument = doc
with pythonopen(filename,"rb") as infile:
with pythonopen(filename,"r") as infile:
verts = []
facets = []
activeobject = None
@@ -257,7 +257,7 @@ def insert(filename,docname):
if line[:7] == "mtllib ":
matlib = os.path.join(os.path.dirname(filename),line[7:])
if os.path.exists(matlib):
with pythonopen(matlib,"rb") as matfile:
with pythonopen(matlib,"r") as matfile:
mname = None
color = None
trans = None
+3 -22
View File
@@ -87,22 +87,13 @@ def errorDXFLib(gui):
if gui:
from PySide import QtGui, QtCore
from DraftTools import translate
if float(FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]) >= 0.17:
message = translate("Draft","""Download of dxf libraries failed.
message = translate("Draft","""Download of dxf libraries failed.
Please install the dxf Library addon manually
from menu Tools -> Addon Manager""")
else:
message = translate("Draft","""Download of dxf libraries failed.
Please download and install them manually.
See complete instructions at
http://www.freecadweb.org/wiki/Dxf_Importer_Install""")
QtGui.QMessageBox.information(None,"",message)
else:
FreeCAD.Console.PrintWarning("The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n")
if float(FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]) >= 0.17:
FreeCAD.Console.PrintWarning("Please install the dxf Library addon from Tools -> Addons Manager\n")
else:
FreeCAD.Console.PrintWarning("Please check https://github.com/yorikvanhavre/Draft-dxf-importer\n")
FreeCAD.Console.PrintWarning("Please install the dxf Library addon from Tools -> Addons Manager\n")
break
progressbar.stop()
sys.path.append(FreeCAD.ConfigGet("UserAppData"))
@@ -110,17 +101,7 @@ http://www.freecadweb.org/wiki/Dxf_Importer_Install""")
if gui:
from PySide import QtGui, QtCore
from DraftTools import translate
if float(FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]) >= 0.17:
message = translate('draft',"""The DXF import/export libraries needed by FreeCAD to handle
the DXF format were not found on this system.
Please either enable FreeCAD to download these libraries:
1 - Load Draft workbench
2 - Menu Edit > Preferences > Import-Export > DXF > Enable downloads
Or install the libraries manually by installing the dxf-Library addon
from menu Tools -> Addon Manager.
To enabled FreeCAD to download these libraries, answer Yes.""")
else:
message = translate('draft',"""The DXF import/export libraries needed by FreeCAD to handle
message = translate('draft',"""The DXF import/export libraries needed by FreeCAD to handle
the DXF format were not found on this system.
Please either enable FreeCAD to download these libraries:
1 - Load Draft workbench
+3 -3
View File
@@ -295,14 +295,14 @@ def fill_femresult_mechanical(res_obj, result_set):
if len(Peeq) > 0:
if len(Peeq.values()) != len(disp.values()):
Pe = []
Pe_extra_nodes = Peeq.values()
Pe_extra_nodes = list(Peeq.values())
nodes = len(disp.values())
for i in range(nodes):
Pe_value = Pe_extra_nodes[i]
Pe.append(Pe_value)
res_obj.Peeq = Pe
else:
res_obj.Peeq = Peeq.values()
res_obj.Peeq = list(Peeq.values())
# fill res_obj.Temperature if they exist
# TODO, check if it is possible to have Temperature without disp, we would need to set NodeNumbers than
@@ -311,7 +311,7 @@ def fill_femresult_mechanical(res_obj, result_set):
if len(Temperature) > 0:
if len(Temperature.values()) != len(disp.values()):
Temp = []
Temp_extra_nodes = Temperature.values()
Temp_extra_nodes = list(Temperature.values())
nodes = len(disp.values())
for i in range(nodes):
Temp_value = Temp_extra_nodes[i]
+6 -1
View File
@@ -28,6 +28,8 @@ __url__ = "http://www.freecadweb.org"
import subprocess
import os.path
import sys
import femtools.femutils as femutils
from .. import run
@@ -112,7 +114,10 @@ class Solve(run.Solve):
def _updateOutput(self, output):
if self.solver.ElmerOutput is None:
self._createOutput()
self.solver.ElmerOutput.Text = output.decode("utf-8")
if sys.version_info.major >= 3:
self.solver.ElmerOutput.Text = output
else:
self.solver.ElmerOutput.Text = output.decode("utf-8")
def _createOutput(self):
self.solver.ElmerOutput = self.analysis.Document.addObject(
+2 -2
View File
@@ -536,11 +536,11 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
ccx_path = FreeCAD.getHomePath() + "bin/ccx.exe"
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx").SetString("ccxBinaryPath", ccx_path)
self.ccx_binary = ccx_path
elif system() == "Linux":
elif system() in ("Linux", "Darwin"):
p1 = subprocess.Popen(['which', 'ccx'], stdout=subprocess.PIPE)
if p1.wait() == 0:
if sys.version_info.major >= 3:
ccx_path = str(p1.stdout.read()).split('\n')[0]
ccx_path = p1.stdout.read().decode("utf8").split('\n')[0]
else:
ccx_path = p1.stdout.read().split('\n')[0]
elif p1.wait() == 1:
+5 -3
View File
@@ -22,11 +22,15 @@
#* Milos Koutny 2010 *
#***************************************************************************/
import FreeCAD, Part, os, FreeCADGui, __builtin__
import FreeCAD, Part, os, FreeCADGui
from FreeCAD import Base
from math import *
import ImportGui
# to distinguish python built-in open function from the one declared here
if open.__module__ in ['__builtin__','io']:
pythonopen = open
##########################################################
# Script version dated 19-Jan-2012 #
##########################################################
@@ -54,8 +58,6 @@ IDF_diag_path="/tmp" # path for output of footprint.lst and missing_models.lst
# End config section do not touch code below #
########################################################################################
pythonopen = __builtin__.open # to distinguish python built-in open function from the one declared here
def open(filename):
"""called when freecad opens an Emn file"""
docname = os.path.splitext(os.path.basename(filename))[0]
@@ -138,8 +138,15 @@ def cmdCreateImageScaling(name):
def accept(self):
sel = FreeCADGui.Selection.getSelection()
try:
locale=QtCore.QLocale.system()
d, ok = locale.toFloat(str(eval(self.lineEdit.text())))
try:
q = FreeCAD.Units.parseQuantity(self.lineEdit.text())
d = q.Value
if q.Unit == FreeCAD.Units.Unit(): # plain number
ok = True
elif q.Unit == FreeCAD.Units.Length:
ok = True
except:
ok = False
if not ok:
raise ValueError
s=d/self.distance
+1 -1
View File
@@ -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)
+19 -9
View File
@@ -42,6 +42,8 @@ except AttributeError:
return QtGui.QApplication.translate(context, text, None)
import io
import sys
PY2 = sys.version_info.major == 2
try:
import FreeCAD
@@ -144,18 +146,23 @@ def callopenscad(inputfilename,outputfilename=None,outputext='csg',keepname=Fals
import FreeCAD,os,subprocess,tempfile,time
def check_output2(*args,**kwargs):
kwargs.update({'stdout':subprocess.PIPE,'stderr':subprocess.PIPE})
p=subprocess.Popen(*args,**kwargs)
if PY2:
p=subprocess.Popen(*args)
else:
p=subprocess.Popen(*args,**kwargs)
stdoutd,stderrd = p.communicate()
stdoutd = stdoutd.decode("utf8")
stderrd = stderrd.decode("utf8")
if not PY2:
stdoutd = stdoutd.decode("utf8")
stderrd = stderrd.decode("utf8")
if p.returncode != 0:
raise OpenSCADError('%s %s\n' % (stdoutd.strip(),stderrd.strip()))
#raise Exception,'stdout %s\n stderr%s' %(stdoutd,stderrd)
if stderrd.strip():
FreeCAD.Console.PrintWarning(stderrd+u'\n')
if stdoutd.strip():
FreeCAD.Console.PrintMessage(stdoutd+u'\n')
return stdoutd
if not PY2:
if stderrd.strip():
FreeCAD.Console.PrintWarning(stderrd+u'\n')
if stdoutd.strip():
FreeCAD.Console.PrintMessage(stdoutd+u'\n')
return stdoutd
osfilename = FreeCAD.ParamGet(\
"User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
@@ -182,7 +189,10 @@ def callopenscadstring(scadstr,outputext='csg'):
dir1=tempfile.gettempdir()
inputfilename=os.path.join(dir1,'%s.scad' % next(tempfilenamegen))
inputfile = io.open(inputfilename,'w', encoding="utf8")
inputfile.write(scadstr)
if PY2:
inputfile.write(scadstr.decode('utf8'))
else:
inputfile.write(scadstr)
inputfile.close()
outputfilename = callopenscad(inputfilename,outputext=outputext,\
keepname=True)
+18 -10
View File
@@ -66,21 +66,29 @@ App::DocumentObjectExecReturn *Compound::execute(void)
TopoDS_Compound comp;
builder.MakeCompound(comp);
// avoid duplicates without changing the order
// See also ViewProviderCompound::updateData
std::set<DocumentObject*> tempLinks;
const std::vector<DocumentObject*>& links = Links.getValues();
for (std::vector<DocumentObject*>::const_iterator it = links.begin(); it != links.end(); ++it) {
if (*it && (*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
Part::Feature* fea = static_cast<Part::Feature*>(*it);
const TopoDS_Shape& sh = fea->Shape.getValue();
if (!sh.IsNull()) {
builder.Add(comp, sh);
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(sh, TopAbs_FACE, faceMap);
ShapeHistory hist;
hist.type = TopAbs_FACE;
for (int i=1; i<=faceMap.Extent(); i++) {
hist.shapeMap[i-1].push_back(countFaces++);
auto pos = tempLinks.insert(fea);
if (pos.second) {
const TopoDS_Shape& sh = fea->Shape.getValue();
if (!sh.IsNull()) {
builder.Add(comp, sh);
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(sh, TopAbs_FACE, faceMap);
ShapeHistory hist;
hist.type = TopAbs_FACE;
for (int i=1; i<=faceMap.Extent(); i++) {
hist.shapeMap[i-1].push_back(countFaces++);
}
history.push_back(hist);
}
history.push_back(hist);
}
}
}
+8 -4
View File
@@ -908,11 +908,15 @@ void CmdPartCompound::activated(int iMsg)
std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection();
std::stringstream str;
std::vector<std::string> tempSelNames;
// avoid duplicates without changing the order
std::set<std::string> tempSelNames;
str << "App.activeDocument()." << FeatName << ".Links = [";
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it){
str << "App.activeDocument()." << it->FeatName << ",";
tempSelNames.push_back(it->FeatName);
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it) {
auto pos = tempSelNames.insert(it->FeatName);
if (pos.second) {
str << "App.activeDocument()." << it->FeatName << ",";
}
}
str << "]";
+7 -7
View File
@@ -383,8 +383,8 @@ void PartGui::DimensionLinear::setupDimension()
//dimension arrows
float dimLength = (point2.getValue()-point1.getValue()).length();
float coneHeight = dimLength * .05;
float coneRadius = coneHeight / 2;
float coneHeight = dimLength * 0.05;
float coneRadius = coneHeight * 0.5;
SoCone *cone = new SoCone();
cone->bottomRadius.setValue(coneRadius);
@@ -392,8 +392,8 @@ void PartGui::DimensionLinear::setupDimension()
char lStr[100];
char rStr[100];
snprintf(lStr, sizeof(lStr), "translation %.2f 0.0 0.0", coneHeight*0.5);
snprintf(rStr, sizeof(rStr), "translation 0.0 -%.2f 0.0", coneHeight*0.5);
snprintf(lStr, sizeof(lStr), "translation %.6f 0.0 0.0", coneHeight * 0.5);
snprintf(rStr, sizeof(rStr), "translation 0.0 -%.6f 0.0", coneHeight * 0.5);
setPart("leftArrow.shape", cone);
set("leftArrow.transform", "rotation 0.0 0.0 1.0 1.5707963");
@@ -1072,7 +1072,7 @@ void PartGui::DimensionAngular::setupDimension()
//dimension arrows
float coneHeight = radius.getValue() * 0.1;
float coneRadius = coneHeight / 2;
float coneRadius = coneHeight * 0.5;
SoCone *cone = new SoCone();
cone->bottomRadius.setValue(coneRadius);
@@ -1080,8 +1080,8 @@ void PartGui::DimensionAngular::setupDimension()
char str1[100];
char str2[100];
snprintf(str1, sizeof(str1), "translation 0.0 %.2f 0.0", coneHeight*0.5);
snprintf(str2, sizeof(str2), "translation 0.0 -%.2f 0.0", coneHeight*0.5);
snprintf(str1, sizeof(str1), "translation 0.0 %.6f 0.0", coneHeight * 0.5);
snprintf(str2, sizeof(str2), "translation 0.0 -%.6f 0.0", coneHeight * 0.5);
setPart("arrow1.shape", cone);
set("arrow1.localTransform", "rotation 0.0 0.0 1.0 3.1415927");
+18
View File
@@ -72,6 +72,24 @@ void ViewProviderCompound::updateData(const App::Property* prop)
(prop)->getValues();
Part::Compound* objComp = static_cast<Part::Compound*>(getObject());
std::vector<App::DocumentObject*> sources = objComp->Links.getValues();
if (hist.size() != sources.size()) {
// avoid duplicates without changing the order
// See also Compound::execute
std::set<App::DocumentObject*> tempSources;
std::vector<App::DocumentObject*> filter;
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it) {
Part::Feature* objBase = dynamic_cast<Part::Feature*>(*it);
if (objBase) {
auto pos = tempSources.insert(objBase);
if (pos.second) {
filter.push_back(objBase);
}
}
}
sources = filter;
}
if (hist.size() != sources.size())
return;
@@ -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])
+4
View File
@@ -1019,6 +1019,10 @@ class TaskPanel:
Draft.move(sel.Object, by)
def updateSelection(self):
# Remove Job object if present in Selection: source of phantom paths
if self.obj in FreeCADGui.Selection.getSelection():
FreeCADGui.Selection.removeSelection(self.obj)
sel = FreeCADGui.Selection.getSelectionEx()
if len(sel) == 1 and len(sel[0].SubObjects) == 1:
+8 -44
View File
@@ -5140,7 +5140,7 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction)
for (std::vector<Part::Geometry *>::const_iterator it=svals.begin(); it != svals.end(); ++it){
Part::Geometry *geoNew = (*it)->copy();
if(construction) {
if(construction && geoNew->getTypeId() != Part::GeomPoint::getClassTypeId()) {
geoNew->Construction = true;
}
newVals.push_back(geoNew);
@@ -5174,11 +5174,13 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction)
int sourceid = 0;
for (std::vector< Sketcher::Constraint * >::const_iterator it= scvals.begin(); it != scvals.end(); ++it,nextcid++,sourceid++) {
if ((*it)->Type == Sketcher::Distance ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Diameter ||
(*it)->Type == Sketcher::Angle ||
(*it)->Type == Sketcher::SnellsLaw) {
if ((*it)->Type == Sketcher::Distance ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Diameter ||
(*it)->Type == Sketcher::Angle ||
(*it)->Type == Sketcher::SnellsLaw ||
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ) {
// then we link its value to the parent
// (there is a plausible alternative for a slightly different use case to copy the expression of the parent if one is existing)
if ((*it)->isDriving) {
@@ -5191,45 +5193,7 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction)
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
}
else if ((*it)->Type == Sketcher::DistanceX) {
// then we link its value to the parent
// (there is a plausible alternative for a slightly different use case to copy the expression of the parent if one is existing)
if ((*it)->isDriving) {
App::ObjectIdentifier spath = psObj->Constraints.createPath(sourceid);
if(xinv) {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, std::string(1,'-') + spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
else {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
}
}
else if ((*it)->Type == Sketcher::DistanceY ) {
// then we link its value to the parent
// (there is a plausible alternative for a slightly different use case to copy the expression of the parent if one is existing)
if ((*it)->isDriving) {
App::ObjectIdentifier spath = psObj->Constraints.createPath(sourceid);
if(yinv) {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, std::string(1,'-') + spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
else {
boost::shared_ptr<App::Expression> expr(App::Expression::parse(this, spath.getDocumentObjectName().getString() +std::string(1,'.') + spath.toString()));
setExpression(Constraints.createPath(nextcid), expr);
}
}
}
}
+8 -2
View File
@@ -1195,11 +1195,17 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
return true;
}
case STATUS_SKETCH_UseRubberBand: {
// Here we must use the device-pixel-ratio to compute the correct y coordinate (#0003130)
#if QT_VERSION >= 0x050600
qreal dpr = viewer->getGLWidget()->devicePixelRatioF();
#else
qreal dpr = 1;
#endif
newCursorPos = cursorPos;
rubberband->setCoords(prvCursorPos.getValue()[0],
viewer->getGLWidget()->height() - prvCursorPos.getValue()[1],
viewer->getGLWidget()->height()*dpr - prvCursorPos.getValue()[1],
newCursorPos.getValue()[0],
viewer->getGLWidget()->height() - newCursorPos.getValue()[1]);
viewer->getGLWidget()->height()*dpr - newCursorPos.getValue()[1]);
viewer->redraw();
return true;
}
+5
View File
@@ -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);
+36 -4
View File
@@ -1,4 +1,36 @@
install(FILES org.freecadweb.FreeCAD.appdata.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
install(FILES org.freecadweb.FreeCAD.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES org.freecadweb.FreeCAD.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps)
install(FILES org.freecadweb.FreeCAD.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages)
include(GNUInstallDirs)
if(NOT DEFINED APPDATA_RELEASE_DATE)
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(COMMAND git log -1 --pretty=%cd --date=short
OUTPUT_VARIABLE APPDATA_RELEASE_DATE
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
file(TIMESTAMP "${CMAKE_SOURCE_DIR}/CMakeLists.txt" APPDATA_RELEASE_DATE "%Y-%m-%d")
endif()
endif()
configure_file(
org.freecadweb.FreeCAD.appdata.xml.in
${CMAKE_BINARY_DIR}/org.freecadweb.FreeCAD.appdata.xml
)
install(
FILES ${CMAKE_BINARY_DIR}/org.freecadweb.FreeCAD.appdata.xml
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo
)
install(
FILES org.freecadweb.FreeCAD.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications
)
install(
FILES org.freecadweb.FreeCAD.svg
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps
)
install(
FILES org.freecadweb.FreeCAD.xml
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mime/packages
)
@@ -29,8 +29,8 @@
<url type="help">https://forum.freecadweb.org</url>
<url type="donation">https://www.freecadweb.org/wiki/Donate</url>
<update_contact>yorik_AT_uncreated.net</update_contact>
<content_rating type="oars-1.1" />
<content_rating type="oars-1.1"/>
<releases>
<release version="0.17" date="2018-04-06"></release>
<release version="@PACKAGE_VERSION@" date="@APPDATA_RELEASE_DATE@"/>
</releases>
</component>