Launcher improvements: ask for data dir and write it to cfg if none is found

and prevent removal of the default profile
pull/21/head
Pieter van der Kloet 13 years ago
parent 1512481c07
commit 5b54a658d8

@ -428,7 +428,7 @@ if (APPLE)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
set(CPACK_GENERATOR "DragNDrop") set(CPACK_GENERATOR "DragNDrop")
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})

@ -72,13 +72,13 @@ endif()
if (APPLE) if (APPLE)
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
"${APP_BUNDLE_DIR}/../launcher.qss") "${APP_BUNDLE_DIR}/resources/../launcher.qss")
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
"${APP_BUNDLE_DIR}/../launcher.cfg") "${APP_BUNDLE_DIR}/../launcher.cfg")
else() else()
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources/launcher.qss")
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.cfg configure_file(${CMAKE_SOURCE_DIR}/files/launcher.cfg
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.cfg") "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}launcher.cfg")
endif() endif()

@ -1,8 +1,6 @@
#include <QtGui> #include <QtGui>
#include <components/esm/esm_reader.hpp> #include <components/esm/esm_reader.hpp>
#include <components/files/collections.hpp>
#include <components/files/multidircollection.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include "datafilespage.hpp" #include "datafilespage.hpp"
@ -120,11 +118,12 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
connect(mPluginsTable, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); connect(mPluginsTable, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)));
connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&)));
createActions();
setupConfig(); setupConfig();
setupDataFiles(); setupDataFiles();
createActions();
} }
void DataFilesPage::setupConfig() void DataFilesPage::setupConfig()
@ -138,8 +137,7 @@ void DataFilesPage::setupConfig()
// Open our config file // Open our config file
mLauncherConfig = new QSettings(config, QSettings::IniFormat); mLauncherConfig = new QSettings(config, QSettings::IniFormat);
mLauncherConfig->sync(); file.close();
// Make sure we have no groups open // Make sure we have no groups open
while (!mLauncherConfig->group().isEmpty()) { while (!mLauncherConfig->group().isEmpty()) {
@ -162,13 +160,14 @@ void DataFilesPage::setupConfig()
// No current profile selected // No current profile selected
currentProfile = "Default"; currentProfile = "Default";
} }
mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(currentProfile));
mLauncherConfig->endGroup(); const int currentIndex = mProfilesComboBox->findText(currentProfile);
if (currentIndex != -1) {
// Profile is found
mProfilesComboBox->setCurrentIndex(currentIndex);
}
// Now we connect the combobox to do something if the profile changes mLauncherConfig->endGroup();
// This prevents strange behaviour while reading and appending the profiles
connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&)));
} }
@ -188,19 +187,51 @@ void DataFilesPage::setupDataFiles()
// Put the paths in a boost::filesystem vector to use with Files::Collections // Put the paths in a boost::filesystem vector to use with Files::Collections
Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>()); Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>());
mDataDirs = dataDirs;
std::string local(variables["data-local"].as<std::string>());
if (!local.empty()) std::string local = variables["data-local"].as<std::string>();
{ if (!local.empty()) {
mDataLocal.push_back(Files::PathContainer::value_type(local));
dataDirs.push_back(Files::PathContainer::value_type(local)); dataDirs.push_back(Files::PathContainer::value_type(local));
} }
if (dataDirs.empty()) mCfgMgr.processPaths(dataDirs);
{
dataDirs.push_back(mCfgMgr.getLocalPath()); while (dataDirs.empty()) {
// No valid data files directory found
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(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(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == dirSelectButton) {
QString dataDir = QFileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
"/home",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
dataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString()));
mDataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString()));
} else {
// Cancel
break;
}
} }
mCfgMgr.processPaths(dataDirs); // Check if cancel was clicked because we can't exit from while loop
if (dataDirs.empty()) {
QApplication::exit(1);
}
// Create a file collection for the dataDirs // Create a file collection for the dataDirs
Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as<bool>()); Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as<bool>());
@ -209,15 +240,13 @@ void DataFilesPage::setupDataFiles()
const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm");
unsigned int i = 0; // Row number unsigned int i = 0; // Row number
for (Files::MultiDirCollection::TIter iter(esm.begin()); iter!=esm.end(); ++iter) for (Files::MultiDirCollection::TIter iter(esm.begin()); iter!=esm.end(); ++iter) {
{
QString currentMaster = QString::fromStdString( QString currentMaster = QString::fromStdString(
boost::filesystem::path (iter->second.filename()).string()); boost::filesystem::path (iter->second.filename()).string());
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly); const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
if (itemList.isEmpty()) // Master is not yet in the widget if (itemList.isEmpty()) { // Master is not yet in the widget
{
mMastersWidget->insertRow(i); mMastersWidget->insertRow(i);
QTableWidgetItem *item = new QTableWidgetItem(currentMaster); QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
mMastersWidget->setItem(i, 0, item); mMastersWidget->setItem(i, 0, item);
@ -228,8 +257,7 @@ void DataFilesPage::setupDataFiles()
// Now on to the plugins // Now on to the plugins
const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp"); const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp");
for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) {
{
ESMReader fileReader; ESMReader fileReader;
QStringList availableMasters; // Will contain all found masters QStringList availableMasters; // Will contain all found masters
@ -245,8 +273,7 @@ void DataFilesPage::setupDataFiles()
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly); const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
if (itemList.isEmpty()) // Master is not yet in the widget if (itemList.isEmpty()) { // Master is not yet in the widget
{
mMastersWidget->insertRow(i); mMastersWidget->insertRow(i);
QTableWidgetItem *item = new QTableWidgetItem(currentMaster); QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
@ -435,18 +462,18 @@ void DataFilesPage::deleteProfile()
return; return;
} }
QMessageBox deleteMessageBox(this); QMessageBox msgBox(this);
deleteMessageBox.setWindowTitle(tr("Delete Profile")); msgBox.setWindowTitle(tr("Delete Profile"));
deleteMessageBox.setText(tr("Are you sure you want to delete <b>%0</b>?").arg(profile)); msgBox.setIcon(QMessageBox::Warning);
deleteMessageBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Cancel);
QAbstractButton *deleteButton = msgBox.setText(tr("Are you sure you want to delete <b>%0</b>?").arg(profile));
deleteMessageBox.addButton(tr("Delete"), QMessageBox::ActionRole);
deleteMessageBox.addButton(QMessageBox::Cancel); QAbstractButton *deleteButton =
msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
deleteMessageBox.exec(); msgBox.exec();
if (deleteMessageBox.clickedButton() == deleteButton) { if (msgBox.clickedButton() == deleteButton) {
// Make sure we have no groups open // Make sure we have no groups open
while (!mLauncherConfig->group().isEmpty()) { while (!mLauncherConfig->group().isEmpty()) {
mLauncherConfig->endGroup(); mLauncherConfig->endGroup();
@ -503,7 +530,6 @@ void DataFilesPage::moveUp()
void DataFilesPage::moveDown() void DataFilesPage::moveDown()
{ {
// Shift the selected plugins down one row // Shift the selected plugins down one row
if (!mPluginsTable->selectionModel()->hasSelection()) { if (!mPluginsTable->selectionModel()->hasSelection()) {
return; return;
} }
@ -919,9 +945,18 @@ void DataFilesPage::filterChanged(const QString filter)
void DataFilesPage::profileChanged(const QString &previous, const QString &current) void DataFilesPage::profileChanged(const QString &previous, const QString &current)
{ {
// Prevent the deletion of the default profile
if (current == "Default") {
mDeleteProfileAction->setEnabled(false);
} else {
mDeleteProfileAction->setEnabled(true);
}
if (!previous.isEmpty()) { if (!previous.isEmpty()) {
writeConfig(previous); writeConfig(previous);
mLauncherConfig->sync(); mLauncherConfig->sync();
} else {
return;
} }
uncheckPlugins(); uncheckPlugins();
@ -989,22 +1024,12 @@ void DataFilesPage::readConfig()
void DataFilesPage::writeConfig(QString profile) void DataFilesPage::writeConfig(QString profile)
{ {
// Don't overwrite the config if no plugins are found // Don't overwrite the config if no masters are found
if (mPluginsModel->rowCount() < 1) { if (mMastersWidget->rowCount() < 1) {
return;
}
if (profile.isEmpty()) {
profile = mProfilesComboBox->currentText();
}
if (profile.isEmpty()) {
return; return;
} }
// Prepare the OpenMW config // Open the OpenMW config as a QFile
// Open the config as a QFile
QFile file(QString::fromStdString((mCfgMgr.getUserPath()/"openmw.cfg").string())); QFile file(QString::fromStdString((mCfgMgr.getUserPath()/"openmw.cfg").string()));
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
@ -1023,10 +1048,14 @@ void DataFilesPage::writeConfig(QString profile)
QTextStream in(&file); QTextStream in(&file);
QByteArray buffer; QByteArray buffer;
// Remove all previous master/plugin entries from config // Remove all previous entries from config
while (!in.atEnd()) { while (!in.atEnd()) {
QString line = in.readLine(); QString line = in.readLine();
if (!line.contains("master") && !line.contains("plugin")) { if (!line.startsWith("master") &&
!line.startsWith("plugin") &&
!line.startsWith("data") &&
!line.startsWith("data-local"))
{
buffer += line += "\n"; buffer += line += "\n";
} }
} }
@ -1046,9 +1075,52 @@ void DataFilesPage::writeConfig(QString profile)
QApplication::exit(1); QApplication::exit(1);
} }
file.write(buffer); if (!buffer.isEmpty()) {
file.write(buffer);
}
QTextStream gameConfig(&file); QTextStream gameConfig(&file);
// First write the list of data dirs
mCfgMgr.processPaths(mDataDirs);
mCfgMgr.processPaths(mDataLocal);
QString path;
// data= directories
for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) {
path = QString::fromStdString(it->string());
path.remove(QChar('\"'));
// Make sure the string is quoted when it contains spaces
if (path.contains(" ")) {
gameConfig << "data=\"" << path << "\"" << endl;
} else {
gameConfig << "data=" << path << endl;
}
}
// data-local directory
if (!mDataLocal.empty()) {
path = QString::fromStdString(mDataLocal.front().string());
path.remove(QChar('\"'));
if (path.contains(" ")) {
gameConfig << "data-local=\"" << path << "\"" << endl;
} else {
gameConfig << "data-local=" << path << endl;
}
}
if (profile.isEmpty()) {
profile = mProfilesComboBox->currentText();
}
if (profile.isEmpty()) {
return;
}
// Make sure we have no groups open // Make sure we have no groups open
while (!mLauncherConfig->group().isEmpty()) { while (!mLauncherConfig->group().isEmpty()) {
mLauncherConfig->endGroup(); mLauncherConfig->endGroup();
@ -1061,7 +1133,7 @@ void DataFilesPage::writeConfig(QString profile)
mLauncherConfig->beginGroup(profile); mLauncherConfig->beginGroup(profile);
mLauncherConfig->remove(""); // Clear the subgroup mLauncherConfig->remove(""); // Clear the subgroup
// First write the masters to the configs // Now write the masters to the configs
const QStringList masters = selectedMasters(); const QStringList masters = selectedMasters();
// We don't use foreach because we need i // We don't use foreach because we need i
@ -1073,11 +1145,10 @@ void DataFilesPage::writeConfig(QString profile)
} }
// Now write all checked plugins // And finally write all checked plugins
const QStringList plugins = checkedPlugins(); const QStringList plugins = checkedPlugins();
for (int i = 0; i < plugins.size(); ++i) for (int i = 0; i < plugins.size(); ++i) {
{
const QString currentPlugin = plugins.at(i); const QString currentPlugin = plugins.at(i);
mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin); mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin);
gameConfig << "plugin=" << currentPlugin << endl; gameConfig << "plugin=" << currentPlugin << endl;
@ -1086,5 +1157,6 @@ void DataFilesPage::writeConfig(QString profile)
file.close(); file.close();
mLauncherConfig->endGroup(); mLauncherConfig->endGroup();
mLauncherConfig->endGroup(); mLauncherConfig->endGroup();
mLauncherConfig->sync();
} }

@ -3,6 +3,9 @@
#include <QWidget> #include <QWidget>
#include <QModelIndex> #include <QModelIndex>
#include <components/files/collections.hpp>
#include "combobox.hpp" #include "combobox.hpp"
class QTableWidget; class QTableWidget;
@ -77,6 +80,8 @@ private:
QAction *mUncheckAction; QAction *mUncheckAction;
Files::ConfigurationManager &mCfgMgr; Files::ConfigurationManager &mCfgMgr;
Files::PathContainer mDataDirs;
Files::PathContainer mDataLocal;
QSettings *mLauncherConfig; QSettings *mLauncherConfig;

Loading…
Cancel
Save