2014-05-09 02:56:11 +00:00
|
|
|
#include <Qt>
|
2014-05-08 11:37:32 +00:00
|
|
|
#include <QProcess>
|
2014-05-09 05:17:33 +00:00
|
|
|
#include <QTextStream>
|
2014-05-09 02:56:11 +00:00
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <windows.h>
|
|
|
|
#include <shlobj.h>
|
|
|
|
#endif
|
|
|
|
|
2013-12-02 00:25:01 +00:00
|
|
|
#include "mainwindow.h"
|
|
|
|
#include "ui_mainwindow.h"
|
2014-05-12 08:49:59 +00:00
|
|
|
#include "installwizard.h"
|
2013-12-02 00:25:01 +00:00
|
|
|
|
|
|
|
ioLaunch::ioLaunch(QWidget *parent) :
|
|
|
|
QMainWindow(parent),
|
2014-05-09 07:06:21 +00:00
|
|
|
ui(new Ui::ioLaunch)
|
2013-12-02 00:25:01 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
2014-05-09 02:56:11 +00:00
|
|
|
// Calculate ioquake3 home path.
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
wchar_t path[MAX_PATH];
|
|
|
|
|
|
|
|
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path)))
|
|
|
|
{
|
|
|
|
homePath = QString::fromWCharArray(path) + "/Quake3";
|
|
|
|
}
|
|
|
|
#elif defined(Q_OS_MAC) || defined(Q_OS_UNIX)
|
|
|
|
const QByteArray homeEnvRaw = qgetenv("HOME");
|
|
|
|
const QString homeEnv(homeEnvRaw.constData());
|
|
|
|
|
|
|
|
#if defined Q_OS_MAC
|
|
|
|
homePath = homeEnv + "/Library/Application Support/Quake3";
|
|
|
|
#elif defined Q_OS_UNIX
|
|
|
|
homePath = homeEnv + "/.q3a";
|
|
|
|
#endif
|
|
|
|
#endif
|
2014-05-09 05:17:33 +00:00
|
|
|
|
|
|
|
QDir homeDir(homePath);
|
|
|
|
|
|
|
|
// Try to parse q3config.cfg to get default settings if this is the first time the program has run.
|
|
|
|
if (!homePath.isEmpty() && homeDir.exists() && !settings.getHaveRun())
|
|
|
|
{
|
|
|
|
parseQuake3Config();
|
|
|
|
}
|
|
|
|
|
2014-05-14 12:53:01 +00:00
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
// On first run, try to get the Q3A path on Windows by reading it from the registry.
|
|
|
|
if (!settings.getHaveRun())
|
|
|
|
{
|
|
|
|
QSettings registry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Id\\Quake III Arena", QSettings::NativeFormat);
|
|
|
|
|
|
|
|
if (registry.contains("INSTALLPATH"))
|
|
|
|
{
|
|
|
|
settings.setQuakePath(registry.value("INSTALLPATH").toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-09 05:17:33 +00:00
|
|
|
settings.setHaveRun(true);
|
2014-05-09 06:17:35 +00:00
|
|
|
|
|
|
|
// Populate the GUI with values read from settings.
|
|
|
|
if (settings.getResolutionMode() >= 0)
|
|
|
|
{
|
|
|
|
// Predefined.
|
|
|
|
ui->cbResolution->setCurrentIndex(2 + settings.getResolutionMode());
|
|
|
|
}
|
|
|
|
else if (settings.getResolutionMode() == -1)
|
|
|
|
{
|
|
|
|
// Custom.
|
2014-05-09 07:06:21 +00:00
|
|
|
ui->cbResolution->setCurrentIndex(1);
|
2014-05-09 06:17:35 +00:00
|
|
|
}
|
|
|
|
else if (settings.getResolutionMode() == -2)
|
|
|
|
{
|
|
|
|
// Desktop.
|
2014-05-09 07:06:21 +00:00
|
|
|
ui->cbResolution->setCurrentIndex(0);
|
2014-05-09 06:17:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ui->sbWidth->setValue(settings.getResolutionWidth());
|
|
|
|
ui->sbHeight->setValue(settings.getResolutionHeight());
|
|
|
|
|
|
|
|
if (settings.getResolutionFullscreen())
|
|
|
|
{
|
|
|
|
ui->rbFull->setChecked(true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ui->rbWin->setChecked(true);
|
|
|
|
}
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ioLaunch::~ioLaunch()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ioLaunch::on_btnLaunch_clicked()
|
|
|
|
{
|
2014-05-09 02:21:42 +00:00
|
|
|
QString ioq3;
|
|
|
|
|
2013-12-02 00:25:01 +00:00
|
|
|
#ifdef Q_OS_WIN32
|
2014-05-12 08:49:59 +00:00
|
|
|
if(!isQuake3PathValid())
|
2013-12-02 00:25:01 +00:00
|
|
|
{
|
2014-05-12 08:49:59 +00:00
|
|
|
InstallWizard wizard(this, &settings);
|
|
|
|
wizard.exec();
|
2014-05-09 02:21:42 +00:00
|
|
|
|
2014-05-12 08:49:59 +00:00
|
|
|
if(!isQuake3PathValid())
|
2014-05-09 02:21:42 +00:00
|
|
|
return;
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
2014-05-09 02:21:42 +00:00
|
|
|
|
2014-05-09 07:06:21 +00:00
|
|
|
ioq3 = QString("\"") + settings.getQuakePath() + "/ioquake3.x86.exe\"";
|
2013-12-02 01:50:15 +00:00
|
|
|
#elif defined Q_OS_MAC
|
2014-05-09 07:06:21 +00:00
|
|
|
ioq3 = "open -a ioquake3 --args";
|
2014-03-24 20:06:49 +00:00
|
|
|
#elif defined Q_OS_UNIX
|
2014-05-09 07:06:21 +00:00
|
|
|
ioq3 = "ioquake3";
|
2014-03-24 20:06:49 +00:00
|
|
|
#else
|
|
|
|
#error "Unsupported platform"
|
2013-12-02 00:25:01 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-09 07:38:28 +00:00
|
|
|
int r_mode = settings.getResolutionMode();
|
|
|
|
int r_width = settings.getResolutionWidth();
|
|
|
|
int r_height = settings.getResolutionHeight();
|
2013-12-02 00:25:01 +00:00
|
|
|
|
2014-05-09 07:38:28 +00:00
|
|
|
// Handle modes outside what ioquake3 recognize.
|
|
|
|
if (r_mode == 12)
|
2013-12-02 00:25:01 +00:00
|
|
|
{
|
2014-05-09 07:38:28 +00:00
|
|
|
r_mode = -1;
|
|
|
|
r_width = 1280;
|
|
|
|
r_height = 720;
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
2014-05-09 07:38:28 +00:00
|
|
|
else if (r_mode == 13)
|
2013-12-02 00:25:01 +00:00
|
|
|
{
|
2014-05-09 07:38:28 +00:00
|
|
|
r_mode = -1;
|
|
|
|
r_width = 1920;
|
|
|
|
r_height = 1080;
|
|
|
|
}
|
|
|
|
else if (r_mode == 14)
|
|
|
|
{
|
|
|
|
r_mode = -1;
|
|
|
|
r_width = 1280;
|
|
|
|
r_height = 800;
|
|
|
|
}
|
|
|
|
|
|
|
|
ioq3 += QString(" +set r_mode \"%1\"").arg(r_mode);
|
|
|
|
|
|
|
|
if (r_mode == -1)
|
|
|
|
{
|
|
|
|
ioq3 += QString(" +set r_customwidth %1").arg(r_width) + QString(" +set r_customheight %1").arg(r_height);
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-09 07:06:21 +00:00
|
|
|
ioq3 += QString(" +set r_fullscreen %1").arg(settings.getResolutionFullscreen() ? "1" : "0");
|
|
|
|
|
|
|
|
if(!QProcess::startDetached(ioq3))
|
2013-12-02 00:25:01 +00:00
|
|
|
{
|
2014-05-09 07:06:21 +00:00
|
|
|
QMessageBox ioq3Failed;
|
2013-12-02 00:25:01 +00:00
|
|
|
ioq3Failed.setText("ioquake3 failed to start!\nIs it installed?\n");
|
|
|
|
ioq3Failed.exec();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ioLaunch::on_cbResolution_currentIndexChanged(int index)
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
if (index == 0)
|
|
|
|
{
|
2014-05-09 07:06:21 +00:00
|
|
|
// Desktop.
|
|
|
|
settings.setResolutionMode(-2);
|
2014-05-09 06:17:35 +00:00
|
|
|
}
|
|
|
|
else if (index == 1)
|
|
|
|
{
|
2014-05-09 07:06:21 +00:00
|
|
|
// Custom.
|
|
|
|
settings.setResolutionMode(-1);
|
2014-05-09 06:17:35 +00:00
|
|
|
}
|
2014-05-09 07:06:21 +00:00
|
|
|
else if (index >= 2)
|
2014-05-09 06:17:35 +00:00
|
|
|
{
|
|
|
|
// Predefined.
|
|
|
|
settings.setResolutionMode(index - 2);
|
|
|
|
}
|
2014-05-09 07:41:45 +00:00
|
|
|
|
|
|
|
if (index == 1)
|
|
|
|
{
|
|
|
|
ui->sbWidth->setEnabled(true);
|
|
|
|
ui->sbHeight->setEnabled(true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ui->sbWidth->setEnabled(false);
|
|
|
|
ui->sbHeight->setEnabled(false);
|
|
|
|
}
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ioLaunch::on_rbFull_toggled(bool checked)
|
|
|
|
{
|
|
|
|
if(checked)
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionFullscreen(true);
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ioLaunch::on_rbWin_toggled(bool checked)
|
|
|
|
{
|
|
|
|
if(checked)
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionFullscreen(false);
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ioLaunch::on_sbWidth_valueChanged(int arg1)
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionWidth(arg1);
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ioLaunch::on_sbHeight_valueChanged(int arg1)
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionHeight(arg1);
|
2013-12-02 00:25:01 +00:00
|
|
|
}
|
2014-05-09 05:17:33 +00:00
|
|
|
|
2014-05-12 08:49:59 +00:00
|
|
|
void ioLaunch::on_btnRunInstallWizard_clicked()
|
|
|
|
{
|
|
|
|
InstallWizard wizard(this, &settings);
|
|
|
|
wizard.exec();
|
|
|
|
}
|
|
|
|
|
2014-05-09 05:17:33 +00:00
|
|
|
// Since q3config.cfg is generated it's nice and clean and shouldn't need a full parser.
|
|
|
|
static QString ParseToken(const QString &s, int &offset)
|
|
|
|
{
|
|
|
|
// Skip whitespace.
|
|
|
|
while (offset < s.length() && s[offset] == ' ')
|
|
|
|
{
|
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset >= s.length())
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
// Check for quoted token.
|
|
|
|
bool quoted = s[offset] == '\"';
|
|
|
|
|
|
|
|
if (quoted)
|
|
|
|
offset++;
|
|
|
|
|
|
|
|
// Parse token.
|
|
|
|
int start = offset;
|
|
|
|
|
|
|
|
while (offset < s.length() && ((quoted && s[offset] != '\"') || (!quoted && s[offset] != ' ')))
|
|
|
|
{
|
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get token substring.
|
|
|
|
int end = offset;
|
|
|
|
|
|
|
|
if (quoted && s[offset] == '\"')
|
|
|
|
{
|
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (end - start <= 0)
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
return s.mid(start, end - start);
|
|
|
|
}
|
|
|
|
|
2014-05-12 08:49:59 +00:00
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
bool ioLaunch::isQuake3PathValid() const
|
|
|
|
{
|
|
|
|
if (!settings.containsQuakePath())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !settings.getQuakePath().isEmpty() && QDir(settings.getQuakePath()).exists();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-09 05:17:33 +00:00
|
|
|
void ioLaunch::parseQuake3Config()
|
|
|
|
{
|
|
|
|
QFile file(homePath + "/baseq3/q3config.cfg");
|
|
|
|
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
|
|
return;
|
|
|
|
|
|
|
|
QTextStream stream(&file);
|
|
|
|
|
|
|
|
while (!stream.atEnd())
|
|
|
|
{
|
|
|
|
const QString line(stream.readLine());
|
|
|
|
|
|
|
|
// Skip comments.
|
|
|
|
if (line.startsWith("//"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
if (ParseToken(line, offset) == "seta")
|
|
|
|
{
|
|
|
|
const QString cvar(ParseToken(line, offset));
|
|
|
|
|
|
|
|
if (cvar == "r_mode")
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionMode(ParseToken(line, offset).toInt());
|
2014-05-09 05:17:33 +00:00
|
|
|
}
|
|
|
|
else if (cvar == "r_customwidth")
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionWidth(ParseToken(line, offset).toInt());
|
2014-05-09 05:17:33 +00:00
|
|
|
}
|
|
|
|
else if (cvar == "r_customheight")
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionHeight(ParseToken(line, offset).toInt());
|
2014-05-09 05:17:33 +00:00
|
|
|
}
|
|
|
|
else if (cvar == "r_fullscreen")
|
|
|
|
{
|
2014-05-09 06:17:35 +00:00
|
|
|
settings.setResolutionFullscreen(ParseToken(line, offset).toInt() != 0);
|
2014-05-09 05:17:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|