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

and prevent removal of the default profile
actorid
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>()); std::string local = variables["data-local"].as<std::string>();
if (!local.empty()) 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);
} }
if (!buffer.isEmpty()) {
file.write(buffer); 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