diff --git a/launch.pro b/launch.pro index b4e62ba..5952940 100644 --- a/launch.pro +++ b/launch.pro @@ -21,7 +21,8 @@ SOURCES += main.cpp\ installwizard_patch.cpp \ installwizard_eula.cpp \ installwizard_copy.cpp \ - filecopy.cpp + filecopy.cpp \ + quakeutils.cpp HEADERS += mainwindow.h \ settings.h \ @@ -31,7 +32,8 @@ HEADERS += mainwindow.h \ installwizard_patch.h \ installwizard_eula.h \ installwizard_copy.h \ - filecopy.h + filecopy.h \ + quakeutils.h FORMS += mainwindow.ui \ installwizard.ui \ diff --git a/mainwindow.cpp b/mainwindow.cpp index 6550d7c..4d4e564 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,16 +1,10 @@ -#include +#include +#include #include -#include - -#ifdef Q_OS_WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#endif - #include "mainwindow.h" #include "ui_mainwindow.h" #include "installwizard.h" +#include "quakeutils.h" ioLaunch::ioLaunch(QWidget *parent) : QMainWindow(parent), @@ -18,45 +12,21 @@ ioLaunch::ioLaunch(QWidget *parent) : { ui->setupUi(this); - // 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 - - QDir homeDir(homePath); + // Calculate the ioquake3 home path. + const QString homePath = QuakeUtils::calculateHomePath(); + const 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(); + QuakeUtils::parseQuake3Config(&settings, homePath); } -#ifdef Q_OS_WIN32 - // On first run, try to get the Q3A path on Windows by reading it from the registry. + // On first run, try to get the Q3A path. 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()); - } + settings.setQuakePath(QuakeUtils::calculateQuake3Path()); } -#endif settings.setHaveRun(true); @@ -221,46 +191,6 @@ void ioLaunch::on_btnRunInstallWizard_clicked() wizard.exec(); } -// 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); -} - #ifdef Q_OS_WIN32 bool ioLaunch::isQuake3PathValid() const { @@ -270,46 +200,3 @@ bool ioLaunch::isQuake3PathValid() const return !settings.getQuakePath().isEmpty() && QDir(settings.getQuakePath()).exists(); } #endif - -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") - { - settings.setResolutionMode(ParseToken(line, offset).toInt()); - } - else if (cvar == "r_customwidth") - { - settings.setResolutionWidth(ParseToken(line, offset).toInt()); - } - else if (cvar == "r_customheight") - { - settings.setResolutionHeight(ParseToken(line, offset).toInt()); - } - else if (cvar == "r_fullscreen") - { - settings.setResolutionFullscreen(ParseToken(line, offset).toInt() != 0); - } - } - } -} diff --git a/mainwindow.h b/mainwindow.h index 62545ce..395e5fa 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,12 +2,6 @@ #define MAINWINDOW_H #include -#include -#include -#include -#include -#include -#include #include "settings.h" namespace Ui { @@ -43,11 +37,8 @@ private: bool isQuake3PathValid() const; #endif - void parseQuake3Config(); - Ui::ioLaunch *ui; Settings settings; - QString homePath; }; #endif // MAINWINDOW_H diff --git a/quakeutils.cpp b/quakeutils.cpp new file mode 100644 index 0000000..b325f82 --- /dev/null +++ b/quakeutils.cpp @@ -0,0 +1,157 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 The ioquake Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include + +#ifdef Q_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +#include +#include +#include "quakeutils.h" +#include "settings.h" + +QString QuakeUtils::calculateQuake3Path() +{ +#ifdef Q_OS_WIN32 + // Try to get the Q3A path on Windows by reading it from the registry. + QSettings registry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Id\\Quake III Arena", QSettings::NativeFormat); + + if (registry.contains("INSTALLPATH")) + { + return registry.value("INSTALLPATH").toString(); + } +#endif + + return QString(); +} + +QString QuakeUtils::calculateHomePath() +{ +#ifdef Q_OS_WIN32 + wchar_t path[MAX_PATH]; + + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path))) + { + return 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 + return homeEnv + "/Library/Application Support/Quake3"; + #elif defined Q_OS_UNIX + return homeEnv + "/.q3a"; + #endif +#endif + + return QString(); +} + +// 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); +} + +void QuakeUtils::parseQuake3Config(Settings *settings, const QString &homePath) +{ + Q_ASSERT(settings); + + 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") + { + settings->setResolutionMode(ParseToken(line, offset).toInt()); + } + else if (cvar == "r_customwidth") + { + settings->setResolutionWidth(ParseToken(line, offset).toInt()); + } + else if (cvar == "r_customheight") + { + settings->setResolutionHeight(ParseToken(line, offset).toInt()); + } + else if (cvar == "r_fullscreen") + { + settings->setResolutionFullscreen(ParseToken(line, offset).toInt() != 0); + } + } + } +} diff --git a/quakeutils.h b/quakeutils.h new file mode 100644 index 0000000..7cfc919 --- /dev/null +++ b/quakeutils.h @@ -0,0 +1,41 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 The ioquake Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef QUAKEUTILS_H +#define QUAKEUTILS_H + +class QString; +class Settings; + +class QuakeUtils +{ +public: + // Try to find an existing Q3A installation (not Steam). + static QString calculateQuake3Path(); + + // Calculate the ioquake3 home path. + static QString calculateHomePath(); + + static void parseQuake3Config(Settings *settings, const QString &homePath); +}; + +#endif // QUAKEUTILS_H