Merge pull request #6 from jpcy/settings

Settings
This commit is contained in:
Zachary J. Slater 2014-05-10 22:05:06 -07:00
commit f0a58961d3
6 changed files with 394 additions and 184 deletions

View file

@ -13,9 +13,11 @@ TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
mainwindow.cpp \
settings.cpp
HEADERS += mainwindow.h
HEADERS += mainwindow.h \
settings.h
FORMS += mainwindow.ui

View file

@ -1,16 +1,79 @@
#include <Qt>
#include <QProcess>
#include <QTextStream>
#ifdef Q_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlobj.h>
#endif
#include "mainwindow.h"
#include "ui_mainwindow.h"
ioLaunch::ioLaunch(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ioLaunch),
ioWidth(0), ioHeight(0), ioWedited(false), ioHedited(false)
ui(new Ui::ioLaunch)
{
ui->setupUi(this);
resOption = "";
screenOption = "";
// 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);
// 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();
}
settings.setHaveRun(true);
// 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.
ui->cbResolution->setCurrentIndex(1);
}
else if (settings.getResolutionMode() == -2)
{
// Desktop.
ui->cbResolution->setCurrentIndex(0);
}
ui->sbWidth->setValue(settings.getResolutionWidth());
ui->sbHeight->setValue(settings.getResolutionHeight());
if (settings.getResolutionFullscreen())
{
ui->rbFull->setChecked(true);
}
else
{
ui->rbWin->setChecked(true);
}
}
ioLaunch::~ioLaunch()
@ -20,150 +83,112 @@ ioLaunch::~ioLaunch()
void ioLaunch::on_btnLaunch_clicked()
{
QString ioq3;
#ifdef Q_OS_WIN32
if(ioq3 == NULL)
// Prompt the user to set the ioq3 path if the settings value either doesn't exist or is invalid.
bool promptForPath = true;
if (settings.containsQuakePath())
{
const QString path = settings.getQuakePath();
const QDir dir(path);
if (!path.isEmpty() && dir.exists())
promptForPath = false;
}
if(promptForPath)
{
QMessageBox msg;
msg.setText("Please select your Quake3 directory");
msg.exec();
QString path = QFileDialog::getExistingDirectory (this, tr("Directory"), directory.path());
ioq3 = QString("\"") + path + QDir::separator() + "ioquake3.x86.exe\" +set r_mode -1";
const QString path = QFileDialog::getExistingDirectory (this, tr("Directory"));
if (path.isEmpty())
return;
settings.setQuakePath(path);
}
ioq3 = QString("\"") + settings.getQuakePath() + "/ioquake3.x86.exe\"";
#elif defined Q_OS_MAC
ioq3 = "open -a ioquake3 --args +set r_mode -1";
ioq3 = "open -a ioquake3 --args";
#elif defined Q_OS_UNIX
ioq3 = "ioquake3 +set r_mode -1";
ioq3 = "ioquake3";
#else
#error "Unsupported platform"
#endif
int r_mode = settings.getResolutionMode();
int r_width = settings.getResolutionWidth();
int r_height = settings.getResolutionHeight();
if(ioWedited == true && ioHedited == true)
// Handle modes outside what ioquake3 recognize.
if (r_mode == 12)
{
resOption = " +set r_customwidth " + QString::number(ioWidth) + " +set r_customheight " + QString::number(ioHeight);
r_mode = -1;
r_width = 1280;
r_height = 720;
}
if(resOption == NULL)
else if (r_mode == 13)
{
resOption = "";
r_mode = -1;
r_width = 1920;
r_height = 1080;
}
if(screenOption == NULL)
else if (r_mode == 14)
{
screenOption = "";
r_mode = -1;
r_width = 1280;
r_height = 800;
}
if(!QProcess::startDetached(ioq3+resOption+screenOption))
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);
}
ioq3 += QString(" +set r_fullscreen %1").arg(settings.getResolutionFullscreen() ? "1" : "0");
if(!QProcess::startDetached(ioq3))
{
QMessageBox ioq3Failed;
ioq3Failed.setText("ioquake3 failed to start!\nIs it installed?\n");
ioq3Failed.exec();
}
}
void ioLaunch::on_cbResolution_highlighted(int /*index*/)
{
ioWedited = false;
ioHedited = false;
}
void ioLaunch::on_cbResolution_currentIndexChanged(int index)
{
ioWedited = false;
ioHedited = false;
switch(index)
if (index == 0)
{
case 0:
{
resOption = "";
break;
// Desktop.
settings.setResolutionMode(-2);
}
case 1:
else if (index == 1)
{
ioWidth = QApplication::desktop()->screenGeometry().width();
ioHeight = QApplication::desktop()->screenGeometry().height();
// Custom.
settings.setResolutionMode(-1);
}
else if (index >= 2)
{
// Predefined.
settings.setResolutionMode(index - 2);
}
resOption = " +set r_customwidth " + QString::number(ioWidth) + " +set r_customheight " + QString::number(ioHeight);
break;
}
case 2:
if (index == 1)
{
resOption = " +set r_customwidth 320 +set r_customheight 240";
break;
ui->sbWidth->setEnabled(true);
ui->sbHeight->setEnabled(true);
}
case 3:
else
{
resOption = " +set r_customwidth 400 +set r_customheight 300";
break;
}
case 4:
{
resOption = " +set r_customwidth 512 +set r_customheight 384";
break;
}
case 5:
{
resOption = " +set r_customwidth 640 +set r_customheight 480";
break;
}
case 6:
{
resOption = " +set r_customwidth 800 +set r_customheight 600";
break;
}
case 7:
{
resOption = " +set r_customwidth 960 +set r_customheight 720";
break;
}
case 8:
{
resOption = " +set r_customwidth 1024 +set r_customheight 768";
break;
}
case 9:
{
resOption = " +set r_customwidth 1152 +set r_customheight 864";
break;
}
case 10:
{
resOption = " +set r_customwidth 1280 +set r_customheight 1024";
break;
}
case 11:
{
resOption = " +set r_customwidth 1600 +set r_customheight 1200";
break;
}
case 12:
{
resOption = " +set r_customwidth 2048 +set r_customheight 1536";
break;
}
case 13:
{
resOption = " +set r_customwidth 856 +set r_customheight 480";
break;
}
case 14:
{
resOption = " +set r_customwidth 1280 +set r_customheight 720";
break;
}
case 15:
{
resOption = " +set r_customwidth 1920 +set r_customheight 1080";
break;
}
case 16:
{
resOption = " +set r_customwidth 1280 +set r_customheight 800";
break;
}
default:
{
resOption = "";
break;
}
ui->sbWidth->setEnabled(false);
ui->sbHeight->setEnabled(false);
}
}
@ -171,7 +196,7 @@ void ioLaunch::on_rbFull_toggled(bool checked)
{
if(checked)
{
screenOption = " +set r_fullscreen 1";
settings.setResolutionFullscreen(true);
}
}
@ -179,41 +204,99 @@ void ioLaunch::on_rbWin_toggled(bool checked)
{
if(checked)
{
screenOption = " +set r_fullscreen 0";
settings.setResolutionFullscreen(false);
}
}
void ioLaunch::on_rbDefault_toggled(bool checked)
{
if(checked)
{
screenOption = "";
}
}
void ioLaunch::on_sbWidth_valueChanged(int arg1)
{
ioWidth = 0;
if(arg1 >= 0)
{
ioWidth = arg1;
ioWedited = true;
}
else{
ioWedited = false;
}
settings.setResolutionWidth(arg1);
}
void ioLaunch::on_sbHeight_valueChanged(int arg1)
{
ioHeight = 0;
if(arg1 >= 0)
settings.setResolutionHeight(arg1);
}
// 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)
{
ioHeight = arg1;
ioHedited = true;
// 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 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);
}
}
else{
ioHedited = false;
}
}

View file

@ -8,6 +8,7 @@
#include <QtGlobal>
#include <QFileDialog>
#include <QDir>
#include "settings.h"
namespace Ui {
class ioLaunch;
@ -24,34 +25,22 @@ public:
private slots:
void on_btnLaunch_clicked();
void on_cbResolution_highlighted(int index);
void on_cbResolution_currentIndexChanged(int index);
void on_rbFull_toggled(bool checked);
void on_rbWin_toggled(bool checked);
void on_rbDefault_toggled(bool checked);
void on_sbWidth_valueChanged(int arg1);
void on_sbHeight_valueChanged(int arg1);
private:
Ui::ioLaunch *ui;
QString ioq3;
QString resOption;
QString screenOption;
QMessageBox msg;
QMessageBox ioq3Failed;
QDir directory;
int ioWidth;
int ioHeight;
bool ioWedited;
bool ioHedited;
void parseQuake3Config();
Ui::ioLaunch *ui;
Settings settings;
QString homePath;
};
#endif // MAINWINDOW_H

View file

@ -137,22 +137,6 @@ QTabWidget::tab-bar{
<attribute name="title">
<string>Settings</string>
</attribute>
<widget class="QRadioButton" name="rbDefault">
<property name="geometry">
<rect>
<x>110</x>
<y>40</y>
<width>91</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Default</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QComboBox" name="cbResolution">
<property name="geometry">
<rect>
@ -164,12 +148,12 @@ QTabWidget::tab-bar{
</property>
<item>
<property name="text">
<string>Default</string>
<string>Native</string>
</property>
</item>
<item>
<property name="text">
<string>Native</string>
<string>Custom</string>
</property>
</item>
<item>
@ -264,7 +248,7 @@ QTabWidget::tab-bar{
<widget class="QRadioButton" name="rbWin">
<property name="geometry">
<rect>
<x>310</x>
<x>200</x>
<y>40</y>
<width>121</width>
<height>21</height>
@ -329,7 +313,7 @@ QTabWidget::tab-bar{
<widget class="QRadioButton" name="rbFull">
<property name="geometry">
<rect>
<x>200</x>
<x>90</x>
<y>40</y>
<width>111</width>
<height>21</height>
@ -339,7 +323,7 @@ QTabWidget::tab-bar{
<string>FullScreen</string>
</property>
<property name="checked">
<bool>false</bool>
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_4">

94
settings.cpp Normal file
View file

@ -0,0 +1,94 @@
/*
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 <QString>
#include "settings.h"
Settings::Settings() :
settings("ioquake", "launch")
{
}
bool Settings::getHaveRun() const
{
return settings.value("haveRun").toBool();
}
void Settings::setHaveRun(bool value)
{
settings.setValue("haveRun", value);
}
QString Settings::getQuakePath() const
{
return settings.value("quakePath").toString();
}
bool Settings::containsQuakePath() const
{
return settings.contains("quakePath");
}
void Settings::setQuakePath(const QString &path)
{
settings.setValue("quakePath", path);
}
int Settings::getResolutionMode() const
{
return settings.value("resolution/mode", 3).toInt();
}
void Settings::setResolutionMode(int mode)
{
settings.setValue("resolution/mode", mode);
}
int Settings::getResolutionWidth() const
{
return settings.value("resolution/width", 1600).toInt();
}
void Settings::setResolutionWidth(int width)
{
settings.setValue("resolution/width", width);
}
int Settings::getResolutionHeight() const
{
return settings.value("resolution/height", 1024).toInt();
}
void Settings::setResolutionHeight(int height)
{
settings.setValue("resolution/height", height);
}
bool Settings::getResolutionFullscreen() const
{
return settings.value("resolution/fullscreen", 1).toBool();
}
void Settings::setResolutionFullscreen(bool value)
{
settings.setValue("resolution/fullscreen", value);
}

58
settings.h Normal file
View file

@ -0,0 +1,58 @@
/*
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 SETTINGS_H
#define SETTINGS_H
#include <QSettings>
class QString;
class Settings
{
public:
Settings();
bool getHaveRun() const;
void setHaveRun(bool value);
QString getQuakePath() const;
bool containsQuakePath() const;
void setQuakePath(const QString &path);
int getResolutionMode() const;
void setResolutionMode(int mode);
int getResolutionWidth() const;
void setResolutionWidth(int width);
int getResolutionHeight() const;
void setResolutionHeight(int height);
bool getResolutionFullscreen() const;
void setResolutionFullscreen(bool value);
private:
QSettings settings;
};
#endif // SETTINGS_H