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 12 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}/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_PACKAGE_VERSION ${OPENMW_VERSION})
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})

@ -72,13 +72,13 @@ endif()
if (APPLE)
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
"${APP_BUNDLE_DIR}/../launcher.cfg")
else()
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
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.cfg")
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}launcher.cfg")
endif()

@ -1,8 +1,6 @@
#include <QtGui>
#include <components/esm/esm_reader.hpp>
#include <components/files/collections.hpp>
#include <components/files/multidircollection.hpp>
#include <components/files/configurationmanager.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(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();
setupDataFiles();
createActions();
}
void DataFilesPage::setupConfig()
@ -138,8 +137,7 @@ void DataFilesPage::setupConfig()
// Open our config file
mLauncherConfig = new QSettings(config, QSettings::IniFormat);
mLauncherConfig->sync();
file.close();
// Make sure we have no groups open
while (!mLauncherConfig->group().isEmpty()) {
@ -162,13 +160,14 @@ void DataFilesPage::setupConfig()
// No current profile selected
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
// 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&)));
mLauncherConfig->endGroup();
}
@ -188,19 +187,51 @@ void DataFilesPage::setupDataFiles()
// Put the paths in a boost::filesystem vector to use with Files::Collections
Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>());
std::string local(variables["data-local"].as<std::string>());
if (!local.empty())
{
mDataDirs = dataDirs;
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));
}
if (dataDirs.empty())
{
dataDirs.push_back(mCfgMgr.getLocalPath());
mCfgMgr.processPaths(dataDirs);
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
Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as<bool>());
@ -209,15 +240,13 @@ void DataFilesPage::setupDataFiles()
const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm");
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(
boost::filesystem::path (iter->second.filename()).string());
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);
QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
mMastersWidget->setItem(i, 0, item);
@ -228,8 +257,7 @@ void DataFilesPage::setupDataFiles()
// Now on to the plugins
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;
QStringList availableMasters; // Will contain all found masters
@ -245,8 +273,7 @@ void DataFilesPage::setupDataFiles()
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);
QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
@ -435,18 +462,18 @@ void DataFilesPage::deleteProfile()
return;
}
QMessageBox deleteMessageBox(this);
deleteMessageBox.setWindowTitle(tr("Delete Profile"));
deleteMessageBox.setText(tr("Are you sure you want to delete <b>%0</b>?").arg(profile));
deleteMessageBox.setIcon(QMessageBox::Warning);
QAbstractButton *deleteButton =
deleteMessageBox.addButton(tr("Delete"), QMessageBox::ActionRole);
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Delete Profile"));
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("Are you sure you want to delete <b>%0</b>?").arg(profile));
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
while (!mLauncherConfig->group().isEmpty()) {
mLauncherConfig->endGroup();
@ -503,7 +530,6 @@ void DataFilesPage::moveUp()
void DataFilesPage::moveDown()
{
// Shift the selected plugins down one row
if (!mPluginsTable->selectionModel()->hasSelection()) {
return;
}
@ -919,9 +945,18 @@ void DataFilesPage::filterChanged(const QString filter)
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()) {
writeConfig(previous);
mLauncherConfig->sync();
} else {
return;
}
uncheckPlugins();
@ -989,22 +1024,12 @@ void DataFilesPage::readConfig()
void DataFilesPage::writeConfig(QString profile)
{
// Don't overwrite the config if no plugins are found
if (mPluginsModel->rowCount() < 1) {
return;
}
if (profile.isEmpty()) {
profile = mProfilesComboBox->currentText();
}
if (profile.isEmpty()) {
// Don't overwrite the config if no masters are found
if (mMastersWidget->rowCount() < 1) {
return;
}
// Prepare the OpenMW config
// Open the config as a QFile
// Open the OpenMW config as a QFile
QFile file(QString::fromStdString((mCfgMgr.getUserPath()/"openmw.cfg").string()));
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
@ -1023,10 +1048,14 @@ void DataFilesPage::writeConfig(QString profile)
QTextStream in(&file);
QByteArray buffer;
// Remove all previous master/plugin entries from config
// Remove all previous entries from config
while (!in.atEnd()) {
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";
}
}
@ -1046,9 +1075,52 @@ void DataFilesPage::writeConfig(QString profile)
QApplication::exit(1);
}
file.write(buffer);
if (!buffer.isEmpty()) {
file.write(buffer);
}
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
while (!mLauncherConfig->group().isEmpty()) {
mLauncherConfig->endGroup();
@ -1061,7 +1133,7 @@ void DataFilesPage::writeConfig(QString profile)
mLauncherConfig->beginGroup(profile);
mLauncherConfig->remove(""); // Clear the subgroup
// First write the masters to the configs
// Now write the masters to the configs
const QStringList masters = selectedMasters();
// 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();
for (int i = 0; i < plugins.size(); ++i)
{
for (int i = 0; i < plugins.size(); ++i) {
const QString currentPlugin = plugins.at(i);
mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin);
gameConfig << "plugin=" << currentPlugin << endl;
@ -1086,5 +1157,6 @@ void DataFilesPage::writeConfig(QString profile)
file.close();
mLauncherConfig->endGroup();
mLauncherConfig->endGroup();
mLauncherConfig->sync();
}

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

Loading…
Cancel
Save