Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175#include "runner.hpp"
#include <utility>
#include <QCoreApplication>#include <QDir>#include <QMessageBox>#include <QProcess>#include <QString>#include <QStringList>#include <QTemporaryFile>#include <QTextStream>
#include <components/debug/debuglog.hpp>#include <components/files/qtconversion.hpp>
#include "operationholder.hpp"
CSMDoc::Runner::Runner(std::filesystem::path projectPath) : mRunning(false) , mStartup(nullptr) , mProjectPath(std::move(projectPath)){ connect(&mProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &Runner::finished);
connect(&mProcess, &QProcess::readyReadStandardOutput, this, &Runner::readyReadStandardOutput);
mProcess.setProcessChannelMode(QProcess::MergedChannels);
mProfile.blank();}
CSMDoc::Runner::~Runner(){ if (mRunning) { disconnect(&mProcess, nullptr, this, nullptr); mProcess.kill(); mProcess.waitForFinished(); }}
void CSMDoc::Runner::start(bool delayed){ if (mStartup) { delete mStartup; mStartup = nullptr; }
if (!delayed) { mLog.clear();
QString path = "openmw";#ifdef Q_OS_WIN path.append(QLatin1String(".exe"));#endif QDir dir(QCoreApplication::applicationDirPath());#ifdef Q_OS_MAC // the CS and engine are in separate .app directories dir.cdUp(); dir.cdUp(); dir.cdUp(); path.prepend("OpenMW.app/Contents/MacOS/");#endif path = dir.absoluteFilePath(path);
mStartup = new QTemporaryFile(this); if (!mStartup->open()) { Log(Debug::Error) << "Unable to open temporary file for --script-run source"; QMessageBox::critical(nullptr, tr("Error launching OpenMW"), tr("Unable to open temporary file.")); return; }
{ QTextStream stream(mStartup);
if (!mStartupInstruction.empty()) stream << QString::fromUtf8(mStartupInstruction.c_str()) << '\n';
stream << QString::fromUtf8(mProfile.mScriptText.c_str()); }
mStartup->close();
QStringList arguments; arguments << "--skip-menu";
if (mProfile.mFlags & ESM::DebugProfile::Flag_BypassNewGame) arguments << "--new-game=0"; else arguments << "--new-game=1";
arguments << ("--script-run=" + mStartup->fileName());
arguments << "--data=\"" + Files::pathToQString(mProjectPath.parent_path()) + "\"";
arguments << "--replace=content";
for (const auto& mContentFile : mContentFiles) { arguments << "--content=" + Files::pathToQString(mContentFile); }
arguments << "--content=" + Files::pathToQString(mProjectPath.filename());
mProcess.start(path, arguments); }
mRunning = true; emit runStateChanged();}
void CSMDoc::Runner::stop(){ delete mStartup; mStartup = nullptr;
if (mProcess.state() == QProcess::NotRunning) { mRunning = false; emit runStateChanged(); } else mProcess.kill();}
bool CSMDoc::Runner::isRunning() const{ return mRunning;}
void CSMDoc::Runner::configure(const ESM::DebugProfile& profile, const std::vector<std::filesystem::path>& contentFiles, const std::string& startupInstruction){ mProfile = profile; mContentFiles = contentFiles; mStartupInstruction = startupInstruction;}
void CSMDoc::Runner::finished(int exitCode, QProcess::ExitStatus exitStatus){ mRunning = false; emit runStateChanged();}
QTextDocument* CSMDoc::Runner::getLog(){ return &mLog;}
void CSMDoc::Runner::readyReadStandardOutput(){ mLog.setPlainText(mLog.toPlainText() + QString::fromUtf8(mProcess.readAllStandardOutput()));}
CSMDoc::SaveWatcher::SaveWatcher(Runner* runner, OperationHolder* operation) : QObject(runner) , mRunner(runner){ connect(operation, &OperationHolder::done, this, &SaveWatcher::saveDone);}
void CSMDoc::SaveWatcher::saveDone(int type, bool failed){ if (failed) mRunner->stop(); else mRunner->start();
deleteLater();}