fix(sim): libsims not unloading (#6005)

This commit is contained in:
Neil Horne
2025-04-01 13:00:02 +10:00
committed by GitHub
parent 84e98e8b4b
commit 00d0384008
3 changed files with 96 additions and 45 deletions
+56 -26
View File
@@ -40,6 +40,8 @@
#include <QMessageBox>
#include <QDir>
#include <QRegularExpression>
#include <QProcess>
#include <QtGlobal>
using namespace Helpers;
@@ -369,35 +371,63 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
simuData->setCurrentModel(modelIdx);
}
SimulatorMainWindow * dialog = new SimulatorMainWindow(parent, simulatorId, flags);
dialog->setWindowModality(Qt::ApplicationModal);
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dialog, &SimulatorMainWindow::destroyed, [simuData] (void) {
#ifdef __APPLE__
simulatorRunning = false;
#endif
// TODO simuData and Horus tmp directory is deleted on simulator close OR we could use it to get back data from the simulation
delete simuData;
});
QString resultMsg;
if (dialog->getExitStatus(&resultMsg)) {
if (resultMsg.isEmpty())
resultMsg = QCoreApplication::translate("Companion", "Uknown error during Simulator startup.");
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Simulator Error"), resultMsg);
dialog->deleteLater();
}
else if (dialog->setRadioData(simuData)) {
#ifdef __APPLE__
simulatorRunning = true;
#endif
dialog->show();
// the directory will be automatically deleted when QTemporaryDir goes out of scope
QTemporaryDir tmpDir(QDir::tempPath() + "/etx-XXXXXX");
if (tmpDir.isValid()) {
qDebug() << "Created temporary settings directory" << tmpDir.path();
}
else {
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Data Load Error"), QCoreApplication::translate("Companion", "Error occurred while starting simulator."));
dialog->deleteLater();
QString resultMsg = QCoreApplication::translate("Companion", "Error creating temporary directory for models and settings.");
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Simulator Error"), resultMsg);
return;
}
simuData->fixModelFilenames();
Storage storage(tmpDir.path());
if (!storage.write(*simuData)) {
QString resultMsg = QCoreApplication::translate("Companion", "Error writing models and settings to temporary directory.");
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Simulator Error"), resultMsg);
return;
}
const QString path = QCoreApplication::applicationDirPath();
#if defined Q_OS_WIN
const QString program = "simulator.exe";
#elif defined Q_OS_APPLE
const QString program = "simulator.dmg";
#else
const QString program = QString("simulator%1%2").arg(VERSION_MAJOR).arg(VERSION_MINOR);
#endif
QStringList arguments;
arguments << "--profile" << g.currentProfile().name()
<< "--start-with" << "folder"
<< "--flags" << QString::number(flags)
<< tmpDir.path();
QProcess *simu = new QProcess(parent);
qDebug() << "Launching simulator with command:" << QDir::toNativeSeparators(path % "/" % program) << arguments;
// wait for the simulator to finish
int result = simu->execute(path % "/" % program, arguments);
QString resultMsg;
if (result == -2)
resultMsg = QCoreApplication::translate("Companion", "Unable to start.");
else if (result == -1)
resultMsg = QCoreApplication::translate("Companion", "Crashed.");
else if (result > 0)
resultMsg = QCoreApplication::translate("Companion", "Exited with result code:") % QString(result);
if (result != 0)
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Simulator Error"), resultMsg);
if (simuData)
delete simuData;
}
QPixmap makePixMap(const QImage & image)
+6 -2
View File
@@ -32,7 +32,7 @@
#define SIMULATOR_FLAGS_NOTX 0x01 // simulating a single model from Companion
#define SIMULATOR_FLAGS_STANDALONE 0x02 // started from stanalone simulator
#define SIMULATOR_OPTIONS_VERSION 3
#define SIMULATOR_OPTIONS_VERSION 4
namespace Simulator
{
@@ -131,6 +131,8 @@ struct SimulatorOptions
QByteArray radioOutputsState; // RadioOutputsWidget UI state
// added in v3
QString simulatorId;
// added in v4
quint8 flags; // Flags passed from Companion
quint16 loadedVersion() const { return m_version; } //! loaded structure definition version (0 if none/error)
@@ -138,7 +140,7 @@ struct SimulatorOptions
{
out << quint16(SIMULATOR_OPTIONS_VERSION) << o.startupDataType << o.firmwareId << o.dataFile << o.dataFolder
<< o.sdPath << o.windowGeometry << o.controlsState << o.lcdColor << o.windowState << o.dbgConsoleState << o.radioOutputsState
<< o.simulatorId;
<< o.simulatorId << o.flags;
return out;
}
@@ -152,6 +154,8 @@ struct SimulatorOptions
in >> o.windowState >> o.dbgConsoleState >> o.radioOutputsState;
if (o.m_version >= 3)
in >> o.simulatorId;
if (o.m_version >= 4)
in >> o.simulatorId;
}
else {
qWarning() << "Error loading SimulatorOptions, saved version not valid:" << o.m_version << "Expected <=" << SIMULATOR_OPTIONS_VERSION;
+34 -17
View File
@@ -129,6 +129,10 @@ CommandLineParseResult cliOptions(SimulatorOptions * simOptions, int * profileId
QApplication::translate("SimulatorMain", "Data source type to use. One of:") + " (file|folder|sd)",
QApplication::translate("SimulatorMain", "type"));
const QCommandLineOption optFlags(QStringList() << "flags" << "f",
QApplication::translate("SimulatorMain", "Flags passed from Companion"),
QApplication::translate("SimulatorMain", "flags"));
cliOptions.addPositionalArgument(QApplication::translate("SimulatorMain", "data-source"),
QApplication::translate("SimulatorMain", "Radio data (.bin/.eeprom/.etx) image file to use OR data folder path (for Horus-style radios).\n"
"NOTE: any existing EEPROM data incompatible with the selected radio type may be overwritten!"),
@@ -138,6 +142,7 @@ CommandLineParseResult cliOptions(SimulatorOptions * simOptions, int * profileId
cliOptions.addOption(optRadio);
cliOptions.addOption(optSdDir);
cliOptions.addOption(optStart);
cliOptions.addOption(optFlags);
QStringList args = QCoreApplication::arguments();
#ifdef Q_OS_WIN
@@ -211,10 +216,10 @@ CommandLineParseResult cliOptions(SimulatorOptions * simOptions, int * profileId
if (stTyp == "file") {
simOptions->startupDataType = SimulatorOptions::START_WITH_FILE;
}
else if (stTyp == "folder") {
else if (stTyp == "folder") {
simOptions->startupDataType = SimulatorOptions::START_WITH_FOLDER;
}
else if (stTyp == "sd") {
else if (stTyp == "sd") {
simOptions->startupDataType = SimulatorOptions::START_WITH_SDPATH;
}
else {
@@ -225,6 +230,17 @@ CommandLineParseResult cliOptions(SimulatorOptions * simOptions, int * profileId
cliOptsFound = true;
}
int flags = 0;
if (cliOptions.isSet(optFlags)) {
bool chk;
flags = cliOptions.value(optFlags).toInt(&chk);
if (!chk)
flags = 0;
}
simOptions->flags = flags;
*profileId = pId;
if (cliOptsFound)
return CommandLineFound;
@@ -292,19 +308,6 @@ int main(int argc, char *argv[])
int profileId = (g.simuLastProfId() > -1 ? g.simuLastProfId() : g.id());
SimulatorOptions simOptions = g.profile[profileId].simulatorOptions();
// TODO : defaults should be set in Profile::init()
if (simOptions.firmwareId.isEmpty()) {
simOptions.firmwareId = g.profile[profileId].fwType();
}
// DO NOT use saved simulatorId as could be changed in later releases
simOptions.simulatorId = SimulatorLoader::findSimulatorByName(Firmware::getFirmwareForId(simOptions.firmwareId)->getSimulatorId());
if (simOptions.dataFolder.isEmpty())
simOptions.dataFolder = g.eepromDir();
if (simOptions.sdPath.isEmpty())
simOptions.sdPath = g.profile[profileId].sdPath();
// Handle startup options
// check for command-line options
@@ -315,7 +318,21 @@ int main(int argc, char *argv[])
if (cliResult == CommandLineExitErr)
return finish(1);
// Present GUI startup options dialog if necessary
// TODO : defaults should be set in Profile::init()
if (simOptions.firmwareId.isEmpty()) {
simOptions.firmwareId = g.profile[profileId].fwType();
}
if (simOptions.dataFolder.isEmpty())
simOptions.dataFolder = g.eepromDir();
if (simOptions.sdPath.isEmpty())
simOptions.sdPath = g.profile[profileId].sdPath();
// DO NOT use saved simulatorId as could be changed in later releases
// must be set after cli parse as --profile will load old data or blank
simOptions.simulatorId = SimulatorLoader::findSimulatorByName(Firmware::getFirmwareForId(simOptions.firmwareId)->getSimulatorId());
// Present GUI startup options dialog if necessary
if (cliResult == CommandLineNone || profileId == -1 || simOptions.simulatorId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
SimulatorStartupDialog * dlg = new SimulatorStartupDialog(&simOptions, &profileId);
int ret = dlg->exec();
@@ -357,7 +374,7 @@ int main(int argc, char *argv[])
//qDebug() << "current firmware:" << getCurrentFirmware()->getId();
int result = 0;
SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simOptions.simulatorId, SIMULATOR_FLAGS_STANDALONE);
SimulatorMainWindow * mainWindow = new SimulatorMainWindow(nullptr, simOptions.simulatorId, (simOptions.flags ? simOptions.flags : SIMULATOR_FLAGS_STANDALONE));
if ((result = mainWindow->getExitStatus(&resultMsg))) {
if (resultMsg.isEmpty())
resultMsg = QApplication::translate("SimulatorMain", "Unknown error during Simulator startup.");