diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 7c4cb5f7e..3fef62bc6 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,8 +1,22 @@ #include +#include +#include +#include #include +#include +#include +#include +#include #include +#include + +#include + #include "maindialog.hpp" +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" + int main(int argc, char *argv[]) { @@ -30,14 +44,136 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - MainDialog mainWin; + // Create setting file handlers + + Files::ConfigurationManager cfgMgr; + QString userPath = QString::fromStdString(cfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(cfgMgr.getGlobalPath().string()); + + GameSettings gameSettings(cfgMgr); + GraphicsSettings graphicsSettings; + + QStringList paths; + paths.append(userPath + QString("openmw.cfg")); + paths.append(QString("openmw.cfg")); + paths.append(globalPath + QString("openmw.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + gameSettings.readFile(stream); + } + file.close(); + } + + if (gameSettings.getDataDirs().isEmpty()) + { + QMessageBox msgBox; + msgBox.setWindowTitle("Error detecting Morrowind installation"); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(QObject::tr("
Could not find the Data Files location

\ + The directory containing the data files was not found.

\ + Press \"Browse...\" to specify the location manually.
")); + + QAbstractButton *dirSelectButton = + msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + QString selectedFile; + if (msgBox.clickedButton() == dirSelectButton) { + selectedFile = QFileDialog::getOpenFileName( + NULL, + QObject::tr("Select master file"), + QDir::currentPath(), + QString("Morrowind master file (*.esm)")); + } + + if (selectedFile.isEmpty()) + return 0; // Cancel was clicked; - if (mainWin.setup()) { + qDebug() << selectedFile; + QFileInfo info(selectedFile); - mainWin.show(); - return app.exec(); + // Add the new dir to the settings file and to the data dir container + gameSettings.setValue(QString("data"), info.absolutePath()); + gameSettings.addDataDir(info.absolutePath()); + + } + + // On to the graphics settings + qDebug() << userPath; + + QFile localDefault(QString("settings-default.cfg")); + QFile globalDefault(globalPath + QString("settings-default.cfg")); + + if (!localDefault.exists() && !globalDefault.exists()) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error reading OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ + The problem may be due to an incomplete installation of OpenMW.
\ + Reinstalling OpenMW may resolve the problem.")); + msgBox.exec(); + return 0; } + paths.clear(); + paths.append(globalPath + QString("settings-default.cfg")); + paths.append(QString("settings-default.cfg")); + + paths.append(userPath + QString("settings.cfg")); + paths.append(QString("settings.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + graphicsSettings.readFile(stream); + } + file.close(); + } + + + MainDialog mainWin; + mainWin.setup(); + + mainWin.show(); + QCoreApplication::processEvents(); + return app.exec(); + + return 0; } diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 32f03ddbe..2420c1e6c 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -1,13 +1,17 @@ #include +#include #include #include #include #include +#include + #include "gamesettings.hpp" -GameSettings::GameSettings() +GameSettings::GameSettings(Files::ConfigurationManager &cfg) + : mCfgMgr(cfg) { } @@ -15,11 +19,124 @@ GameSettings::~GameSettings() { } -bool GameSettings::writeFile(QTextStream &stream) +void GameSettings::validatePaths() { - QMap settings = SettingsBase::getSettings(); + qDebug() << "validate paths!"; + + if (mSettings.isEmpty()) + return; + + QStringList paths = mSettings.values(QString("data")); + Files::PathContainer dataDirs; + + foreach (const QString &path, paths) { + dataDirs.push_back(Files::PathContainer::value_type(path.toStdString())); + } + + // Parse the data dirs to convert the tokenized paths + mCfgMgr.processPaths(dataDirs); + +// // Replace the existing data paths with valid untokenized ones +// mSettings.remove(QString("data")); + mDataDirs.clear(); + + for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { + QString path = QString::fromStdString(it->string()); + path.remove(QChar('\"')); + + QDir dir(path); + if (dir.exists()) + mDataDirs.append(path); + } + + // Do the same for data-local + QString local = mSettings.value(QString("data-local")); - QMapIterator i(settings); + if (local.isEmpty()) + return; + + dataDirs.clear(); + dataDirs.push_back(Files::PathContainer::value_type(local.toStdString())); + + mCfgMgr.processPaths(dataDirs); +// mSettings.remove(QString("data-local")); + + if (!dataDirs.empty()) { + QString path = QString::fromStdString(dataDirs.front().string()); + path.remove(QChar('\"')); + + QDir dir(path); + if (dir.exists()) + mDataLocal = path; + } + qDebug() << mSettings; + + +} + +QStringList GameSettings::values(const QString &key, const QStringList &defaultValues) +{ + if (!mSettings.values(key).isEmpty()) + return mSettings.values(key); + return defaultValues; +} + +bool GameSettings::readFile(QTextStream &stream) +{ + QMap cache; + QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); + + while (!stream.atEnd()) { + QString line = stream.readLine().simplified(); + + if (line.isEmpty() || line.startsWith("#")) + continue; + + qDebug() << "line: " << line; + if (keyRe.indexIn(line) != -1) { + + QString key = keyRe.cap(1).simplified(); + QString value = keyRe.cap(2).simplified(); + + qDebug() << "key: " << key; + // There can be multiple data keys + if (key == QLatin1String("data")) { + cache.insertMulti(key, value); + } else { + cache.insert(key, value); + } + } + } + + if (mSettings.isEmpty()) { + mSettings = cache; // This is the first time we read a file + validatePaths(); + return true; + } + + // Replace values from previous settings + QMapIterator i(cache); + while (i.hasNext()) { + i.next(); + + // Don't remove existing data entries + if (i.key() == QLatin1String("data")) + continue; + + if (mSettings.contains(i.key())) + mSettings.remove(i.key()); + } + + // Merge the changed keys with those which didn't + mSettings.unite(cache); + validatePaths(); + qDebug() << mSettings; + return true; +} + +bool GameSettings::writeFile(QTextStream &stream) +{ + QMapIterator i(mSettings); while (i.hasNext()) { i.next(); diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index c81c67d97..717ce6e87 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -1,15 +1,50 @@ #ifndef GAMESETTINGS_HPP #define GAMESETTINGS_HPP -#include "settingsbase.hpp" +#include -class GameSettings : public SettingsBase> +#include + +class QTextStream; +class QStringList; +class QString; + +namespace Files { typedef std::vector PathContainer; + struct ConfigurationManager;} + +class GameSettings { public: - GameSettings(); + GameSettings(Files::ConfigurationManager &cfg); ~GameSettings(); - bool writeFile(QTextStream &stream); + inline QString value(const QString &key, const QString &defaultValue = QString()) + { + return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); + } + + + inline void setValue(const QString &key, const QString &value) + { + mSettings.insert(key, value); + } + + inline QStringList getDataDirs() { return mDataDirs; } + inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } + inline QString getDataLocal() {return mDataLocal; } + + QStringList values(const QString &key, const QStringList &defaultValues = QStringList()); + bool readFile(QTextStream &stream); + bool writeFile(QTextStream &stream); + +private: + Files::ConfigurationManager &mCfgMgr; + + void validatePaths(); + QMap mSettings; + + QStringList mDataDirs; + QString mDataLocal; }; #endif // GAMESETTINGS_HPP