diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt
index f81e27ed8f..0b90e1748d 100755
--- a/src/Mod/Fem/App/CMakeLists.txt
+++ b/src/Mod/Fem/App/CMakeLists.txt
@@ -83,6 +83,7 @@ SET(FemScripts_SRCS
MechanicalMaterial.py
ShowDisplacement.ui
_ResultControlTaskPanel.py
+ _JobControlTaskPanel.py
)
#SOURCE_GROUP("Scripts" FILES ${FemScripts_SRCS})
diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt
index d2c4ef75ab..5edbf56b3c 100755
--- a/src/Mod/Fem/CMakeLists.txt
+++ b/src/Mod/Fem/CMakeLists.txt
@@ -25,6 +25,7 @@ INSTALL(
MechanicalAnalysis.ui
ShowDisplacement.ui
_ResultControlTaskPanel.py
+ _JobControlTaskPanel.py
DESTINATION
Mod/Fem
)
diff --git a/src/Mod/Fem/MechanicalAnalysis.py b/src/Mod/Fem/MechanicalAnalysis.py
index 94dca52046..d8be50e441 100644
--- a/src/Mod/Fem/MechanicalAnalysis.py
+++ b/src/Mod/Fem/MechanicalAnalysis.py
@@ -20,18 +20,13 @@
#* *
#***************************************************************************
-import ccxFrdReader
import FreeCAD
from FemTools import FemTools
-import os
-import time
if FreeCAD.GuiUp:
import FreeCADGui
import FemGui
from PySide import QtCore, QtGui
- from PySide.QtCore import Qt
- from PySide.QtGui import QApplication
__title__ = "Mechanical Analysis managment"
__author__ = "Juergen Riegel"
@@ -117,7 +112,8 @@ class _CommandMechanicalJobControl:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_JobControl", "Dialog to start the calculation of the mechanical anlysis")}
def Activated(self):
- taskd = _JobControlTaskPanel(FemGui.getActiveAnalysis())
+ import _JobControlTaskPanel
+ taskd = _JobControlTaskPanel._JobControlTaskPanel(FemGui.getActiveAnalysis())
#taskd.obj = vobj.Object
taskd.update()
FreeCADGui.Control.showDialog(taskd)
@@ -277,7 +273,8 @@ class _ViewProviderFemAnalysis:
FemGui.setActiveAnalysis(self.Object)
return True
else:
- taskd = _JobControlTaskPanel(self.Object)
+ import _JobControlTaskPanel
+ taskd = _JobControlTaskPanel._JobControlTaskPanel(self.Object)
FreeCADGui.Control.showDialog(taskd)
return True
@@ -288,211 +285,6 @@ class _ViewProviderFemAnalysis:
return None
-class _JobControlTaskPanel:
- def __init__(self, analysis_object):
- self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/MechanicalAnalysis.ui")
- self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
- 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)
- else:
- from platform import system
- if system() == 'Linux':
- self.CalculixBinary = 'ccx'
- elif system() == 'Windows':
- self.CalculixBinary = FreeCAD.getHomePath() + 'bin/ccx.exe'
- else:
- self.CalculixBinary = 'ccx'
- self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
- 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)
-
- self.fem_console_message = ''
-
- #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.Calculix, QtCore.SIGNAL("started()"), self.calculixStarted)
- QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("stateChanged(QProcess::ProcessState)"), self.calculixStateChanged)
- QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("error(QProcess::ProcessError)"), self.calculixError)
- QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("finished(int)"), self.calculixFinished)
-
- QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.UpdateText)
-
- self.update()
-
- def femConsoleMessage(self, message="", color="#000000"):
- self.fem_console_message = self.fem_console_message + '{0:4.1f}: {2}
'.\
- format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
- self.form.textEdit_Output.setText(self.fem_console_message)
- self.form.textEdit_Output.moveCursor(QtGui.QTextCursor.End)
-
- def printCalculiXstdout(self):
- out = self.Calculix.readAllStandardOutput()
- if out.isEmpty():
- self.femConsoleMessage("CalculiX stdout is empty", "#FF0000")
- else:
- try:
- out = unicode(out, 'utf-8', 'replace')
- rx = QtCore.QRegExp("\\*ERROR.*\\n\\n")
- rx.setMinimal(True)
- pos = rx.indexIn(out)
- while not pos < 0:
- match = rx.cap(0)
- FreeCAD.Console.PrintError(match.strip().replace('\n', ' ') + '\n')
- pos = rx.indexIn(out, pos + 1)
- out = os.linesep.join([s for s in out.splitlines() if s])
- self.femConsoleMessage(out.replace('\n', '
'))
- except UnicodeDecodeError:
- self.femConsoleMessage("Error converting stdout from CalculiX", "#FF0000")
-
- 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))
-
- def calculixError(self, error):
- print "Error()", 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")
-
- def calculixStateChanged(self, newState):
- if (newState == QtCore.QProcess.ProcessState.Starting):
- self.femConsoleMessage("Starting CalculiX...")
- if (newState == QtCore.QProcess.ProcessState.Running):
- self.femConsoleMessage("CalculiX is running...")
- if (newState == QtCore.QProcess.ProcessState.NotRunning):
- self.femConsoleMessage("CalculiX stopped.")
-
- def calculixFinished(self, exitCode):
- print "calculixFinished()", exitCode
- print self.Calculix.state()
-
- # Restore previous cwd
- QtCore.QDir.setCurrent(self.cwd)
-
- self.printCalculiXstdout()
- self.Timer.stop()
-
- self.femConsoleMessage("Calculix done!", "#00AA00")
-
- self.form.pushButton_generate.setText("Re-run Calculix")
- print "Loading results...."
- self.femConsoleMessage("Loading result sets...")
- self.form.label_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'
- if os.path.isfile(frd_result_file):
- QApplication.setOverrideCursor(Qt.WaitCursor)
- ccxFrdReader.importFrd(frd_result_file, FemGui.getActiveAnalysis())
- QApplication.restoreOverrideCursor()
- 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))
-
- def getStandardButtons(self):
- return int(QtGui.QDialogButtonBox.Close)
-
- def update(self):
- 'fills the widgets'
- self.form.le_working_dir.setText(self.working_dir)
- return
-
- def accept(self):
- FreeCADGui.Control.closeDialog()
-
- def reject(self):
- 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)
-
- def write_input_file_handler(self):
- QApplication.restoreOverrideCursor()
- if self.check_prerequisites_helper():
- QApplication.setOverrideCursor(Qt.WaitCursor)
- self.inp_file_name = ""
- fea = FemTools()
- 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)
- else:
- self.femConsoleMessage("Write .inp file failed!", "#FF0000")
- QApplication.restoreOverrideCursor()
-
- 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))
-
- fea = FemTools()
- fea.update_objects()
- message = fea.check_prerequisites()
- if message != "":
- QtGui.QMessageBox.critical(None, "Missing prerequisit(s)", message)
- return False
- return True
-
- def start_ext_editor(self, ext_editor_path, filename):
- if not hasattr(self, "ext_editor_process"):
- self.ext_editor_process = QtCore.QProcess()
- if self.ext_editor_process.state() != QtCore.QProcess.Running:
- self.ext_editor_process.start(ext_editor_path, [filename])
-
- def editCalculixInputFile(self):
- print 'editCalculixInputFile {}'.format(self.inp_file_name)
- if self.fem_prefs.GetBool("UseInternalEditor", True):
- FemGui.open(self.inp_file_name)
- else:
- ext_editor_path = self.fem_prefs.GetString("ExternalEditorPath", "")
- 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"
- FemGui.open(self.inp_file_name)
-
- def runCalculix(self):
- 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]
- # 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()
- fi = QtCore.QFileInfo(self.inp_file_name)
- QtCore.QDir.setCurrent(fi.path())
- self.Calculix.start(self.CalculixBinary, ['-i', fi.baseName()])
-
- QApplication.restoreOverrideCursor()
-
-
# Helpers
diff --git a/src/Mod/Fem/_JobControlTaskPanel.py b/src/Mod/Fem/_JobControlTaskPanel.py
new file mode 100644
index 0000000000..735ec70be8
--- /dev/null
+++ b/src/Mod/Fem/_JobControlTaskPanel.py
@@ -0,0 +1,217 @@
+from FemTools import FemTools
+import FreeCAD
+import ccxFrdReader
+import os
+import time
+
+if FreeCAD.GuiUp:
+ import FreeCADGui
+ import FemGui
+ from PySide import QtCore, QtGui
+ from PySide.QtCore import Qt
+ from PySide.QtGui import QApplication
+
+
+class _JobControlTaskPanel:
+ def __init__(self, analysis_object):
+ self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/MechanicalAnalysis.ui")
+ self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
+ 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)
+ else:
+ from platform import system
+ if system() == 'Linux':
+ self.CalculixBinary = 'ccx'
+ elif system() == 'Windows':
+ self.CalculixBinary = FreeCAD.getHomePath() + 'bin/ccx.exe'
+ else:
+ self.CalculixBinary = 'ccx'
+ self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
+ 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)
+
+ self.fem_console_message = ''
+
+ #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.Calculix, QtCore.SIGNAL("started()"), self.calculixStarted)
+ QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("stateChanged(QProcess::ProcessState)"), self.calculixStateChanged)
+ QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("error(QProcess::ProcessError)"), self.calculixError)
+ QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("finished(int)"), self.calculixFinished)
+
+ QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.UpdateText)
+
+ self.update()
+
+ def femConsoleMessage(self, message="", color="#000000"):
+ self.fem_console_message = self.fem_console_message + '{0:4.1f}: {2}
'.\
+ format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
+ self.form.textEdit_Output.setText(self.fem_console_message)
+ self.form.textEdit_Output.moveCursor(QtGui.QTextCursor.End)
+
+ def printCalculiXstdout(self):
+ out = self.Calculix.readAllStandardOutput()
+ if out.isEmpty():
+ self.femConsoleMessage("CalculiX stdout is empty", "#FF0000")
+ else:
+ try:
+ out = unicode(out, 'utf-8', 'replace')
+ rx = QtCore.QRegExp("\\*ERROR.*\\n\\n")
+ rx.setMinimal(True)
+ pos = rx.indexIn(out)
+ while not pos < 0:
+ match = rx.cap(0)
+ FreeCAD.Console.PrintError(match.strip().replace('\n', ' ') + '\n')
+ pos = rx.indexIn(out, pos + 1)
+ out = os.linesep.join([s for s in out.splitlines() if s])
+ self.femConsoleMessage(out.replace('\n', '
'))
+ except UnicodeDecodeError:
+ self.femConsoleMessage("Error converting stdout from CalculiX", "#FF0000")
+
+ 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))
+
+ def calculixError(self, error):
+ print "Error()", 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")
+
+ def calculixStateChanged(self, newState):
+ if (newState == QtCore.QProcess.ProcessState.Starting):
+ self.femConsoleMessage("Starting CalculiX...")
+ if (newState == QtCore.QProcess.ProcessState.Running):
+ self.femConsoleMessage("CalculiX is running...")
+ if (newState == QtCore.QProcess.ProcessState.NotRunning):
+ self.femConsoleMessage("CalculiX stopped.")
+
+ def calculixFinished(self, exitCode):
+ print "calculixFinished()", exitCode
+ print self.Calculix.state()
+
+ # Restore previous cwd
+ QtCore.QDir.setCurrent(self.cwd)
+
+ self.printCalculiXstdout()
+ self.Timer.stop()
+
+ self.femConsoleMessage("Calculix done!", "#00AA00")
+
+ self.form.pushButton_generate.setText("Re-run Calculix")
+ print "Loading results...."
+ self.femConsoleMessage("Loading result sets...")
+ self.form.label_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'
+ if os.path.isfile(frd_result_file):
+ QApplication.setOverrideCursor(Qt.WaitCursor)
+ ccxFrdReader.importFrd(frd_result_file, FemGui.getActiveAnalysis())
+ QApplication.restoreOverrideCursor()
+ 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))
+
+ def getStandardButtons(self):
+ return int(QtGui.QDialogButtonBox.Close)
+
+ def update(self):
+ 'fills the widgets'
+ self.form.le_working_dir.setText(self.working_dir)
+ return
+
+ def accept(self):
+ FreeCADGui.Control.closeDialog()
+
+ def reject(self):
+ 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)
+
+ def write_input_file_handler(self):
+ QApplication.restoreOverrideCursor()
+ if self.check_prerequisites_helper():
+ QApplication.setOverrideCursor(Qt.WaitCursor)
+ self.inp_file_name = ""
+ fea = FemTools()
+ 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)
+ else:
+ self.femConsoleMessage("Write .inp file failed!", "#FF0000")
+ QApplication.restoreOverrideCursor()
+
+ 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))
+
+ fea = FemTools()
+ fea.update_objects()
+ message = fea.check_prerequisites()
+ if message != "":
+ QtGui.QMessageBox.critical(None, "Missing prerequisit(s)", message)
+ return False
+ return True
+
+ def start_ext_editor(self, ext_editor_path, filename):
+ if not hasattr(self, "ext_editor_process"):
+ self.ext_editor_process = QtCore.QProcess()
+ if self.ext_editor_process.state() != QtCore.QProcess.Running:
+ self.ext_editor_process.start(ext_editor_path, [filename])
+
+ def editCalculixInputFile(self):
+ print 'editCalculixInputFile {}'.format(self.inp_file_name)
+ if self.fem_prefs.GetBool("UseInternalEditor", True):
+ FemGui.open(self.inp_file_name)
+ else:
+ ext_editor_path = self.fem_prefs.GetString("ExternalEditorPath", "")
+ 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"
+ FemGui.open(self.inp_file_name)
+
+ def runCalculix(self):
+ 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]
+ # 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()
+ fi = QtCore.QFileInfo(self.inp_file_name)
+ QtCore.QDir.setCurrent(fi.path())
+ self.Calculix.start(self.CalculixBinary, ['-i', fi.baseName()])
+
+ QApplication.restoreOverrideCursor()