Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c16c27cd0e
|
@ -160,7 +160,7 @@ Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::Perform()
|
|||
static Standard_Real readFloat(OSD_File& theFile)
|
||||
{
|
||||
union {
|
||||
Standard_Boolean i;
|
||||
Standard_Integer i;
|
||||
Standard_ShortReal f;
|
||||
}u;
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@
|
|||
#include <Standard_ErrorHandler.hxx>
|
||||
|
||||
// Netgen include files
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4067)
|
||||
#endif
|
||||
|
||||
namespace nglib {
|
||||
#include <nglib.h>
|
||||
}
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
/*
|
||||
Netgen include files
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4067)
|
||||
#endif
|
||||
|
||||
namespace nglib {
|
||||
#include <nglib.h>
|
||||
}
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
/*
|
||||
Netgen include files
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4067)
|
||||
#endif
|
||||
|
||||
namespace nglib {
|
||||
#include <nglib.h>
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
|
||||
#if defined(_MSC_VER)
|
||||
#define strtoll _strtoi64
|
||||
#pragma warning(disable : 4003)
|
||||
#pragma warning(disable : 4065)
|
||||
#endif
|
||||
|
||||
using namespace Base;
|
||||
|
|
|
@ -706,8 +706,23 @@ void Application::slotActiveDocument(const App::Document& Doc)
|
|||
{
|
||||
std::map<const App::Document*, Gui::Document*>::iterator doc = d->documents.find(&Doc);
|
||||
// this can happen when closing a document with two views opened
|
||||
if (doc != d->documents.end())
|
||||
if (doc != d->documents.end()) {
|
||||
// this can happen when calling App.setActiveDocument directly from Python
|
||||
// because no MDI view will be activated
|
||||
if (d->activeDocument != doc->second) {
|
||||
d->activeDocument = doc->second;
|
||||
if (d->activeDocument) {
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Object active(d->activeDocument->getPyObject(), true);
|
||||
Py::Module("FreeCADGui").setAttr(std::string("ActiveDocument"),active);
|
||||
}
|
||||
else {
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Module("FreeCADGui").setAttr(std::string("ActiveDocument"),Py::None());
|
||||
}
|
||||
}
|
||||
signalActiveDocument(*doc->second);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotNewObject(const ViewProvider& vp)
|
||||
|
|
|
@ -231,6 +231,7 @@ public:
|
|||
PYFUNCDEF_S(sExport);
|
||||
|
||||
PYFUNCDEF_S(sActiveDocument);
|
||||
PYFUNCDEF_S(sSetActiveDocument);
|
||||
PYFUNCDEF_S(sGetDocument);
|
||||
|
||||
PYFUNCDEF_S(sDoCommand);
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "Language/Translator.h"
|
||||
#include "DownloadManager.h"
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <App/DocumentPy.h>
|
||||
#include <App/PropertyFile.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Console.h>
|
||||
|
@ -139,6 +140,9 @@ PyMethodDef Application::Methods[] = {
|
|||
{"activeDocument", (PyCFunction) Application::sActiveDocument, 1,
|
||||
"activeDocument() -> object or None\n\n"
|
||||
"Return the active document or None if no one exists"},
|
||||
{"setActiveDocument", (PyCFunction) Application::sSetActiveDocument,1,
|
||||
"setActiveDocument(string or App.Document) -> None\n\n"
|
||||
"Activate the specified document"},
|
||||
{"getDocument", (PyCFunction) Application::sGetDocument, 1,
|
||||
"getDocument(string) -> object\n\n"
|
||||
"Get a document by its name"},
|
||||
|
@ -171,19 +175,71 @@ PyObject* Gui::Application::sActiveDocument(PyObject * /*self*/, PyObject *args,
|
|||
}
|
||||
}
|
||||
|
||||
PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
|
||||
PyObject* Gui::Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
|
||||
{
|
||||
char *pstr=0;
|
||||
if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
Document *pcDoc = 0;
|
||||
|
||||
do {
|
||||
char *pstr=0;
|
||||
if (PyArg_ParseTuple(args, "s", &pstr)) {
|
||||
pcDoc = Instance->getDocument(pstr);
|
||||
if (!pcDoc) {
|
||||
PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
PyObject* doc;
|
||||
if (PyArg_ParseTuple(args, "O!", &(App::DocumentPy::Type), &doc)) {
|
||||
pcDoc = Instance->getDocument(static_cast<App::DocumentPy*>(doc)->getDocumentPtr());
|
||||
if (!pcDoc) {
|
||||
PyErr_Format(PyExc_KeyError, "Unknown document instance");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(false);
|
||||
|
||||
Document *pcDoc = Instance->getDocument(pstr);
|
||||
if (!pcDoc) {
|
||||
PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
|
||||
PyErr_SetString(PyExc_TypeError, "Either string or App.Document expected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pcDoc->getPyObject();
|
||||
if (Instance->activeDocument() != pcDoc) {
|
||||
Gui::MDIView* view = pcDoc->getActiveView();
|
||||
getMainWindow()->setActiveWindow(view);
|
||||
}
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
|
||||
{
|
||||
char *pstr=0;
|
||||
if (PyArg_ParseTuple(args, "s", &pstr)) {
|
||||
Document *pcDoc = Instance->getDocument(pstr);
|
||||
if (!pcDoc) {
|
||||
PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
|
||||
return 0;
|
||||
}
|
||||
return pcDoc->getPyObject();
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
PyObject* doc;
|
||||
if (PyArg_ParseTuple(args, "O!", &(App::DocumentPy::Type), &doc)) {
|
||||
Document *pcDoc = Instance->getDocument(static_cast<App::DocumentPy*>(doc)->getDocumentPtr());
|
||||
if (!pcDoc) {
|
||||
PyErr_Format(PyExc_KeyError, "Unknown document instance");
|
||||
return 0;
|
||||
}
|
||||
return pcDoc->getPyObject();
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Either string or App.Document exprected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* Application::sHide(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
|
||||
|
|
|
@ -213,7 +213,9 @@ void DlgExpressionInput::mousePressEvent(QMouseEvent* ev)
|
|||
#endif
|
||||
//we need to reject the dialog when clicked on the background. As the background is transparent
|
||||
//this is the expected behaviour for the user
|
||||
this->reject();
|
||||
bool on = ui->expression->completerActive();
|
||||
if (!on)
|
||||
this->reject();
|
||||
}
|
||||
|
||||
void DlgExpressionInput::showEvent(QShowEvent* ev)
|
||||
|
@ -240,8 +242,12 @@ bool DlgExpressionInput::eventFilter(QObject *obj, QEvent *ev)
|
|||
// on the size of the widget. Instead, it must be checked if the
|
||||
// cursor is on this or an underlying widget or outside.
|
||||
if (!underMouse()) {
|
||||
qApp->removeEventFilter(this);
|
||||
reject();
|
||||
bool on = ui->expression->completerActive();
|
||||
// Do this only if the completer is not shown
|
||||
if (!on) {
|
||||
qApp->removeEventFilter(this);
|
||||
reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,12 +111,7 @@ PyObject* DocumentPy::setEdit(PyObject *args)
|
|||
}
|
||||
|
||||
bool ok = getDocumentPtr()->setEdit(getDocumentPtr()->getViewProvider(obj),mod);
|
||||
if (!ok) {
|
||||
PyErr_Format(Base::BaseExceptionFreeCADError, "Failed to set object '%s' in edit mode", psFeatStr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_Return;
|
||||
return PyBool_FromLong(ok ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* DocumentPy::getInEdit(PyObject *args)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef _PreComp_
|
||||
# include <QApplication>
|
||||
# include <QButtonGroup>
|
||||
# include <QCompleter>
|
||||
# include <QComboBox>
|
||||
# include <QDesktopServices>
|
||||
# include <QGridLayout>
|
||||
|
@ -521,7 +522,14 @@ FileChooser::FileChooser ( QWidget * parent )
|
|||
layout->setMargin( 0 );
|
||||
layout->setSpacing( 6 );
|
||||
|
||||
lineEdit = new QLineEdit( this );
|
||||
lineEdit = new QLineEdit ( this );
|
||||
completer = new QCompleter ( this );
|
||||
completer->setMaxVisibleItems( 12 );
|
||||
fs_model = new QFileSystemModel( completer );
|
||||
fs_model->setRootPath(QString::fromUtf8(""));
|
||||
completer->setModel( fs_model );
|
||||
lineEdit->setCompleter( completer );
|
||||
|
||||
layout->addWidget( lineEdit );
|
||||
|
||||
connect(lineEdit, SIGNAL(textChanged(const QString &)),
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <QFileDialog>
|
||||
#include <QFileIconProvider>
|
||||
#include <QFileSystemModel>
|
||||
#include <QCompleter>
|
||||
|
||||
class QButtonGroup;
|
||||
class QGridLayout;
|
||||
|
@ -177,6 +179,8 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
QLineEdit *lineEdit;
|
||||
QCompleter *completer;
|
||||
QFileSystemModel *fs_model;
|
||||
QPushButton *button;
|
||||
Mode md;
|
||||
QString _filter;
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\**************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
|
||||
#include <Quarter/devices/InputDevice.h>
|
||||
#include <QtGui/QInputEvent>
|
||||
#include <Inventor/events/SoEvents.h>
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
|
||||
#include <Quarter/devices/Keyboard.h>
|
||||
|
||||
#include <QtCore/QEvent>
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
QuarterWidget.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
|
||||
#include <Quarter/devices/Mouse.h>
|
||||
|
||||
#include <QtCore/QEvent>
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
\endcode
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <QtCore/QEvent>
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include <Quarter/QuarterWidget.h>
|
||||
#include <Quarter/eventhandlers/EventFilter.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtGui/QMenu>
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\**************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
|
||||
#include <Quarter/devices/SpaceNavigatorDevice.h>
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
|
|
|
@ -989,7 +989,9 @@ PyMethodDef SelectionSingleton::Methods[] = {
|
|||
{"getSelection", (PyCFunction) SelectionSingleton::sGetSelection, 1,
|
||||
"getSelection([string]) -- Return a list of selected objets\n"
|
||||
"Return a list of selected objects for a given document name. If no\n"
|
||||
"document is given the complete selection is returned."},
|
||||
"document name is given the selection for the active document is returned."},
|
||||
{"getCompleteSelection", (PyCFunction) SelectionSingleton::sGetCompleteSelection, 1,
|
||||
"getCompleteSelection() -- Return a list of selected objects of all documents."},
|
||||
{"getSelectionEx", (PyCFunction) SelectionSingleton::sGetSelectionEx, 1,
|
||||
"getSelectionEx([string]) -- Return a list of SelectionObjects\n"
|
||||
"Return a list of SelectionObjects for a given document name. If no\n"
|
||||
|
@ -1107,10 +1109,27 @@ PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args,
|
|||
return NULL; // NULL triggers exception
|
||||
|
||||
std::vector<SelectionSingleton::SelObj> sel;
|
||||
if (documentName)
|
||||
sel = Selection().getSelection(documentName);
|
||||
else
|
||||
sel = Selection().getCompleteSelection();
|
||||
sel = Selection().getSelection(documentName);
|
||||
|
||||
try {
|
||||
Py::List list;
|
||||
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
|
||||
list.append(Py::asObject(it->pObject->getPyObject()));
|
||||
}
|
||||
return Py::new_reference_to(list);
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *SelectionSingleton::sGetCompleteSelection(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
std::vector<SelectionSingleton::SelObj> sel;
|
||||
sel = Selection().getCompleteSelection();
|
||||
|
||||
try {
|
||||
Py::List list;
|
||||
|
|
|
@ -311,6 +311,7 @@ protected:
|
|||
static PyObject *sIsSelected (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sCountObjectsOfType (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sGetSelection (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sGetCompleteSelection(PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sGetSelectionEx (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sGetSelectionObject (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sAddSelObserver (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
# include <QGLFormat>
|
||||
# include <QGLWidget>
|
||||
# include <QGLPixelBuffer>
|
||||
# include <QMessageBox>
|
||||
# include <QPainter>
|
||||
# include <QPrinter>
|
||||
# include <QPrintDialog>
|
||||
|
@ -531,6 +532,13 @@ void View3DInventor::print(QPrinter* printer)
|
|||
#else
|
||||
QImage img;
|
||||
QPainter p(printer);
|
||||
if (!p.isActive() && !printer->outputFileName().isEmpty()) {
|
||||
qApp->setOverrideCursor(Qt::ArrowCursor);
|
||||
QMessageBox::critical(this, tr("Opening file failed"),
|
||||
tr("Can't open file '%1' for writing.").arg(printer->outputFileName()));
|
||||
qApp->restoreOverrideCursor();
|
||||
return;
|
||||
}
|
||||
QRect rect = printer->pageRect();
|
||||
|
||||
bool pbuffer = QGLPixelBuffer::hasOpenGLPbuffers();
|
||||
|
|
|
@ -2151,6 +2151,7 @@ QVariant PropertyPathItem::toolTip(const App::Property* prop) const
|
|||
QWidget* PropertyPathItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
|
||||
{
|
||||
Gui::FileChooser *fc = new Gui::FileChooser(parent);
|
||||
fc->setMode(FileChooser::Directory);
|
||||
fc->setAutoFillBackground(true);
|
||||
QObject::connect(fc, SIGNAL(fileNameSelected(const QString&)), receiver, method);
|
||||
return fc;
|
||||
|
|
|
@ -422,11 +422,12 @@ def formatObject(target,origin=None):
|
|||
for p in matchrep.PropertiesList:
|
||||
if not p in ["DisplayMode","BoundingBox","Proxy","RootNode","Visibility"]:
|
||||
if p in obrep.PropertiesList:
|
||||
if hasattr(getattr(matchrep,p),"Value"):
|
||||
val = getattr(matchrep,p).Value
|
||||
else:
|
||||
val = getattr(matchrep,p)
|
||||
setattr(obrep,p,val)
|
||||
if not obrep.getEditorMode(p):
|
||||
if hasattr(getattr(matchrep,p),"Value"):
|
||||
val = getattr(matchrep,p).Value
|
||||
else:
|
||||
val = getattr(matchrep,p)
|
||||
setattr(obrep,p,val)
|
||||
if matchrep.DisplayMode in obrep.listDisplayModes():
|
||||
obrep.DisplayMode = matchrep.DisplayMode
|
||||
if hasattr(matchrep,"DiffuseColor") and hasattr(obrep,"DiffuseColor"):
|
||||
|
@ -998,13 +999,14 @@ def makeCopy(obj,force=None,reparent=False):
|
|||
for p in obj.PropertiesList:
|
||||
if not p in ["Proxy"]:
|
||||
if p in newobj.PropertiesList:
|
||||
try:
|
||||
setattr(newobj,p,obj.getPropertyByName(p))
|
||||
except AttributeError:
|
||||
if not newobj.getEditorMode(p):
|
||||
try:
|
||||
setattr(newobj,p,obj.getPropertyByName(p).Value)
|
||||
setattr(newobj,p,obj.getPropertyByName(p))
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
setattr(newobj,p,obj.getPropertyByName(p).Value)
|
||||
except AttributeError:
|
||||
pass
|
||||
if reparent:
|
||||
parents = obj.InList
|
||||
if parents:
|
||||
|
|
|
@ -593,6 +593,13 @@ void DrawingView::print(QPrinter* printer)
|
|||
}
|
||||
|
||||
QPainter p(printer);
|
||||
if (!p.isActive() && !printer->outputFileName().isEmpty()) {
|
||||
qApp->setOverrideCursor(Qt::ArrowCursor);
|
||||
QMessageBox::critical(this, tr("Opening file failed"),
|
||||
tr("Can't open file '%1' for writing.").arg(printer->outputFileName()));
|
||||
qApp->restoreOverrideCursor();
|
||||
return;
|
||||
}
|
||||
QRect rect = printer->paperRect();
|
||||
#ifdef Q_OS_WIN32
|
||||
// On Windows the preview looks broken when using paperRect as render area.
|
||||
|
|
|
@ -118,6 +118,7 @@ void AppFemExport initFem()
|
|||
|
||||
Fem::FemAnalysis ::init();
|
||||
Fem::FemAnalysisPython ::init();
|
||||
Fem::FeaturePython ::init();
|
||||
Fem::FemMesh ::init();
|
||||
Fem::FemMeshObject ::init();
|
||||
Fem::FemMeshShapeObject ::init();
|
||||
|
|
|
@ -88,7 +88,6 @@ SET(FemScripts_SRCS
|
|||
_ViewProviderFemAnalysis.py
|
||||
_FemAnalysis.py
|
||||
_CommandMechanicalShowResult.py
|
||||
_CommandFrequencyAnalysis.py
|
||||
_CommandQuickAnalysis.py
|
||||
_CommandPurgeFemResults.py
|
||||
_CommandMechanicalJobControl.py
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "FemAnalysis.h"
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <Base/Placement.h>
|
||||
#include <Base/Uuid.h>
|
||||
|
||||
|
@ -88,4 +89,24 @@ template<> const char* Fem::FemAnalysisPython::getViewProviderName(void) const {
|
|||
|
||||
// explicit template instantiation
|
||||
template class AppFemExport FeaturePythonT<Fem::FemAnalysis>;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
namespace App {
|
||||
/// @cond DOXERR
|
||||
PROPERTY_SOURCE_TEMPLATE(Fem::FeaturePython, App::DocumentObject)
|
||||
template<> const char* Fem::FeaturePython::getViewProviderName(void) const {
|
||||
return "Gui::ViewProviderPythonFeature";
|
||||
}
|
||||
template<> PyObject* Fem::FeaturePython::getPyObject(void) {
|
||||
if (PythonObject.is(Py::_None())) {
|
||||
// ref counter is set to 1
|
||||
PythonObject = Py::Object(new App::FeaturePythonPyT<App::DocumentObjectPy>(this),true);
|
||||
}
|
||||
return Py::new_reference_to(PythonObject);
|
||||
}
|
||||
// explicit template instantiation
|
||||
template class AppFemExport FeaturePythonT<App::DocumentObject>;
|
||||
/// @endcond
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ protected:
|
|||
};
|
||||
|
||||
typedef App::FeaturePythonT<FemAnalysis> FemAnalysisPython;
|
||||
typedef App::FeaturePythonT<App::DocumentObject> FeaturePython;
|
||||
|
||||
|
||||
} //namespace Fem
|
||||
|
|
|
@ -911,7 +911,12 @@ void FemMesh::writeABAQUS(const std::string &Filename) const
|
|||
|
||||
std::ofstream anABAQUS_Output;
|
||||
anABAQUS_Output.open(Filename.c_str());
|
||||
|
||||
// add nodes
|
||||
//
|
||||
anABAQUS_Output << "*Node, NSET=Nall" << std::endl;
|
||||
typedef std::map<int, Base::Vector3d> VertexMap;
|
||||
VertexMap vertexMap;
|
||||
|
||||
//Extract Nodes and Elements of the current SMESH datastructure
|
||||
SMDS_NodeIteratorPtr aNodeIter = myMesh->GetMeshDS()->nodesIterator();
|
||||
|
@ -921,10 +926,16 @@ void FemMesh::writeABAQUS(const std::string &Filename) const
|
|||
const SMDS_MeshNode* aNode = aNodeIter->next();
|
||||
current_node.Set(aNode->X(),aNode->Y(),aNode->Z());
|
||||
current_node = _Mtrx * current_node;
|
||||
anABAQUS_Output << aNode->GetID() << ", "
|
||||
<< current_node.x << ", "
|
||||
<< current_node.y << ", "
|
||||
<< current_node.z << std::endl;
|
||||
vertexMap[aNode->GetID()] = current_node;
|
||||
}
|
||||
|
||||
// This way we get sorted output.
|
||||
// See http://forum.freecadweb.org/viewtopic.php?f=18&t=12646&start=40#p103004
|
||||
for (VertexMap::iterator it = vertexMap.begin(); it != vertexMap.end(); ++it) {
|
||||
anABAQUS_Output << it->first << ", "
|
||||
<< it->second.x << ", "
|
||||
<< it->second.y << ", "
|
||||
<< it->second.z << std::endl;
|
||||
}
|
||||
|
||||
typedef std::map<int, std::vector<int> > NodesMap;
|
||||
|
|
|
@ -30,7 +30,6 @@ INSTALL(
|
|||
_ViewProviderFemAnalysis.py
|
||||
_FemAnalysis.py
|
||||
_CommandMechanicalShowResult.py
|
||||
_CommandFrequencyAnalysis.py
|
||||
_CommandQuickAnalysis.py
|
||||
_CommandPurgeFemResults.py
|
||||
_CommandMechanicalJobControl.py
|
||||
|
|
|
@ -37,7 +37,7 @@ __url__ = "http://www.freecadweb.org"
|
|||
|
||||
def makeFemBeamSection(width=20.0, height=20.0, name="BeamSection"):
|
||||
'''makeFemBeamSection([width], [height], [name]): creates an beamsection object to define a cross section'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", name)
|
||||
obj = FemGui.getActiveAnalysis().Document.addObject("Fem::FeaturePython", name)
|
||||
_FemBeamSection(obj)
|
||||
obj.Width = width
|
||||
obj.Height = height
|
||||
|
@ -57,8 +57,7 @@ class _CommandFemBeamSection:
|
|||
def Activated(self):
|
||||
FreeCAD.ActiveDocument.openTransaction("Create FemBeamSection")
|
||||
FreeCADGui.addModule("FemBeamSection")
|
||||
FreeCADGui.doCommand("FemBeamSection.makeFemBeamSection()")
|
||||
FreeCADGui.doCommand("App.activeDocument()." + FemGui.getActiveAnalysis().Name + ".Member = App.activeDocument()." + FemGui.getActiveAnalysis().Name + ".Member + [App.ActiveDocument.ActiveObject]")
|
||||
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemBeamSection.makeFemBeamSection()]")
|
||||
|
||||
def IsActive(self):
|
||||
if FemGui.getActiveAnalysis():
|
||||
|
|
|
@ -51,11 +51,11 @@ class FemCommands(object):
|
|||
elif self.is_active == 'with_document':
|
||||
active = FreeCADGui.ActiveDocument is not None
|
||||
elif self.is_active == 'with_analysis':
|
||||
active = FreeCADGui.ActiveDocument is not None and FemGui.getActiveAnalysis() is not None
|
||||
active = FemGui.getActiveAnalysis() is not None and self.active_analysis_in_active_doc()
|
||||
elif self.is_active == 'with_results':
|
||||
active = FreeCADGui.ActiveDocument is not None and FemGui.getActiveAnalysis() is not None and self.results_present()
|
||||
active = FemGui.getActiveAnalysis() is not None and self.active_analysis_in_active_doc() and self.results_present()
|
||||
elif self.is_active == 'with_part_feature':
|
||||
active = FreeCADGui.ActiveDocument is not None and FemGui.getActiveAnalysis() is not None and self.part_feature_selected()
|
||||
active = FemGui.getActiveAnalysis() is not None and self.active_analysis_in_active_doc() and self.part_feature_selected()
|
||||
return active
|
||||
|
||||
def results_present(self):
|
||||
|
@ -72,3 +72,6 @@ class FemCommands(object):
|
|||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def active_analysis_in_active_doc(self):
|
||||
return FemGui.getActiveAnalysis().Document is FreeCAD.ActiveDocument
|
||||
|
|
|
@ -37,7 +37,7 @@ __url__ = "http://www.freecadweb.org"
|
|||
|
||||
def makeFemShellThickness(thickness=20.0, name="ShellThickness"):
|
||||
'''makeFemShellThickness([thickness], [name]): creates an shellthickness object to define a plate thickness'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", name)
|
||||
obj = FemGui.getActiveAnalysis().Document.addObject("Fem::FeaturePython", name)
|
||||
_FemShellThickness(obj)
|
||||
obj.Thickness = thickness
|
||||
if FreeCAD.GuiUp:
|
||||
|
@ -56,8 +56,7 @@ class _CommandFemShellThickness:
|
|||
def Activated(self):
|
||||
FreeCAD.ActiveDocument.openTransaction("Create FemShellThickness")
|
||||
FreeCADGui.addModule("FemShellThickness")
|
||||
FreeCADGui.doCommand("FemShellThickness.makeFemShellThickness()")
|
||||
FreeCADGui.doCommand("App.activeDocument()." + FemGui.getActiveAnalysis().Name + ".Member = App.activeDocument()." + FemGui.getActiveAnalysis().Name + ".Member + [App.ActiveDocument.ActiveObject]")
|
||||
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemShellThickness.makeFemShellThickness()]")
|
||||
|
||||
def IsActive(self):
|
||||
if FemGui.getActiveAnalysis():
|
||||
|
|
|
@ -29,13 +29,21 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
|
||||
finished = QtCore.Signal(int)
|
||||
|
||||
def __init__(self, analysis=None):
|
||||
known_analysis_types = ["static", "frequency"]
|
||||
|
||||
## The constructor
|
||||
# @param analysis - analysis object to be used as the core object.
|
||||
# @param test_mode - True indicates that no real calculations will take place, so ccx bianry is not required. Used by test module.
|
||||
# "__init__" tries to use current active analysis in analysis is left empty.
|
||||
# Rises exception if analysis is not set and there is no active analysis
|
||||
def __init__(self, analysis=None, test_mode=False):
|
||||
QtCore.QRunnable.__init__(self)
|
||||
QtCore.QObject.__init__(self)
|
||||
|
||||
self.known_analysis_types = ["static", "frequency"]
|
||||
|
||||
if analysis:
|
||||
## @var analysis
|
||||
# FEM analysis - the core object. Has to be present.
|
||||
# It's set to analysis passed in "__init__" or set to current active analysis by default if nothing has been passed to "__init__".
|
||||
self.analysis = analysis
|
||||
else:
|
||||
import FemGui
|
||||
|
@ -44,10 +52,18 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
self.update_objects()
|
||||
self.set_analysis_type()
|
||||
self.set_eigenmode_parameters()
|
||||
## @var base_name
|
||||
# base name of .inp/.frd file (without extension). It is used to construct .inp file path that is passed to CalculiX ccx
|
||||
self.base_name = ""
|
||||
## @var results_present
|
||||
# boolean variable indicating if there are calculation results ready for use
|
||||
self.results_present = False
|
||||
self.setup_working_dir()
|
||||
self.setup_ccx()
|
||||
if test_mode:
|
||||
self.ccx_binary_present = True
|
||||
else:
|
||||
self.ccx_binary_present = False
|
||||
self.setup_ccx()
|
||||
else:
|
||||
raise Exception('FEM: No active analysis found!')
|
||||
|
||||
|
@ -56,7 +72,7 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
def purge_results(self):
|
||||
for m in self.analysis.Member:
|
||||
if (m.isDerivedFrom('Fem::FemResultObject')):
|
||||
FreeCAD.ActiveDocument.removeObject(m.Name)
|
||||
self.analysis.Document.removeObject(m.Name)
|
||||
self.results_present = False
|
||||
|
||||
## Resets mesh deformation
|
||||
|
@ -80,6 +96,13 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
self.reset_mesh_color()
|
||||
self.reset_mesh_deformation()
|
||||
|
||||
## Sets mesh color using selected type of results (Sabs by default)
|
||||
# @param self The python object self
|
||||
# @param result_type Type of FEM result, allowed are:
|
||||
# - U1, U2, U3 - deformation
|
||||
# - Uabs - absolute deformation
|
||||
# - Sabs - Von Mises stress
|
||||
# @param limit cutoff value. All values over the limit are treated as equel to the limit. Useful for filtering out hot spots.
|
||||
def show_result(self, result_type="Sabs", limit=None):
|
||||
self.update_objects()
|
||||
if result_type == "None":
|
||||
|
@ -96,6 +119,10 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
values = list(d[match[result_type]])
|
||||
self.show_color_by_scalar_with_cutoff(values, limit)
|
||||
|
||||
## Sets mesh color using list of values. Internally used by show_result function.
|
||||
# @param self The python object self
|
||||
# @param values list of values
|
||||
# @param limit cutoff value. All values over the limit are treated as equel to the limit. Useful for filtering out hot spots.
|
||||
def show_color_by_scalar_with_cutoff(self, values, limit=None):
|
||||
if limit:
|
||||
filtered_values = []
|
||||
|
@ -120,10 +147,22 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
# [{'Object':pressure_constraints, 'xxxxxxxx':value}, {}, ...]
|
||||
# [{'Object':beam_sections, 'xxxxxxxx':value}, {}, ...]
|
||||
# [{'Object':shell_thicknesses, 'xxxxxxxx':value}, {}, ...]
|
||||
|
||||
## @var mesh
|
||||
# mesh of the analysis. Used to generate .inp file and to show results
|
||||
self.mesh = None
|
||||
self.material = []
|
||||
## @var fixed_constraints
|
||||
# set of fixed constraints from the analysis. Updated with update_objects
|
||||
# Individual constraints are "Fem::ConstraintFixed" type
|
||||
self.fixed_constraints = []
|
||||
## @var force_constraints
|
||||
# set of force constraints from the analysis. Updated with update_objects
|
||||
# Individual constraints are "Fem::ConstraintForce" type
|
||||
self.force_constraints = []
|
||||
## @var pressure_constraints
|
||||
# set of pressure constraints from the analysis. Updated with update_objects
|
||||
# Individual constraints are "Fem::ConstraintPressure" type
|
||||
self.pressure_constraints = []
|
||||
self.beam_sections = []
|
||||
self.shell_thicknesses = []
|
||||
|
@ -162,6 +201,11 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
message += "No active Analysis\n"
|
||||
if self.analysis_type not in self.known_analysis_types:
|
||||
message += "Unknown analysis type: {}\n".format(self.analysis_type)
|
||||
if not self.working_dir:
|
||||
message += "Working directory not set\n"
|
||||
import os
|
||||
if not (os.path.isdir(self.working_dir)):
|
||||
message += "Working directory \'{}\' doesn't exist.".format(self.working_dir)
|
||||
if not self.mesh:
|
||||
message += "No mesh object in the Analysis\n"
|
||||
if not self.material:
|
||||
|
@ -207,7 +251,9 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
import multiprocessing
|
||||
import os
|
||||
import subprocess
|
||||
if self.inp_file_name != "":
|
||||
self.ccx_stdout = ""
|
||||
self.ccx_stderr = ""
|
||||
if self.inp_file_name != "" and self.ccx_binary_present:
|
||||
ont_backup = os.environ.get('OMP_NUM_THREADS')
|
||||
if not ont_backup:
|
||||
ont_backup = ""
|
||||
|
@ -226,7 +272,7 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
return p.returncode
|
||||
return -1
|
||||
|
||||
## sets eigenmode parameters for CalculiX frequency analysis
|
||||
## Sets eigenmode parameters for CalculiX frequency analysis
|
||||
# @param self The python object self
|
||||
# @param number number of eigenmodes that wll be calculated, default 10
|
||||
# @param limit_low lower value of requested eigenfrequency range, default 0.0
|
||||
|
@ -234,6 +280,9 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
def set_eigenmode_parameters(self, number=10, limit_low=0.0, limit_high=1000000.0):
|
||||
self.eigenmode_parameters = (number, limit_low, limit_high)
|
||||
|
||||
## Sets base_name
|
||||
# @param self The python object self
|
||||
# @param base_name base name of .inp/.frd file (without extension). It is used to construct .inp file path that is passed to CalculiX ccx
|
||||
def set_base_name(self, base_name=None):
|
||||
if base_name is None:
|
||||
self.base_name = ""
|
||||
|
@ -242,34 +291,55 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
# Update inp file name
|
||||
self.set_inp_file_name()
|
||||
|
||||
## sets inp file name that is used to determine location and name of frd result file.
|
||||
## Sets inp file name that is used to determine location and name of frd result file.
|
||||
# Normally inp file name is set set by write_inp_file
|
||||
# Can be used to read mock calculations file
|
||||
# @param self The python object self
|
||||
# @inp_file_name .inp file name. If empty the .inp file path is constructed from working_dir, base_name and string ".inp"
|
||||
def set_inp_file_name(self, inp_file_name=None):
|
||||
if inp_file_name is not None:
|
||||
self.inp_file_name = inp_file_name
|
||||
else:
|
||||
self.inp_file_name = self.working_dir + '/' + self.base_name + '.inp'
|
||||
|
||||
def set_analysis_type(self, analysis_type=None):
|
||||
if analysis_type is None:
|
||||
self.analysis_type = "static"
|
||||
else:
|
||||
self.analysis_type = analysis_type
|
||||
|
||||
## Sets working dir for ccx execution. Called with no working_dir uses WorkingDir for FEM preferences
|
||||
## Sets analysis type.
|
||||
# @param self The python object self
|
||||
# @working_dir directory to be used for .inp file and ccx execution
|
||||
def setup_working_dir(self, working_dir=None):
|
||||
if working_dir is None:
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
self.working_dir = self.fem_prefs.GetString("WorkingDir", "/tmp")
|
||||
# @param analysis_type type of the analysis. Allowed values are:
|
||||
# - static
|
||||
# - frequency
|
||||
def set_analysis_type(self, analysis_type=None):
|
||||
if analysis_type is not None:
|
||||
self.analysis_type = analysis_type
|
||||
else:
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
self.analysis_type = self.fem_prefs.GetString("AnalysisType", "static")
|
||||
|
||||
## Sets working dir for ccx execution. Called with no working_dir uses WorkingDir from FEM preferences
|
||||
# @param self The python object self
|
||||
# @working_dir directory to be used for writing .inp file and executing CalculiX ccx
|
||||
def setup_working_dir(self, working_dir=None):
|
||||
import os
|
||||
if working_dir is not None:
|
||||
self.working_dir = working_dir
|
||||
else:
|
||||
self.working_dir = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").GetString("WorkingDir")
|
||||
|
||||
if not (os.path.isdir(self.working_dir)):
|
||||
try:
|
||||
os.makedirs(self.working_dir)
|
||||
except:
|
||||
print ("Dir \'{}\' doesn't exist and cannot be created.".format(self.working_dir))
|
||||
import tempfile
|
||||
self.working_dir = tempfile.gettempdir()
|
||||
print ("Dir \'{}\' will be used instead.".format(self.working_dir))
|
||||
# Update inp file name
|
||||
self.set_inp_file_name()
|
||||
|
||||
def setup_ccx(self, ccx_binary=None):
|
||||
## Sets CalculiX ccx binary path and velidates if the binary can be executed
|
||||
# @param self The python object self
|
||||
# @ccx_binary path to ccx binary, default is guessed: "bin/ccx" windows, "ccx" for other systems
|
||||
# @ccx_binary_sig expected output form ccx when run empty. Default value is "CalculiX.exe -i jobname"
|
||||
def setup_ccx(self, ccx_binary=None, ccx_binary_sig="CalculiX"):
|
||||
if not ccx_binary:
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
ccx_binary = self.fem_prefs.GetString("ccxBinaryPath", "")
|
||||
|
@ -282,8 +352,23 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
else:
|
||||
ccx_binary = "ccx"
|
||||
self.ccx_binary = ccx_binary
|
||||
import subprocess
|
||||
try:
|
||||
p = subprocess.Popen([self.ccx_binary], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=False)
|
||||
ccx_stdout, ccx_stderr = p.communicate()
|
||||
if ccx_binary_sig in ccx_stdout:
|
||||
self.ccx_binary_present = True
|
||||
except OSError, e:
|
||||
FreeCAD.Console.PrintError(e.message)
|
||||
if e.errno == 2:
|
||||
raise Exception("FEM: CalculiX binary ccx \'{}\' not found. Please set it in FEM preferences.".format(ccx_binary))
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintError(e.message)
|
||||
raise Exception("FEM: CalculiX ccx \'{}\' output \'{}\' doesn't contain expected phrase \'{}\'. Please use ccx 2.6 or newer".
|
||||
format(ccx_binary, ccx_stdout, ccx_binary_sig))
|
||||
|
||||
## Load results of ccx calculiations from .frd file.
|
||||
## Load results of ccx calculations from .frd file.
|
||||
# @param self The python object self
|
||||
def load_results(self):
|
||||
import ccxFrdReader
|
||||
|
@ -306,7 +391,7 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
self.result_object = m
|
||||
break
|
||||
if not self.result_object:
|
||||
raise ("{} doesn't exist".format(results_name))
|
||||
raise Exception("{} doesn't exist".format(results_name))
|
||||
|
||||
def run(self):
|
||||
ret_code = 0
|
||||
|
@ -330,9 +415,13 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
|
|||
print self.ccx_stdout
|
||||
print "--------end of stdout---------"
|
||||
|
||||
## returns minimum, average and maximum value for provided result type
|
||||
## Returns minimum, average and maximum value for provided result type
|
||||
# @param self The python object self
|
||||
# @result_type Type of FEM result, allowed U1, U2, U3, Uabs, Sabs and None
|
||||
# @param result_type Type of FEM result, allowed are:
|
||||
# - U1, U2, U3 - deformation
|
||||
# - Uabs - absolute deformation
|
||||
# - Sabs - Von Mises stress
|
||||
# - None - always return (0.0, 0.0, 0.0)
|
||||
def get_stats(self, result_type):
|
||||
stats = (0.0, 0.0, 0.0)
|
||||
for m in self.analysis.Member:
|
||||
|
|
|
@ -105,7 +105,6 @@ void FemGuiExport initFemGui()
|
|||
Base::Interpreter().loadModule("FemCommands");
|
||||
|
||||
Base::Interpreter().loadModule("_CommandMechanicalShowResult");
|
||||
Base::Interpreter().loadModule("_CommandFrequencyAnalysis");
|
||||
Base::Interpreter().loadModule("_CommandQuickAnalysis");
|
||||
Base::Interpreter().loadModule("_CommandPurgeFemResults");
|
||||
Base::Interpreter().loadModule("_CommandMechanicalJobControl");
|
||||
|
|
|
@ -240,7 +240,7 @@ void CmdFemConstraintBearing::activated(int iMsg)
|
|||
|
||||
bool CmdFemConstraintBearing::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject();
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
@ -278,7 +278,7 @@ void CmdFemConstraintFixed::activated(int iMsg)
|
|||
|
||||
bool CmdFemConstraintFixed::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject();
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
@ -317,7 +317,7 @@ void CmdFemConstraintForce::activated(int iMsg)
|
|||
|
||||
bool CmdFemConstraintForce::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject();
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
@ -357,7 +357,7 @@ void CmdFemConstraintPressure::activated(int iMsg)
|
|||
|
||||
bool CmdFemConstraintPressure::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject();
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
@ -395,7 +395,7 @@ void CmdFemConstraintGear::activated(int iMsg)
|
|||
|
||||
bool CmdFemConstraintGear::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject();
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
@ -438,7 +438,7 @@ void CmdFemConstraintPulley::activated(int iMsg)
|
|||
|
||||
bool CmdFemConstraintPulley::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject();
|
||||
}
|
||||
|
||||
// #####################################################################################################
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>555</width>
|
||||
<height>429</height>
|
||||
<height>453</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -193,6 +193,73 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_analysis_params">
|
||||
<property name="title">
|
||||
<string>Default analysis type</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="Gui::PrefComboBox" name="cb_analysis_type">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>148</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Default type on analysis</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>AnalysisType</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Fem</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Static</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/Fem.qrc">
|
||||
<normaloff>:/icons/fem-new-analysis.svg</normaloff>:/icons/fem-new-analysis.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/Fem.qrc">
|
||||
<normaloff>:/icons/fem-frequency-analysis.svg</normaloff>:/icons/fem-frequency-analysis.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_materials">
|
||||
<property name="title">
|
||||
|
@ -336,6 +403,11 @@
|
|||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Resources/Fem.qrc"/>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "Gui/Application.h"
|
||||
#include "DlgSettingsFemImp.h"
|
||||
#include <Gui/PrefWidgets.h>
|
||||
|
||||
|
@ -43,10 +44,15 @@ DlgSettingsFemImp::~DlgSettingsFemImp()
|
|||
|
||||
void DlgSettingsFemImp::saveSettings()
|
||||
{
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Mod/Fem");
|
||||
hGrp->SetInt("AnalysisType", cb_analysis_type->currentIndex());
|
||||
|
||||
fc_ccx_working_directory->onSave();
|
||||
cb_int_editor->onSave();
|
||||
fc_ext_editor->onSave();
|
||||
fc_ccx_binary->onSave();
|
||||
cb_analysis_type->onSave();
|
||||
cb_use_built_in_materials->onSave();
|
||||
cb_use_mat_from_config_dir->onSave();
|
||||
cb_use_mat_from_custom_dir->onSave();
|
||||
|
@ -59,10 +65,16 @@ void DlgSettingsFemImp::loadSettings()
|
|||
cb_int_editor->onRestore();
|
||||
fc_ext_editor->onRestore();
|
||||
fc_ccx_binary->onRestore();
|
||||
cb_analysis_type->onRestore();
|
||||
cb_use_built_in_materials->onRestore();
|
||||
cb_use_mat_from_config_dir->onRestore();
|
||||
cb_use_mat_from_custom_dir->onRestore();
|
||||
fc_custom_mat_dir->onRestore();
|
||||
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Mod/Fem");
|
||||
int index = hGrp->GetInt("AnalysisType", 0);
|
||||
if (index > -1) cb_analysis_type->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,7 +83,9 @@ void DlgSettingsFemImp::loadSettings()
|
|||
void DlgSettingsFemImp::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
int c_index = cb_analysis_type->currentIndex();
|
||||
retranslateUi(this);
|
||||
cb_analysis_type->setCurrentIndex(c_index);
|
||||
}
|
||||
else {
|
||||
QWidget::changeEvent(e);
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
#include <queue>
|
||||
#include <bitset>
|
||||
|
||||
// boost
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
|
|
@ -274,7 +274,7 @@ TaskDlgFemConstraintGear::TaskDlgFemConstraintGear(ViewProviderFemConstraintGear
|
|||
{
|
||||
this->ConstraintView = ConstraintView;
|
||||
assert(ConstraintView);
|
||||
this->parameter = new TaskFemConstraintGear(ConstraintView, 0, "Fem_ConstraintGear");
|
||||
this->parameter = new TaskFemConstraintGear(ConstraintView, 0, "fem-constraint-gear");
|
||||
|
||||
Content.push_back(parameter);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ using namespace Gui;
|
|||
/* TRANSLATOR FemGui::TaskFemConstraintPulley */
|
||||
|
||||
TaskFemConstraintPulley::TaskFemConstraintPulley(ViewProviderFemConstraintPulley *ConstraintView,QWidget *parent)
|
||||
: TaskFemConstraintGear(ConstraintView, parent, "Fem_ConstraintPulley")
|
||||
: TaskFemConstraintGear(ConstraintView, parent, "fem-constraint-pulley")
|
||||
{
|
||||
connect(ui->spinOtherDiameter, SIGNAL(valueChanged(double)),
|
||||
this, SLOT(onOtherDiameterChanged(double)));
|
||||
|
|
|
@ -25,12 +25,16 @@
|
|||
|
||||
#ifndef _PreComp_
|
||||
# include <Standard_math.hxx>
|
||||
# include <boost/bind.hpp>
|
||||
# include <QAction>
|
||||
# include <QMenu>
|
||||
#endif
|
||||
|
||||
#include "ViewProviderAnalysis.h"
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/ActionFunction.h>
|
||||
|
||||
#include <Mod/Fem/App/FemAnalysis.h>
|
||||
#include <Mod/Fem/App/FemMeshObject.h>
|
||||
|
@ -43,10 +47,7 @@
|
|||
using namespace FemGui;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TRANSLATOR FemGui::ViewProviderFemAnalysis */
|
||||
|
||||
PROPERTY_SOURCE(FemGui::ViewProviderFemAnalysis, Gui::ViewProviderDocumentObject)
|
||||
|
||||
|
@ -85,10 +86,9 @@ std::vector<App::DocumentObject*> ViewProviderFemAnalysis::claimChildren(void)co
|
|||
|
||||
void ViewProviderFemAnalysis::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
|
||||
{
|
||||
//QAction* act;
|
||||
//act = menu->addAction(QObject::tr("Edit pad"), receiver, member);
|
||||
//act->setData(QVariant((int)ViewProvider::Default));
|
||||
//PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member);
|
||||
Gui::ActionFunction* func = new Gui::ActionFunction(menu);
|
||||
QAction* act = menu->addAction(tr("Activate analysis"));
|
||||
func->trigger(act, boost::bind(&ViewProviderFemAnalysis::doubleClicked, this));
|
||||
}
|
||||
|
||||
bool ViewProviderFemAnalysis::setEdit(int ModNum)
|
||||
|
@ -119,11 +119,10 @@ bool ViewProviderFemAnalysis::setEdit(int ModNum)
|
|||
// Gui::Control().showDialog(padDlg);
|
||||
// else
|
||||
|
||||
Fem::FemAnalysis* pcAna = static_cast<Fem::FemAnalysis*>(this->getObject());
|
||||
|
||||
Gui::Control().showDialog(new TaskDlgAnalysis(pcAna));
|
||||
|
||||
return true;
|
||||
//Fem::FemAnalysis* pcAna = static_cast<Fem::FemAnalysis*>(this->getObject());
|
||||
//Gui::Control().showDialog(new TaskDlgAnalysis(pcAna));
|
||||
//return true;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return Gui::ViewProviderDocumentObject::setEdit(ModNum);
|
||||
|
@ -176,6 +175,8 @@ bool ViewProviderFemAnalysis::canDragObject(App::DocumentObject* obj) const
|
|||
return true;
|
||||
else if (obj->getTypeId().isDerivedFrom(Fem::FemSetObject::getClassTypeId()))
|
||||
return true;
|
||||
else if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Fem::FeaturePython")))
|
||||
return true;
|
||||
else if (obj->getTypeId().isDerivedFrom(App::MaterialObject::getClassTypeId()))
|
||||
return true;
|
||||
else
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <Gui/ViewProviderGeometryObject.h>
|
||||
#include <Gui/ViewProviderBuilder.h>
|
||||
#include <Gui/ViewProviderPythonFeature.h>
|
||||
#include <QCoreApplication>
|
||||
|
||||
class SoCoordinate3;
|
||||
class SoDrawStyle;
|
||||
|
@ -42,6 +43,7 @@ namespace FemGui
|
|||
|
||||
class FemGuiExport ViewProviderFemAnalysis : public Gui::ViewProviderDocumentObject
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(FemGui::ViewProviderFemAnalysis)
|
||||
PROPERTY_HEADER(FemGui::ViewProviderAnalysis);
|
||||
|
||||
public:
|
||||
|
|
|
@ -72,7 +72,6 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
<< "Separator"
|
||||
<< "Fem_MechanicalJobControl"
|
||||
<< "Fem_Quick_Analysis"
|
||||
<< "Fem_Frequency_Analysis"
|
||||
<< "Fem_PurgeResults"
|
||||
<< "Fem_ShowResult";
|
||||
return root;
|
||||
|
@ -102,7 +101,6 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "Separator"
|
||||
<< "Fem_MechanicalJobControl"
|
||||
<< "Fem_Quick_Analysis"
|
||||
<< "Fem_Frequency_Analysis"
|
||||
<< "Fem_PurgeResults"
|
||||
<< "Fem_ShowResult";
|
||||
|
||||
|
|
|
@ -52,9 +52,29 @@ class FemWorkbench (Workbench):
|
|||
ccx_path = p1.stdout.read().split('\n')[0]
|
||||
elif system() == 'Windows':
|
||||
ccx_path = FreeCAD.getHomePath() + 'bin/ccx.exe'
|
||||
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").SetString("ccxBinaryPath", ccx_path)
|
||||
if ccx_path:
|
||||
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").SetString("ccxBinaryPath", ccx_path)
|
||||
else:
|
||||
FreeCAD.Console.PrintError("CalculiX ccx binary not found! Please set it manually in FEM preferences.\n")
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintError(e.message)
|
||||
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
|
||||
import os
|
||||
working_dir = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").GetString("WorkingDir")
|
||||
if not (os.path.isdir(working_dir)):
|
||||
try:
|
||||
os.makedirs(working_dir)
|
||||
except:
|
||||
print ("Dir \'{}\' from FEM preferences doesn't exist and cannot be created.".format(working_dir))
|
||||
import tempfile
|
||||
working_dir = tempfile.gettempdir()
|
||||
print ("Dir \'{}\' will be used instead.".format(working_dir))
|
||||
if working_dir:
|
||||
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").SetString("WorkingDir", working_dir)
|
||||
else:
|
||||
FreeCAD.Console.PrintError("Setting working directory \'{}\' for ccx failed!\n")
|
||||
|
||||
|
||||
def GetClassName(self):
|
||||
return "FemGui::Workbench"
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>193</width>
|
||||
<height>384</height>
|
||||
<width>258</width>
|
||||
<height>458</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -15,56 +15,103 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="le_working_dir">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<widget class="QGroupBox" name="gb_working_dir">
|
||||
<property name="title">
|
||||
<string>Working directory</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="le_working_dir">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="tb_choose_working_dir">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_analysis_type">
|
||||
<property name="title">
|
||||
<string>Analysis type</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="Gui::PrefRadioButton" name="rb_static_analysis">
|
||||
<property name="text">
|
||||
<string>Static</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefRadioButton" name="rb_frequency_analysis">
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gl_actions">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="pb_write_inp">
|
||||
<property name="text">
|
||||
<string>Write .inp file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="tb_choose_working_dir">
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pb_edit_inp">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<string>Edit .inp file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="pb_run_ccx">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Run Calculix</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_write">
|
||||
<property name="text">
|
||||
<string>Write Calculix Input File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_edit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit Calculix Input File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_generate">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Run Calculix</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit_Output">
|
||||
<property name="lineWrapMode">
|
||||
|
@ -73,7 +120,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_Time">
|
||||
<widget class="QLabel" name="l_time">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
|
@ -86,6 +133,13 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::PrefRadioButton</class>
|
||||
<extends>QRadioButton</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
# ***************************************************************************
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
|
@ -45,13 +46,15 @@ def makeMechanicalMaterial(name):
|
|||
return obj
|
||||
|
||||
|
||||
class _CommandMechanicalMaterial:
|
||||
class _CommandMechanicalMaterial(FemCommands):
|
||||
"the Fem Material command definition"
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'fem-material',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_Material", "Mechanical material..."),
|
||||
'Accel': "M, M",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_Material", "Creates or edit the mechanical material definition.")}
|
||||
def __init__(self):
|
||||
super(_CommandMechanicalMaterial, self).__init__()
|
||||
self.resources = {'Pixmap': 'fem-material',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_Material", "Mechanical material..."),
|
||||
'Accel': "M, M",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_Material", "Creates or edit the mechanical material definition.")}
|
||||
self.is_active = 'with_analysis'
|
||||
|
||||
def Activated(self):
|
||||
MatObj = None
|
||||
|
@ -60,6 +63,9 @@ class _CommandMechanicalMaterial:
|
|||
MatObj = i
|
||||
|
||||
if (not MatObj):
|
||||
femDoc = FemGui.getActiveAnalysis().Document
|
||||
if FreeCAD.ActiveDocument is not femDoc:
|
||||
FreeCADGui.setActiveDocument(femDoc)
|
||||
FreeCAD.ActiveDocument.openTransaction("Create Material")
|
||||
FreeCADGui.addModule("MechanicalMaterial")
|
||||
FreeCADGui.doCommand("MechanicalMaterial.makeMechanicalMaterial('MechanicalMaterial')")
|
||||
|
@ -67,14 +73,10 @@ class _CommandMechanicalMaterial:
|
|||
FreeCADGui.doCommand("Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name,0)")
|
||||
# FreeCADGui.doCommand("Fem.makeMaterial()")
|
||||
else:
|
||||
if FreeCAD.ActiveDocument is not MatObj.Document:
|
||||
FreeCADGui.setActiveDocument(MatObj.Document)
|
||||
FreeCADGui.doCommand("Gui.activeDocument().setEdit('" + MatObj.Name + "',0)")
|
||||
|
||||
def IsActive(self):
|
||||
if FemGui.getActiveAnalysis():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class _MechanicalMaterial:
|
||||
"The Material object"
|
||||
|
@ -153,11 +155,13 @@ class _MechanicalMaterialTaskPanel:
|
|||
|
||||
def accept(self):
|
||||
self.obj.Material = self.material
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
doc = FreeCADGui.getDocument(self.obj.Document)
|
||||
doc.resetEdit()
|
||||
doc.Document.recompute()
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
doc = FreeCADGui.getDocument(self.obj.Document)
|
||||
doc.resetEdit()
|
||||
|
||||
def goMatWeb(self):
|
||||
import webbrowser
|
||||
|
|
|
@ -117,9 +117,11 @@ class FemTest(unittest.TestCase):
|
|||
|
||||
def compare_inp_files(self, file_name1, file_name2):
|
||||
file1 = open(file_name1, 'r')
|
||||
file2 = open(file_name2, 'r')
|
||||
f1 = file1.readlines()
|
||||
file1.close()
|
||||
file2 = open(file_name2, 'r')
|
||||
f2 = file2.readlines()
|
||||
file2.close()
|
||||
lf1 = [l for l in f1 if not l.startswith('** written ')]
|
||||
lf2 = [l for l in f2 if not l.startswith('** written ')]
|
||||
import difflib
|
||||
|
@ -127,8 +129,8 @@ class FemTest(unittest.TestCase):
|
|||
result = ''
|
||||
for l in diff:
|
||||
result += l
|
||||
file1.close()
|
||||
file2.close()
|
||||
if result:
|
||||
result = "Comparing {} to {} failed!\n".format(file_name1, file_name2) + result
|
||||
return result
|
||||
|
||||
def compare_stats(self, fea, stat_file=None):
|
||||
|
@ -179,17 +181,21 @@ class FemTest(unittest.TestCase):
|
|||
self.assertTrue(self.pressure_constraint, "FemTest of new pressure constraint failed")
|
||||
self.analysis.Member = self.analysis.Member + [self.pressure_constraint]
|
||||
|
||||
fea = FemTools.FemTools(self.analysis)
|
||||
fcc_print('Checking FEM inp file prerequisites...')
|
||||
fea = FemTools.FemTools(self.analysis, test_mode=True)
|
||||
fcc_print('Setting up working directory {}'.format(static_analysis_dir))
|
||||
fea.setup_working_dir(static_analysis_dir)
|
||||
self.assertTrue(True if fea.working_dir == static_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(static_analysis_dir))
|
||||
|
||||
fcc_print('Checking FEM inp file prerequisites for static analysis...')
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(error, "FemTools check_prerequisites returned error message: {}".format(error))
|
||||
|
||||
fcc_print('Checking FEM inp file write...')
|
||||
|
||||
fcc_print('Setting up working directory {}'.format(static_analysis_dir))
|
||||
fea.setup_working_dir(static_analysis_dir)
|
||||
self.assertTrue(True if fea.working_dir == static_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(static_analysis_dir))
|
||||
fcc_print('Setting analysis type to \'static\"')
|
||||
fea.set_analysis_type("static")
|
||||
self.assertTrue(True if fea.analysis_type == 'static' else False, "Setting anlysis type to \'static\' failed")
|
||||
|
||||
fcc_print('Writing {}/{}.inp for static analysis'.format(static_analysis_dir, mesh_name))
|
||||
error = fea.write_inp_file()
|
||||
|
@ -232,6 +238,10 @@ class FemTest(unittest.TestCase):
|
|||
self.assertTrue(True if fea.working_dir == frequency_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(frequency_analysis_dir))
|
||||
|
||||
fcc_print('Checking FEM inp file prerequisites for frequency analysis...')
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(error, "FemTools check_prerequisites returned error message: {}".format(error))
|
||||
|
||||
fcc_print('Writing {}/{}.inp for frequency analysis'.format(frequency_analysis_dir, mesh_name))
|
||||
error = fea.write_inp_file()
|
||||
self.assertFalse(error, "Writing failed")
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2013-2015 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
__title__ = "Command Frequency Analysis"
|
||||
__author__ = "Juergen Riegel"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
from FemTools import FemTools
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
|
||||
|
||||
class _CommandFrequencyAnalysis(FemCommands):
|
||||
def __init__(self):
|
||||
super(_CommandFrequencyAnalysis, self).__init__()
|
||||
self.resources = {'Pixmap': 'fem-frequency-analysis',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_Frequency_Analysis", "Run frequency analysis with CalculiX ccx"),
|
||||
'Accel': "R, F",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_Frequency_Analysis", "Write .inp file and run frequency analysis with CalculiX ccx")}
|
||||
self.is_active = 'with_analysis'
|
||||
|
||||
def Activated(self):
|
||||
def load_results(ret_code):
|
||||
if ret_code == 0:
|
||||
self.fea.load_results()
|
||||
else:
|
||||
print "CalculiX failed ccx finished with error {}".format(ret_code)
|
||||
|
||||
self.fea = FemTools()
|
||||
self.fea.reset_all()
|
||||
self.fea.set_analysis_type('frequency')
|
||||
message = self.fea.check_prerequisites()
|
||||
if message:
|
||||
QtGui.QMessageBox.critical(None, "Missing prerequisite", message)
|
||||
return
|
||||
self.fea.finished.connect(load_results)
|
||||
QtCore.QThreadPool.globalInstance().start(self.fea)
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Fem_Frequency_Analysis', _CommandFrequencyAnalysis())
|
|
@ -46,7 +46,6 @@ class _CommandNewMechanicalAnalysis(FemCommands):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create Analysis")
|
||||
FreeCADGui.addModule("FemGui")
|
||||
FreeCADGui.addModule("MechanicalAnalysis")
|
||||
#FreeCADGui.doCommand("FreeCADGui.ActiveDocument.ActiveView.setAxisCross(True)")
|
||||
FreeCADGui.doCommand("MechanicalAnalysis.makeMechanicalAnalysis('MechanicalAnalysis')")
|
||||
FreeCADGui.doCommand("FemGui.setActiveAnalysis(App.activeDocument().ActiveObject)")
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
|
@ -57,12 +56,7 @@ class _CommandNewMechanicalAnalysis(FemCommands):
|
|||
FreeCADGui.doCommand("App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject', '" + sel[0].Name + "_Mesh')")
|
||||
FreeCADGui.doCommand("App.activeDocument().ActiveObject.Shape = App.activeDocument()." + sel[0].Name)
|
||||
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [App.activeDocument().ActiveObject]")
|
||||
#FreeCADGui.doCommand("Gui.activeDocument().hide('" + sel[0].Name + "')")
|
||||
#FreeCADGui.doCommand("App.activeDocument().ActiveObject.touch()")
|
||||
#FreeCADGui.doCommand("App.activeDocument().recompute()")
|
||||
FreeCADGui.doCommand("Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name)")
|
||||
|
||||
#FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
|
|
|
@ -48,7 +48,7 @@ class _CommandQuickAnalysis(FemCommands):
|
|||
self.fea.load_results()
|
||||
self.show_results_on_mesh()
|
||||
else:
|
||||
print "CalculiX failed ccx finished with error {}".format(ret_code)
|
||||
print ("CalculiX failed ccx finished with error {}".format(ret_code))
|
||||
|
||||
self.fea = FemTools()
|
||||
self.fea.reset_all()
|
||||
|
|
|
@ -24,13 +24,20 @@ __title__ = "Fem Analysis"
|
|||
__author__ = "Juergen Riegel"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemTools import FemTools
|
||||
|
||||
|
||||
class _FemAnalysis:
|
||||
"The FemAnalysis container object"
|
||||
def __init__(self, obj):
|
||||
self.Type = "FemAnalysis"
|
||||
obj.Proxy = self
|
||||
obj.addProperty("App::PropertyString", "OutputDir", "Base", "Directory where the jobs get generated")
|
||||
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
obj.addProperty("App::PropertyEnumeration", "AnalysisType", "Fem", "Type of the analysis")
|
||||
obj.AnalysisType = FemTools.known_analysis_types
|
||||
analysis_type = fem_prefs.GetInt("AnalysisType", 0)
|
||||
obj.AnalysisType = FemTools.known_analysis_types[analysis_type]
|
||||
|
||||
def execute(self, obj):
|
||||
return
|
||||
|
|
|
@ -45,7 +45,7 @@ class _JobControlTaskPanel:
|
|||
ccx_binary = self.fem_prefs.GetString("ccxBinaryPath", "")
|
||||
if ccx_binary:
|
||||
self.CalculixBinary = ccx_binary
|
||||
print "Using ccx binary path from FEM preferences: {}".format(ccx_binary)
|
||||
print ("Using ccx binary path from FEM preferences: {}".format(ccx_binary))
|
||||
else:
|
||||
from platform import system
|
||||
if system() == 'Linux':
|
||||
|
@ -58,6 +58,7 @@ class _JobControlTaskPanel:
|
|||
self.working_dir = self.fem_prefs.GetString("WorkingDir", '/tmp')
|
||||
|
||||
self.analysis_object = analysis_object
|
||||
|
||||
self.Calculix = QtCore.QProcess()
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(300)
|
||||
|
@ -66,9 +67,11 @@ class _JobControlTaskPanel:
|
|||
|
||||
#Connect Signals and Slots
|
||||
QtCore.QObject.connect(self.form.tb_choose_working_dir, QtCore.SIGNAL("clicked()"), self.choose_working_dir)
|
||||
QtCore.QObject.connect(self.form.pushButton_write, QtCore.SIGNAL("clicked()"), self.write_input_file_handler)
|
||||
QtCore.QObject.connect(self.form.pushButton_edit, QtCore.SIGNAL("clicked()"), self.editCalculixInputFile)
|
||||
QtCore.QObject.connect(self.form.pushButton_generate, QtCore.SIGNAL("clicked()"), self.runCalculix)
|
||||
QtCore.QObject.connect(self.form.pb_write_inp, QtCore.SIGNAL("clicked()"), self.write_input_file_handler)
|
||||
QtCore.QObject.connect(self.form.pb_edit_inp, QtCore.SIGNAL("clicked()"), self.editCalculixInputFile)
|
||||
QtCore.QObject.connect(self.form.pb_run_ccx, QtCore.SIGNAL("clicked()"), self.runCalculix)
|
||||
QtCore.QObject.connect(self.form.rb_static_analysis, QtCore.SIGNAL("clicked()"), self.select_static_analysis)
|
||||
QtCore.QObject.connect(self.form.rb_frequency_analysis, QtCore.SIGNAL("clicked()"), self.select_frequency_analysis)
|
||||
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("started()"), self.calculixStarted)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("stateChanged(QProcess::ProcessState)"), self.calculixStateChanged)
|
||||
|
@ -106,16 +109,16 @@ class _JobControlTaskPanel:
|
|||
|
||||
def UpdateText(self):
|
||||
if(self.Calculix.state() == QtCore.QProcess.ProcessState.Running):
|
||||
self.form.label_Time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def calculixError(self, error):
|
||||
print "Error()", error
|
||||
print ("Error() {}".format(error))
|
||||
self.femConsoleMessage("CalculiX execute error: {}".format(error), "#FF0000")
|
||||
|
||||
def calculixStarted(self):
|
||||
print "calculixStarted()"
|
||||
print self.Calculix.state()
|
||||
self.form.pushButton_generate.setText("Break Calculix")
|
||||
print ("calculixStarted()")
|
||||
print (self.Calculix.state())
|
||||
self.form.pb_run_ccx.setText("Break CalculiX")
|
||||
|
||||
def calculixStateChanged(self, newState):
|
||||
if (newState == QtCore.QProcess.ProcessState.Starting):
|
||||
|
@ -126,8 +129,8 @@ class _JobControlTaskPanel:
|
|||
self.femConsoleMessage("CalculiX stopped.")
|
||||
|
||||
def calculixFinished(self, exitCode):
|
||||
print "calculixFinished()", exitCode
|
||||
print self.Calculix.state()
|
||||
print ("calculixFinished() {}".format(exitCode))
|
||||
print (self.Calculix.state())
|
||||
|
||||
# Restore previous cwd
|
||||
QtCore.QDir.setCurrent(self.cwd)
|
||||
|
@ -137,10 +140,9 @@ class _JobControlTaskPanel:
|
|||
|
||||
self.femConsoleMessage("Calculix done!", "#00AA00")
|
||||
|
||||
self.form.pushButton_generate.setText("Re-run Calculix")
|
||||
print "Loading results...."
|
||||
self.form.pb_run_ccx.setText("Re-run CalculiX")
|
||||
self.femConsoleMessage("Loading result sets...")
|
||||
self.form.label_Time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
fea = FemTools()
|
||||
fea.reset_all()
|
||||
frd_result_file = os.path.splitext(self.inp_file_name)[0] + '.frd'
|
||||
|
@ -151,7 +153,7 @@ class _JobControlTaskPanel:
|
|||
self.femConsoleMessage("Loading results done!", "#00AA00")
|
||||
else:
|
||||
self.femConsoleMessage("Loading results failed! Results file doesn\'t exist", "#FF0000")
|
||||
self.form.label_Time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
@ -159,6 +161,10 @@ class _JobControlTaskPanel:
|
|||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.le_working_dir.setText(self.working_dir)
|
||||
if self.analysis_object.AnalysisType == 'static':
|
||||
self.form.rb_static_analysis.setChecked(True)
|
||||
elif self.analysis_object.AnalysisType == 'frequency':
|
||||
self.form.rb_frequency_analysis.setChecked(True)
|
||||
return
|
||||
|
||||
def accept(self):
|
||||
|
@ -168,13 +174,14 @@ class _JobControlTaskPanel:
|
|||
FreeCADGui.Control.closeDialog()
|
||||
|
||||
def choose_working_dir(self):
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
self.working_dir = QtGui.QFileDialog.getExistingDirectory(None,
|
||||
'Choose CalculiX working directory',
|
||||
self.fem_prefs.GetString("WorkingDir", '/tmp'))
|
||||
if self.working_dir:
|
||||
self.fem_prefs.SetString("WorkingDir", str(self.working_dir))
|
||||
self.form.le_working_dir.setText(self.working_dir)
|
||||
current_wd = get_working_dir()
|
||||
wd = QtGui.QFileDialog.getExistingDirectory(None, 'Choose CalculiX working directory',
|
||||
current_wd)
|
||||
if wd:
|
||||
self.analysis_object.WorkingDir = wd
|
||||
else:
|
||||
self.analysis_object.WorkingDir = current_wd
|
||||
self.form.le_working_dir.setText(self.analysis_object.WorkingDir)
|
||||
|
||||
def write_input_file_handler(self):
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
@ -182,13 +189,14 @@ class _JobControlTaskPanel:
|
|||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
self.inp_file_name = ""
|
||||
fea = FemTools()
|
||||
fea.set_analysis_type(self.analysis_object.AnalysisType)
|
||||
fea.update_objects()
|
||||
fea.write_inp_file()
|
||||
if fea.inp_file_name != "":
|
||||
self.inp_file_name = fea.inp_file_name
|
||||
self.femConsoleMessage("Write completed.")
|
||||
self.form.pushButton_edit.setEnabled(True)
|
||||
self.form.pushButton_generate.setEnabled(True)
|
||||
self.form.pb_edit_inp.setEnabled(True)
|
||||
self.form.pb_run_ccx.setEnabled(True)
|
||||
else:
|
||||
self.femConsoleMessage("Write .inp file failed!", "#FF0000")
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
@ -196,7 +204,7 @@ class _JobControlTaskPanel:
|
|||
def check_prerequisites_helper(self):
|
||||
self.Start = time.time()
|
||||
self.femConsoleMessage("Check dependencies...")
|
||||
self.form.label_Time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
fea = FemTools()
|
||||
fea.update_objects()
|
||||
|
@ -213,7 +221,7 @@ class _JobControlTaskPanel:
|
|||
self.ext_editor_process.start(ext_editor_path, [filename])
|
||||
|
||||
def editCalculixInputFile(self):
|
||||
print 'editCalculixInputFile {}'.format(self.inp_file_name)
|
||||
print ('editCalculixInputFile {}'.format(self.inp_file_name))
|
||||
if self.fem_prefs.GetBool("UseInternalEditor", True):
|
||||
FemGui.open(self.inp_file_name)
|
||||
else:
|
||||
|
@ -221,18 +229,18 @@ class _JobControlTaskPanel:
|
|||
if ext_editor_path:
|
||||
self.start_ext_editor(ext_editor_path, self.inp_file_name)
|
||||
else:
|
||||
print "External editor is not defined in FEM preferences. Falling back to internal editor"
|
||||
print ("External editor is not defined in FEM preferences. Falling back to internal editor")
|
||||
FemGui.open(self.inp_file_name)
|
||||
|
||||
def runCalculix(self):
|
||||
print 'runCalculix'
|
||||
print ('runCalculix')
|
||||
self.Start = time.time()
|
||||
|
||||
self.femConsoleMessage("CalculiX binary: {}".format(self.CalculixBinary))
|
||||
self.femConsoleMessage("Run Calculix...")
|
||||
|
||||
# run Calculix
|
||||
print 'run Calculix at: ', self.CalculixBinary, ' with: ', os.path.splitext(self.inp_file_name)[0]
|
||||
print ('run Calculix at: {} with: {}'.format(self.CalculixBinary, os.path.splitext(self.inp_file_name)[0]))
|
||||
# change cwd because ccx may crash if directory has no write permission
|
||||
# there is also a limit of the length of file names so jump to the document directory
|
||||
self.cwd = QtCore.QDir.currentPath()
|
||||
|
@ -241,3 +249,30 @@ class _JobControlTaskPanel:
|
|||
self.Calculix.start(self.CalculixBinary, ['-i', fi.baseName()])
|
||||
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def select_analysis_type(self, analysis_type):
|
||||
if self.analysis_object.AnalysisType != analysis_type:
|
||||
self.analysis_object.AnalysisType = analysis_type
|
||||
self.form.pb_edit_inp.setEnabled(False)
|
||||
self.form.pb_run_ccx.setEnabled(False)
|
||||
|
||||
def select_static_analysis(self):
|
||||
self.select_analysis_type('static')
|
||||
|
||||
def select_frequency_analysis(self):
|
||||
self.select_analysis_type('frequency')
|
||||
|
||||
|
||||
#Code duplication!!!!
|
||||
def get_working_dir():
|
||||
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
|
||||
working_dir = fem_prefs.GetString("WorkingDir", "")
|
||||
if not (os.path.isdir(working_dir)):
|
||||
try:
|
||||
os.path.makedirs(working_dir)
|
||||
except:
|
||||
print ("Dir \'{}\' from FEM preferences doesn't exist and cannot be created.".format(working_dir))
|
||||
import tempfile
|
||||
working_dir = tempfile.gettempdir()
|
||||
print ("Dir \'{}\' will be used instead.".format(working_dir))
|
||||
return working_dir
|
||||
|
|
|
@ -290,51 +290,58 @@ void PropertyPartShape::SaveDocFile (Base::Writer &writer) const
|
|||
shape.exportBinary(writer.Stream());
|
||||
}
|
||||
else {
|
||||
// create a temporary file and copy the content to the zip stream
|
||||
// once the tmp. filename is known use always the same because otherwise
|
||||
// we may run into some problems on the Linux platform
|
||||
static Base::FileInfo fi(App::Application::getTempFileName());
|
||||
bool direct = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Mod/Part/General")->GetBool("DirectAccess", false);
|
||||
if (!direct) {
|
||||
// create a temporary file and copy the content to the zip stream
|
||||
// once the tmp. filename is known use always the same because otherwise
|
||||
// we may run into some problems on the Linux platform
|
||||
static Base::FileInfo fi(App::Application::getTempFileName());
|
||||
|
||||
if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) {
|
||||
// Note: Do NOT throw an exception here because if the tmp. file could
|
||||
// not be created we should not abort.
|
||||
// We only print an error message but continue writing the next files to the
|
||||
// stream...
|
||||
App::PropertyContainer* father = this->getContainer();
|
||||
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
|
||||
Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n",
|
||||
obj->Label.getValue(),fi.filePath().c_str());
|
||||
}
|
||||
else {
|
||||
Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
|
||||
if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) {
|
||||
// Note: Do NOT throw an exception here because if the tmp. file could
|
||||
// not be created we should not abort.
|
||||
// We only print an error message but continue writing the next files to the
|
||||
// stream...
|
||||
App::PropertyContainer* father = this->getContainer();
|
||||
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
|
||||
Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n",
|
||||
obj->Label.getValue(),fi.filePath().c_str());
|
||||
}
|
||||
else {
|
||||
Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Cannot save BRep file '" << fi.filePath() << "'";
|
||||
writer.addError(ss.str());
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Cannot save BRep file '" << fi.filePath() << "'";
|
||||
writer.addError(ss.str());
|
||||
Base::ifstream file(fi, std::ios::in | std::ios::binary);
|
||||
if (file){
|
||||
unsigned long ulSize = 0;
|
||||
std::streambuf* buf = file.rdbuf();
|
||||
if (buf) {
|
||||
unsigned long ulCurr;
|
||||
ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
|
||||
ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
|
||||
buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
|
||||
}
|
||||
|
||||
// read in the ASCII file and write back to the stream
|
||||
std::strstreambuf sbuf(ulSize);
|
||||
file >> &sbuf;
|
||||
writer.Stream() << &sbuf;
|
||||
}
|
||||
|
||||
file.close();
|
||||
// remove temp file
|
||||
fi.deleteFile();
|
||||
}
|
||||
|
||||
Base::ifstream file(fi, std::ios::in | std::ios::binary);
|
||||
if (file){
|
||||
unsigned long ulSize = 0;
|
||||
std::streambuf* buf = file.rdbuf();
|
||||
if (buf) {
|
||||
unsigned long ulCurr;
|
||||
ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
|
||||
ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
|
||||
buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
|
||||
}
|
||||
|
||||
// read in the ASCII file and write back to the stream
|
||||
std::strstreambuf sbuf(ulSize);
|
||||
file >> &sbuf;
|
||||
writer.Stream() << &sbuf;
|
||||
else {
|
||||
BRepTools::Write(myShape, writer.Stream());
|
||||
}
|
||||
|
||||
file.close();
|
||||
// remove temp file
|
||||
fi.deleteFile();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,47 +354,55 @@ void PropertyPartShape::RestoreDocFile(Base::Reader &reader)
|
|||
setValue(shape);
|
||||
}
|
||||
else {
|
||||
BRep_Builder builder;
|
||||
bool direct = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Mod/Part/General")->GetBool("DirectAccess", false);
|
||||
if (!direct) {
|
||||
BRep_Builder builder;
|
||||
// create a temporary file and copy the content from the zip stream
|
||||
Base::FileInfo fi(App::Application::getTempFileName());
|
||||
|
||||
// create a temporary file and copy the content from the zip stream
|
||||
Base::FileInfo fi(App::Application::getTempFileName());
|
||||
// read in the ASCII file and write back to the file stream
|
||||
Base::ofstream file(fi, std::ios::out | std::ios::binary);
|
||||
unsigned long ulSize = 0;
|
||||
if (reader) {
|
||||
std::streambuf* buf = file.rdbuf();
|
||||
reader >> buf;
|
||||
file.flush();
|
||||
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
|
||||
}
|
||||
file.close();
|
||||
|
||||
// read in the ASCII file and write back to the file stream
|
||||
Base::ofstream file(fi, std::ios::out | std::ios::binary);
|
||||
unsigned long ulSize = 0;
|
||||
if (reader) {
|
||||
std::streambuf* buf = file.rdbuf();
|
||||
reader >> buf;
|
||||
file.flush();
|
||||
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
|
||||
}
|
||||
file.close();
|
||||
|
||||
// Read the shape from the temp file, if the file is empty the stored shape was already empty.
|
||||
// If it's still empty after reading the (non-empty) file there must occurred an error.
|
||||
TopoDS_Shape shape;
|
||||
if (ulSize > 0) {
|
||||
if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) {
|
||||
// Note: Do NOT throw an exception here because if the tmp. created file could
|
||||
// not be read it's NOT an indication for an invalid input stream 'reader'.
|
||||
// We only print an error message but continue reading the next files from the
|
||||
// stream...
|
||||
App::PropertyContainer* father = this->getContainer();
|
||||
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
|
||||
Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n",
|
||||
fi.filePath().c_str(),obj->Label.getValue());
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
|
||||
// Read the shape from the temp file, if the file is empty the stored shape was already empty.
|
||||
// If it's still empty after reading the (non-empty) file there must occurred an error.
|
||||
TopoDS_Shape shape;
|
||||
if (ulSize > 0) {
|
||||
if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) {
|
||||
// Note: Do NOT throw an exception here because if the tmp. created file could
|
||||
// not be read it's NOT an indication for an invalid input stream 'reader'.
|
||||
// We only print an error message but continue reading the next files from the
|
||||
// stream...
|
||||
App::PropertyContainer* father = this->getContainer();
|
||||
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
|
||||
Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n",
|
||||
fi.filePath().c_str(),obj->Label.getValue());
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete the temp file
|
||||
fi.deleteFile();
|
||||
setValue(shape);
|
||||
}
|
||||
else {
|
||||
BRep_Builder builder;
|
||||
TopoDS_Shape shape;
|
||||
BRepTools::Read(shape, reader, builder);
|
||||
setValue(shape);
|
||||
}
|
||||
|
||||
// delete the temp file
|
||||
fi.deleteFile();
|
||||
|
||||
setValue(shape);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#include <boost/progress.hpp>
|
||||
#include <boost/timer.hpp>
|
||||
|
|
|
@ -30,19 +30,17 @@
|
|||
#ifdef FC_OS_WIN32
|
||||
# define PointsExport __declspec(dllexport)
|
||||
#else // for Linux
|
||||
# define PointsExport
|
||||
# define PointsExport
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// here get the warnings of too long specifiers disabled (needed for VC6)
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( disable : 4251 )
|
||||
# pragma warning( disable : 4503 )
|
||||
# pragma warning( disable : 4275 )
|
||||
# pragma warning( disable : 4786 ) // specifier longer then 255 chars
|
||||
# pragma warning( disable : 4181 )
|
||||
# pragma warning( disable : 4305 )
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// standard
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4800)
|
||||
#endif
|
||||
|
||||
#include "svd_eigen_HH.hpp"
|
||||
|
||||
namespace KDL{
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <Eigen/QR>
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
#include "ViewProviderSketch.h"
|
||||
#include "DrawSketchHandler.h"
|
||||
#include "TaskDlgEditSketch.h"
|
||||
#include "TaskSketcherValidation.h"
|
||||
|
||||
// The first is used to point at a SoDatumLabel for some
|
||||
// constraints, and at a SoMaterial for others...
|
||||
|
@ -4151,7 +4152,7 @@ void ViewProviderSketch::attach(App::DocumentObject *pcFeat)
|
|||
|
||||
void ViewProviderSketch::setupContextMenu(QMenu *menu, QObject *receiver, const char *member)
|
||||
{
|
||||
menu->addAction(QObject::tr("Edit sketch"), receiver, member);
|
||||
menu->addAction(tr("Edit sketch"), receiver, member);
|
||||
}
|
||||
|
||||
bool ViewProviderSketch::setEdit(int ModNum)
|
||||
|
@ -4165,8 +4166,8 @@ bool ViewProviderSketch::setEdit(int ModNum)
|
|||
sketchDlg = 0; // another sketch left open its task panel
|
||||
if (dlg && !sketchDlg) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(QObject::tr("A dialog is already open in the task panel"));
|
||||
msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?"));
|
||||
msgBox.setText(tr("A dialog is already open in the task panel"));
|
||||
msgBox.setInformativeText(tr("Do you want to close this dialog?"));
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
msgBox.setDefaultButton(QMessageBox::Yes);
|
||||
int ret = msgBox.exec();
|
||||
|
@ -4178,8 +4179,21 @@ bool ViewProviderSketch::setEdit(int ModNum)
|
|||
|
||||
Sketcher::SketchObject* sketch = getSketchObject();
|
||||
if (!sketch->evaluateConstraints()) {
|
||||
QMessageBox::critical(Gui::getMainWindow(), tr("Invalid sketch"),
|
||||
tr("The sketch is invalid and cannot be edited.\nUse the sketch validation tool."));
|
||||
QMessageBox box(Gui::getMainWindow());
|
||||
box.setIcon(QMessageBox::Critical);
|
||||
box.setWindowTitle(tr("Invalid sketch"));
|
||||
box.setText(tr("Do you want to open the sketch validation tool?"));
|
||||
box.setInformativeText(tr("The sketch is invalid and cannot be edited."));
|
||||
box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
box.setDefaultButton(QMessageBox::Yes);
|
||||
switch (box.exec())
|
||||
{
|
||||
case QMessageBox::Yes:
|
||||
Gui::Control().showDialog(new TaskSketcherValidation(getSketchObject()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
|
||||
#if defined(_MSC_VER)
|
||||
#define strtoll _strtoi64
|
||||
#pragma warning(disable : 4003)
|
||||
#pragma warning(disable : 4065)
|
||||
#endif
|
||||
|
||||
using namespace App;
|
||||
|
|
|
@ -179,6 +179,13 @@ class ParameterTestCase(unittest.TestCase):
|
|||
self.failUnless(b.XLength==0,"X length > 0")
|
||||
self.failUnless(b.YLength==0,"Y length > 0")
|
||||
self.failUnless(b.ZLength==0,"Z length > 0")
|
||||
self.failUnless(b.Center==FreeCAD.Vector(0,0,0),"Center is not at (0,0,0)")
|
||||
self.failUnless(b.isInside(b.Center),"Center is not inside Bbox")
|
||||
b.add(2,2,2)
|
||||
self.failUnless(b.isInside(b.getIntersectionPoint(b.Center,FreeCAD.Vector(0,1,0))),"Intersection point is not inside Bbox")
|
||||
self.failUnless(b.intersect(b),"Bbox doesn't intersect with itself")
|
||||
self.failUnless(not b.intersected(FreeCAD.BoundBox(4,4,4,6,6,6)).isValid(),"Bbox should not intersect with Bbox outside")
|
||||
self.failUnless(b.intersected(FreeCAD.BoundBox(-2,-2,-2,2,2,2)).Center == b.Center,"Bbox is not a full subset")
|
||||
|
||||
def testNesting(self):
|
||||
# Parameter testing
|
||||
|
|
|
@ -79,41 +79,6 @@ private:
|
|||
return Py::None();
|
||||
}
|
||||
};
|
||||
/*
|
||||
static PyObject* addTest(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *pstr=0;
|
||||
if (!PyArg_ParseTuple(args, "|s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
TestGui::UnitTestDialog* dlg = TestGui::UnitTestDialog::instance();
|
||||
if (pstr)
|
||||
dlg->addUnitTest(QString::fromLatin1(pstr));
|
||||
dlg->show();
|
||||
dlg->raise();
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
static PyObject* setTest(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *pstr=0;
|
||||
if (!PyArg_ParseTuple(args, "|s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
TestGui::UnitTestDialog* dlg = TestGui::UnitTestDialog::instance();
|
||||
if (pstr)
|
||||
dlg->setUnitTest(QString::fromLatin1(pstr));
|
||||
dlg->show();
|
||||
dlg->raise();
|
||||
Py_Return;
|
||||
}
|
||||
*/
|
||||
/* registration table */
|
||||
//static struct PyMethodDef TestGui_methods[] = {
|
||||
// {"addTest", addTest, 1},
|
||||
// {"setTest", setTest, 1},
|
||||
// {NULL, NULL} /* end of table marker */
|
||||
//};
|
||||
|
||||
void loadTestResource()
|
||||
{
|
||||
|
@ -130,10 +95,6 @@ void AppTestGuiExport initQtUnitGui()
|
|||
// with the Python runtime system
|
||||
(void)new UnitTestModule;
|
||||
|
||||
//if(PyType_Ready(&TestGui::UnitTestPy::Type) < 0) return;
|
||||
//PyObject* pyModule = Py_InitModule("QtUnitGui", TestGui_methods); /* mod name, table ptr */
|
||||
//union PyType_Object pyDlgType = {&TestGui::UnitTestPy::Type};
|
||||
//PyModule_AddObject(pyModule, "UnitTest", pyDlgType.o);
|
||||
Base::Console().Log("Loading GUI of Test module... done\n");
|
||||
|
||||
// add resources and reloads the translators
|
||||
|
|
|
@ -117,7 +117,22 @@ void UnitTestDialog::setProgressColor(const QColor& col)
|
|||
*/
|
||||
void UnitTestDialog::on_treeViewFailure_itemDoubleClicked(QTreeWidgetItem * item, int column)
|
||||
{
|
||||
QMessageBox::information(this, item->text(0), item->data(0, Qt::UserRole).toString());
|
||||
QString text = item->data(0, Qt::UserRole).toString();
|
||||
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setIcon(QMessageBox::Information);
|
||||
msgBox.setWindowTitle(item->text(0));
|
||||
msgBox.setDetailedText(text);
|
||||
|
||||
// truncate the visible text when it's too long
|
||||
if (text.count(QLatin1Char('\n')) > 20) {
|
||||
QStringList lines = text.split(QLatin1Char('\n'));
|
||||
lines.erase(lines.begin()+20, lines.end());
|
||||
text = lines.join(QLatin1String("\n"));
|
||||
}
|
||||
|
||||
msgBox.setText(text);
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,6 +244,14 @@ void UnitTestDialog::setUnitTest(const QString& unit)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the unit tests.
|
||||
*/
|
||||
void UnitTestDialog::clearUnitTests()
|
||||
{
|
||||
this->comboTests->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unit test.
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
void showErrorDialog(const char* title, const char* message);
|
||||
void addUnitTest(const QString& unit);
|
||||
void setUnitTest(const QString& unit);
|
||||
void clearUnitTests();
|
||||
QString getUnitTest() const;
|
||||
void setStatusText(const QString& text);
|
||||
void setProgressFraction(float fraction, const QString& = QString::null);
|
||||
|
|
|
@ -55,6 +55,8 @@ void UnitTestDialogPy::init_type()
|
|||
add_varargs_method("setErrorCount",&UnitTestDialogPy::setErrorCount,"setErrorCount");
|
||||
add_varargs_method("setRemainCount",&UnitTestDialogPy::setRemainCount,"setRemainCount");
|
||||
add_varargs_method("updateGUI",&UnitTestDialogPy::updateGUI,"updateGUI");
|
||||
add_varargs_method("addUnitTest",&UnitTestDialogPy::addUnitTest,"addUnitTest");
|
||||
add_varargs_method("clearUnitTests",&UnitTestDialogPy::clearUnitTests,"clearUnitTests");
|
||||
}
|
||||
|
||||
UnitTestDialogPy::UnitTestDialogPy()
|
||||
|
@ -191,262 +193,25 @@ Py::Object UnitTestDialogPy::updateGUI(const Py::Tuple& args)
|
|||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), ""))
|
||||
throw Py::Exception();
|
||||
qApp->processEvents();
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Type structure
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
PyTypeObject TestGui::UnitTestPy::Type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /*ob_size*/
|
||||
"TestGui.UnitTest", /*tp_name*/
|
||||
sizeof(UnitTestPy), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
PyDestructor, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
__getattr, /*tp_getattr*/
|
||||
__setattr, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
__repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call */
|
||||
0, /*tp_str */
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
/* --- Functions to access object as input/output buffer ---------*/
|
||||
0, /* tp_as_buffer */
|
||||
/* --- Flags to define presence of optional/expanded features */
|
||||
Py_TPFLAGS_HAVE_CLASS, /*tp_flags */
|
||||
"About TestGui.UnitTest", /*tp_doc */
|
||||
0, /*tp_traverse */
|
||||
0, /*tp_clear */
|
||||
0, /*tp_richcompare */
|
||||
0, /*tp_weaklistoffset */
|
||||
0, /*tp_iter */
|
||||
0, /*tp_iternext */
|
||||
0, /*tp_methods */
|
||||
0, /*tp_members */
|
||||
0, /*tp_getset */
|
||||
&Base::PyObjectBase::Type, /*tp_base */
|
||||
0, /*tp_dict */
|
||||
0, /*tp_descr_get */
|
||||
0, /*tp_descr_set */
|
||||
0, /*tp_dictoffset */
|
||||
0, /*tp_init */
|
||||
0, /*tp_alloc */
|
||||
UnitTestPy::PyMake, /*tp_new */
|
||||
0, /*tp_free Low-level free-memory routine */
|
||||
0, /*tp_is_gc For PyObject_IS_GC */
|
||||
0, /*tp_bases */
|
||||
0, /*tp_mro method resolution order */
|
||||
0, /*tp_cache */
|
||||
0, /*tp_subclasses */
|
||||
0 /*tp_weaklist */
|
||||
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Methods structure
|
||||
//--------------------------------------------------------------------------
|
||||
PyMethodDef TestGui::UnitTestPy::Methods[] = {
|
||||
PYMETHODEDEF(clearErrorList)
|
||||
PYMETHODEDEF(insertError)
|
||||
PYMETHODEDEF(setUnitTest)
|
||||
PYMETHODEDEF(getUnitTest)
|
||||
PYMETHODEDEF(setStatusText)
|
||||
PYMETHODEDEF(setProgressFraction)
|
||||
PYMETHODEDEF(errorDialog)
|
||||
PYMETHODEDEF(setRunCount)
|
||||
PYMETHODEDEF(setFailCount)
|
||||
PYMETHODEDEF(setErrorCount)
|
||||
PYMETHODEDEF(setRemainCount)
|
||||
PYMETHODEDEF(updateGUI)
|
||||
{NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
TestGui::UnitTestPy::UnitTestPy(PyTypeObject *T)
|
||||
: PyObjectBase(0, T)
|
||||
Py::Object UnitTestDialogPy::addUnitTest(const Py::Tuple& args)
|
||||
{
|
||||
char *pstr;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr))
|
||||
throw Py::Exception();
|
||||
|
||||
TestGui::UnitTestDialog* dlg = TestGui::UnitTestDialog::instance();
|
||||
dlg->addUnitTest(QString::fromLatin1(pstr));
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
PyObject *UnitTestPy::PyMake(PyTypeObject *ignored, PyObject *args, PyObject *kwds) // Python wrapper
|
||||
Py::Object UnitTestDialogPy::clearUnitTests(const Py::Tuple& args)
|
||||
{
|
||||
return new UnitTestPy();
|
||||
if (!PyArg_ParseTuple(args.ptr(), ""))
|
||||
throw Py::Exception();
|
||||
UnitTestDialog::instance()->clearUnitTests();
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// destructor
|
||||
//--------------------------------------------------------------------------
|
||||
UnitTestPy::~UnitTestPy() // Everything handled in parent
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// UnitTestPy representation
|
||||
//--------------------------------------------------------------------------
|
||||
PyObject *UnitTestPy::_repr(void)
|
||||
{
|
||||
return Py_BuildValue("s", "UnitTest");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// UnitTestPy Attributes
|
||||
//--------------------------------------------------------------------------
|
||||
PyObject *UnitTestPy::_getattr(char *attr) // __getattr__ function: note only need to handle new state
|
||||
{
|
||||
_getattr_up(PyObjectBase);
|
||||
}
|
||||
|
||||
int UnitTestPy::_setattr(char *attr, PyObject *value) // __setattr__ function: note only need to handle new state
|
||||
{
|
||||
return PyObjectBase::_setattr(attr, value);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Python wrappers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,clearErrorList)
|
||||
{
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->clearErrorList();
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,insertError)
|
||||
{
|
||||
char *failure=0;
|
||||
char *details=0;
|
||||
if (!PyArg_ParseTuple(args, "ss", &failure,&details)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->insertError(QString::fromLatin1(failure),
|
||||
QString::fromLatin1(details));
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setUnitTest)
|
||||
{
|
||||
char *pstr=0;
|
||||
if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->setUnitTest(QString::fromLatin1(pstr));
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,getUnitTest)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
return Py_BuildValue("s", (const char*)UnitTestDialog::instance()->getUnitTest().toAscii());
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setStatusText)
|
||||
{
|
||||
char *pstr=0;
|
||||
if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->setStatusText(QString::fromLatin1(pstr));
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setProgressFraction)
|
||||
{
|
||||
float fraction;
|
||||
char* pColor=0;
|
||||
if (!PyArg_ParseTuple(args, "f|s",&fraction, &pColor)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
PY_TRY {
|
||||
if (pColor)
|
||||
UnitTestDialog::instance()->setProgressFraction(fraction,QString::fromLatin1(pColor));
|
||||
else
|
||||
UnitTestDialog::instance()->setProgressFraction(fraction);
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,errorDialog)
|
||||
{
|
||||
char *title=0;
|
||||
char *message=0;
|
||||
if (!PyArg_ParseTuple(args, "ss", &title, &message)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->showErrorDialog(title,message);
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setRunCount)
|
||||
{
|
||||
int count;
|
||||
if (!PyArg_ParseTuple(args, "i", &count)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->setRunCount(count);
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setFailCount)
|
||||
{
|
||||
int count;
|
||||
if (!PyArg_ParseTuple(args, "i", &count)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->setFailCount(count);
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setErrorCount)
|
||||
{
|
||||
int count;
|
||||
if (!PyArg_ParseTuple(args, "i", &count)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->setErrorCount(count);
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,setRemainCount)
|
||||
{
|
||||
int count;
|
||||
if (!PyArg_ParseTuple(args, "i", &count)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
PY_TRY {
|
||||
UnitTestDialog::instance()->setRemainCount(count);
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
PYFUNCIMP_D(UnitTestPy,updateGUI)
|
||||
{
|
||||
PY_TRY {
|
||||
qApp->processEvents();
|
||||
Py_Return;
|
||||
}PY_CATCH;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ public:
|
|||
Py::Object setErrorCount (const Py::Tuple&);
|
||||
Py::Object setRemainCount (const Py::Tuple&);
|
||||
Py::Object updateGUI (const Py::Tuple&);
|
||||
Py::Object addUnitTest (const Py::Tuple&);
|
||||
Py::Object clearUnitTests (const Py::Tuple&);
|
||||
|
||||
private:
|
||||
typedef PyObject* (*method_varargs_handler)(PyObject *_self, PyObject *_args);
|
||||
|
@ -63,43 +65,6 @@ private:
|
|||
static PyObject *method_varargs_ext_handler(PyObject *_self, PyObject *_args);
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// UnitTestPy - Python wrapper
|
||||
//===========================================================================
|
||||
|
||||
class UnitTestPy :public Base::PyObjectBase
|
||||
{
|
||||
Py_Header;
|
||||
|
||||
protected:
|
||||
~UnitTestPy();
|
||||
|
||||
public:
|
||||
UnitTestPy(PyTypeObject *T = &Type);
|
||||
static PyObject *PyMake(PyTypeObject *, PyObject *, PyObject *);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// python exports goes here +++++++++++++++++++++++++++++++++++++++++++
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
virtual PyObject *_repr(void); // the representation
|
||||
PyObject *_getattr(char *attr); // __getattr__ function
|
||||
int _setattr(char *attr, PyObject *value); // __setattr__ function
|
||||
|
||||
PYFUNCDEF_D(UnitTestPy,clearErrorList)
|
||||
PYFUNCDEF_D(UnitTestPy,insertError)
|
||||
PYFUNCDEF_D(UnitTestPy,setUnitTest)
|
||||
PYFUNCDEF_D(UnitTestPy,getUnitTest)
|
||||
PYFUNCDEF_D(UnitTestPy,setStatusText)
|
||||
PYFUNCDEF_D(UnitTestPy,setProgressFraction)
|
||||
PYFUNCDEF_D(UnitTestPy,errorDialog)
|
||||
PYFUNCDEF_D(UnitTestPy,setRunCount)
|
||||
PYFUNCDEF_D(UnitTestPy,setFailCount)
|
||||
PYFUNCDEF_D(UnitTestPy,setErrorCount)
|
||||
PYFUNCDEF_D(UnitTestPy,setRemainCount)
|
||||
PYFUNCDEF_D(UnitTestPy,updateGUI)
|
||||
};
|
||||
|
||||
} //namespace TESTGUI_UNITTESTPY_H
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ def Test(s):
|
|||
|
||||
|
||||
def testAll():
|
||||
TestText(All())
|
||||
r = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
|
||||
r.run(All())
|
||||
|
||||
|
||||
def testUnit():
|
||||
|
|
Loading…
Reference in New Issue
Block a user