MinetestMapperGUI/minetestmapperexe.cpp

277 lines
7.9 KiB
C++

#include "minetestmapperexe.h"
MinetestMapperExe::MinetestMapperExe(const QString &program, QObject *parent) : QObject(parent)
{
process = new QProcess(this);
setExecutableFile(program);
connect(process, &QProcess::errorOccurred,
this, &MinetestMapperExe::errorOccured);
connect(process, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(finished(int,QProcess::ExitStatus))); // TODO: get the pointer of this overloaded function
connect(process, &QProcess::readyReadStandardOutput,
this, &MinetestMapperExe::readStandardOutput);
connect(process, &QProcess::readyReadStandardError,
this, &MinetestMapperExe::readStandardError);
}
void MinetestMapperExe::setExecutableFile(const QString &program)
{
if(!program.isEmpty()) {
state = Uninitialized;
minetestMapperExecutableFile = program;
process->setProgram(program);
} else {
state = Error;
valid = false;
minetestMapper = false;
}
}
QStringList MinetestMapperExe::getSupportedBackends() const
{
static const QRegularExpression regexp("\\W+");
QString backends = options.value("--backend", "<auto>");
QStringList list = backends.split(regexp, QString::SkipEmptyParts);
return list;
}
void MinetestMapperExe::run()
{
switch (state) {
case Uninitialized:
state = InitVersion;
process->setArguments(QStringList("--version"));
process->start(QIODevice::ReadOnly);
break;
case InitVersion:
state = InitHelp;
process->setArguments(QStringList("--help"));
process->start(QIODevice::ReadOnly);
break;
case Ready:
state = MappingStart;
process->start(QIODevice::ReadOnly);
break;
case MappingStart:
case MappingProgress:
case MappingEnd:
qDebug() << "Cant run MinetestMapper: Still running";
break;
case Error:
default:
qDebug() << "Cant run MinetestMapper: Some Error";
break;
}
}
bool MinetestMapperExe::init(){
if(state == Uninitialized)
{
emit busyStateChanged(true);
emit progressRangeChanged(0, 0);
state = InitVersion;
emit stateChanged("Init Version...");
process->setArguments(QStringList("--version"));
process->start(QIODevice::ReadOnly);
return true;
}
return false;
}
bool MinetestMapperExe::startMapping(const QStringList &arguments){
if(state == Ready)
{
//state = Mapping;
emit busyStateChanged(true);
process->setArguments(arguments);
run();
return true;
}
return false;
}
void MinetestMapperExe::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
qDebug()<< exitCode << exitStatus;
switch (state) {
case InitVersion:
if(initVersion())
{
state = InitHelp;
emit stateChanged("Init Help...");
process->setArguments(QStringList("--help"));
process->start(QIODevice::ReadOnly);
}
break;
case InitHelp:
if(initHelp())
{
valid = true;
minetestMapper = true;
state = Ready;
emit stateChanged("Ready");
emit busyStateChanged(false);
finishInitialization();
}
break;
case MappingStart:
case MappingProgress:
case MappingEnd:
state = Ready;
emit mappingFinished(exitCode, exitStatus);
emit stateChanged("Ready");
emit busyStateChanged(false);
default:
break;
}
}
bool MinetestMapperExe::initVersion()
{
static const QRegularExpression regexp(".*Version-ID: *");
QByteArray dataRaw;
QString data;
dataRaw = process->readAllStandardError();
data = QString(dataRaw).trimmed();
if (data.contains("unrecognized option")) {
return false;
}
dataRaw = process->readAllStandardOutput();
data = QString(dataRaw).trimmed();
if (!data.contains("Version-ID:")) {
return false;
}
version = data.replace(regexp, "");
return true;
}
bool MinetestMapperExe::initHelp()
{
static const QRegularExpression optionRegex("^(|-[a-zA-Z].*)(--[a-zA-Z0-9][a-zA-Z0-9-_]+)( *(.*[^ \t\r\n]))?[ \t\r\n]*$");
//QMap<QString, QString> options;
QByteArray helpTextRaw = process->readAllStandardOutput();
QStringList helpText = QString(helpTextRaw).trimmed().split("\n");
for (int i = 0; i < helpText.count(); i++) {
QString helpLine = helpText[i].trimmed();
if (helpLine.contains("Color format: '#000000'")) {
tree = Minetest;
}
else if (helpLine.contains("X and Y coordinate formats:")) {
tree = Rogier5;
}
QString option = helpLine;
option.replace(optionRegex, "\\2");
if (option[1] != '-' || option.contains(' ')) continue;
QString arguments = helpLine;
arguments.replace(optionRegex, "\\4");
if (arguments == helpLine) arguments = "";
options[option] = arguments;
}
//this->options = options;
return true;
}
void MinetestMapperExe::readStandardOutput()
{
static const QRegularExpression re("([0-9]{1,3})(\\%)");
if(state == MappingStart || state == MappingProgress || state == MappingEnd) {
QByteArray outData = process->readAllStandardOutput();
QString out = QString(outData).trimmed();
if(!out.isEmpty()) {
QRegularExpressionMatch match = re.match(out);
if(match.hasMatch()){
if(state == MappingStart)
{
state = MappingProgress;
emit progressRangeChanged(0, 100);
}
int percent = match.captured(1).toInt(); // percent == number
emit progressChanged(percent);
}
else {
if(state == MappingProgress)
{
state = MappingEnd;
emit progressRangeChanged(0, 0);
}
}
emit stateChanged(out);
emit mappingStandardOutput(out);
}
}
}
void MinetestMapperExe::readStandardError()
{
if(state == MappingStart || state == MappingProgress || state == MappingEnd) {
const QByteArray outData = process->readAllStandardError();
if(outData.length() >1) {
const QString out = QString(outData).trimmed();
emit mappingStandardError(out);
}
}
}
void MinetestMapperExe::finishInitialization()
{
emit initialisationFinished(true);
}
QString MinetestMapperExe::getMinetestMapperExecutableFile() const
{
return minetestMapperExecutableFile;
}
MinetestMapperExe::Tree MinetestMapperExe::getTree() const
{
return tree;
}
QString MinetestMapperExe::getTreeString() const
{
QMetaEnum metaEnum = QMetaEnum::fromType<MinetestMapperExe::Tree>();
return QString(metaEnum.valueToKey(tree));
}
QString MinetestMapperExe::getVersion() const
{
return version;
}
bool MinetestMapperExe::isMinetestMapper() const
{
return minetestMapper;
}
bool MinetestMapperExe::isValid() const
{
return valid;
}
void MinetestMapperExe::cancel() const
{
if(process->state() == QProcess::Running)
{
process->kill();
}
}
void MinetestMapperExe::errorOccured(QProcess::ProcessError error)
{
emit mappingStandardError(process->errorString());
emit busyStateChanged(false);
qDebug() <<"Error starting MinetestMapper:"<<error
<<"Error code: "<<process->error()
<<"Error string: "<<process->errorString();
QMessageBox::critical(dynamic_cast<QWidget*>(this->parent()), tr("Minetest Mapper failed"),
tr("<h1>ERROR</h1> <h2>minetestmapper failed</h2>"
"Error code: <i>%1</i> <br>"
"Error Message: <pre>%2</pre><br>")
.arg(error)
.arg(process->errorString()));
}