|
|
|
#include "maindialog.hpp"
|
|
|
|
|
|
|
|
#include <components/version/version.hpp>
|
|
|
|
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QDate>
|
|
|
|
#include <QTime>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QFontDatabase>
|
|
|
|
#include <QInputDialog>
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QCloseEvent>
|
|
|
|
#include <QTextCodec>
|
|
|
|
#include <QProcess>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QDir>
|
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include "unshieldthread.hpp"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "textslotmsgbox.hpp"
|
|
|
|
|
|
|
|
#include "utils/checkablemessagebox.hpp"
|
|
|
|
|
|
|
|
#include "playpage.hpp"
|
|
|
|
#include "graphicspage.hpp"
|
|
|
|
#include "datafilespage.hpp"
|
|
|
|
|
|
|
|
Launcher::MainDialog::MainDialog(QWidget *parent)
|
|
|
|
: mGameSettings(mCfgMgr), QMainWindow (parent)
|
|
|
|
{
|
|
|
|
// Install the stylesheet font
|
|
|
|
QFile file;
|
|
|
|
QFontDatabase fontDatabase;
|
|
|
|
|
|
|
|
const QStringList fonts = fontDatabase.families();
|
|
|
|
|
|
|
|
// Check if the font is installed
|
|
|
|
if (!fonts.contains("EB Garamond")) {
|
|
|
|
|
|
|
|
QString font = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
|
|
|
file.setFileName(font);
|
|
|
|
|
|
|
|
if (!file.exists()) {
|
|
|
|
font = QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
|
|
|
}
|
|
|
|
|
|
|
|
fontDatabase.addApplicationFont(font);
|
|
|
|
}
|
|
|
|
|
|
|
|
setupUi(this);
|
|
|
|
|
|
|
|
iconWidget->setViewMode(QListView::IconMode);
|
|
|
|
iconWidget->setWrapping(false);
|
|
|
|
iconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure
|
|
|
|
iconWidget->setIconSize(QSize(48, 48));
|
|
|
|
iconWidget->setMovement(QListView::Static);
|
|
|
|
|
|
|
|
iconWidget->setSpacing(4);
|
|
|
|
iconWidget->setCurrentRow(0);
|
|
|
|
iconWidget->setFlow(QListView::LeftToRight);
|
|
|
|
|
|
|
|
QPushButton *playButton = new QPushButton(tr("Play"));
|
|
|
|
buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole);
|
|
|
|
|
|
|
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
|
|
|
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(play()));
|
|
|
|
|
|
|
|
// Remove what's this? button
|
|
|
|
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
|
|
|
|
|
// Add version information to bottom of the window
|
|
|
|
QString revision(OPENMW_VERSION_COMMITHASH);
|
|
|
|
QString tag(OPENMW_VERSION_TAGHASH);
|
|
|
|
|
|
|
|
if (revision == tag) {
|
|
|
|
versionLabel->setText(tr("OpenMW %0 release").arg(OPENMW_VERSION));
|
|
|
|
} else {
|
|
|
|
versionLabel->setText(tr("OpenMW development (%0)").arg(revision.left(10)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the compile date and time
|
|
|
|
versionLabel->setToolTip(tr("Compiled on %0 %1").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(),
|
|
|
|
QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate),
|
|
|
|
QLocale(QLocale::C).toTime(QString(__TIME__).simplified(),
|
|
|
|
QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate)));
|
|
|
|
|
|
|
|
createIcons();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::createIcons()
|
|
|
|
{
|
|
|
|
if (!QIcon::hasThemeIcon("document-new"))
|
|
|
|
QIcon::setThemeName("tango");
|
|
|
|
|
|
|
|
// We create a fallback icon because the default fallback doesn't work
|
|
|
|
QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png");
|
|
|
|
|
|
|
|
QListWidgetItem *playButton = new QListWidgetItem(iconWidget);
|
|
|
|
playButton->setIcon(QIcon(":/images/openmw.png"));
|
|
|
|
playButton->setText(tr("Play"));
|
|
|
|
playButton->setTextAlignment(Qt::AlignCenter);
|
|
|
|
playButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
|
|
|
|
|
|
QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget);
|
|
|
|
graphicsButton->setIcon(QIcon::fromTheme("video-display", graphicsIcon));
|
|
|
|
graphicsButton->setText(tr("Graphics"));
|
|
|
|
graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute);
|
|
|
|
graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
|
|
|
|
|
|
QListWidgetItem *dataFilesButton = new QListWidgetItem(iconWidget);
|
|
|
|
dataFilesButton->setIcon(QIcon(":/images/openmw-plugin.png"));
|
|
|
|
dataFilesButton->setText(tr("Data Files"));
|
|
|
|
dataFilesButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
|
|
|
dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
|
|
|
|
|
|
connect(iconWidget,
|
|
|
|
SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
|
|
|
|
this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::createPages()
|
|
|
|
{
|
|
|
|
mPlayPage = new PlayPage(this);
|
|
|
|
mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this);
|
|
|
|
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
|
|
|
|
|
|
|
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
|
|
|
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
|
|
|
mPlayPage->setProfilesIndex(mDataFilesPage->profilesIndex());
|
|
|
|
|
|
|
|
// Add the pages to the stacked widget
|
|
|
|
pagesWidget->addWidget(mPlayPage);
|
|
|
|
pagesWidget->addWidget(mGraphicsPage);
|
|
|
|
pagesWidget->addWidget(mDataFilesPage);
|
|
|
|
|
|
|
|
// Select the first page
|
|
|
|
iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select);
|
|
|
|
|
|
|
|
connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play()));
|
|
|
|
|
|
|
|
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int)));
|
|
|
|
connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::showFirstRunDialog()
|
|
|
|
{
|
|
|
|
QStringList iniPaths;
|
|
|
|
|
|
|
|
foreach (const QString &path, mGameSettings.getDataDirs()) {
|
|
|
|
QDir dir(path);
|
|
|
|
dir.setPath(dir.canonicalPath()); // Resolve symlinks
|
|
|
|
|
|
|
|
if (dir.exists(QString("Morrowind.ini")))
|
|
|
|
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!dir.cdUp())
|
|
|
|
continue; // Cannot move from Data Files
|
|
|
|
|
|
|
|
if (dir.exists(QString("Morrowind.ini")))
|
|
|
|
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ask the user where the Morrowind.ini is
|
|
|
|
if (iniPaths.empty()) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error detecting Morrowind configuration"));
|
|
|
|
msgBox.setIcon(QMessageBox::Warning);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not find Morrowind.ini</b><br><br> \
|
|
|
|
OpenMW needs to import settings from this file.<br><br> \
|
|
|
|
Press \"Browse...\" to specify the location manually.<br>"));
|
|
|
|
|
|
|
|
QAbstractButton *dirSelectButton =
|
|
|
|
msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole);
|
|
|
|
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
QString iniFile;
|
|
|
|
if (msgBox.clickedButton() == dirSelectButton) {
|
|
|
|
iniFile = QFileDialog::getOpenFileName(
|
|
|
|
NULL,
|
|
|
|
QObject::tr("Select configuration file"),
|
|
|
|
QDir::currentPath(),
|
|
|
|
QString(tr("Morrowind configuration file (*.ini)")));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iniFile.isEmpty())
|
|
|
|
return false; // Cancel was clicked;
|
|
|
|
|
|
|
|
QFileInfo info(iniFile);
|
|
|
|
iniPaths.clear();
|
|
|
|
iniPaths.append(info.absoluteFilePath());
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckableMessageBox msgBox(this);
|
|
|
|
msgBox.setWindowTitle(tr("Morrowind installation detected"));
|
|
|
|
|
|
|
|
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion);
|
|
|
|
int size = QApplication::style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
|
|
|
|
msgBox.setIconPixmap(icon.pixmap(size, size));
|
|
|
|
|
|
|
|
QAbstractButton *importerButton =
|
|
|
|
msgBox.addButton(tr("Import"), QDialogButtonBox::AcceptRole); // ActionRole doesn't work?!
|
|
|
|
QAbstractButton *skipButton =
|
|
|
|
msgBox.addButton(tr("Skip"), QDialogButtonBox::RejectRole);
|
|
|
|
|
|
|
|
Q_UNUSED(skipButton); // Surpress compiler unused warning
|
|
|
|
|
|
|
|
msgBox.setStandardButtons(QDialogButtonBox::NoButton);
|
|
|
|
msgBox.setText(tr("<br><b>An existing Morrowind configuration was detected</b><br> \
|
|
|
|
<br>Would you like to import settings from Morrowind.ini?<br> \
|
|
|
|
<br><b>Warning: In most cases OpenMW needs these settings to run properly</b><br>"));
|
|
|
|
msgBox.setCheckBoxText(tr("Include selected masters and plugins (creates a new profile)"));
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
|
|
|
|
if (msgBox.clickedButton() == importerButton) {
|
|
|
|
|
|
|
|
if (iniPaths.count() > 1) {
|
|
|
|
// Multiple Morrowind.ini files found
|
|
|
|
bool ok;
|
|
|
|
QString path = QInputDialog::getItem(this, tr("Multiple configurations found"),
|
|
|
|
tr("<br><b>There are multiple Morrowind.ini files found.</b><br><br> \
|
|
|
|
Please select the one you wish to import from:"), iniPaths, 0, false, &ok);
|
|
|
|
if (ok && !path.isEmpty()) {
|
|
|
|
iniPaths.clear();
|
|
|
|
iniPaths.append(path);
|
|
|
|
} else {
|
|
|
|
// Cancel was clicked
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the file if it doesn't already exist, else the importer will fail
|
|
|
|
QString path = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + QString("openmw.cfg");
|
|
|
|
QFile file(path);
|
|
|
|
|
|
|
|
if (!file.exists()) {
|
|
|
|
if (!file.open(QIODevice::ReadWrite)) {
|
|
|
|
// File cannot be created
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Construct the arguments to run the importer
|
|
|
|
QStringList arguments;
|
|
|
|
|
|
|
|
if (msgBox.isChecked())
|
|
|
|
arguments.append(QString("--game-files"));
|
|
|
|
|
|
|
|
arguments.append(QString("--encoding"));
|
|
|
|
arguments.append(mGameSettings.value(QString("encoding"), QString("win1252")));
|
|
|
|
arguments.append(QString("--ini"));
|
|
|
|
arguments.append(iniPaths.first());
|
|
|
|
arguments.append(QString("--cfg"));
|
|
|
|
arguments.append(path);
|
|
|
|
|
|
|
|
if (!startProgram(QString("mwiniimport"), arguments, false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Re-read the game settings
|
|
|
|
if (!setupGameSettings())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Add a new profile
|
|
|
|
if (msgBox.isChecked()) {
|
|
|
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), QString("Imported"));
|
|
|
|
mLauncherSettings.remove(QString("Profiles/Imported/content"));
|
|
|
|
|
|
|
|
QStringList contents = mGameSettings.values(QString("content"));
|
|
|
|
foreach (const QString &content, contents) {
|
|
|
|
mLauncherSettings.setMultiValue(QString("Profiles/Imported/content"), content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::setup()
|
|
|
|
{
|
|
|
|
if (!setupLauncherSettings())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!setupGameSettings())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!setupGraphicsSettings())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check if we need to show the importer
|
|
|
|
if (mLauncherSettings.value(QString("General/firstrun"), QString("true")) == QLatin1String("true"))
|
|
|
|
{
|
|
|
|
if (!showFirstRunDialog())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now create the pages as they need the settings
|
|
|
|
createPages();
|
|
|
|
|
|
|
|
// Call this so we can exit on Ogre/SDL errors before mainwindow is shown
|
|
|
|
if (!mGraphicsPage->loadSettings())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
loadSettings();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
|
|
|
|
{
|
|
|
|
if (!current)
|
|
|
|
current = previous;
|
|
|
|
|
|
|
|
int currentIndex = iconWidget->row(current);
|
|
|
|
int previousIndex = iconWidget->row(previous);
|
|
|
|
|
|
|
|
pagesWidget->setCurrentIndex(currentIndex);
|
|
|
|
|
|
|
|
DataFilesPage *previousPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(previousIndex));
|
|
|
|
DataFilesPage *currentPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(currentIndex));
|
|
|
|
|
|
|
|
//special call to update/save data files page list view when it's displayed/hidden.
|
|
|
|
if (previousPage)
|
|
|
|
{
|
|
|
|
if (previousPage->objectName() == "DataFilesPage")
|
|
|
|
previousPage->saveSettings();
|
|
|
|
}
|
|
|
|
else if (currentPage)
|
|
|
|
{
|
|
|
|
if (currentPage->objectName() == "DataFilesPage")
|
|
|
|
currentPage->loadSettings();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::setupLauncherSettings()
|
|
|
|
{
|
|
|
|
mLauncherSettings.setMultiValueEnabled(true);
|
|
|
|
|
|
|
|
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
|
|
|
|
|
|
|
QStringList paths;
|
|
|
|
paths.append(QString("launcher.cfg"));
|
|
|
|
paths.append(userPath + QString("launcher.cfg"));
|
|
|
|
|
|
|
|
foreach (const QString &path, paths) {
|
|
|
|
qDebug() << "Loading config file:" << qPrintable(path);
|
|
|
|
QFile file(path);
|
|
|
|
if (file.exists()) {
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QTextStream stream(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mLauncherSettings.readFile(stream);
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
bool Launcher::expansions(Launcher::UnshieldThread& cd)
|
|
|
|
{
|
|
|
|
if(cd.BloodmoonDone())
|
|
|
|
{
|
|
|
|
cd.Done();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMessageBox expansionsBox;
|
|
|
|
expansionsBox.setText(QObject::tr("<br>Would you like to install expansions now ? (make sure you have the disc)<br> \
|
|
|
|
If you want to install both Bloodmoon and Tribunal, you have to install Tribunal first.<br>"));
|
|
|
|
|
|
|
|
QAbstractButton* tribunalButton = NULL;
|
|
|
|
if(!cd.TribunalDone())
|
|
|
|
tribunalButton = expansionsBox.addButton(QObject::tr("&Tribunal"), QMessageBox::ActionRole);
|
|
|
|
|
|
|
|
QAbstractButton* bloodmoonButton = expansionsBox.addButton(QObject::tr("&Bloodmoon"), QMessageBox::ActionRole);
|
|
|
|
QAbstractButton* noneButton = expansionsBox.addButton(QObject::tr("&None"), QMessageBox::ActionRole);
|
|
|
|
|
|
|
|
expansionsBox.exec();
|
|
|
|
|
|
|
|
if(expansionsBox.clickedButton() == noneButton)
|
|
|
|
{
|
|
|
|
cd.Done();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if(expansionsBox.clickedButton() == tribunalButton)
|
|
|
|
{
|
|
|
|
|
|
|
|
TextSlotMsgBox cdbox;
|
|
|
|
cdbox.setStandardButtons(QMessageBox::Cancel);
|
|
|
|
|
|
|
|
QObject::connect(&cd,SIGNAL(signalGUI(const QString&)), &cdbox, SLOT(setTextSlot(const QString&)));
|
|
|
|
QObject::connect(&cd,SIGNAL(close()), &cdbox, SLOT(reject()));
|
|
|
|
|
|
|
|
cd.SetTribunalPath(
|
|
|
|
QFileDialog::getOpenFileName(
|
|
|
|
NULL,
|
|
|
|
QObject::tr("Select data1.hdr from Tribunal Installation CD (Tribunal/data1.hdr on GOTY CDs)"),
|
|
|
|
QDir::currentPath(),
|
|
|
|
QString(QObject::tr("Installshield hdr file (*.hdr)"))).toUtf8().constData());
|
|
|
|
|
|
|
|
cd.start();
|
|
|
|
cdbox.exec();
|
|
|
|
}
|
|
|
|
else if(expansionsBox.clickedButton() == bloodmoonButton)
|
|
|
|
{
|
|
|
|
|
|
|
|
TextSlotMsgBox cdbox;
|
|
|
|
cdbox.setStandardButtons(QMessageBox::Cancel);
|
|
|
|
|
|
|
|
QObject::connect(&cd,SIGNAL(signalGUI(const QString&)), &cdbox, SLOT(setTextSlot(const QString&)));
|
|
|
|
QObject::connect(&cd,SIGNAL(close()), &cdbox, SLOT(reject()));
|
|
|
|
|
|
|
|
cd.SetBloodmoonPath(
|
|
|
|
QFileDialog::getOpenFileName(
|
|
|
|
NULL,
|
|
|
|
QObject::tr("Select data1.hdr from Bloodmoon Installation CD (Bloodmoon/data1.hdr on GOTY CDs)"),
|
|
|
|
QDir::currentPath(),
|
|
|
|
QString(QObject::tr("Installshield hdr file (*.hdr)"))).toUtf8().constData());
|
|
|
|
|
|
|
|
cd.start();
|
|
|
|
cdbox.exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif // WIN32
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::setupGameSettings()
|
|
|
|
{
|
|
|
|
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
|
|
|
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
|
|
|
|
|
|
|
// Load the user config file first, separately
|
|
|
|
// So we can write it properly, uncontaminated
|
|
|
|
QString path = userPath + QLatin1String("openmw.cfg");
|
|
|
|
QFile file(path);
|
|
|
|
|
|
|
|
qDebug() << "Loading config file:" << qPrintable(path);
|
|
|
|
|
|
|
|
if (file.exists()) {
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QTextStream stream(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mGameSettings.readUserFile(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now the rest
|
|
|
|
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 config file:" << qPrintable(path);
|
|
|
|
|
|
|
|
QFile file(path);
|
|
|
|
if (file.exists()) {
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QTextStream stream(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mGameSettings.readFile(stream);
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList dataDirs;
|
|
|
|
|
|
|
|
// Check if the paths actually contain data files
|
|
|
|
foreach (const QString path, mGameSettings.getDataDirs()) {
|
|
|
|
QDir dir(path);
|
|
|
|
QStringList filters;
|
|
|
|
filters << "*.esp" << "*.esm" << "*.omwgame" << "*.omwaddon";
|
|
|
|
|
|
|
|
if (!dir.entryList(filters).isEmpty())
|
|
|
|
dataDirs.append(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dataDirs.isEmpty())
|
|
|
|
{
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error detecting Morrowind installation"));
|
|
|
|
msgBox.setIcon(QMessageBox::Warning);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not find the Data Files location</b><br><br> \
|
|
|
|
The directory containing the data files was not found.<br><br> \
|
|
|
|
Press \"Browse...\" to specify the location manually.<br>"));
|
|
|
|
|
|
|
|
QAbstractButton *dirSelectButton =
|
|
|
|
msgBox.addButton(QObject::tr("Browse to &Install..."), QMessageBox::ActionRole);
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
QAbstractButton *cdSelectButton =
|
|
|
|
msgBox.addButton(QObject::tr("Browse to &CD..."), QMessageBox::ActionRole);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
QString selectedFile;
|
|
|
|
if (msgBox.clickedButton() == dirSelectButton) {
|
|
|
|
selectedFile = QFileDialog::getOpenFileName(
|
|
|
|
NULL,
|
|
|
|
QObject::tr("Select master file"),
|
|
|
|
QDir::currentPath(),
|
|
|
|
QString(tr("Morrowind master file (*.esm)")));
|
|
|
|
}
|
|
|
|
#ifndef WIN32
|
|
|
|
else if(msgBox.clickedButton() == cdSelectButton) {
|
|
|
|
UnshieldThread cd;
|
|
|
|
|
|
|
|
{
|
|
|
|
TextSlotMsgBox cdbox;
|
|
|
|
cdbox.setStandardButtons(QMessageBox::Cancel);
|
|
|
|
|
|
|
|
QObject::connect(&cd,SIGNAL(signalGUI(const QString&)), &cdbox, SLOT(setTextSlot(const QString&)));
|
|
|
|
QObject::connect(&cd,SIGNAL(close()), &cdbox, SLOT(reject()));
|
|
|
|
|
|
|
|
cd.SetMorrowindPath(
|
|
|
|
QFileDialog::getOpenFileName(
|
|
|
|
NULL,
|
|
|
|
QObject::tr("Select data1.hdr from Morrowind Installation CD"),
|
|
|
|
QDir::currentPath(),
|
|
|
|
QString(tr("Installshield hdr file (*.hdr)"))).toUtf8().constData());
|
|
|
|
|
|
|
|
cd.SetOutputPath(
|
|
|
|
QFileDialog::getExistingDirectory(
|
|
|
|
NULL,
|
|
|
|
QObject::tr("Select where to extract files to"),
|
|
|
|
QDir::currentPath(),
|
|
|
|
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toUtf8().constData());
|
|
|
|
|
|
|
|
cd.start();
|
|
|
|
cdbox.exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
while(expansions(cd));
|
|
|
|
|
|
|
|
selectedFile = QString::fromStdString(cd.GetMWEsmPath());
|
|
|
|
}
|
|
|
|
#endif // WIN32
|
|
|
|
|
|
|
|
if (selectedFile.isEmpty())
|
|
|
|
return false; // Cancel was clicked;
|
|
|
|
|
|
|
|
QFileInfo info(selectedFile);
|
|
|
|
|
|
|
|
// Add the new dir to the settings file and to the data dir container
|
|
|
|
mGameSettings.setMultiValue(QString("data"), info.absolutePath());
|
|
|
|
mGameSettings.addDataDir(info.absolutePath());
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::setupGraphicsSettings()
|
|
|
|
{
|
|
|
|
mGraphicsSettings.setMultiValueEnabled(false);
|
|
|
|
|
|
|
|
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
|
|
|
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
|
|
|
|
|
|
|
QFile localDefault(QString("settings-default.cfg"));
|
|
|
|
QFile globalDefault(globalPath + QString("settings-default.cfg"));
|
|
|
|
|
|
|
|
if (!localDefault.exists() && !globalDefault.exists()) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error reading OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not find settings-default.cfg</b><br><br> \
|
|
|
|
The problem may be due to an incomplete installation of OpenMW.<br> \
|
|
|
|
Reinstalling OpenMW may resolve the problem."));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QStringList paths;
|
|
|
|
paths.append(globalPath + QString("settings-default.cfg"));
|
|
|
|
paths.append(QString("settings-default.cfg"));
|
|
|
|
paths.append(userPath + QString("settings.cfg"));
|
|
|
|
|
|
|
|
foreach (const QString &path, paths) {
|
|
|
|
qDebug() << "Loading config file:" << qPrintable(path);
|
|
|
|
QFile file(path);
|
|
|
|
if (file.exists()) {
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QTextStream stream(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mGraphicsSettings.readFile(stream);
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::loadSettings()
|
|
|
|
{
|
|
|
|
int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt();
|
|
|
|
int height = mLauncherSettings.value(QString("General/MainWindow/height")).toInt();
|
|
|
|
|
|
|
|
int posX = mLauncherSettings.value(QString("General/MainWindow/posx")).toInt();
|
|
|
|
int posY = mLauncherSettings.value(QString("General/MainWindow/posy")).toInt();
|
|
|
|
|
|
|
|
resize(width, height);
|
|
|
|
move(posX, posY);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::saveSettings()
|
|
|
|
{
|
|
|
|
QString width = QString::number(this->width());
|
|
|
|
QString height = QString::number(this->height());
|
|
|
|
|
|
|
|
mLauncherSettings.setValue(QString("General/MainWindow/width"), width);
|
|
|
|
mLauncherSettings.setValue(QString("General/MainWindow/height"), height);
|
|
|
|
|
|
|
|
QString posX = QString::number(this->pos().x());
|
|
|
|
QString posY = QString::number(this->pos().y());
|
|
|
|
|
|
|
|
mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX);
|
|
|
|
mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY);
|
|
|
|
|
|
|
|
mLauncherSettings.setValue(QString("General/firstrun"), QString("false"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::writeSettings()
|
|
|
|
{
|
|
|
|
// Now write all config files
|
|
|
|
saveSettings();
|
|
|
|
mGraphicsPage->saveSettings();
|
|
|
|
mDataFilesPage->saveSettings();
|
|
|
|
|
|
|
|
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
|
|
|
QDir dir(userPath);
|
|
|
|
|
|
|
|
if (!dir.exists()) {
|
|
|
|
if (!dir.mkpath(userPath)) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error creating OpenMW configuration directory"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not create %0</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(userPath));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Game settings
|
|
|
|
QFile file(userPath + QString("openmw.cfg"));
|
|
|
|
|
|
|
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
|
|
|
// File cannot be opened or created
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QTextStream stream(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mGameSettings.writeFile(stream);
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
// Graphics settings
|
|
|
|
file.setFileName(userPath + QString("settings.cfg"));
|
|
|
|
|
|
|
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
|
|
|
// File cannot be opened or created
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream.setDevice(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mGraphicsSettings.writeFile(stream);
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
// Launcher settings
|
|
|
|
file.setFileName(userPath + QString("launcher.cfg"));
|
|
|
|
|
|
|
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
|
|
|
// File cannot be opened or created
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error writing Launcher configuration file"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
|
|
|
Please make sure you have the right permissions \
|
|
|
|
and try again.<br>").arg(file.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream.setDevice(&file);
|
|
|
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
|
|
|
|
|
|
mLauncherSettings.writeFile(stream);
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::closeEvent(QCloseEvent *event)
|
|
|
|
{
|
|
|
|
writeSettings();
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::MainDialog::play()
|
|
|
|
{
|
|
|
|
if (!writeSettings()) {
|
|
|
|
qApp->quit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!mGameSettings.hasMaster()) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("No game file selected"));
|
|
|
|
msgBox.setIcon(QMessageBox::Warning);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>You do not have no game file selected.</b><br><br> \
|
|
|
|
OpenMW will not start without a game file selected.<br>"));
|
|
|
|
msgBox.exec();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Launch the game detached
|
|
|
|
startProgram(QString("openmw"), true);
|
|
|
|
qApp->quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Launcher::MainDialog::startProgram(const QString &name, const QStringList &arguments, bool detached)
|
|
|
|
{
|
|
|
|
QString path = name;
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
path.append(QString(".exe"));
|
|
|
|
#elif defined(Q_OS_MAC)
|
|
|
|
QDir dir(QCoreApplication::applicationDirPath());
|
|
|
|
path = dir.absoluteFilePath(name);
|
|
|
|
#else
|
|
|
|
path.prepend(QString("./"));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
QFile file(path);
|
|
|
|
|
|
|
|
QProcess process;
|
|
|
|
QFileInfo info(file);
|
|
|
|
|
|
|
|
if (!file.exists()) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
|
|
|
msgBox.setIcon(QMessageBox::Warning);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not find %1</b><br><br> \
|
|
|
|
The application is not found.<br> \
|
|
|
|
Please make sure OpenMW is installed correctly and try again.<br>").arg(info.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!info.isExecutable()) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
|
|
|
msgBox.setIcon(QMessageBox::Warning);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not start %1</b><br><br> \
|
|
|
|
The application is not executable.<br> \
|
|
|
|
Please make sure you have the right permissions and try again.<br>").arg(info.fileName()));
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start the executable
|
|
|
|
if (detached) {
|
|
|
|
if (!process.startDetached(path, arguments)) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not start %1</b><br><br> \
|
|
|
|
An error occurred while starting %1.<br><br> \
|
|
|
|
Press \"Show Details...\" for more information.<br>").arg(info.fileName()));
|
|
|
|
msgBox.setDetailedText(process.errorString());
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
process.start(path, arguments);
|
|
|
|
if (!process.waitForFinished()) {
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error starting executable"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Could not start %1</b><br><br> \
|
|
|
|
An error occurred while starting %1.<br><br> \
|
|
|
|
Press \"Show Details...\" for more information.<br>").arg(info.fileName()));
|
|
|
|
msgBox.setDetailedText(process.errorString());
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.exitCode() != 0 || process.exitStatus() == QProcess::CrashExit) {
|
|
|
|
QString error(process.readAllStandardError());
|
|
|
|
error.append(tr("\nArguments:\n"));
|
|
|
|
error.append(arguments.join(" "));
|
|
|
|
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setWindowTitle(tr("Error running executable"));
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.setText(tr("<br><b>Executable %1 returned an error</b><br><br> \
|
|
|
|
An error occurred while running %1.<br><br> \
|
|
|
|
Press \"Show Details...\" for more information.<br>").arg(info.fileName()));
|
|
|
|
msgBox.setDetailedText(error);
|
|
|
|
msgBox.exec();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|