Merge pull request #23709 from marioalexis84/fem-solver_file_chooser

Fem: Fix use of file chooser Qt signals in solvers preferences.
This commit is contained in:
Chris Hennes
2025-09-22 10:41:42 -05:00
committed by GitHub
18 changed files with 133 additions and 607 deletions

View File

@@ -34,34 +34,8 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout" columnstretch="2,3">
<item row="2" column="0">
<widget class="QLabel" name="l_ccx_binary_std">
<property name="text">
<string>CalculiX binary</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::PrefCheckBox" name="cb_ccx_binary_std">
<property name="text">
<string>Search in known binary directories</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseStandardCcxLocation</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="l_ccx_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>100</width>
@@ -69,15 +43,12 @@
</size>
</property>
<property name="text">
<string>CCX binary path</string>
<string>CalculiX path</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::PrefFileChooser" name="fc_ccx_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<widget class="Gui::PrefFileChooser" name="fc_ccx_binary_path" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -968,37 +939,5 @@ Only takes effect if 'Pipeline only' is enabled</string>
</hint>
</hints>
</connection>
<connection>
<sender>cb_ccx_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>l_ccx_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>406</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>148</x>
<y>68</y>
</hint>
</hints>
</connection>
<connection>
<sender>cb_ccx_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>fc_ccx_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>406</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>406</x>
<y>68</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -26,6 +26,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QStandardPaths>
#include <QThread>
#endif
@@ -47,9 +48,9 @@ DlgSettingsFemCcxImp::DlgSettingsFemCcxImp(QWidget* parent)
ui->dsb_ccx_initial_time_increment->setMaximum(std::numeric_limits<float>::max());
connect(ui->fc_ccx_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
&Gui::PrefFileChooser::fileNameSelected,
this,
&DlgSettingsFemCcxImp::onfileNameChanged);
&DlgSettingsFemCcxImp::onfileNameSelected);
}
DlgSettingsFemCcxImp::~DlgSettingsFemCcxImp() = default;
@@ -83,7 +84,6 @@ void DlgSettingsFemCcxImp::saveSettings()
ui->cb_int_editor->onSave();
ui->fc_ext_editor->onSave();
ui->cb_ccx_binary_std->onSave();
ui->fc_ccx_binary_path->onSave();
ui->cb_split_inp_writer->onSave();
}
@@ -112,7 +112,6 @@ void DlgSettingsFemCcxImp::loadSettings()
ui->cb_int_editor->onRestore();
ui->fc_ext_editor->onRestore();
ui->cb_ccx_binary_std->onRestore();
ui->fc_ccx_binary_path->onRestore();
ui->cb_split_inp_writer->onRestore();
@@ -148,14 +147,10 @@ void DlgSettingsFemCcxImp::changeEvent(QEvent* e)
}
}
void DlgSettingsFemCcxImp::onfileNameChanged(QString FileName)
void DlgSettingsFemCcxImp::onfileNameSelected(const QString& fileName)
{
if (!QFileInfo::exists(FileName)) {
QMessageBox::critical(this,
tr("File does not exist"),
tr("The specified executable\n'%1'\n does not exist!\n"
"Specify another file.")
.arg(FileName));
if (!fileName.isEmpty() && QStandardPaths::findExecutable(fileName).isEmpty()) {
QMessageBox::critical(this, tr("CalculiX"), tr("Executable '%1' not found").arg(fileName));
}
}

View File

@@ -42,7 +42,7 @@ public:
~DlgSettingsFemCcxImp() override;
protected Q_SLOTS:
void onfileNameChanged(QString FileName);
void onfileNameSelected(const QString& fileName);
protected:
void saveSettings() override;

View File

@@ -33,17 +33,20 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="l_grid_binary_std">
<widget class="QLabel" name="l_elmer_binary_path">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>ElmerGrid</string>
<string>ElmerSolver path</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::PrefFileChooser" name="fc_elmer_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<item row="0" column="1">
<widget class="Gui::PrefFileChooser" name="fc_elmer_binary_path" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -69,7 +72,7 @@
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Leave blank to use default Elmer elmer binary file&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt; To use multithreading you must specify here&lt;br&gt; the executable variant with the suffix &amp;quot;_mpi&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Leave blank to use default ElmerSolver binary file</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>elmerBinaryPath</cstring>
@@ -79,27 +82,21 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::PrefCheckBox" name="cb_grid_binary_std">
<item row="1" column="0">
<widget class="QLabel" name="l_grid_binary_path">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Search in known binary directories</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseStandardGridLocation</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Elmer</cstring>
<string>ElmerGrid path</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefFileChooser" name="fc_grid_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<widget class="Gui::PrefFileChooser" name="fc_grid_binary_path" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -135,61 +132,6 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="l_elmer_binary_std">
<property name="text">
<string>ElmerSolver</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::PrefCheckBox" name="cb_elmer_binary_std">
<property name="text">
<string>Search in known binary directories</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseStandardElmerLocation</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Elmer</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="l_grid_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>ElmerGrid binary path</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="l_elmer_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>ElmerSolver binary path</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -198,40 +140,27 @@
<property name="title">
<string>Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="l_elmer_multithreading">
<property name="text">
<string>Multithreading</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_cores">
<property name="enabled">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="hbl_otions">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="l_num_processes">
<property name="text">
<string>CPU cores to be used</string>
<string>Number of processes</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefSpinBox" name="sb_elmer_num_cores">
<property name="enabled">
<bool>true</bool>
<item row="0" column="1">
<widget class="Gui::PrefSpinBox" name="sb_num_processes">
<property name="alignment">
<set>Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt; It is recommended to use an even number of cores to benefit from mesh symmetries. (Using 8 cores can be faster than 9 cores.)&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note too:&lt;/span&gt; In extreme cases ElmerSolver might not converge if the core number is too high.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Number of parallel tasks. Set to `1` if Elmer does not use MPI.&lt;br&gt;It is recommended to use an even number of cores to benefit from mesh symmetries&lt;br&gt;(Using 8 cores can be faster than 9 cores).&lt;br&gt;In extreme cases ElmerSolver might not converge if the core number is too high.</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>32</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseNumberOfCores</cstring>
</property>
@@ -240,48 +169,27 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="2" column="0">
<widget class="Gui::PrefCheckBox" name="cb_filtering">
<property name="toolTip">
<string>Merge mesh volume regions processed by each CPU core to make boundaries invisible.</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="text">
<string>Filter results</string>
</property>
</spacer>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>FilterMultiCPUResults</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Elmer</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="l_elmer_multiCPU">
<property name="text">
<string>Multi-core CPU support</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefCheckBox" name="cb_elmer_filtering">
<property name="toolTip">
<string>The mesh volume regions processed by each CPU core
will be merged to make the volume boundaries invisible.</string>
</property>
<property name="text">
<string>Filter results</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>FilterMultiCPUResults</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Elmer</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -292,7 +200,7 @@ will be merged to make the volume boundaries invisible.</string>
</property>
<layout class="QGridLayout" name="gdl_results">
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="ckb_elmer_format">
<widget class="Gui::PrefCheckBox" name="ckb_binary_format">
<property name="toolTip">
<string>Save result in binary format</string>
</property>
@@ -311,7 +219,7 @@ will be merged to make the volume boundaries invisible.</string>
</widget>
</item>
<item row="1" column="0">
<widget class="Gui::PrefCheckBox" name="ckb_elmer_geom_id">
<widget class="Gui::PrefCheckBox" name="ckb_geom_id">
<property name="toolTip">
<string>Save the index of geometric entities</string>
</property>
@@ -352,11 +260,6 @@ will be merged to make the volume boundaries invisible.</string>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>Gui::FileChooser</class>
<extends>QWidget</extends>
<header>Gui/FileDialog.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefFileChooser</class>
<extends>Gui::FileChooser</extends>
@@ -376,70 +279,4 @@ will be merged to make the volume boundaries invisible.</string>
<resources>
<include location="Resources/Fem.qrc"/>
</resources>
<connections>
<connection>
<sender>cb_grid_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>l_grid_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>247</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>71</x>
<y>68</y>
</hint>
</hints>
</connection>
<connection>
<sender>cb_grid_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>fc_grid_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>247</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>247</x>
<y>68</y>
</hint>
</hints>
</connection>
<connection>
<sender>cb_elmer_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>fc_elmer_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>247</x>
<y>91</y>
</hint>
<hint type="destinationlabel">
<x>247</x>
<y>114</y>
</hint>
</hints>
</connection>
<connection>
<sender>cb_elmer_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>l_elmer_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>247</x>
<y>91</y>
</hint>
<hint type="destinationlabel">
<x>71</x>
<y>114</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -25,7 +25,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QThread>
#include <QStandardPaths>
#endif
#include "DlgSettingsFemElmerImp.h"
@@ -40,56 +40,40 @@ DlgSettingsFemElmerImp::DlgSettingsFemElmerImp(QWidget* parent)
{
ui->setupUi(this);
// determine number of CPU cores
processor_count = QThread::idealThreadCount();
ui->sb_elmer_num_cores->setMaximum(processor_count);
connect(ui->fc_grid_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
&Gui::PrefFileChooser::fileNameSelected,
this,
&DlgSettingsFemElmerImp::onfileNameChanged);
&DlgSettingsFemElmerImp::onfileNameSelected);
connect(ui->fc_elmer_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
&Gui::PrefFileChooser::fileNameSelected,
this,
&DlgSettingsFemElmerImp::onfileNameChanged);
connect(ui->fc_elmer_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
this,
&DlgSettingsFemElmerImp::onfileNameChangedMT);
connect(ui->sb_elmer_num_cores,
qOverload<int>(&Gui::PrefSpinBox::valueChanged),
this,
&DlgSettingsFemElmerImp::onCoresValueChanged);
&DlgSettingsFemElmerImp::onfileNameSelected);
}
DlgSettingsFemElmerImp::~DlgSettingsFemElmerImp() = default;
void DlgSettingsFemElmerImp::saveSettings()
{
ui->cb_elmer_binary_std->onSave();
ui->fc_elmer_binary_path->onSave();
ui->cb_grid_binary_std->onSave();
ui->fc_grid_binary_path->onSave();
ui->sb_elmer_num_cores->onSave();
ui->cb_elmer_filtering->onSave();
ui->ckb_elmer_format->onSave();
ui->ckb_elmer_geom_id->onSave();
ui->sb_num_processes->onSave();
ui->cb_filtering->onSave();
ui->ckb_binary_format->onSave();
ui->ckb_geom_id->onSave();
}
void DlgSettingsFemElmerImp::loadSettings()
{
ui->cb_elmer_binary_std->onRestore();
ui->fc_elmer_binary_path->onRestore();
ui->cb_grid_binary_std->onRestore();
ui->fc_grid_binary_path->onRestore();
ui->sb_elmer_num_cores->onRestore();
ui->cb_elmer_filtering->onRestore();
ui->ckb_elmer_format->onRestore();
ui->ckb_elmer_geom_id->onRestore();
ui->sb_num_processes->onRestore();
ui->cb_filtering->onRestore();
ui->ckb_binary_format->onRestore();
ui->ckb_geom_id->onRestore();
}
/**
@@ -105,55 +89,10 @@ void DlgSettingsFemElmerImp::changeEvent(QEvent* e)
}
}
void DlgSettingsFemElmerImp::onfileNameChanged(QString FileName)
void DlgSettingsFemElmerImp::onfileNameSelected(const QString& fileName)
{
if (!QFileInfo::exists(FileName)) {
QMessageBox::critical(this,
tr("File does not exist"),
tr("The specified executable\n'%1'\n does not exist!\n"
"Specify another file.")
.arg(FileName));
}
}
void DlgSettingsFemElmerImp::onfileNameChangedMT(QString FileName)
{
ui->sb_elmer_num_cores->setMaximum(processor_count);
if (ui->sb_elmer_num_cores->value() == 1) {
return;
}
#if defined(FC_OS_WIN32)
// name ends with "_mpi.exe"
if (!FileName.endsWith(QLatin1String("_mpi.exe"))) {
QMessageBox::warning(this,
tr("FEM Elmer: Not suitable for multithreading"),
tr("Wrong Elmer setting: You use more than one CPU core.\n"
"Therefore an executable with the suffix '_mpi.exe' is required."));
ui->sb_elmer_num_cores->setValue(1);
ui->sb_elmer_num_cores->setMaximum(1);
return;
}
#elif defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
// name ends with "_mpi"
if (!FileName.endsWith(QLatin1String("_mpi"))) {
QMessageBox::warning(this,
tr("FEM Elmer: Not suitable for multithreading"),
tr("Wrong Elmer setting: You use more than one CPU core.\n"
"Therefore an executable with the suffix '_mpi' is required."));
ui->sb_elmer_num_cores->setValue(1);
ui->sb_elmer_num_cores->setMaximum(1);
return;
}
#endif
}
void DlgSettingsFemElmerImp::onCoresValueChanged(int cores)
{
if (cores > 1) {
// check if the right executable is loaded
onfileNameChangedMT(ui->fc_elmer_binary_path->fileName());
if (!fileName.isEmpty() && QStandardPaths::findExecutable(fileName).isEmpty()) {
QMessageBox::critical(this, tr("Elmer"), tr("Executable '%1' not found").arg(fileName));
}
}

View File

@@ -41,9 +41,7 @@ public:
~DlgSettingsFemElmerImp() override;
protected Q_SLOTS:
void onfileNameChanged(QString FileName);
void onfileNameChangedMT(QString FileName);
void onCoresValueChanged(int cores);
void onfileNameSelected(const QString& fileName);
protected:
void saveSettings() override;

View File

@@ -86,7 +86,7 @@
</size>
</property>
<property name="text">
<string>Gmsh binary path</string>
<string>Gmsh path</string>
</property>
</widget>
</item>

View File

@@ -83,15 +83,10 @@ void DlgSettingsFemGmshImp::changeEvent(QEvent* e)
}
}
void DlgSettingsFemGmshImp::onfileNameSelected(QString FileName)
void DlgSettingsFemGmshImp::onfileNameSelected(const QString& fileName)
{
if (!FileName.isEmpty() && QStandardPaths::findExecutable(FileName).isEmpty()) {
QMessageBox::critical(
this,
tr("Not an executable binary"),
tr("The specified file \n'%1'\n does not exist or is not executable.\n"
"Specify another file.")
.arg(FileName));
if (!fileName.isEmpty() && QStandardPaths::findExecutable(fileName).isEmpty()) {
QMessageBox::critical(this, tr("Gmsh"), tr("Executable '%1' not found").arg(fileName));
}
}

View File

@@ -41,7 +41,7 @@ public:
~DlgSettingsFemGmshImp() override;
protected Q_SLOTS:
void onfileNameSelected(QString FileName);
void onfileNameSelected(const QString& fileName);
protected:
void saveSettings() override;

View File

@@ -34,22 +34,6 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="Gui::PrefCheckBox" name="cb_mystran_binary_std">
<property name="text">
<string>Search in known binary directories</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseStandardMystranLocation</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Mystran</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="l_mystran_binary_path">
<property name="enabled">
@@ -62,15 +46,12 @@
</size>
</property>
<property name="text">
<string>Mystran binary path</string>
<string>Mystran path</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefFileChooser" name="fc_mystran_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<widget class="Gui::PrefFileChooser" name="fc_mystran_binary_path" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -96,7 +77,7 @@
</size>
</property>
<property name="toolTip">
<string>Leave blank to use default Mystran binary file location</string>
<string>Leave blank to use default mystran binary file</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>mystranBinaryPath</cstring>
@@ -170,38 +151,4 @@
<resources>
<include location="Resources/Fem.qrc"/>
</resources>
<connections>
<connection>
<sender>cb_mystran_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>l_mystran_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>406</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>148</x>
<y>68</y>
</hint>
</hints>
</connection>
<connection>
<sender>cb_mystran_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>fc_mystran_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>406</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>406</x>
<y>68</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -25,6 +25,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QStandardPaths>
#endif
#include "DlgSettingsFemMystranImp.h"
@@ -40,23 +41,21 @@ DlgSettingsFemMystranImp::DlgSettingsFemMystranImp(QWidget* parent)
ui->setupUi(this);
connect(ui->fc_mystran_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
&Gui::PrefFileChooser::fileNameSelected,
this,
&DlgSettingsFemMystranImp::onfileNameChanged);
&DlgSettingsFemMystranImp::onfileNameSelected);
}
DlgSettingsFemMystranImp::~DlgSettingsFemMystranImp() = default;
void DlgSettingsFemMystranImp::saveSettings()
{
ui->cb_mystran_binary_std->onSave();
ui->fc_mystran_binary_path->onSave();
ui->cb_mystran_write_comments->onSave();
}
void DlgSettingsFemMystranImp::loadSettings()
{
ui->cb_mystran_binary_std->onRestore();
ui->fc_mystran_binary_path->onRestore();
ui->cb_mystran_write_comments->onRestore();
}
@@ -74,14 +73,10 @@ void DlgSettingsFemMystranImp::changeEvent(QEvent* e)
}
}
void DlgSettingsFemMystranImp::onfileNameChanged(QString FileName)
void DlgSettingsFemMystranImp::onfileNameSelected(const QString& fileName)
{
if (!QFileInfo::exists(FileName)) {
QMessageBox::critical(this,
tr("File does not exist"),
tr("The specified executable\n'%1'\n does not exist!\n"
"Specify another file.")
.arg(FileName));
if (!fileName.isEmpty() && QStandardPaths::findExecutable(fileName).isEmpty()) {
QMessageBox::critical(this, tr("Mystran"), tr("Executable '%1' not found").arg(fileName));
}
}

View File

@@ -42,7 +42,7 @@ public:
~DlgSettingsFemMystranImp() override;
protected Q_SLOTS:
void onfileNameChanged(QString FileName);
void onfileNameSelected(const QString& fileName);
protected:
void saveSettings() override;

View File

@@ -34,33 +34,8 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gl_z88">
<item row="0" column="2">
<widget class="Gui::PrefCheckBox" name="cb_z88_binary_std">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Search in known binary directories</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseStandardZ88Location</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Z88</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="0" column="0">
<widget class="QLabel" name="l_z88_binary_path">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -74,15 +49,12 @@
</size>
</property>
<property name="text">
<string>z88r binary path</string>
<string>z88r path</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefFileChooser" name="fc_z88_binary_path">
<property name="enabled">
<bool>false</bool>
</property>
<item row="0" column="1">
<widget class="Gui::PrefFileChooser" name="fc_z88_binary_path" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -92,7 +64,7 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
<height>0</height>
</size>
</property>
<property name="sizeIncrement">
@@ -108,7 +80,7 @@
</size>
</property>
<property name="toolTip">
<string>Leave blank to use default Z88, z88r binary file</string>
<string>Leave blank to use default z88r binary file</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>z88BinaryPath</cstring>
@@ -332,38 +304,4 @@ that &quot;MAXKOI&quot; needs to be increased.</string>
<resources>
<include location="Resources/Fem.qrc"/>
</resources>
<connections>
<connection>
<sender>cb_z88_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>l_z88_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>406</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>148</x>
<y>68</y>
</hint>
</hints>
</connection>
<connection>
<sender>cb_z88_binary_std</sender>
<signal>toggled(bool)</signal>
<receiver>fc_z88_binary_path</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>406</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>406</x>
<y>68</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -25,6 +25,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QStandardPaths>
#endif
#include <Gui/Application.h>
@@ -42,16 +43,15 @@ DlgSettingsFemZ88Imp::DlgSettingsFemZ88Imp(QWidget* parent)
ui->setupUi(this);
connect(ui->fc_z88_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
&Gui::PrefFileChooser::fileNameSelected,
this,
&DlgSettingsFemZ88Imp::onfileNameChanged);
&DlgSettingsFemZ88Imp::onfileNameSelected);
}
DlgSettingsFemZ88Imp::~DlgSettingsFemZ88Imp() = default;
void DlgSettingsFemZ88Imp::saveSettings()
{
ui->cb_z88_binary_std->onSave();
ui->fc_z88_binary_path->onSave();
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
@@ -66,7 +66,6 @@ void DlgSettingsFemZ88Imp::saveSettings()
void DlgSettingsFemZ88Imp::loadSettings()
{
ui->cb_z88_binary_std->onRestore();
ui->fc_z88_binary_path->onRestore();
ui->cmb_solver->onRestore();
ui->sb_Z88_MaxGS->onRestore();
@@ -100,33 +99,11 @@ void DlgSettingsFemZ88Imp::changeEvent(QEvent* e)
}
}
void DlgSettingsFemZ88Imp::onfileNameChanged(QString FileName)
void DlgSettingsFemZ88Imp::onfileNameSelected(const QString& fileName)
{
if (!QFileInfo::exists(FileName)) {
QMessageBox::critical(this,
tr("File does not exist"),
tr("The specified z88r executable\n'%1'\n does not exist!\n"
"Specify another file.")
.arg(FileName));
return;
if (!fileName.isEmpty() && QStandardPaths::findExecutable(fileName).isEmpty()) {
QMessageBox::critical(this, tr("Z88"), tr("Executable '%1' not found").arg(fileName));
}
// since the Z88 folder is full of files like "z88h", "z88o" etc. one can easily make a
// mistake and is then lost why the solver fails. Therefore check for the correct filename.
auto strName = FileName.toStdString();
#if defined(FC_OS_WIN32)
if (strName.substr(strName.length() - 8) != "z88r.exe") {
QMessageBox::critical(this,
tr("Wrong file"),
tr("You must specify the path to the z88r.exe!"));
return;
}
#elif defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
if (strName.substr(strName.length() - 4) != "z88r") {
QMessageBox::critical(this, tr("Wrong file"), tr("You must specify the path to the z88r!"));
return;
}
#endif
}
#include "moc_DlgSettingsFemZ88Imp.cpp"

View File

@@ -42,7 +42,7 @@ public:
~DlgSettingsFemZ88Imp() override;
protected Q_SLOTS:
void onfileNameChanged(QString FileName);
void onfileNameSelected(const QString& fileName);
protected:
void saveSettings() override;

View File

@@ -214,10 +214,9 @@ class _SolverDlg:
WRITE_COMMENTS_PARAM = "writeCommentsToInputFile"
def __init__(self, default, param_path, use_default, custom_path):
def __init__(self, default, param_path, custom_path):
self.default = default
self.param_path = param_path
self.use_default = use_default
self.custom_path = custom_path
self.param_group = FreeCAD.ParamGet(self.param_path)
@@ -229,15 +228,11 @@ class _SolverDlg:
# TODO the binaries provided with the FreeCAD distribution should be found
# without any additional user input
# see ccxttols, it works for Windows and Linux there
binary = self.default
binary = self.param_group.GetString(self.custom_path)
if not binary:
binary = self.default
FreeCAD.Console.PrintLog(f"Solver binary path default: {binary} \n")
# check if use_default is set to True
# if True the standard binary path will be overwritten with a user binary path
if self.param_group.GetBool(self.use_default, True) is False:
binary = self.param_group.GetString(self.custom_path)
FreeCAD.Console.PrintLog(f"Solver binary path user setting: {binary} \n")
# get the whole binary path name for the given command or binary path and return it
# None is returned if the binary has not been found
# The user does not know what exactly has going wrong.
@@ -264,31 +259,26 @@ _SOLVER_PARAM = {
"Calculix": _SolverDlg(
default="ccx",
param_path=_PARAM_PATH + "Ccx",
use_default="UseStandardCcxLocation",
custom_path="ccxBinaryPath",
),
"ElmerSolver": _SolverDlg(
default="ElmerSolver",
param_path=_PARAM_PATH + "Elmer",
use_default="UseStandardElmerLocation",
custom_path="elmerBinaryPath",
),
"ElmerGrid": _SolverDlg(
default="ElmerGrid",
param_path=_PARAM_PATH + "Elmer",
use_default="UseStandardGridLocation",
custom_path="gridBinaryPath",
),
"Mystran": _SolverDlg(
default="mystran",
param_path=_PARAM_PATH + "Mystran",
use_default="UseStandardMystranLocation",
custom_path="mystranBinaryPath",
),
"Z88": _SolverDlg(
default="z88r",
param_path=_PARAM_PATH + "Z88",
use_default="UseStandardZ88Location",
custom_path="z88BinaryPath",
),
}

View File

@@ -68,7 +68,10 @@ class _TaskPanel:
# task panel, may be deactivate write and run button.
self.fea = ccx(solver_object)
self.fea.setup_working_dir()
self.fea.setup_ccx()
try:
self.fea.setup_ccx()
except FileNotFoundError as e:
FreeCAD.Console.PrintWarning(e.args[0])
self.Calculix = QtCore.QProcess()
self.Timer = QtCore.QTimer()

View File

@@ -32,6 +32,7 @@ __url__ = "https://www.freecad.org"
import os
import sys
import subprocess
import shutil
import FreeCAD
@@ -400,52 +401,24 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
Defaults to 'CalculiX'. Expected output from `ccx` when run empty.
"""
error_title = "No or wrong CalculiX binary ccx"
error_message = ""
from platform import system
self.ccx_binary = ccx_binary
if self.ccx_binary is None:
self.ccx_binary = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/Ccx"
).GetString("ccxBinaryPath", "")
ccx_std_location = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/Ccx"
).GetBool("UseStandardCcxLocation", True)
if ccx_std_location:
if system() == "Windows":
ccx_path = FreeCAD.getHomePath() + "bin/ccx.exe"
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx").SetString(
"ccxBinaryPath", ccx_path
)
self.ccx_binary = ccx_path
elif system() in ("Linux", "Darwin"):
p1 = subprocess.Popen(["which", "ccx"], stdout=subprocess.PIPE)
if p1.wait() == 0:
ccx_path = p1.stdout.read().decode("utf8").split("\n")[0]
elif p1.wait() == 1:
error_message = (
"FEM: CalculiX binary ccx not found in "
"standard system binary path. "
"Please install ccx or set path to binary "
"in FEM preferences tab CalculiX.\n"
)
if FreeCAD.GuiUp:
QtGui.QMessageBox.critical(None, error_title, error_message)
raise Exception(error_message)
self.ccx_binary = ccx_path
if not self.ccx_binary:
# search in system
self.ccx_binary = shutil.which("ccx")
else:
if not ccx_binary:
self.ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
ccx_binary = self.ccx_prefs.GetString("ccxBinaryPath", "")
if not ccx_binary:
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx").SetBool(
"UseStandardCcxLocation", True
)
error_message = (
"FEM: CalculiX binary ccx path not set at all. "
"The use of standard path was activated in "
"FEM preferences tab CalculiX. Please try again!\n"
)
if FreeCAD.GuiUp:
QtGui.QMessageBox.critical(None, error_title, error_message)
FreeCAD.Console.PrintError(error_message)
self.ccx_binary = ccx_binary
# check user defined path
self.ccx_binary = shutil.which(self.ccx_binary)
if self.ccx_binary is None:
raise FileNotFoundError(
"CalculiX binary not found\n"
"Install CalculiX or set path to binary in FEM user preferences"
)
ccx_stdout = None
ccx_stderr = None
@@ -474,7 +447,7 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
error_message = (
"FEM: CalculiX binary ccx '{}' not found. "
"Please set the CalculiX binary ccx path in "
"FEM preferences tab CalculiX.\n".format(ccx_binary)
"FEM preferences tab CalculiX.\n".format(self.ccx_binary)
)
if FreeCAD.GuiUp:
QtGui.QMessageBox.critical(None, error_title, error_message)
@@ -487,7 +460,7 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
"contain expected phrase '{}'. "
"There are some problems when running the ccx binary. "
"Check if ccx runs standalone without FreeCAD.\n".format(
ccx_binary, ccx_stdout, ccx_binary_sig
self.ccx_binary, ccx_stdout, ccx_binary_sig
)
)
if FreeCAD.GuiUp: