From 1bfc91046badb609261c78b4b5e03bba4dcb61bd Mon Sep 17 00:00:00 2001
From: Tannin
Date: Mon, 28 Dec 2015 14:33:30 +0100
Subject: removed get-prefix from many getters. removed const from managed_game
variable. other fixes
---
src/settings.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/settings.cpp')
diff --git a/src/settings.cpp b/src/settings.cpp
index 479dd3ab..25b58df7 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -108,7 +108,7 @@ void Settings::registerAsNXMHandler(bool force)
std::wstring nxmPath = ToWString(QCoreApplication::applicationDirPath() + "/nxmhandler.exe");
std::wstring executable = ToWString(QCoreApplication::applicationFilePath());
std::wstring mode = force ? L"forcereg" : L"reg";
- std::wstring parameters = mode + L" " + m_GamePlugin->getGameShortName().toStdWString() + L" \"" + executable + L"\"";
+ std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString() + L" \"" + executable + L"\"";
HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL);
if ((int)res <= 32) {
QMessageBox::critical(nullptr, tr("Failed"),
--
cgit v1.3.1
From 2aae65d6f6c1ab3309e54437a339d1644088c5c8 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Sun, 10 Jan 2016 20:19:56 +0100
Subject: made instance-switching usable
this includes tons and tons of changes to how paths are determined.
the profiles-dir can now also be configured
---
src/CMakeLists.txt | 22 +--
src/installationmanager.cpp | 2 +-
src/instancemanager.cpp | 206 ++++++++++++++++++++++++++++
src/instancemanager.h | 62 +++++++++
src/logbuffer.cpp | 120 ++++++++--------
src/main.cpp | 323 ++++++++++++++++++++++----------------------
src/mainwindow.cpp | 26 ++--
src/mainwindow.h | 7 +-
src/organizercore.cpp | 22 ++-
src/organizercore.h | 2 +
src/profile.cpp | 7 +-
src/profilesdialog.cpp | 6 +-
src/selectiondialog.cpp | 5 +
src/selectiondialog.h | 2 +
src/selfupdater.cpp | 2 +-
src/settings.cpp | 274 +++++++++++++++++++++----------------
src/settings.h | 20 ++-
src/settingsdialog.cpp | 24 +++-
src/settingsdialog.h | 3 +
src/settingsdialog.ui | 242 +++++++++++++++++++--------------
20 files changed, 897 insertions(+), 480 deletions(-)
create mode 100644 src/instancemanager.cpp
create mode 100644 src/instancemanager.h
(limited to 'src/settings.cpp')
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7cd66739..fda85b76 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -35,11 +35,11 @@ SET(organizer_SRCS
modlist.cpp
modinfodialog.cpp
modinfo.cpp
- modinfobackup.cpp
- modinfoforeign.cpp
- modinfooverwrite.cpp
- modinforegular.cpp
- modinfowithconflictinfo.cpp
+ modinfobackup.cpp
+ modinfoforeign.cpp
+ modinfooverwrite.cpp
+ modinforegular.cpp
+ modinfowithconflictinfo.cpp
messagedialog.cpp
mainwindow.cpp
main.cpp
@@ -87,6 +87,7 @@ SET(organizer_SRCS
viewmarkingscrollbar.cpp
plugincontainer.cpp
organizercore.cpp
+ instancemanager.cpp
usvfsconnector.cpp
shared/inject.cpp
@@ -131,11 +132,11 @@ SET(organizer_HDRS
modlist.h
modinfodialog.h
modinfo.h
- modinfobackup.h
- modinfoforeign.h
- modinfooverwrite.h
- modinforegular.h
- modinfowithconflictinfo.h
+ modinfobackup.h
+ modinfoforeign.h
+ modinfooverwrite.h
+ modinforegular.h
+ modinfowithconflictinfo.h
messagedialog.h
mainwindow.h
loghighlighter.h
@@ -183,6 +184,7 @@ SET(organizer_HDRS
plugincontainer.h
organizercore.h
iuserinterface.h
+ instancemanager.h
usvfsconnector.h
shared/inject.h
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index 739948cd..58565489 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -78,7 +78,7 @@ InstallationManager::InstallationManager()
: m_ParentWidget(nullptr)
, m_SupportedExtensions({ "zip", "rar", "7z", "fomod", "001" })
{
- QLibrary archiveLib("dlls\\archive.dll");
+ QLibrary archiveLib(QCoreApplication::applicationDirPath() + "\\dlls\\archive.dll");
if (!archiveLib.load()) {
throw MyException(tr("archive.dll not loaded: \"%1\"").arg(archiveLib.errorString()));
}
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
new file mode 100644
index 00000000..48c12d42
--- /dev/null
+++ b/src/instancemanager.cpp
@@ -0,0 +1,206 @@
+/*
+Copyright (C) 2016 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see .
+*/
+
+
+#include "instancemanager.h"
+#include "selectiondialog.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+static const char COMPANY_NAME[] = "Tannin";
+static const char APPLICATION_NAME[] = "Mod Organizer";
+static const char INSTANCE_KEY[] = "CurrentInstance";
+
+
+
+InstanceManager::InstanceManager()
+ : m_AppSettings(COMPANY_NAME, APPLICATION_NAME)
+{
+}
+
+
+QString InstanceManager::currentInstance() const
+{
+ return m_AppSettings.value(INSTANCE_KEY, "").toString();
+}
+
+void InstanceManager::clearCurrentInstance()
+{
+ setCurrentInstance("");
+}
+
+void InstanceManager::setCurrentInstance(const QString &name)
+{
+ m_AppSettings.setValue(INSTANCE_KEY, name);
+}
+
+
+QString InstanceManager::queryInstanceName() const
+{
+ QString instanceId;
+ while (instanceId.isEmpty()) {
+ QInputDialog dialog;
+ // would be neat if we could take the names from the game plugins but
+ // the required initialization order requires the ini file to be
+ // available *before* we load plugins
+ dialog.setComboBoxItems({ "Oblivion", "Skyrim", "Fallout 3",
+ "Fallout NV", "Fallout 4" });
+ dialog.setComboBoxEditable(true);
+ dialog.setWindowTitle(QObject::tr("Enter Instance Name"));
+ dialog.setLabelText(QObject::tr("Name"));
+ if (dialog.exec() == QDialog::Rejected) {
+ throw MOBase::MyException(QObject::tr("Canceled"));
+ }
+ instanceId = dialog.textValue().replace(QRegExp("[^0-9a-zA-Z ]"), "");
+ }
+ return instanceId;
+}
+
+
+QString InstanceManager::chooseInstance(const QStringList &instanceList) const
+{
+ SelectionDialog selection(QObject::tr("Choose Instance"), nullptr);
+ selection.disableCancel();
+ for (const QString &instance : instanceList) {
+ selection.addChoice(instance, "", instance);
+ }
+
+ selection.addChoice(QObject::tr("New"),
+ QObject::tr("Create a new instance."),
+ "");
+ if (selection.exec() == QDialog::Rejected) {
+ qDebug("rejected");
+ throw MOBase::MyException(QObject::tr("Canceled"));
+ }
+
+ QString choice = selection.getChoiceData().toString();
+
+ if (choice.isEmpty()) {
+ return queryInstanceName();
+ } else {
+ return choice;
+ }
+}
+
+
+QString InstanceManager::instancePath() const
+{
+ return QDir::fromNativeSeparators(
+ QStandardPaths::writableLocation(QStandardPaths::DataLocation));
+}
+
+
+QStringList InstanceManager::instances() const
+{
+ return QDir(instancePath()).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+}
+
+
+bool InstanceManager::portableInstall() const
+{
+ return QFile::exists(qApp->applicationDirPath() + "/" +
+ QString::fromStdWString(AppConfig::iniFileName()));
+}
+
+
+InstanceManager::InstallationMode InstanceManager::queryInstallMode() const
+{
+ SelectionDialog selection(QObject::tr("Installation Mode"), nullptr);
+ selection.disableCancel();
+ selection.addChoice(QObject::tr("Portable"),
+ QObject::tr("Everything in one directory, only one game per installation."),
+ 0);
+ selection.addChoice(QObject::tr("Regular"),
+ QObject::tr("Data in separate directory, multiple games supported."),
+ 1);
+ if (selection.exec() == QDialog::Rejected) {
+ throw MOBase::MyException(QObject::tr("Canceled"));
+ }
+
+ switch (selection.getChoiceData().toInt()) {
+ case 0: return InstallationMode::PORTABLE;
+ default: return InstallationMode::REGULAR;
+ }
+}
+
+
+void InstanceManager::createDataPath(const QString &dataPath) const
+{
+ if (!QDir(dataPath).exists()) {
+ if (!QDir().mkpath(dataPath)) {
+ throw MOBase::MyException(
+ QObject::tr("failed to create %1").arg(dataPath));
+ } else {
+ QMessageBox::information(
+ nullptr, QObject::tr("Data directory created"),
+ QObject::tr("New data directory created at %1. If you don't want to "
+ "store a lot of data there, reconfigure the storage "
+ "directories via settings.").arg(dataPath));
+ }
+ }
+}
+
+
+QString InstanceManager::determineDataPath()
+{
+ QString instanceId = currentInstance();
+
+ if (instanceId.isEmpty() && !portableInstall()) {
+ // no portable install and no selected instance
+
+ QStringList instanceList = instances();
+
+ qDebug("%d - %s", instanceList.size(), qPrintable(instanceList.join(";")));
+
+ if (instanceList.size() == 0) {
+ switch (queryInstallMode()) {
+ case InstallationMode::PORTABLE: {
+ instanceId = QString();
+ } break;
+ case InstallationMode::REGULAR: {
+ instanceId = queryInstanceName();
+ } break;
+ }
+ } else {
+ instanceId = chooseInstance(instanceList);
+ }
+ }
+
+ if (instanceId.isEmpty()) {
+ qDebug("portable mode");
+ return qApp->applicationDirPath();
+ } else {
+ setCurrentInstance(instanceId);
+
+ QString dataPath = QDir::fromNativeSeparators(
+ QStandardPaths::writableLocation(QStandardPaths::DataLocation)
+ + "/" + instanceId);
+
+ createDataPath(dataPath);
+
+ return dataPath;
+ }
+}
+
diff --git a/src/instancemanager.h b/src/instancemanager.h
new file mode 100644
index 00000000..2e17d1c0
--- /dev/null
+++ b/src/instancemanager.h
@@ -0,0 +1,62 @@
+/*
+Copyright (C) 2016 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see .
+*/
+
+
+#pragma once
+
+
+#include
+#include
+
+
+class InstanceManager {
+
+ enum class InstallationMode {
+ PORTABLE,
+ REGULAR
+ };
+
+public:
+
+ InstanceManager();
+
+ QString determineDataPath();
+ QStringList instances() const;
+ void clearCurrentInstance();
+
+private:
+
+ QString currentInstance() const;
+ QString instancePath() const;
+
+ bool portableInstall() const;
+
+ void setCurrentInstance(const QString &name);
+
+ QString queryInstanceName() const;
+ QString chooseInstance(const QStringList &instanceList) const;
+
+ void createDataPath(const QString &dataPath) const;
+ InstallationMode queryInstallMode() const;
+
+private:
+
+ QSettings m_AppSettings;
+
+};
diff --git a/src/logbuffer.cpp b/src/logbuffer.cpp
index 2c3fc101..01ff2b87 100644
--- a/src/logbuffer.cpp
+++ b/src/logbuffer.cpp
@@ -26,37 +26,33 @@ along with Mod Organizer. If not, see .
#include
#include
-
using MOBase::reportError;
QScopedPointer LogBuffer::s_Instance;
QMutex LogBuffer::s_Mutex;
-
-LogBuffer::LogBuffer(int messageCount, QtMsgType minMsgType, const QString &outputFileName)
- : QAbstractItemModel(nullptr), m_OutFileName(outputFileName), m_ShutDown(false),
- m_MinMsgType(minMsgType), m_NumMessages(0)
+LogBuffer::LogBuffer(int messageCount, QtMsgType minMsgType,
+ const QString &outputFileName)
+ : QAbstractItemModel(nullptr)
+ , m_OutFileName(outputFileName)
+ , m_ShutDown(false)
+ , m_MinMsgType(minMsgType)
+ , m_NumMessages(0)
{
m_Messages.resize(messageCount);
}
LogBuffer::~LogBuffer()
{
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+ qDebug("closing log buffer");
qInstallMessageHandler(0);
-#else
- qInstallMsgHandler(0);
-#endif
-// if (!m_ShutDown) {
- write();
-// }
+ write();
}
-
void LogBuffer::logMessage(QtMsgType type, const QString &message)
{
if (type >= m_MinMsgType) {
- Message msg = { type, QTime::currentTime(), message };
+ Message msg = {type, QTime::currentTime(), message};
if (m_NumMessages < m_Messages.size()) {
beginInsertRows(QModelIndex(), m_NumMessages, m_NumMessages + 1);
}
@@ -73,7 +69,6 @@ void LogBuffer::logMessage(QtMsgType type, const QString &message)
}
}
-
void LogBuffer::write() const
{
if (m_NumMessages == 0) {
@@ -84,12 +79,15 @@ void LogBuffer::write() const
QFile file(m_OutFileName);
if (!file.open(QIODevice::WriteOnly)) {
- reportError(tr("failed to write log to %1: %2").arg(m_OutFileName).arg(file.errorString()));
+ reportError(tr("failed to write log to %1: %2")
+ .arg(m_OutFileName)
+ .arg(file.errorString()));
return;
}
- unsigned int i = (m_NumMessages > m_Messages.size()) ? m_NumMessages - m_Messages.size()
- : 0U;
+ unsigned int i = (m_NumMessages > m_Messages.size())
+ ? m_NumMessages - m_Messages.size()
+ : 0U;
for (; i < m_NumMessages; ++i) {
file.write(m_Messages.at(i % m_Messages.size()).toString().toUtf8());
file.write("\r\n");
@@ -97,68 +95,68 @@ void LogBuffer::write() const
::SetLastError(lastError);
}
-
-void LogBuffer::init(int messageCount, QtMsgType minMsgType, const QString &outputFileName)
+void LogBuffer::init(int messageCount, QtMsgType minMsgType,
+ const QString &outputFileName)
{
QMutexLocker guard(&s_Mutex);
- if (!s_Instance.isNull()) {
- s_Instance.reset();
- }
s_Instance.reset(new LogBuffer(messageCount, minMsgType, outputFileName));
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
qInstallMessageHandler(LogBuffer::log);
-#else
- qInstallMsgHandler(LogBuffer::log);
-#endif
}
char LogBuffer::msgTypeID(QtMsgType type)
{
switch (type) {
- case QtDebugMsg: return 'D';
- case QtWarningMsg: return 'W';
- case QtCriticalMsg: return 'C';
- case QtFatalMsg: return 'F';
- default: return '?';
+ case QtDebugMsg:
+ return 'D';
+ case QtWarningMsg:
+ return 'W';
+ case QtCriticalMsg:
+ return 'C';
+ case QtFatalMsg:
+ return 'F';
+ default:
+ return '?';
}
}
-void LogBuffer::log(QtMsgType type, const QMessageLogContext &context, const QString &message)
+void LogBuffer::log(QtMsgType type, const QMessageLogContext &context,
+ const QString &message)
{
// QMutexLocker doesn't support timeout...
if (!s_Mutex.tryLock(100)) {
fprintf(stderr, "failed to log: %s", qPrintable(message));
return;
}
- ON_BLOCK_EXIT([] () {
- s_Mutex.unlock();
- });
+ ON_BLOCK_EXIT([]() { s_Mutex.unlock(); });
if (!s_Instance.isNull()) {
s_Instance->logMessage(type, message);
}
-// fprintf(stdout, "(%s:%u) %s\n", context.file, context.line, qPrintable(message));
if (type == QtDebugMsg) {
- fprintf(stdout, "%s [%c] %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type), qPrintable(message));
+ fprintf(stdout, "%s [%c] %s\n", qPrintable(QTime::currentTime().toString()),
+ msgTypeID(type), qPrintable(message));
} else {
if (context.line != 0) {
- fprintf(stdout, "%s [%c] (%s:%u) %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type),
+ fprintf(stdout, "%s [%c] (%s:%u) %s\n",
+ qPrintable(QTime::currentTime().toString()), msgTypeID(type),
context.file, context.line, qPrintable(message));
} else {
- fprintf(stdout, "%s [%c] %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type), qPrintable(message));
+ fprintf(stdout, "%s [%c] %s\n",
+ qPrintable(QTime::currentTime().toString()), msgTypeID(type),
+ qPrintable(message));
}
}
fflush(stdout);
}
-QModelIndex LogBuffer::index(int row, int column, const QModelIndex&) const
+QModelIndex LogBuffer::index(int row, int column, const QModelIndex &) const
{
return createIndex(row, column, row);
}
-QModelIndex LogBuffer::parent(const QModelIndex&) const
+QModelIndex LogBuffer::parent(const QModelIndex &) const
{
return QModelIndex();
}
@@ -171,16 +169,16 @@ int LogBuffer::rowCount(const QModelIndex &parent) const
return std::min(m_NumMessages, m_Messages.size());
}
-int LogBuffer::columnCount(const QModelIndex&) const
+int LogBuffer::columnCount(const QModelIndex &) const
{
return 2;
}
-
QVariant LogBuffer::data(const QModelIndex &index, int role) const
{
- unsigned offset = m_NumMessages < m_Messages.size() ? 0
- : m_NumMessages - m_Messages.size();
+ unsigned offset = m_NumMessages < m_Messages.size()
+ ? 0
+ : m_NumMessages - m_Messages.size();
unsigned int msgIndex = (offset + index.row() + 1) % m_Messages.size();
switch (role) {
case Qt::DisplayRole: {
@@ -198,20 +196,28 @@ QVariant LogBuffer::data(const QModelIndex &index, int role) const
case Qt::DecorationRole: {
if (index.column() == 1) {
switch (m_Messages[msgIndex].type) {
- case QtDebugMsg: return QIcon(":/MO/gui/information");
- case QtWarningMsg: return QIcon(":/MO/gui/warning");
- case QtCriticalMsg: return QIcon(":/MO/gui/important");
- case QtFatalMsg: return QIcon(":/MO/gui/problem");
+ case QtDebugMsg:
+ return QIcon(":/MO/gui/information");
+ case QtWarningMsg:
+ return QIcon(":/MO/gui/warning");
+ case QtCriticalMsg:
+ return QIcon(":/MO/gui/important");
+ case QtFatalMsg:
+ return QIcon(":/MO/gui/problem");
}
}
} break;
case Qt::UserRole: {
if (index.column() == 1) {
switch (m_Messages[msgIndex].type) {
- case QtDebugMsg: return "D";
- case QtWarningMsg: return "W";
- case QtCriticalMsg: return "C";
- case QtFatalMsg: return "F";
+ case QtDebugMsg:
+ return "D";
+ case QtWarningMsg:
+ return "W";
+ case QtCriticalMsg:
+ return "C";
+ case QtFatalMsg:
+ return "F";
}
}
} break;
@@ -227,7 +233,6 @@ void LogBuffer::writeNow()
}
}
-
void LogBuffer::cleanQuit()
{
QMutexLocker guard(&s_Mutex);
@@ -255,5 +260,8 @@ void log(const char *format, ...)
QString LogBuffer::Message::toString() const
{
- return QString("%1 [%2] %3").arg(time.toString()).arg(msgTypeID(type)).arg(message);
+ return QString("%1 [%2] %3")
+ .arg(time.toString())
+ .arg(msgTypeID(type))
+ .arg(message);
}
diff --git a/src/main.cpp b/src/main.cpp
index 30938485..a262d031 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -45,6 +45,8 @@ along with Mod Organizer. If not, see .
#include "moapplication.h"
#include "tutorialmanager.h"
#include "nxmaccessmanager.h"
+#include "instancemanager.h"
+
#include
#include
@@ -84,6 +86,7 @@ along with Mod Organizer. If not, see .
using namespace MOBase;
using namespace MOShared;
+
bool createAndMakeWritable(const std::wstring &subPath)
{
QString const dataPath = qApp->property("dataPath").toString();
@@ -135,43 +138,6 @@ bool bootstrap()
return true;
}
-void cleanupDir()
-{
- // files from previous versions of MO that are no longer
- // required (in that location)
- QStringList fileNames {
- "imageformats/",
- "loot/resources/",
- "plugins/previewDDS.dll",
- "dlls/boost_python-vc100-mt-1_55.dll",
- "dlls/QtCore4.dll",
- "dlls/QtDeclarative4.dll",
- "dlls/QtGui4.dll",
- "dlls/QtNetwork4.dll",
- "dlls/QtOpenGL4.dll",
- "dlls/QtScript4.dll",
- "dlls/QtSql4.dll",
- "dlls/QtSvg4.dll",
- "dlls/QtWebKit4.dll",
- "dlls/QtXml4.dll",
- "dlls/QtXmlPatterns4.dll",
- "msvcp100.dll",
- "msvcr100.dll",
- "proxy.dll"
- };
-
- for (const QString &fileName : fileNames) {
- QString fullPath = qApp->applicationDirPath() + "/" + fileName;
- if (QFile::exists(fullPath)) {
- if (shellDelete(QStringList(fullPath), true)) {
- qDebug("removed obsolete file %s", qPrintable(fullPath));
- } else {
- qDebug("failed to remove obsolete %s", qPrintable(fullPath));
- }
- }
- }
-}
-
bool isNxmLink(const QString &link)
{
@@ -195,6 +161,10 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
if (dbgDLL) {
FuncMiniDumpWriteDump funcDump = (FuncMiniDumpWriteDump)::GetProcAddress(dbgDLL, "MiniDumpWriteDump");
if (funcDump) {
+ wchar_t exeNameBuffer[MAX_PATH];
+ ::GetModuleFileNameW(nullptr, exeNameBuffer, MAX_PATH);
+ QString dumpName = QString::fromWCharArray(exeNameBuffer) + ".dmp";
+
if (QMessageBox::question(nullptr, QObject::tr("Woops"),
QObject::tr("ModOrganizer has crashed! "
"Should a diagnostic file be created? "
@@ -202,12 +172,10 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
"the bug is a lot more likely to be fixed. "
"Please include a short description of what you were "
"doing when the crash happened"
- ).arg(qApp->applicationFilePath().append(".dmp")),
+ ).arg(dumpName),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- std::wstring dumpName = ToWString(qApp->applicationFilePath().append(".dmp"));
-
- HANDLE dumpFile = ::CreateFile(dumpName.c_str(),
+ HANDLE dumpFile = ::CreateFile(dumpName.toStdWString().c_str(),
GENERIC_WRITE, FILE_SHARE_WRITE, nullptr,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (dumpFile != INVALID_HANDLE_VALUE) {
@@ -225,10 +193,10 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
return EXCEPTION_EXECUTE_HANDLER;
}
_snprintf(errorBuffer, errorLen, "failed to save minidump to %ls (error %lu)",
- dumpName.c_str(), ::GetLastError());
+ dumpName.toStdWString().c_str(), ::GetLastError());
} else {
_snprintf(errorBuffer, errorLen, "failed to create %ls (error %lu)",
- dumpName.c_str(), ::GetLastError());
+ dumpName.toStdWString().c_str(), ::GetLastError());
}
} else {
return result;
@@ -435,139 +403,95 @@ MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &sett
return nullptr;
}
-int main(int argc, char *argv[])
+
+// extend path to include dll directory so plugins don't need a manifest
+// (using AddDllDirectory would be an alternative to this but it seems fairly
+// complicated esp.
+// since it isn't easily accessible on Windows < 8
+// SetDllDirectory replaces other search directories and this seems to
+// propagate to child processes)
+void setupPath()
{
- MOApplication application(argc, argv);
+ static const int BUFSIZE = 4096;
- qDebug("application name: %s", qPrintable(application.applicationName()));
-
- QString instanceID;
- QFile instanceFile(application.applicationDirPath() + "/INSTANCE");
- if (instanceFile.open(QIODevice::ReadOnly)) {
- instanceID = instanceFile.readAll().trimmed();
- }
-
- QString const dataPath =
- instanceID.isEmpty() ? application.applicationDirPath()
- : QDir::fromNativeSeparators(
- QStandardPaths::writableLocation(QStandardPaths::DataLocation)
- + "/" + instanceID
- );
- application.setProperty("dataPath", dataPath);
-
- if (!QDir(dataPath).exists()) {
- if (!QDir().mkpath(dataPath)) {
- qCritical("failed to create %s", qPrintable(dataPath));
- return 1;
- }
+ qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(
+ QCoreApplication::applicationDirPath())));
+
+ boost::scoped_array oldPath(new TCHAR[BUFSIZE]);
+ DWORD offset = ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), BUFSIZE);
+ if (offset > BUFSIZE) {
+ oldPath.reset(new TCHAR[offset]);
+ ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset);
}
- SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
+ std::wstring newPath(oldPath.get());
+ newPath += L";";
+ newPath += ToWString(QDir::toNativeSeparators(
+ QCoreApplication::applicationDirPath()))
+ .c_str();
+ newPath += L"\\dlls";
- if (!HaveWriteAccess(ToWString(application.applicationDirPath()))) {
- QStringList arguments = application.arguments();
- arguments.pop_front();
- ::ShellExecuteW( nullptr
- , L"runas"
- , ToWString(QString("\"%1\"").arg(QCoreApplication::applicationFilePath())).c_str()
- , ToWString(arguments.join(" ")).c_str()
- , ToWString(QDir::currentPath()).c_str(), SW_SHOWNORMAL);
- return 1;
- }
+ ::SetEnvironmentVariableW(L"PATH", newPath.c_str());
+}
+
+int runApplication(MOApplication &application, SingleInstance &instance)
+{
+ qDebug("start main application");
QPixmap pixmap(":/MO/gui/splash");
QSplashScreen splash(pixmap);
- try {
- if (!bootstrap()) {
- return -1;
- }
+ QString dataPath = application.property("dataPath").toString();
+ qDebug("data path: %s", qPrintable(dataPath));
- LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
+ if (!bootstrap()) {
+ reportError("failed to set up data path");
+ return 1;
+ }
-#if QT_VERSION >= 0x050000 && !defined(QT_NO_SSL)
- qDebug("ssl support: %d", QSslSocket::supportsSsl());
-#endif
+ QStringList arguments = application.arguments();
+ try {
qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
- qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(application.applicationDirPath())));
splash.show();
-
- cleanupDir();
} catch (const std::exception &e) {
reportError(e.what());
return 1;
}
- { // extend path to include dll directory so plugins don't need a manifest
- // (using AddDllDirectory would be an alternative to this but it seems fairly complicated esp.
- // since it isn't easily accessible on Windows < 8
- // SetDllDirectory replaces other search directories and this seems to propagate to child processes)
- static const int BUFSIZE = 4096;
-
- boost::scoped_array oldPath(new TCHAR[BUFSIZE]);
- DWORD offset = ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), BUFSIZE);
- if (offset > BUFSIZE) {
- oldPath.reset(new TCHAR[offset]);
- ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset);
- }
-
- std::wstring newPath(oldPath.get());
- newPath += L";";
- newPath += ToWString(QDir::toNativeSeparators(QCoreApplication::applicationDirPath())).c_str();
- newPath += L"\\dlls";
-
- ::SetEnvironmentVariableW(L"PATH", newPath.c_str());
- }
-
- QStringList arguments = application.arguments();
-
- bool forcePrimary = false;
- if (arguments.contains("update")) {
- arguments.removeAll("update");
- forcePrimary = true;
- }
-
try {
- SingleInstance instance(forcePrimary);
- if (!instance.primaryInstance()) {
- if ((arguments.size() == 2) && isNxmLink(arguments.at(1))) {
- qDebug("not primary instance, sending download message");
- instance.sendMessage(arguments.at(1));
- return 0;
- } else if (arguments.size() == 1) {
- QMessageBox::information(nullptr, QObject::tr("Mod Organizer"), QObject::tr("An instance of Mod Organizer is already running"));
- return 0;
- }
- } // we continue for the primary instance OR if MO has been called with parameters
-
- QSettings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat);
+ QSettings settings(dataPath + "/"
+ + QString::fromStdWString(AppConfig::iniFileName()),
+ QSettings::IniFormat);
qDebug("initializing core");
OrganizerCore organizer(settings);
qDebug("initialize plugins");
PluginContainer pluginContainer(&organizer);
pluginContainer.loadPlugins();
- MOBase::IPluginGame *game = determineCurrentGame(application.applicationDirPath(), settings, pluginContainer);
+ MOBase::IPluginGame *game = determineCurrentGame(
+ application.applicationDirPath(), settings, pluginContainer);
if (game == nullptr) {
return 1;
}
organizer.setManagedGame(game);
-
organizer.createDefaultProfile();
- //See the pragma - we apparently don't use this so not sure why we check it
if (!settings.contains("game_edition")) {
QStringList editions = game->gameVariants();
if (editions.size() > 1) {
- SelectionDialog selection(QObject::tr("Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)"), nullptr);
+ SelectionDialog selection(
+ QObject::tr("Please select the game edition you have (MO can't "
+ "start the game correctly if this is set "
+ "incorrectly!)"),
+ nullptr);
int index = 0;
for (const QString &edition : editions) {
selection.addChoice(edition, "", index++);
}
if (selection.exec() == QDialog::Rejected) {
- return -1;
+ return 1;
} else {
settings.setValue("game_edition", selection.getChoiceString());
}
@@ -575,8 +499,8 @@ int main(int argc, char *argv[])
}
game->setGameVariant(settings.value("game_edition").toString());
-#pragma message("edition isn't used?")
- qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(game->gameDirectory().absolutePath())));
+ qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(
+ game->gameDirectory().absolutePath())));
organizer.updateExecutablesList(settings);
@@ -585,27 +509,35 @@ int main(int argc, char *argv[])
// if we have a command line parameter, it is either a nxm link or
// a binary to start
- if ((arguments.size() > 1)
- && !isNxmLink(arguments.at(1))) {
- QString exeName = arguments.at(1);
- qDebug("starting %s from command line", qPrintable(exeName));
- arguments.removeFirst(); // remove application name (ModOrganizer.exe)
- arguments.removeFirst(); // remove binary name
- // pass the remaining parameters to the binary
- try {
- organizer.startApplication(exeName, arguments, QString(), QString());
- return 0;
- } catch (const std::exception &e) {
- reportError(QObject::tr("failed to start application: %1").arg(e.what()));
- return 1;
+ if (arguments.size() > 1) {
+ if (isNxmLink(arguments.at(1))) {
+ qDebug("starting download from command line: %s",
+ qPrintable(arguments.at(1)));
+ organizer.externalMessage(arguments.at(1));
+ } else {
+ QString exeName = arguments.at(1);
+ qDebug("starting %s from command line", qPrintable(exeName));
+ arguments.removeFirst(); // remove application name (ModOrganizer.exe)
+ arguments.removeFirst(); // remove binary name
+ // pass the remaining parameters to the binary
+ try {
+ organizer.startApplication(exeName, arguments, QString(), QString());
+ } catch (const std::exception &e) {
+ reportError(
+ QObject::tr("failed to start application: %1").arg(e.what()));
+ return 1;
+ }
}
+ return 0;
}
NexusInterface::instance()->getAccessManager()->startLoginCheck();
qDebug("initializing tutorials");
- TutorialManager::init(qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::tutorialsPath()) + "/",
- &organizer);
+ TutorialManager::init(
+ qApp->applicationDirPath() + "/"
+ + QString::fromStdWString(AppConfig::tutorialsPath()) + "/",
+ &organizer);
if (!application.setStyleFile(settings.value("Settings/style", "").toString())) {
// disable invalid stylesheet
@@ -615,27 +547,94 @@ int main(int argc, char *argv[])
int res = 1;
{ // scope to control lifetime of mainwindow
// set up main window and its data structures
- MainWindow mainWindow(argv[0], settings, organizer, pluginContainer);
+ MainWindow mainWindow(settings, organizer, pluginContainer);
- QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString)));
- QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer, SLOT(externalMessage(QString)));
+ QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application,
+ SLOT(setStyleFile(QString)));
+ QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer,
+ SLOT(externalMessage(QString)));
mainWindow.readSettings();
qDebug("displaying main window");
mainWindow.show();
- if ((arguments.size() > 1)
- && isNxmLink(arguments.at(1))) {
- qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
- organizer.externalMessage(arguments.at(1));
- }
splash.finish(&mainWindow);
- res = application.exec();
+ return application.exec();
}
- return res;
} catch (const std::exception &e) {
reportError(e.what());
return 1;
}
}
+
+
+int main(int argc, char *argv[])
+{
+ SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
+
+ MOApplication application(argc, argv);
+ QStringList arguments = application.arguments();
+
+ if ((arguments.length() >= 4) && (arguments.at(1) == "launch")) {
+ // all we're supposed to do is launch another process
+ QProcess process;
+ process.setWorkingDirectory(QDir::fromNativeSeparators(arguments.at(2)));
+ process.setProgram(QDir::fromNativeSeparators(arguments.at(3)));
+ process.setArguments(arguments.mid(4));
+ process.start();
+ process.waitForFinished(-1);
+ return process.exitCode();
+ }
+
+ setupPath();
+
+ #if !defined(QT_NO_SSL)
+ qDebug("ssl support: %d", QSslSocket::supportsSsl());
+ #else
+ qDebug("non-ssl build");
+ #endif
+
+ bool forcePrimary = false;
+ if (arguments.contains("update")) {
+ arguments.removeAll("update");
+ forcePrimary = true;
+ }
+
+ SingleInstance instance(forcePrimary);
+ if (!instance.primaryInstance()) {
+ if ((arguments.size() == 2) && isNxmLink(arguments.at(1))) {
+ qDebug("not primary instance, sending download message");
+ instance.sendMessage(arguments.at(1));
+ return 0;
+ } else if (arguments.size() == 1) {
+ QMessageBox::information(
+ nullptr, QObject::tr("Mod Organizer"),
+ QObject::tr("An instance of Mod Organizer is already running"));
+ return 0;
+ }
+ } // we continue for the primary instance OR if MO was called with parameters
+
+ do {
+ QString dataPath;
+
+ try {
+ dataPath = InstanceManager().determineDataPath();
+ } catch (const std::exception &e) {
+ QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"),
+ e.what());
+ return 1;
+ }
+
+ application.setProperty("dataPath", dataPath);
+
+ LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
+
+ int result = runApplication(application, instance);
+
+ if (result != INT_MAX) {
+ return result;
+ }
+ argc = 1;
+ } while (true);
+}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 0c54fc8d..80e3490c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -74,6 +74,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
#include
@@ -146,8 +147,7 @@ using namespace MOBase;
using namespace MOShared;
-MainWindow::MainWindow(const QString &exeName
- , QSettings &initSettings
+MainWindow::MainWindow(QSettings &initSettings
, OrganizerCore &organizerCore
, PluginContainer &pluginContainer
, QWidget *parent)
@@ -155,7 +155,6 @@ MainWindow::MainWindow(const QString &exeName
, ui(new Ui::MainWindow)
, m_WasVisible(false)
, m_Tutorial(this, "MainWindow")
- , m_ExeName(exeName)
, m_OldProfileIndex(-1)
, m_ModListGroupingProxy(nullptr)
, m_ModListSortProxy(nullptr)
@@ -301,6 +300,7 @@ MainWindow::MainWindow(const QString &exeName
connect(ui->toolBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(toolBar_customContextMenuRequested(QPoint)));
connect(&m_OrganizerCore, &OrganizerCore::modInstalled, this, &MainWindow::modInstalled);
+ connect(&m_OrganizerCore, &OrganizerCore::close, this, &QMainWindow::close);
connect(&m_IntegratedBrowser, SIGNAL(requestDownload(QUrl,QNetworkReply*)), &m_OrganizerCore, SLOT(requestDownload(QUrl,QNetworkReply*)));
@@ -347,6 +347,8 @@ MainWindow::MainWindow(const QString &exeName
MainWindow::~MainWindow()
{
+ cleanup();
+
m_PluginContainer.setUserInterface(nullptr, nullptr);
m_OrganizerCore.setUserInterface(nullptr, nullptr);
m_IntegratedBrowser.close();
@@ -810,6 +812,14 @@ void MainWindow::closeEvent(QCloseEvent* event)
}
setCursor(Qt::WaitCursor);
+}
+
+void MainWindow::cleanup()
+{
+ if (ui->logList->model() != nullptr) {
+ disconnect(ui->logList->model(), nullptr, nullptr, nullptr);
+ ui->logList->setModel(nullptr);
+ }
m_IntegratedBrowser.close();
}
@@ -1175,7 +1185,7 @@ bool MainWindow::refreshProfiles(bool selectProfile)
profileBox->clear();
profileBox->addItem(QObject::tr(""));
- QDir profilesDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()));
+ QDir profilesDir(Settings::instance().getProfileDirectory());
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
QDirIterator profileIter(profilesDir);
@@ -3166,7 +3176,7 @@ QString getStartMenuLinkfile(const Executable &exec)
void MainWindow::addWindowsLink(const ShortcutType mapping)
{
- Executable const &selectedExecutable(getSelectedExecutable());
+ const Executable &selectedExecutable(getSelectedExecutable());
QString const linkName = getLinkfile(mapping == ShortcutType::Desktop ? getDesktopDirectory() : getStartMenuDirectory(),
selectedExecutable);
@@ -4217,6 +4227,7 @@ void MainWindow::on_bossButton_clicked()
HANDLE stdOutRead = INVALID_HANDLE_VALUE;
createStdoutPipe(&stdOutRead, &stdOutWrite);
m_OrganizerCore.prepareVFS();
+
HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"),
parameters.join(" "),
qApp->applicationDirPath() + "/loot",
@@ -4313,6 +4324,7 @@ void MainWindow::on_bossButton_clicked()
} catch (const std::exception &e) {
reportError(tr("failed to run loot: %1").arg(e.what()));
}
+
if (errorMessages.length() > 0) {
QMessageBox *warn = new QMessageBox(QMessageBox::Warning, tr("Errors occured"), errorMessages.c_str(), QMessageBox::Ok, this);
warn->setModal(false);
@@ -4326,11 +4338,7 @@ void MainWindow::on_bossButton_clicked()
QStringList temp = report.split("?");
QUrl url = QUrl::fromLocalFile(temp.at(0));
if (temp.size() > 1) {
-#if QT_VERSION >= 0x050000
url.setQuery(temp.at(1).toUtf8());
-#else
- url.setEncodedQuery(temp.at(1).toUtf8());
-#endif
}
m_IntegratedBrowser.openUrl(url);
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 49476bf3..530097cf 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -26,7 +26,6 @@ along with Mod Organizer. If not, see .
#include
#include
#include
-#include
#include
#include
#include
@@ -75,7 +74,7 @@ class MainWindow : public QMainWindow, public IUserInterface
public:
- explicit MainWindow(const QString &exeName, QSettings &initSettings,
+ explicit MainWindow(QSettings &initSettings,
OrganizerCore &organizerCore, PluginContainer &pluginContainer,
QWidget *parent = 0);
~MainWindow();
@@ -155,6 +154,8 @@ protected:
private:
+ void cleanup();
+
void actionToToolButton(QAction *&sourceAction);
void updateToolBar();
@@ -263,8 +264,6 @@ private:
MOBase::TutorialControl m_Tutorial;
- QString m_ExeName;
-
int m_OldProfileIndex;
std::vector m_ModNameList; // the mod-list to go with the directory structure
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index c84b603d..a73e6845 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -535,7 +535,7 @@ InstallationManager *OrganizerCore::installationManager()
void OrganizerCore::createDefaultProfile()
{
- QString profilesPath = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath());
+ QString profilesPath = settings().getProfileDirectory();
if (QDir(profilesPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size() == 0) {
Profile newProf("Default", managedGame(), false);
}
@@ -552,7 +552,7 @@ void OrganizerCore::setCurrentProfile(const QString &profileName)
(profileName == m_CurrentProfile->name())) {
return;
}
- QString profileDir = qApp->property("dataPath").toString() + "/" + ToQString(AppConfig::profilesPath()) + "/" + profileName;
+ QString profileDir = settings().getProfileDirectory() + "/" + profileName;
Profile *newProfile = new Profile(QDir(profileDir), managedGame());
delete m_CurrentProfile;
@@ -994,10 +994,9 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString &
m_CurrentProfile->modlistWriter().writeImmediately(true);
}
- // TODO: should also pass arguments
if (m_AboutToRun(binary.absoluteFilePath())) {
m_USVFS.updateMapping(fileMapping());
- QString modsPath(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::modsPath()));
+ QString modsPath = settings().getModDirectory();
QString binPath = binary.absoluteFilePath();
@@ -1008,15 +1007,14 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString &
QString cwdPath = currentDirectory.absolutePath();
int binOffset = binPath.indexOf('/', modsPath.length() + 1);
- int cwdOffset = cwdPath.indexOf('/', cwdPath.length() + 1);
- QString binPath = m_GamePlugin->dataDirectory().absolutePath() + "/" + binPath.mid(binOffset);
- QString cwd = m_GamePlugin->dataDirectory().absolutePath() + "/" + cwdPath.mid(cwdOffset);
+ int cwdOffset = cwdPath.indexOf('/', modsPath.length() + 1);
+ QString dataBinPath = m_GamePlugin->dataDirectory().absolutePath() + binPath.mid(binOffset, -1);
+ QString dataCwd = m_GamePlugin->dataDirectory().absolutePath() + cwdPath.mid(cwdOffset, -1);
QString cmdline = QString("launch \"%1\" \"%2\" %3")
- .arg(QDir::toNativeSeparators(cwd),
- QDir::toNativeSeparators(binPath),
+ .arg(QDir::toNativeSeparators(dataCwd),
+ QDir::toNativeSeparators(dataBinPath),
arguments);
-
- return startBinary(QFileInfo(QCoreApplication::applicationDirPath() + "/helper.exe"),
+ return startBinary(QFileInfo(QCoreApplication::applicationFilePath()),
cmdline,
QCoreApplication::applicationDirPath(), true);
} else {
@@ -1600,7 +1598,7 @@ std::vector OrganizerCore::fileMapping()
int overwriteId = m_DirectoryStructure->getOriginByName(L"Overwrite").getID();
- const IPluginGame *game = qApp->property("managed_game").value();
+ IPluginGame *game = qApp->property("managed_game").value();
MappingType result = fileMapping(
QDir::toNativeSeparators(game->dataDirectory().absolutePath()),
"\\",
diff --git a/src/organizercore.h b/src/organizercore.h
index d86033eb..bf6c5a8b 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -201,6 +201,8 @@ signals:
void managedGameChanged(MOBase::IPluginGame const *gamePlugin);
+ void close();
+
private:
void storeSettings();
diff --git a/src/profile.cpp b/src/profile.cpp
index 4b916a2f..99a6bd90 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -22,6 +22,7 @@ along with Mod Organizer. If not, see .
#include "windows_error.h"
#include "modinfo.h"
#include "safewritefile.h"
+#include "settings.h"
#include
#include
#include
@@ -58,7 +59,7 @@ Profile::Profile(const QString &name, IPluginGame const *gamePlugin, bool useDef
: m_ModListWriter(std::bind(&Profile::writeModlistNow, this))
, m_GamePlugin(gamePlugin)
{
- QString profilesDir = qApp->property("dataPath").toString() + "/" + ToQString(AppConfig::profilesPath());
+ QString profilesDir = Settings::instance().getProfileDirectory();
QDir profileBase(profilesDir);
QString fixedName = name;
@@ -487,7 +488,7 @@ void Profile::setModPriority(unsigned int index, int &newPriority)
Profile *Profile::createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame const *gamePlugin)
{
- QString profileDirectory = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()) + "/" + name;
+ QString profileDirectory = Settings::instance().getProfileDirectory() + "/" + name;
reference.copyFilesTo(profileDirectory);
return new Profile(QDir(profileDirectory), gamePlugin);
}
@@ -691,7 +692,7 @@ QString Profile::absolutePath() const
void Profile::rename(const QString &newName)
{
- QDir profileDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()));
+ QDir profileDir(Settings::instance().getProfileDirectory());
profileDir.rename(name(), newName);
m_Directory = profileDir.absoluteFilePath(newName);
}
diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp
index b21aee53..49fbda4e 100644
--- a/src/profilesdialog.cpp
+++ b/src/profilesdialog.cpp
@@ -25,6 +25,7 @@ along with Mod Organizer. If not, see .
#include "profileinputdialog.h"
#include "mainwindow.h"
#include "aboutdialog.h"
+#include "settings.h"
#include
#include
#include
@@ -50,7 +51,7 @@ ProfilesDialog::ProfilesDialog(const QString &profileName, MOBase::IPluginGame c
{
ui->setupUi(this);
- QDir profilesDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()));
+ QDir profilesDir(Settings::instance().getProfileDirectory());
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
m_ProfilesList = findChild("profilesList");
@@ -187,8 +188,7 @@ void ProfilesDialog::on_removeProfileButton_clicked()
Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value();
QString profilePath;
if (currentProfile.get() == nullptr) {
- profilePath = qApp->property("dataPath").toString()
- + "/" + QString::fromStdWString(AppConfig::profilesPath())
+ profilePath = Settings::instance().getProfileDirectory()
+ "/" + profilesList->currentItem()->text();
if (QMessageBox::question(this, tr("Profile broken"),
tr("This profile you're about to delete seems to be broken or the path is invalid. "
diff --git a/src/selectiondialog.cpp b/src/selectiondialog.cpp
index aae95f56..55728751 100644
--- a/src/selectiondialog.cpp
+++ b/src/selectiondialog.cpp
@@ -79,6 +79,11 @@ QString SelectionDialog::getChoiceString()
}
}
+void SelectionDialog::disableCancel()
+{
+ ui->cancelButton->setEnabled(false);
+ ui->cancelButton->setHidden(true);
+}
void SelectionDialog::on_buttonBox_clicked(QAbstractButton *button)
{
diff --git a/src/selectiondialog.h b/src/selectiondialog.h
index 43ba9767..3c4b25df 100644
--- a/src/selectiondialog.h
+++ b/src/selectiondialog.h
@@ -53,6 +53,8 @@ public:
QVariant getChoiceData();
QString getChoiceString();
+ void disableCancel();
+
private slots:
void on_buttonBox_clicked(QAbstractButton *button);
diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp
index 0cfd7f08..ae75b9cb 100644
--- a/src/selfupdater.cpp
+++ b/src/selfupdater.cpp
@@ -65,7 +65,7 @@ SelfUpdater::SelfUpdater(NexusInterface *nexusInterface)
, m_Attempts(3)
, m_NexusDownload(nullptr)
{
- QLibrary archiveLib("dlls\\archive.dll");
+ QLibrary archiveLib(QCoreApplication::applicationDirPath() + "\\dlls\\archive.dll");
if (!archiveLib.load()) {
throw MyException(tr("archive.dll not loaded: \"%1\"").arg(archiveLib.errorString()));
}
diff --git a/src/settings.cpp b/src/settings.cpp
index 7b812759..c99b434d 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -125,7 +125,7 @@ void Settings::registerPlugin(IPlugin *plugin)
m_Plugins.push_back(plugin);
m_PluginSettings.insert(plugin->name(), QMap());
m_PluginDescriptions.insert(plugin->name(), QMap());
- foreach (const PluginSetting &setting, plugin->settings()) {
+ for (const PluginSetting &setting : plugin->settings()) {
QVariant temp = m_Settings.value("Plugins/" + plugin->name() + "/" + setting.key, setting.defaultValue);
if (!temp.convert(setting.defaultValue.type())) {
qWarning("failed to interpret \"%s\" as correct type for \"%s\" in plugin \"%s\", using default",
@@ -183,7 +183,7 @@ void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond)
{
m_Settings.beginGroup("Servers");
- foreach (const QString &serverKey, m_Settings.childKeys()) {
+ for (const QString &serverKey : m_Settings.childKeys()) {
QVariantMap data = m_Settings.value(serverKey).toMap();
if (serverKey == serverName) {
data["downloadCount"] = data["downloadCount"].toInt() + 1;
@@ -201,7 +201,7 @@ std::map Settings::getPreferredServers()
std::map result;
m_Settings.beginGroup("Servers");
- foreach (const QString &serverKey, m_Settings.childKeys()) {
+ for (const QString &serverKey : m_Settings.childKeys()) {
QVariantMap data = m_Settings.value(serverKey).toMap();
int preference = data["preferred"].toInt();
if (preference > 0) {
@@ -233,6 +233,11 @@ QString Settings::getModDirectory() const
return getConfigurablePath("mod_directory", ToQString(AppConfig::modsPath()));
}
+QString Settings::getProfileDirectory() const
+{
+ return getConfigurablePath("profiles_directory", ToQString(AppConfig::profilesPath()));
+}
+
QString Settings::getNMMVersion() const
{
static const QString MIN_NMM_VERSION = "0.52.3";
@@ -411,7 +416,7 @@ void Settings::updateServers(const QList &servers)
m_Settings.beginGroup("Servers");
QStringList oldServerKeys = m_Settings.childKeys();
- foreach (const ServerInfo &server, servers) {
+ for (const ServerInfo &server : servers) {
if (!oldServerKeys.contains(server.name)) {
// not yet known server
QVariantMap newVal;
@@ -433,7 +438,7 @@ void Settings::updateServers(const QList &servers)
// clean up unavailable servers
QDate now = QDate::currentDate();
- foreach (const QString &key, m_Settings.childKeys()) {
+ for (const QString &key : m_Settings.childKeys()) {
QVariantMap val = m_Settings.value(key).toMap();
QDate lastSeen = val["lastSeen"].toDate();
if (lastSeen.daysTo(now) > 30) {
@@ -457,7 +462,7 @@ void Settings::writePluginBlacklist()
{
m_Settings.beginWriteArray("pluginBlacklist");
int idx = 0;
- foreach (const QString &plugin, m_PluginBlacklist) {
+ for (const QString &plugin : m_PluginBlacklist) {
m_Settings.setArrayIndex(idx++);
m_Settings.setValue("name", plugin);
}
@@ -522,7 +527,7 @@ void Settings::resetDialogs()
{
m_Settings.beginGroup("DialogChoices");
QStringList keys = m_Settings.childKeys();
- foreach (QString key, keys) {
+ for (QString key : keys) {
m_Settings.remove(key);
}
@@ -539,6 +544,7 @@ void Settings::query(QWidget *parent)
std::vector> tabs;
tabs.push_back(std::unique_ptr(new GeneralTab(this, dialog)));
+ tabs.push_back(std::unique_ptr(new PathsTab(this, dialog)));
tabs.push_back(std::unique_ptr(new NexusTab(this, dialog)));
tabs.push_back(std::unique_ptr(new SteamTab(this, dialog)));
tabs.push_back(std::unique_ptr(new PluginsTab(this, dialog)));
@@ -552,56 +558,54 @@ void Settings::query(QWidget *parent)
}
}
-Settings::SettingsTab::SettingsTab(Settings *m_parent, SettingsDialog &m_dialog) :
- m_parent(m_parent),
- m_Settings(m_parent->m_Settings),
- m_dialog(m_dialog)
-{}
+Settings::SettingsTab::SettingsTab(Settings *m_parent, SettingsDialog &m_dialog)
+ : m_parent(m_parent)
+ , m_Settings(m_parent->m_Settings)
+ , m_dialog(m_dialog)
+{
+}
Settings::SettingsTab::~SettingsTab()
{}
-Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog) :
- Settings::SettingsTab(m_parent, m_dialog),
- m_languageBox(m_dialog.findChild("languageBox")),
- m_styleBox(m_dialog.findChild("styleBox")),
- m_logLevelBox(m_dialog.findChild("logLevelBox")),
- m_downloadDirEdit(m_dialog.findChild("downloadDirEdit")),
- m_modDirEdit(m_dialog.findChild("modDirEdit")),
- m_cacheDirEdit(m_dialog.findChild("cacheDirEdit")),
- m_compactBox(m_dialog.findChild("compactBox")),
- m_showMetaBox(m_dialog.findChild("showMetaBox"))
+Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
+ : Settings::SettingsTab(m_parent, m_dialog)
+ , m_languageBox(m_dialog.findChild("languageBox"))
+ , m_styleBox(m_dialog.findChild("styleBox"))
+ , m_logLevelBox(m_dialog.findChild("logLevelBox"))
+ , m_compactBox(m_dialog.findChild("compactBox"))
+ , m_showMetaBox(m_dialog.findChild("showMetaBox"))
+{
+ // FIXME I think 'addLanguages' lives in here not in parent
+ m_parent->addLanguages(m_languageBox);
{
- //FIXME I think 'addLanguages' lives in here not in parent
- m_parent->addLanguages(m_languageBox);
- {
- QString languageCode = m_parent->language();
- int currentID = m_languageBox->findData(languageCode);
- // I made a mess. :( Most languages are stored with only the iso country code (2 characters like "de") but chinese
- // with the exact language variant (zh_TW) so I have to search for both variants
- if (currentID == -1) {
- currentID = m_languageBox->findData(languageCode.mid(0, 2));
- }
- if (currentID != -1) {
- m_languageBox->setCurrentIndex(currentID);
- }
+ QString languageCode = m_parent->language();
+ int currentID = m_languageBox->findData(languageCode);
+ // I made a mess. :( Most languages are stored with only the iso country
+ // code (2 characters like "de") but chinese
+ // with the exact language variant (zh_TW) so I have to search for both
+ // variants
+ if (currentID == -1) {
+ currentID = m_languageBox->findData(languageCode.mid(0, 2));
+ }
+ if (currentID != -1) {
+ m_languageBox->setCurrentIndex(currentID);
}
+ }
- //FIXME I think addStyles lives in here not in parent
- m_parent->addStyles(m_styleBox);
- {
- int currentID = m_styleBox->findData(m_Settings.value("Settings/style", "").toString());
- if (currentID != -1) {
- m_styleBox->setCurrentIndex(currentID);
- }
+ // FIXME I think addStyles lives in here not in parent
+ m_parent->addStyles(m_styleBox);
+ {
+ int currentID = m_styleBox->findData(
+ m_Settings.value("Settings/style", "").toString());
+ if (currentID != -1) {
+ m_styleBox->setCurrentIndex(currentID);
}
+ }
- m_logLevelBox->setCurrentIndex(m_parent->logLevel());
- m_downloadDirEdit->setText(m_parent->getDownloadDirectory());
- m_modDirEdit->setText(m_parent->getModDirectory());
- m_cacheDirEdit->setText(m_parent->getCacheDirectory());
- m_compactBox->setChecked(m_parent->compactDownloads());
- m_showMetaBox->setChecked(m_parent->metaDownloads());
+ m_logLevelBox->setCurrentIndex(m_parent->logLevel());
+ m_compactBox->setChecked(m_parent->compactDownloads());
+ m_showMetaBox->setChecked(m_parent->metaDownloads());
}
void Settings::GeneralTab::update()
@@ -622,68 +626,108 @@ void Settings::GeneralTab::update()
m_Settings.setValue("Settings/log_level", m_logLevelBox->currentIndex());
- { // advanced settings
- if ((QDir::fromNativeSeparators(m_modDirEdit->text()) != QDir::fromNativeSeparators(m_parent->getModDirectory())) &&
- (QMessageBox::question(nullptr, tr("Confirm"), tr("Changing the mod directory affects all your profiles! "
- "Mods not present (or named differently) in the new location will be disabled in all profiles. "
- "There is no way to undo this unless you backed up your profiles manually. Proceed?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) {
- m_modDirEdit->setText(m_parent->getModDirectory());
- }
- if (!QDir(m_downloadDirEdit->text()).exists()) {
- QDir().mkpath(m_downloadDirEdit->text());
- }
- if (QFileInfo(m_downloadDirEdit->text()) !=
- QFileInfo(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::downloadPath()))) {
- m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(m_downloadDirEdit->text()));
- } else {
- m_Settings.remove("Settings/download_directory");
- }
+ m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked());
+ m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked());
+}
- if (!QDir(m_modDirEdit->text()).exists()) {
- QDir().mkpath(m_modDirEdit->text());
- }
- if (QFileInfo(m_modDirEdit->text()) !=
- QFileInfo(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::modsPath()))) {
- m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(m_modDirEdit->text()));
- } else {
- m_Settings.remove("Settings/mod_directory");
- }
+Settings::PathsTab::PathsTab(Settings *parent, SettingsDialog &dialog)
+ : SettingsTab(parent, dialog)
+ , m_downloadDirEdit(m_dialog.findChild("downloadDirEdit"))
+ , m_modDirEdit(m_dialog.findChild("modDirEdit"))
+ , m_cacheDirEdit(m_dialog.findChild("cacheDirEdit"))
+ , m_profilesDirEdit(m_dialog.findChild("profilesDirEdit"))
+{
+ m_downloadDirEdit->setText(m_parent->getDownloadDirectory());
+ m_modDirEdit->setText(m_parent->getModDirectory());
+ m_cacheDirEdit->setText(m_parent->getCacheDirectory());
+ m_profilesDirEdit->setText(m_parent->getProfileDirectory());
+}
+
+void Settings::PathsTab::update()
+{
+ if ((QDir::fromNativeSeparators(m_modDirEdit->text())
+ != QDir::fromNativeSeparators(m_parent->getModDirectory()))
+ && (QMessageBox::question(
+ nullptr, tr("Confirm"),
+ tr("Changing the mod directory affects all your profiles! "
+ "Mods not present (or named differently) in the new location "
+ "will be disabled in all profiles. "
+ "There is no way to undo this unless you backed up your "
+ "profiles manually. Proceed?"),
+ QMessageBox::Yes | QMessageBox::No)
+ == QMessageBox::No)) {
+ m_modDirEdit->setText(m_parent->getModDirectory());
+ }
- if (!QDir(m_cacheDirEdit->text()).exists()) {
- QDir().mkpath(m_cacheDirEdit->text());
- }
- if (QFileInfo(m_cacheDirEdit->text()) !=
- QFileInfo(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::cachePath()))) {
- m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(m_cacheDirEdit->text()));
- } else {
- m_Settings.remove("Settings/cache_directory");
- }
+ if (!QDir(m_downloadDirEdit->text()).exists()) {
+ QDir().mkpath(m_downloadDirEdit->text());
+ }
+ if (QFileInfo(m_downloadDirEdit->text())
+ != QFileInfo(qApp->property("dataPath").toString() + "/"
+ + QString::fromStdWString(AppConfig::downloadPath()))) {
+ m_Settings.setValue("Settings/download_directory",
+ QDir::toNativeSeparators(m_downloadDirEdit->text()));
+ } else {
+ m_Settings.remove("Settings/download_directory");
}
- m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked());
- m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked());
+ if (!QDir(m_modDirEdit->text()).exists()) {
+ QDir().mkpath(m_modDirEdit->text());
+ }
+ if (QFileInfo(m_modDirEdit->text())
+ != QFileInfo(qApp->property("dataPath").toString() + "/"
+ + QString::fromStdWString(AppConfig::modsPath()))) {
+ m_Settings.setValue("Settings/mod_directory",
+ QDir::toNativeSeparators(m_modDirEdit->text()));
+ } else {
+ m_Settings.remove("Settings/mod_directory");
+ }
+
+ if (!QDir(m_cacheDirEdit->text()).exists()) {
+ QDir().mkpath(m_cacheDirEdit->text());
+ }
+ if (QFileInfo(m_cacheDirEdit->text())
+ != QFileInfo(qApp->property("dataPath").toString() + "/"
+ + QString::fromStdWString(AppConfig::cachePath()))) {
+ m_Settings.setValue("Settings/cache_directory",
+ QDir::toNativeSeparators(m_cacheDirEdit->text()));
+ } else {
+ m_Settings.remove("Settings/cache_directory");
+ }
+
+ if (!QDir(m_profilesDirEdit->text()).exists()) {
+ QDir().mkpath(m_profilesDirEdit->text());
+ }
+ if (QFileInfo(m_profilesDirEdit->text())
+ != QFileInfo(qApp->property("dataPath").toString() + "/"
+ + QString::fromStdWString(AppConfig::profilesPath()))) {
+ m_Settings.setValue("Settings/profiles_directory",
+ QDir::toNativeSeparators(m_profilesDirEdit->text()));
+ } else {
+ m_Settings.remove("Settings/profiles_directory");
+ }
}
-Settings::NexusTab::NexusTab(Settings *m_parent, SettingsDialog &m_dialog) :
- Settings::SettingsTab(m_parent, m_dialog),
- m_loginCheckBox(m_dialog.findChild("loginCheckBox")),
- m_usernameEdit(m_dialog.findChild("usernameEdit")),
- m_passwordEdit(m_dialog.findChild("passwordEdit")),
- m_offlineBox(m_dialog.findChild("offlineBox")),
- m_proxyBox(m_dialog.findChild("proxyBox")),
- m_knownServersList(m_dialog.findChild("knownServersList")),
- m_preferredServersList(m_dialog.findChild("preferredServersList"))
+Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog)
+ : Settings::SettingsTab(parent, dialog)
+ , m_loginCheckBox(dialog.findChild("loginCheckBox"))
+ , m_usernameEdit(dialog.findChild("usernameEdit"))
+ , m_passwordEdit(dialog.findChild("passwordEdit"))
+ , m_offlineBox(dialog.findChild("offlineBox"))
+ , m_proxyBox(dialog.findChild("proxyBox"))
+ , m_knownServersList(dialog.findChild("knownServersList"))
+ , m_preferredServersList(
+ dialog.findChild("preferredServersList"))
{
- if (m_parent->automaticLoginEnabled()) {
+ if (parent->automaticLoginEnabled()) {
m_loginCheckBox->setChecked(true);
m_usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString());
m_passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()));
}
- m_offlineBox->setChecked(m_parent->offlineMode());
- m_proxyBox->setChecked(m_parent->useProxy());
+ m_offlineBox->setChecked(parent->offlineMode());
+ m_proxyBox->setChecked(parent->useProxy());
// display server preferences
m_Settings.beginGroup("Servers");
@@ -743,11 +787,10 @@ void Settings::NexusTab::update()
m_Settings.endGroup();
}
-
-Settings::SteamTab::SteamTab(Settings *m_parent, SettingsDialog &m_dialog) :
- Settings::SettingsTab(m_parent, m_dialog),
- m_steamUserEdit(m_dialog.findChild("steamUserEdit")),
- m_steamPassEdit(m_dialog.findChild("steamPassEdit"))
+Settings::SteamTab::SteamTab(Settings *m_parent, SettingsDialog &m_dialog)
+ : Settings::SettingsTab(m_parent, m_dialog)
+ , m_steamUserEdit(m_dialog.findChild("steamUserEdit"))
+ , m_steamPassEdit(m_dialog.findChild("steamPassEdit"))
{
if (m_Settings.contains("Settings/steam_username")) {
m_steamUserEdit->setText(m_Settings.value("Settings/steam_username", "").toString());
@@ -763,10 +806,10 @@ void Settings::SteamTab::update()
m_parent->setSteamLogin(m_steamUserEdit->text(), m_steamPassEdit->text());
}
-Settings::PluginsTab::PluginsTab(Settings *m_parent, SettingsDialog &m_dialog) :
- Settings::SettingsTab(m_parent, m_dialog),
- m_pluginsList(m_dialog.findChild("pluginsList")),
- m_pluginBlacklistList(m_dialog.findChild("pluginBlacklist"))
+Settings::PluginsTab::PluginsTab(Settings *m_parent, SettingsDialog &m_dialog)
+ : Settings::SettingsTab(m_parent, m_dialog)
+ , m_pluginsList(m_dialog.findChild("pluginsList"))
+ , m_pluginBlacklistList(m_dialog.findChild("pluginBlacklist"))
{
// display plugin settings
for (IPlugin *plugin : m_parent->m_Plugins) {
@@ -799,20 +842,21 @@ void Settings::PluginsTab::update()
// store plugin blacklist
m_parent->m_PluginBlacklist.clear();
- foreach (QListWidgetItem *item, m_pluginBlacklistList->findItems("*", Qt::MatchWildcard)) {
+ for (QListWidgetItem *item : m_pluginBlacklistList->findItems("*", Qt::MatchWildcard)) {
m_parent->m_PluginBlacklist.insert(item->text());
}
m_parent->writePluginBlacklist();
}
-Settings::WorkaroundsTab::WorkaroundsTab(Settings *m_parent, SettingsDialog &m_dialog) :
- Settings::SettingsTab(m_parent, m_dialog),
- m_appIDEdit(m_dialog.findChild("appIDEdit")),
- m_mechanismBox(m_dialog.findChild("mechanismBox")),
- m_nmmVersionEdit(m_dialog.findChild("nmmVersionEdit")),
- m_hideUncheckedBox(m_dialog.findChild("hideUncheckedBox")),
- m_forceEnableBox(m_dialog.findChild("forceEnableBox")),
- m_displayForeignBox(m_dialog.findChild("displayForeignBox"))
+Settings::WorkaroundsTab::WorkaroundsTab(Settings *m_parent,
+ SettingsDialog &m_dialog)
+ : Settings::SettingsTab(m_parent, m_dialog)
+ , m_appIDEdit(m_dialog.findChild("appIDEdit"))
+ , m_mechanismBox(m_dialog.findChild("mechanismBox"))
+ , m_nmmVersionEdit(m_dialog.findChild("nmmVersionEdit"))
+ , m_hideUncheckedBox(m_dialog.findChild("hideUncheckedBox"))
+ , m_forceEnableBox(m_dialog.findChild("forceEnableBox"))
+ , m_displayForeignBox(m_dialog.findChild("displayForeignBox"))
{
m_appIDEdit->setText(m_parent->getSteamAppID());
diff --git a/src/settings.h b/src/settings.h
index 1ee16e76..85a3dac0 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -130,6 +130,11 @@ public:
**/
QString getCacheDirectory() const;
+ /**
+ * retrieve the directory where profiles stored (with native separators)
+ **/
+ QString getProfileDirectory() const;
+
/**
* @return true if the user has set up automatic login to nexus
**/
@@ -339,11 +344,22 @@ private:
QComboBox *m_languageBox;
QComboBox *m_styleBox;
QComboBox *m_logLevelBox;
+ QCheckBox *m_compactBox;
+ QCheckBox *m_showMetaBox;
+ };
+
+ class PathsTab : public SettingsTab
+ {
+ public:
+ PathsTab(Settings *parent, SettingsDialog &dialog);
+
+ void update();
+
+ private:
QLineEdit *m_downloadDirEdit;
QLineEdit *m_modDirEdit;
QLineEdit *m_cacheDirEdit;
- QCheckBox *m_compactBox;
- QCheckBox *m_showMetaBox;
+ QLineEdit *m_profilesDirEdit;
};
/** Display/store the configuration in the 'nexus' tab of the settings dialogue */
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index 4e2f89a1..341fa19d 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -25,6 +25,7 @@ along with Mod Organizer. If not, see .
#include "noeditdelegate.h"
#include "iplugingame.h"
#include "settings.h"
+#include "instancemanager.h"
#include
#include
@@ -39,11 +40,13 @@ using namespace MOBase;
SettingsDialog::SettingsDialog(QWidget *parent)
- : TutorableDialog("SettingsDialog", parent), ui(new Ui::SettingsDialog)
+ : TutorableDialog("SettingsDialog", parent)
+ , ui(new Ui::SettingsDialog)
{
ui->setupUi(this);
- QShortcut *delShortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist);
+ QShortcut *delShortcut
+ = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist);
connect(delShortcut, SIGNAL(activated()), this, SLOT(deleteBlacklistItem()));
}
@@ -54,7 +57,7 @@ SettingsDialog::~SettingsDialog()
void SettingsDialog::addPlugins(const std::vector &plugins)
{
- foreach (IPlugin *plugin, plugins) {
+ for (IPlugin *plugin : plugins) {
ui->pluginsList->addItem(plugin->name());
}
}
@@ -89,7 +92,8 @@ void SettingsDialog::on_categoriesBtn_clicked()
void SettingsDialog::on_bsaDateBtn_clicked()
{
- IPluginGame const *game = qApp->property("managed_game").value();
+ IPluginGame const *game
+ = qApp->property("managed_game").value();
QDir dir = game->dataDirectory();
Helper::backdateBSAs(qApp->property("dataPath").toString().toStdWString(),
@@ -186,3 +190,15 @@ void SettingsDialog::on_associateButton_clicked()
{
Settings::instance().registerAsNXMHandler(true);
}
+
+void SettingsDialog::on_changeInstanceButton_clicked()
+{
+ if (QMessageBox::question(this, tr("Are you sure?"),
+ tr("This will restart MO, continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel)
+ == QMessageBox::Yes) {
+ InstanceManager().clearCurrentInstance();
+ this->reject();
+ qApp->exit(INT_MAX);
+ }
+}
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
index e99fb3e3..8bd080ab 100644
--- a/src/settingsdialog.h
+++ b/src/settingsdialog.h
@@ -52,6 +52,9 @@ signals:
void resetDialogs();
+private slots:
+ void on_changeInstanceButton_clicked();
+
private:
void storeSettings(QListWidgetItem *pluginItem);
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index b88885dc..805a5060 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -108,114 +108,60 @@ p, li { white-space: pre-wrap; }
-
-
+
- Advanced
-
-
- true
-
-
- false
+ User interface
-
-
-
-
+
+
-
+
- Directory where downloads are stored.
+ If checked, the download interface will be more compact.
-
- Directory where downloads are stored.
+
+ Compact Download Interface
- -
-
-
-
- 0
- 0
-
+
-
+
+
+ If checked, the download list will display meta information instead of file names.
- ...
+ Download Meta Information
- -
-
-
- Mod Directory
+
-
+
+
+
+ 16777215
+ 16777215
+
-
-
- -
-
- Directory where mods are stored.
+ Reset stored information from dialogs.
- Directory where mods are stored. Please note that changing this will break all associations of profiles with mods that don't exist in the new location (with the same name).
-
-
-
- -
-
-
- ...
-
-
-
- -
-
-
- Download Directory
-
-
-
- -
-
-
- Cache Directory
+ This will make all dialogs show up again where you checked the "Remember selection"-box.
-
-
- -
-
-
- -
-
- ...
+ Reset Dialogs
-
-
-
- -
-
-
- User interface
-
-
-
-
+
- If checked, the download interface will be more compact.
+ Modify the categories available to arrange your mods.
-
- Compact Download Interface
-
-
-
- -
-
-
- If checked, the download list will display meta information instead of file names.
+
+ Modify the categories available to arrange your mods.
- Download Meta Information
+ Configure Mod Categories
@@ -223,26 +169,132 @@ p, li { white-space: pre-wrap; }
-
-
-
+
+
+ Qt::Vertical
+
+
- 16777215
- 16777215
+ 20
+ 40
+
+
+ -
+
- Reset stored information from dialogs.
+ Restart MO and choose a different set of data paths.
- This will make all dialogs show up again where you checked the "Remember selection"-box.
+ This will restart MO and give you opportunity to switch to a different set of data paths.
- Reset Dialogs
+ Change Instance
+
+
+
+
+ Paths
+
+
-
-
+
+
-
+
+
+ Downloads
+
+
+
+ -
+
+
+ Caches
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ -
+
+
+ Directory where downloads are stored.
+
+
+ Directory where downloads are stored.
+
+
+
+ -
+
+
+ Mods
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ Directory where mods are stored.
+
+
+ Directory where mods are stored. Please note that changing this will break all associations of profiles with mods that don't exist in the new location (with the same name).
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ ...
+
+
+
+ -
+
+
+ Profiles
+
+
+
+ -
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
Qt::Vertical
@@ -255,15 +307,9 @@ p, li { white-space: pre-wrap; }
-
-
-
- Modify the categories available to arrange your mods.
-
-
- Modify the categories available to arrange your mods.
-
+
- Configure Mod Categories
+ Important: All directories have to be writeable!
--
cgit v1.3.1
From 9df612c7ca0ba4cb0b62d958df4e2745fe0c04ec Mon Sep 17 00:00:00 2001
From: Tannin
Date: Wed, 2 Mar 2016 21:28:17 +0100
Subject: more configuration options
- overwrite path configurable
- one can now set a base directory for all configurable paths
- user can now opt in/out of receiving pre-release updates (not functional yet)
---
src/settings.cpp | 129 ++++++++++++++++++++++++++++++++++++++++--------
src/settings.h | 27 ++++++++--
src/settingsdialog.cpp | 17 +++++++
src/settingsdialog.h | 6 +++
src/settingsdialog.ui | 131 +++++++++++++++++++++++++++++++++++++++----------
5 files changed, 257 insertions(+), 53 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/settings.cpp b/src/settings.cpp
index c99b434d..41d176ea 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -33,6 +33,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
@@ -179,6 +180,11 @@ QString Settings::getSteamAppID() const
return m_Settings.value("Settings/app_id", m_GamePlugin->steamAPPId()).toString();
}
+bool Settings::usePrereleases() const
+{
+ return m_Settings.value("Settings/use_prereleases", false).toBool();
+}
+
void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond)
{
m_Settings.beginGroup("Servers");
@@ -213,34 +219,55 @@ std::map Settings::getPreferredServers()
return result;
}
-QString Settings::getConfigurablePath(const QString &key, const QString &def) const
+QString Settings::getConfigurablePath(const QString &key,
+ const QString &def,
+ bool resolve) const
+{
+ QString result = QDir::fromNativeSeparators(
+ m_Settings.value(QString("settings/") + key,
+ qApp->property("dataPath").toString() + "/" + def)
+ .toString());
+ if (resolve) {
+ result.replace("%BASE_DIR%", getBaseDirectory());
+ }
+ return result;
+}
+
+QString Settings::getBaseDirectory() const
{
- return QDir::fromNativeSeparators(m_Settings.value(QString("settings/") + key, qApp->property("dataPath").toString() + "/" + def).toString());
+ return QDir::fromNativeSeparators(m_Settings.value(
+ "settings/base_directory", qApp->property("dataPath").toString()).toString());
}
-QString Settings::getDownloadDirectory() const
+QString Settings::getDownloadDirectory(bool resolve) const
{
- return getConfigurablePath("download_directory", ToQString(AppConfig::downloadPath()));
+ return getConfigurablePath("download_directory", ToQString(AppConfig::downloadPath()), resolve);
}
-QString Settings::getCacheDirectory() const
+QString Settings::getCacheDirectory(bool resolve) const
{
- return getConfigurablePath("cache_directory", ToQString(AppConfig::cachePath()));
+ return getConfigurablePath("cache_directory", ToQString(AppConfig::cachePath()), resolve);
}
-QString Settings::getModDirectory() const
+QString Settings::getModDirectory(bool resolve) const
{
- return getConfigurablePath("mod_directory", ToQString(AppConfig::modsPath()));
+ return getConfigurablePath("mod_directory", ToQString(AppConfig::modsPath()), resolve);
}
-QString Settings::getProfileDirectory() const
+QString Settings::getProfileDirectory(bool resolve) const
{
- return getConfigurablePath("profiles_directory", ToQString(AppConfig::profilesPath()));
+ return getConfigurablePath("profiles_directory", ToQString(AppConfig::profilesPath()), resolve);
+}
+
+QString Settings::getOverwriteDirectory(bool resolve) const
+{
+ return getConfigurablePath("overwrite_directory",
+ ToQString(AppConfig::overwritePath()), resolve);
}
QString Settings::getNMMVersion() const
{
- static const QString MIN_NMM_VERSION = "0.52.3";
+ static const QString MIN_NMM_VERSION = "0.61.13";
QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString();
if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) {
result = MIN_NMM_VERSION;
@@ -508,12 +535,7 @@ void Settings::addLanguages(QComboBox *languageBox)
void Settings::addStyles(QComboBox *styleBox)
{
styleBox->addItem("None", "");
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
styleBox->addItem("Fusion", "Fusion");
-#else
- styleBox->addItem("Plastique", "Plastique");
- styleBox->addItem("Cleanlooks", "Cleanlooks");
-#endif
QDirIterator langIter(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::stylesheetsPath()), QStringList("*.qss"), QDir::Files);
while (langIter.hasNext()) {
@@ -575,6 +597,7 @@ Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
, m_logLevelBox(m_dialog.findChild("logLevelBox"))
, m_compactBox(m_dialog.findChild("compactBox"))
, m_showMetaBox(m_dialog.findChild("showMetaBox"))
+ , m_usePrereleaseBox(m_dialog.findChild("usePrereleaseBox"))
{
// FIXME I think 'addLanguages' lives in here not in parent
m_parent->addLanguages(m_languageBox);
@@ -606,6 +629,7 @@ Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
m_logLevelBox->setCurrentIndex(m_parent->logLevel());
m_compactBox->setChecked(m_parent->compactDownloads());
m_showMetaBox->setChecked(m_parent->metaDownloads());
+ m_usePrereleaseBox->setChecked(m_parent->usePrereleases());
}
void Settings::GeneralTab::update()
@@ -629,23 +653,53 @@ void Settings::GeneralTab::update()
m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked());
m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked());
+ m_Settings.setValue("Settings/use_prereleases", m_usePrereleaseBox->isChecked());
}
Settings::PathsTab::PathsTab(Settings *parent, SettingsDialog &dialog)
: SettingsTab(parent, dialog)
+ , m_baseDirEdit(m_dialog.findChild("baseDirEdit"))
, m_downloadDirEdit(m_dialog.findChild("downloadDirEdit"))
, m_modDirEdit(m_dialog.findChild("modDirEdit"))
, m_cacheDirEdit(m_dialog.findChild("cacheDirEdit"))
, m_profilesDirEdit(m_dialog.findChild("profilesDirEdit"))
-{
- m_downloadDirEdit->setText(m_parent->getDownloadDirectory());
- m_modDirEdit->setText(m_parent->getModDirectory());
- m_cacheDirEdit->setText(m_parent->getCacheDirectory());
- m_profilesDirEdit->setText(m_parent->getProfileDirectory());
+ , m_overwriteDirEdit(m_dialog.findChild("overwriteDirEdit"))
+{
+ m_baseDirEdit->setText(m_parent->getBaseDirectory());
+ /*
+ m_downloadDirEdit->setText(m_parent->getDownloadDirectory(false));
+ m_modDirEdit->setText(m_parent->getModDirectory(false));
+ m_cacheDirEdit->setText(m_parent->getCacheDirectory(false));
+ m_profilesDirEdit->setText(m_parent->getProfileDirectory(false));
+ m_overwriteDirEdit->setText(m_parent->getOverwriteDirectory(false));
+ */
+
+ QString basePath = parent->getBaseDirectory();
+ QDir baseDir(basePath);
+ for (const auto &dir : {
+ std::make_pair(m_downloadDirEdit, m_parent->getDownloadDirectory(false)),
+ std::make_pair(m_modDirEdit, m_parent->getModDirectory(false)),
+ std::make_pair(m_cacheDirEdit, m_parent->getCacheDirectory(false)),
+ std::make_pair(m_profilesDirEdit, m_parent->getProfileDirectory(false)),
+ std::make_pair(m_overwriteDirEdit, m_parent->getOverwriteDirectory(false))
+ }) {
+ QString storePath = baseDir.relativeFilePath(dir.second);
+ qDebug("%s -> %s", qPrintable(dir.second), qPrintable(storePath));
+ if (storePath.startsWith("..") || QDir::isAbsolutePath(storePath)) {
+ storePath = dir.second;
+ } else {
+ storePath = QString("%BASE_DIR%/") + storePath;
+ }
+ dir.first->setText(storePath);
+ }
}
void Settings::PathsTab::update()
{
+ typedef std::tuple Directory;
+
+ QString basePath = m_parent->getBaseDirectory();
+
if ((QDir::fromNativeSeparators(m_modDirEdit->text())
!= QDir::fromNativeSeparators(m_parent->getModDirectory()))
&& (QMessageBox::question(
@@ -660,6 +714,38 @@ void Settings::PathsTab::update()
m_modDirEdit->setText(m_parent->getModDirectory());
}
+ for (const Directory &dir :{
+ Directory{m_downloadDirEdit->text(), "download_directory", AppConfig::downloadPath()},
+ Directory{m_cacheDirEdit->text(), "cache_directory", AppConfig::cachePath()},
+ Directory{m_modDirEdit->text(), "mod_directory", AppConfig::modsPath()},
+ Directory{m_overwriteDirEdit->text(), "overwrite_directory", AppConfig::overwritePath()},
+ Directory{m_profilesDirEdit->text(), "profiles_directory", AppConfig::profilesPath()}
+ }) {
+ QString path, settingsKey;
+ std::wstring defaultName;
+ std::tie(path, settingsKey, defaultName) = dir;
+
+ settingsKey = QString("Settings/%1").arg(settingsKey);
+
+ QString realPath = path;
+ realPath.replace("%BASE_DIR%", m_parent->getBaseDirectory());
+
+ if (!QDir(realPath).exists()) {
+ QDir().mkpath(realPath);
+ }
+
+ qDebug("%s -> %s", qPrintable(path), qPrintable(realPath));
+
+ if (QFileInfo(realPath)
+ != QFileInfo(basePath + "/" + QString::fromStdWString(defaultName))) {
+ m_Settings.setValue(settingsKey, path);
+ } else {
+ m_Settings.remove(settingsKey);
+ }
+ }
+
+
+/*
if (!QDir(m_downloadDirEdit->text()).exists()) {
QDir().mkpath(m_downloadDirEdit->text());
}
@@ -707,6 +793,7 @@ void Settings::PathsTab::update()
} else {
m_Settings.remove("Settings/profiles_directory");
}
+ */
}
Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog)
diff --git a/src/settings.h b/src/settings.h
index 85a3dac0..9676df70 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -105,10 +105,16 @@ public:
**/
QString getSteamAppID() const;
+ /**
+ * retrieves the base directory under which the other directories usually
+ * reside
+ */
+ QString getBaseDirectory() const;
+
/**
* retrieve the directory where downloads are stored (with native separators)
**/
- QString getDownloadDirectory() const;
+ QString getDownloadDirectory(bool resolve = true) const;
/**
* retrieve a sorted list of preferred servers
@@ -118,7 +124,7 @@ public:
/**
* retrieve the directory where mods are stored (with native separators)
**/
- QString getModDirectory() const;
+ QString getModDirectory(bool resolve = true) const;
/**
* returns the version of nmm to impersonate when connecting to nexus
@@ -128,12 +134,18 @@ public:
/**
* retrieve the directory where the web cache is stored (with native separators)
**/
- QString getCacheDirectory() const;
+ QString getCacheDirectory(bool resolve = true) const;
/**
* retrieve the directory where profiles stored (with native separators)
**/
- QString getProfileDirectory() const;
+ QString getProfileDirectory(bool resolve = true) const;
+
+ /**
+ * retrieve the directory were new files are stored that can't be assigned
+ * to a mod (with native separators)
+ */
+ QString getOverwriteDirectory(bool resolve = true) const;
/**
* @return true if the user has set up automatic login to nexus
@@ -295,6 +307,8 @@ public:
*/
std::vector plugins() const { return m_Plugins; }
+ bool usePrereleases() const;
+
/**
* @brief register MO as the handler for nxm links
* @param force set to true to enforce the registration dialog to show up,
@@ -315,7 +329,7 @@ private:
void addStyles(QComboBox *styleBox);
void readPluginBlacklist();
void writePluginBlacklist();
- QString getConfigurablePath(const QString &key, const QString &def) const;
+ QString getConfigurablePath(const QString &key, const QString &def, bool resolve) const;
class SettingsTab
{
@@ -346,6 +360,7 @@ private:
QComboBox *m_logLevelBox;
QCheckBox *m_compactBox;
QCheckBox *m_showMetaBox;
+ QCheckBox *m_usePrereleaseBox;
};
class PathsTab : public SettingsTab
@@ -356,10 +371,12 @@ private:
void update();
private:
+ QLineEdit *m_baseDirEdit;
QLineEdit *m_downloadDirEdit;
QLineEdit *m_modDirEdit;
QLineEdit *m_cacheDirEdit;
QLineEdit *m_profilesDirEdit;
+ QLineEdit *m_overwriteDirEdit;
};
/** Display/store the configuration in the 'nexus' tab of the settings dialogue */
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index 5b58c9da..d354b29b 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -100,6 +100,15 @@ void SettingsDialog::on_bsaDateBtn_clicked()
dir.absolutePath().toStdWString());
}
+void SettingsDialog::on_browseBaseDirBtn_clicked()
+{
+ QString temp = QFileDialog::getExistingDirectory(
+ this, tr("Select base directory"), ui->baseDirEdit->text());
+ if (!temp.isEmpty()) {
+ ui->baseDirEdit->setText(temp);
+ }
+}
+
void SettingsDialog::on_browseDownloadDirBtn_clicked()
{
QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), ui->downloadDirEdit->text());
@@ -132,6 +141,14 @@ void SettingsDialog::on_browseProfilesDirBtn_clicked()
}
}
+void SettingsDialog::on_browseOverwriteDirBtn_clicked()
+{
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select overwrite directory"), ui->overwriteDirEdit->text());
+ if (!temp.isEmpty()) {
+ ui->overwriteDirEdit->setText(temp);
+ }
+}
+
void SettingsDialog::on_resetDialogsButton_clicked()
{
if (QMessageBox::question(this, tr("Confirm?"),
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
index d1a566b1..d266488d 100644
--- a/src/settingsdialog.h
+++ b/src/settingsdialog.h
@@ -52,6 +52,12 @@ signals:
void resetDialogs();
+private slots:
+ void on_browseBaseDirBtn_clicked();
+
+private slots:
+ void on_browseOverwriteDirBtn_clicked();
+
private slots:
void on_browseProfilesDirBtn_clicked();
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index f54ab895..808d8296 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -107,6 +107,36 @@ p, li { white-space: pre-wrap; }
+ -
+
+
+ Update to non-stable releases.
+
+
+ If this is enabled, the integrated update mechanism will notify of all releases, including pre-releases (alphas, betas).
+
+Please use this only if you're sufficiently tech-savvy to investigate issues, look for known problems in the issue tracker and create meaningful reports.
+
+If you use pre-releases, never contact me directly by e-mail or via private messages!
+
+
+ Install Pre-releases (Betas)
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
-
@@ -204,54 +234,71 @@ p, li { white-space: pre-wrap; }
-
-
-
+
- Downloads
+ Base Directory
- -
+
-
+
+
+ ...
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ Overwrite
+
+
+
+ -
Caches
- -
+
-
...
- -
+
-
- -
-
-
- Directory where downloads are stored.
-
-
- Directory where downloads are stored.
-
-
-
- -
-
+
-
+
- Mods
+ Downloads
- -
+
-
...
- -
+
-
Directory where mods are stored.
@@ -261,7 +308,7 @@ p, li { white-space: pre-wrap; }
- -
+
-
@@ -274,23 +321,53 @@ p, li { white-space: pre-wrap; }
+ -
+
+
+ Directory where downloads are stored.
+
+
+ Directory where downloads are stored.
+
+
+
-
-
+
- Profiles
+ Mods
- -
-
-
- -
+
-
...
+ -
+
+
+ -
+
+
+ Profiles
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
-
--
cgit v1.3.1
From 0b07cfa3f02d8d48bbb753539ed54f7bec884ae8 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Thu, 19 May 2016 19:10:33 +0200
Subject: cleanup
---
src/activatemodsdialog.cpp | 5 --
src/nexusinterface.cpp | 4 --
src/organizerproxy.cpp | 5 --
src/organizerproxy.h | 1 -
src/savegame.h | 121 ---------------------------------------------
src/settings.cpp | 58 ----------------------
6 files changed, 194 deletions(-)
delete mode 100644 src/savegame.h
(limited to 'src/settings.cpp')
diff --git a/src/activatemodsdialog.cpp b/src/activatemodsdialog.cpp
index 5ef0a4e5..c7e3dca2 100644
--- a/src/activatemodsdialog.cpp
+++ b/src/activatemodsdialog.cpp
@@ -35,13 +35,8 @@ ActivateModsDialog::ActivateModsDialog(SaveGameInfo::MissingAssets const &missin
QTableWidget *modsTable = findChild("modsTable");
QHeaderView *headerView = modsTable->horizontalHeader();
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
headerView->setSectionResizeMode(1, QHeaderView::Interactive);
-#else
- headerView->setResizeMode(0, QHeaderView::Stretch);
- headerView->setResizeMode(1, QHeaderView::Interactive);
-#endif
int row = 0;
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index 4a44c067..f5baa6ab 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -339,10 +339,6 @@ int NexusInterface::requestFiles(int modID, QObject *receiver, QVariant userData
connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
-// QTimer::singleShot(1000, this, SLOT(fakeFiles()));
-// static int fID = 42;
-// return fID++;
-
nextRequest();
return requestInfo.m_ID;
}
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp
index fe6809e3..b6dbd242 100644
--- a/src/organizerproxy.cpp
+++ b/src/organizerproxy.cpp
@@ -152,11 +152,6 @@ QList OrganizerProxy::findFileInfos(const QString
return m_Proxied->findFileInfos(path, filter);
}
-MOBase::IProfile *OrganizerProxy::profile()
-{
- return m_Proxied->currentProfile();
-}
-
MOBase::IDownloadManager *OrganizerProxy::downloadManager() const
{
return m_Proxied->downloadManager();
diff --git a/src/organizerproxy.h b/src/organizerproxy.h
index 77600671..7d925482 100644
--- a/src/organizerproxy.h
+++ b/src/organizerproxy.h
@@ -34,7 +34,6 @@ public:
virtual QStringList findFiles(const QString &path, const std::function &filter) const;
virtual QStringList getFileOrigins(const QString &fileName) const;
virtual QList findFileInfos(const QString &path, const std::function &filter) const;
- virtual MOBase::IProfile *profile();
virtual MOBase::IDownloadManager *downloadManager() const;
virtual MOBase::IPluginList *pluginList() const;
diff --git a/src/savegame.h b/src/savegame.h
deleted file mode 100644
index e7220fcc..00000000
--- a/src/savegame.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see .
-*/
-
-#ifndef SAVEGAME_H
-#define SAVEGAME_H
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define WIN32_LEAN_AND_MEAN
-#include
-
-namespace MOBase { class IPluginGame; }
-
-/**
- * @brief represents a single save game
- **/
-class SaveGame : public QObject {
-
-Q_OBJECT
-
-public:
-
- /**
- * @brief construct a save game and immediately read out information from the file
- *
- * @param filename absolute path of the save game file
- **/
- SaveGame(QObject *parent, const QString &filename, MOBase::IPluginGame const *game);
-
- virtual ~SaveGame();
-
- /**
- * @brief read out information from a savegame
- *
- * @param fileName absolute path of the save game file
- **/
- virtual void readFile(const QString) { }
-
- /**
- * @return filename of this savegame
- */
- const QString &fileName() const { return m_FileName; }
-
- /**
- * @return a list of additional files that belong to this savegame
- */
- virtual QStringList attachedFiles() const;
-
- /**
- * @return a list of all files that belong to this savegame
- */
- virtual QStringList saveFiles() const;
-
- /**
- * @return name of the player character
- **/
- const QString &pcName() const { return m_PCName; }
-
- /**
- * @return level of the player character
- **/
- unsigned short pcLevel() const { return m_PCLevel; }
-
- /**
- * @return location of the player character
- **/
- const QString &pcLocation() const { return m_PCLocation; }
-
- /**
- * @return index of the save game
- **/
- unsigned long saveNumber() const { return m_SaveNumber; }
-
- /**
- * @return creation time of the save game
- **/
- SYSTEMTIME creationTime() const { return m_CreationTime; }
-
- /**
- * @return screenshot in the savegame
- **/
- const QImage &screenshot() const { return m_Screenshot; }
-
-protected:
-
- QString m_FileName;
- QString m_PCName { "N/A" };
- unsigned short m_PCLevel { 0 };
- QString m_PCLocation { "N/A" };
- unsigned long m_SaveNumber { 0 };
- SYSTEMTIME m_CreationTime;
- QImage m_Screenshot;
-
-private:
- MOBase::IPluginGame const * const m_Game;
-};
-
-
-#endif // SAVEGAME_H
diff --git a/src/settings.cpp b/src/settings.cpp
index 41d176ea..a0625c4c 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -666,13 +666,6 @@ Settings::PathsTab::PathsTab(Settings *parent, SettingsDialog &dialog)
, m_overwriteDirEdit(m_dialog.findChild("overwriteDirEdit"))
{
m_baseDirEdit->setText(m_parent->getBaseDirectory());
- /*
- m_downloadDirEdit->setText(m_parent->getDownloadDirectory(false));
- m_modDirEdit->setText(m_parent->getModDirectory(false));
- m_cacheDirEdit->setText(m_parent->getCacheDirectory(false));
- m_profilesDirEdit->setText(m_parent->getProfileDirectory(false));
- m_overwriteDirEdit->setText(m_parent->getOverwriteDirectory(false));
- */
QString basePath = parent->getBaseDirectory();
QDir baseDir(basePath);
@@ -743,57 +736,6 @@ void Settings::PathsTab::update()
m_Settings.remove(settingsKey);
}
}
-
-
-/*
- if (!QDir(m_downloadDirEdit->text()).exists()) {
- QDir().mkpath(m_downloadDirEdit->text());
- }
- if (QFileInfo(m_downloadDirEdit->text())
- != QFileInfo(qApp->property("dataPath").toString() + "/"
- + QString::fromStdWString(AppConfig::downloadPath()))) {
- m_Settings.setValue("Settings/download_directory",
- QDir::toNativeSeparators(m_downloadDirEdit->text()));
- } else {
- m_Settings.remove("Settings/download_directory");
- }
-
- if (!QDir(m_modDirEdit->text()).exists()) {
- QDir().mkpath(m_modDirEdit->text());
- }
- if (QFileInfo(m_modDirEdit->text())
- != QFileInfo(qApp->property("dataPath").toString() + "/"
- + QString::fromStdWString(AppConfig::modsPath()))) {
- m_Settings.setValue("Settings/mod_directory",
- QDir::toNativeSeparators(m_modDirEdit->text()));
- } else {
- m_Settings.remove("Settings/mod_directory");
- }
-
- if (!QDir(m_cacheDirEdit->text()).exists()) {
- QDir().mkpath(m_cacheDirEdit->text());
- }
- if (QFileInfo(m_cacheDirEdit->text())
- != QFileInfo(qApp->property("dataPath").toString() + "/"
- + QString::fromStdWString(AppConfig::cachePath()))) {
- m_Settings.setValue("Settings/cache_directory",
- QDir::toNativeSeparators(m_cacheDirEdit->text()));
- } else {
- m_Settings.remove("Settings/cache_directory");
- }
-
- if (!QDir(m_profilesDirEdit->text()).exists()) {
- QDir().mkpath(m_profilesDirEdit->text());
- }
- if (QFileInfo(m_profilesDirEdit->text())
- != QFileInfo(qApp->property("dataPath").toString() + "/"
- + QString::fromStdWString(AppConfig::profilesPath()))) {
- m_Settings.setValue("Settings/profiles_directory",
- QDir::toNativeSeparators(m_profilesDirEdit->text()));
- } else {
- m_Settings.remove("Settings/profiles_directory");
- }
- */
}
Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog)
--
cgit v1.3.1
From bbab59f68112278bb23ff3bdc69737515b916667 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Fri, 27 May 2016 15:51:01 +0200
Subject: fixed handling of base dir in settings dialog (and fixed the tab
order in the settings dialog)
---
src/settings.cpp | 33 +++++++++------------------------
src/settingsdialog.cpp | 43 ++++++++++++++++++++++++++++++++++++++-----
src/settingsdialog.h | 3 +++
src/settingsdialog.ui | 44 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 94 insertions(+), 29 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/settings.cpp b/src/settings.cpp
index a0625c4c..d9fa833d 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -224,8 +224,7 @@ QString Settings::getConfigurablePath(const QString &key,
bool resolve) const
{
QString result = QDir::fromNativeSeparators(
- m_Settings.value(QString("settings/") + key,
- qApp->property("dataPath").toString() + "/" + def)
+ m_Settings.value(QString("settings/") + key, QString("%BASE_DIR%/") + def)
.toString());
if (resolve) {
result.replace("%BASE_DIR%", getBaseDirectory());
@@ -677,12 +676,7 @@ Settings::PathsTab::PathsTab(Settings *parent, SettingsDialog &dialog)
std::make_pair(m_overwriteDirEdit, m_parent->getOverwriteDirectory(false))
}) {
QString storePath = baseDir.relativeFilePath(dir.second);
- qDebug("%s -> %s", qPrintable(dir.second), qPrintable(storePath));
- if (storePath.startsWith("..") || QDir::isAbsolutePath(storePath)) {
- storePath = dir.second;
- } else {
- storePath = QString("%BASE_DIR%/") + storePath;
- }
+ storePath = dir.second;
dir.first->setText(storePath);
}
}
@@ -693,20 +687,6 @@ void Settings::PathsTab::update()
QString basePath = m_parent->getBaseDirectory();
- if ((QDir::fromNativeSeparators(m_modDirEdit->text())
- != QDir::fromNativeSeparators(m_parent->getModDirectory()))
- && (QMessageBox::question(
- nullptr, tr("Confirm"),
- tr("Changing the mod directory affects all your profiles! "
- "Mods not present (or named differently) in the new location "
- "will be disabled in all profiles. "
- "There is no way to undo this unless you backed up your "
- "profiles manually. Proceed?"),
- QMessageBox::Yes | QMessageBox::No)
- == QMessageBox::No)) {
- m_modDirEdit->setText(m_parent->getModDirectory());
- }
-
for (const Directory &dir :{
Directory{m_downloadDirEdit->text(), "download_directory", AppConfig::downloadPath()},
Directory{m_cacheDirEdit->text(), "cache_directory", AppConfig::cachePath()},
@@ -727,8 +707,6 @@ void Settings::PathsTab::update()
QDir().mkpath(realPath);
}
- qDebug("%s -> %s", qPrintable(path), qPrintable(realPath));
-
if (QFileInfo(realPath)
!= QFileInfo(basePath + "/" + QString::fromStdWString(defaultName))) {
m_Settings.setValue(settingsKey, path);
@@ -736,6 +714,13 @@ void Settings::PathsTab::update()
m_Settings.remove(settingsKey);
}
}
+
+ if (QFileInfo(m_baseDirEdit->text()) !=
+ QFileInfo(qApp->property("dataPath").toString())) {
+ m_Settings.setValue("Settings/base_directory", m_baseDirEdit->text());
+ } else {
+ m_Settings.remove("Settings/base_directory");
+ }
}
Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog)
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index 0d86018c..62134c9b 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -65,6 +65,23 @@ void SettingsDialog::addPlugins(const std::vector &plugins)
void SettingsDialog::accept()
{
+ QString newModPath = ui->modDirEdit->text();
+ newModPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+
+ if ((QDir::fromNativeSeparators(newModPath) !=
+ QDir::fromNativeSeparators(
+ Settings::instance().getModDirectory(true))) &&
+ (QMessageBox::question(
+ nullptr, tr("Confirm"),
+ tr("Changing the mod directory affects all your profiles! "
+ "Mods not present (or named differently) in the new location "
+ "will be disabled in all profiles. "
+ "There is no way to undo this unless you backed up your "
+ "profiles manually. Proceed?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) {
+ return;
+ }
+
storeSettings(ui->pluginsList->currentItem());
TutorableDialog::accept();
}
@@ -112,7 +129,10 @@ void SettingsDialog::on_browseBaseDirBtn_clicked()
void SettingsDialog::on_browseDownloadDirBtn_clicked()
{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), ui->downloadDirEdit->text());
+ QString searchPath = ui->downloadDirEdit->text();
+ searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), searchPath);
if (!temp.isEmpty()) {
ui->downloadDirEdit->setText(temp);
}
@@ -120,7 +140,10 @@ void SettingsDialog::on_browseDownloadDirBtn_clicked()
void SettingsDialog::on_browseModDirBtn_clicked()
{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select mod directory"), ui->modDirEdit->text());
+ QString searchPath = ui->modDirEdit->text();
+ searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select mod directory"), searchPath);
if (!temp.isEmpty()) {
ui->modDirEdit->setText(temp);
}
@@ -128,7 +151,10 @@ void SettingsDialog::on_browseModDirBtn_clicked()
void SettingsDialog::on_browseCacheDirBtn_clicked()
{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select cache directory"), ui->cacheDirEdit->text());
+ QString searchPath = ui->cacheDirEdit->text();
+ searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select cache directory"), searchPath);
if (!temp.isEmpty()) {
ui->cacheDirEdit->setText(temp);
}
@@ -136,7 +162,10 @@ void SettingsDialog::on_browseCacheDirBtn_clicked()
void SettingsDialog::on_browseProfilesDirBtn_clicked()
{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select profiles directory"), ui->profilesDirEdit->text());
+ QString searchPath = ui->profilesDirEdit->text();
+ searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select profiles directory"), searchPath);
if (!temp.isEmpty()) {
ui->profilesDirEdit->setText(temp);
}
@@ -144,7 +173,10 @@ void SettingsDialog::on_browseProfilesDirBtn_clicked()
void SettingsDialog::on_browseOverwriteDirBtn_clicked()
{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select overwrite directory"), ui->overwriteDirEdit->text());
+ QString searchPath = ui->overwriteDirEdit->text();
+ searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select overwrite directory"), searchPath);
if (!temp.isEmpty()) {
ui->overwriteDirEdit->setText(temp);
}
@@ -222,3 +254,4 @@ void SettingsDialog::on_clearCacheButton_clicked()
QDir(Settings::instance().getCacheDirectory()).removeRecursively();
NexusInterface::instance()->clearCache();
}
+
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
index 658fbce4..e9d995d3 100644
--- a/src/settingsdialog.h
+++ b/src/settingsdialog.h
@@ -87,6 +87,9 @@ private slots:
private:
Ui::SettingsDialog *ui;
+
};
+
+
#endif // WORKAROUNDDIALOG_H
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 1f751da8..6ae415d1 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -1026,6 +1026,50 @@ For the other games this is not a sufficient replacement for AI!
+
+ languageBox
+ styleBox
+ logLevelBox
+ usePrereleaseBox
+ compactBox
+ showMetaBox
+ resetDialogsButton
+ categoriesBtn
+ baseDirEdit
+ browseBaseDirBtn
+ downloadDirEdit
+ browseDownloadDirBtn
+ modDirEdit
+ browseModDirBtn
+ cacheDirEdit
+ browseCacheDirBtn
+ profilesDirEdit
+ browseProfilesDirBtn
+ overwriteDirEdit
+ browseOverwriteDirBtn
+ loginCheckBox
+ usernameEdit
+ passwordEdit
+ clearCacheButton
+ offlineBox
+ proxyBox
+ associateButton
+ knownServersList
+ preferredServersList
+ steamUserEdit
+ steamPassEdit
+ pluginsList
+ pluginSettingsList
+ pluginBlacklist
+ appIDEdit
+ mechanismBox
+ nmmVersionEdit
+ hideUncheckedBox
+ forceEnableBox
+ displayForeignBox
+ bsaDateBtn
+ tabWidget
+
--
cgit v1.3.1
From 8bf3037d4bd3be9ac3035ef49ea4fe4303f51a62 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Fri, 3 Jun 2016 18:49:48 +0200
Subject: bugfix: changing from local language to english doesn't stick
---
src/settings.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/settings.cpp')
diff --git a/src/settings.cpp b/src/settings.cpp
index d9fa833d..193c6a35 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -633,7 +633,7 @@ Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
void Settings::GeneralTab::update()
{
- QString oldLanguage = m_Settings.value("Settings/language", "en_US").toString();
+ QString oldLanguage = m_parent->language();
QString newLanguage = m_languageBox->itemData(m_languageBox->currentIndex()).toString();
if (newLanguage != oldLanguage) {
m_Settings.setValue("Settings/language", newLanguage);
--
cgit v1.3.1
From 8a3af93b39b05b95462869fc7df7169c5862c966 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Thu, 23 Jun 2016 21:00:46 +0200
Subject: fixed creation of data paths after changing paths in settings and
update of profile list after change
---
src/main.cpp | 49 ++++++----------
src/mainwindow.cpp | 1 +
src/modinfooverwrite.cpp | 3 +-
src/organizer_en.ts | 149 ++++++++++++++++++++++++-----------------------
src/organizercore.cpp | 35 ++++++++++-
src/organizercore.h | 4 ++
src/pluginlist.cpp | 10 ++--
src/settings.cpp | 10 +++-
src/settingsdialog.ui | 7 +++
9 files changed, 154 insertions(+), 114 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 6b585b5c..16b6b80f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -85,38 +85,21 @@ along with Mod Organizer. If not, see .
using namespace MOBase;
using namespace MOShared;
-
-bool createAndMakeWritable(const std::wstring &subPath)
-{
+bool createAndMakeWritable(const std::wstring &subPath) {
QString const dataPath = qApp->property("dataPath").toString();
QString fullPath = dataPath + "/" + QString::fromStdWString(subPath);
- if (!QDir(fullPath).exists()) {
- QDir().mkdir(fullPath);
- }
-
- QFileInfo fileInfo(fullPath);
- if (!fileInfo.exists() || !fileInfo.isWritable()) {
- if (QMessageBox::question(nullptr, QObject::tr("Permissions required"),
- QObject::tr("The current user account doesn't have the required access rights to run "
- "Mod Organizer. The neccessary changes can be made automatically (the MO directory "
- "will be made writable for the current user account). You will be asked to run "
- "\"helper.exe\" with administrative rights."),
- QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Yes) {
- if (!Helper::init(qApp->applicationDirPath().toStdWString(),
- dataPath.toStdWString())) {
- return false;
- }
- } else {
- return false;
- }
- // no matter which directory didn't exist/wasn't writable, the helper
- // should have created them all so we don't have to worry this message box would appear repeatedly
+ if (!QDir(fullPath).exists() && !QDir().mkdir(fullPath)) {
+ QMessageBox::critical(nullptr, QObject::tr("Error"),
+ QObject::tr("Failed to create \"%1\". Your user "
+ "account probably lacks permission.")
+ .arg(fullPath));
+ return false;
+ } else {
+ return true;
}
- return true;
}
-
bool bootstrap()
{
// remove the temporary backup directory in case we're restarting after an update
@@ -129,11 +112,9 @@ bool bootstrap()
removeOldFiles(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()),
"usvfs*.log", 5, QDir::Name);
- createAndMakeWritable(AppConfig::profilesPath());
- createAndMakeWritable(AppConfig::modsPath());
- createAndMakeWritable(AppConfig::downloadPath());
- createAndMakeWritable(AppConfig::overwritePath());
- createAndMakeWritable(AppConfig::logPath());
+ if (!createAndMakeWritable(AppConfig::logPath())) {
+ return false;
+ }
return true;
}
@@ -445,7 +426,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
qDebug("data path: %s", qPrintable(dataPath));
if (!bootstrap()) {
- reportError("failed to set up data path");
+ reportError("failed to set up data paths");
return 1;
}
@@ -465,6 +446,10 @@ int runApplication(MOApplication &application, SingleInstance &instance,
QSettings::IniFormat);
qDebug("initializing core");
OrganizerCore organizer(settings);
+ if (!organizer.bootstrap()) {
+ reportError("failed to set up data paths");
+ return 1;
+ }
qDebug("initialize plugins");
PluginContainer pluginContainer(&organizer);
pluginContainer.loadPlugins();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index c90448c2..b7687d2a 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -3197,6 +3197,7 @@ void MainWindow::on_actionSettings_triggered()
m_OrganizerCore.installationManager()->setDownloadDirectory(m_OrganizerCore.settings().getDownloadDirectory());
fixCategories();
refreshFilters();
+ refreshProfiles();
if (QDir::fromNativeSeparators(m_OrganizerCore.downloadManager()->getOutputDirectory()) != QDir::fromNativeSeparators(m_OrganizerCore.settings().getDownloadDirectory())) {
if (m_OrganizerCore.downloadManager()->downloadsInProgress()) {
MessageDialog::showMessage(tr("Can't change download directory while downloads are in progress!"), this);
diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp
index 4380a255..0104998a 100644
--- a/src/modinfooverwrite.cpp
+++ b/src/modinfooverwrite.cpp
@@ -1,6 +1,7 @@
#include "modinfooverwrite.h"
#include "appconfig.h"
+#include "settings.h"
#include
#include
@@ -21,7 +22,7 @@ bool ModInfoOverwrite::isEmpty() const
QString ModInfoOverwrite::absolutePath() const
{
- return QDir::fromNativeSeparators(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::overwritePath()));
+ return Settings::instance().getOverwriteDirectory();
}
std::vector ModInfoOverwrite::getFlags() const
diff --git a/src/organizer_en.ts b/src/organizer_en.ts
index 7920c98b..686e15db 100644
--- a/src/organizer_en.ts
+++ b/src/organizer_en.ts
@@ -2629,62 +2629,62 @@ This function will guess the versioning scheme under the assumption that the ins
ModInfo
-
+
Plugins
-
+
Textures
-
+
Meshes
-
+
BSA
-
+
UI Changes
-
+
Sound Effects
-
+
Scripts
-
+
SKSE Plugins
-
+
SkyProc Tools
-
+
invalid content type %1
-
+
invalid mod index %1
-
+
remove: invalid mod index %1
@@ -3225,7 +3225,7 @@ p, li { white-space: pre-wrap; }
ModInfoOverwrite
-
+
This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit)
@@ -4630,17 +4630,17 @@ p, li { white-space: pre-wrap; }
-
+
failed to spawn "%1"
-
+
Elevation required
-
+
This process requires elevation to run.
This is a potential security risk so I highly advice you to investigate if
"%1"
@@ -4650,7 +4650,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe
-
+
failed to spawn "%1": %2
@@ -5037,23 +5037,28 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
-
+
+ Use %BASE_DIR% to refer to the Base Directory.
+
+
+
+
Important: All directories have to be writeable!
-
-
+
+
Nexus
-
+
Allows automatic log-in when the Nexus-Page for the game is clicked.
-
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -5062,144 +5067,144 @@ p, li { white-space: pre-wrap; }
-
+
If checked and if correct credentials are entered below, log-in to Nexus (for browsing and downloading) is automatic.
-
+
Automatically Log-In to Nexus
-
-
+
+
Username
-
-
+
+
Password
-
+
Remove cache and cookies. Forces a new login.
-
+
Clear Cache
-
+
Disable automatic internet features
-
+
Disable automatic internet features. This does not affect features that are explicitly invoked by the user (like checking mods for updates, endorsing, opening the web browser)
-
+
Offline Mode
-
+
Use a proxy for network connections.
-
+
Use a proxy for network connections. This uses the system-wide settings which can be configured in Internet Explorer. Please note that MO will start up a few seconds slower on some systems when using a proxy.
-
+
Use HTTP Proxy (Uses System Settings)
-
+
Associate with "Download with manager" links
-
+
Known Servers (updated on download)
-
+
Preferred Servers (Drag & Drop)
-
+
Steam
-
+
If you save your steam user ID and password here, they will be used when logging into steam. Note, however, your password will be stored unencrypted, so make sure your computer is secure.
-
+
Plugins
-
+
Author:
-
+
Version:
-
+
Description:
-
+
Key
-
+
Value
-
+
Blacklisted Plugins (use <del> to remove):
-
+
Workarounds
-
+
Steam App ID
-
+
The Steam AppID for your game
-
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -5215,17 +5220,17 @@ p, li { white-space: pre-wrap; }
-
+
Load Mechanism
-
+
Select loading mechanism. See help for details.
-
+
Mod Organizer needs a dll to be injected into the game so all mods are visible to it.
There are several means to do this:
*Mod Organizer* (default) In this mode the Mod Organizer itself injects the dll. The disadvantage is that you always have to start the game through MO or a link created by it.
@@ -5236,17 +5241,17 @@ If you use the Steam version of Oblivion the default will NOT work. In this case
-
+
NMM Version
-
+
The Version of Nexus Mod Manager to impersonate.
-
+
Mod Organizer uses an API provided by the Nexus to provide features like checking for updates and downloading files. Unfortunately this API has not been made available officially to third party tools like MO so we have to impersonate the Nexus Mod Manager to be allowed in.
On top of this Nexus has used the client identification to lock out outdated versions of NMM to force users to update. This means that MO also needs to impersonate the new version of NMM even if MO doesn't need an update. Therefore you can configure the version to identify as here.
Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent.
@@ -5255,44 +5260,44 @@ tl;dr-version: If Nexus-features don't work, insert the current version num
-
+
Enforces that inactive ESPs and ESMs are never loaded.
-
+
It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins.
I don't yet know what the circumstances are, but user reports imply it is in some cases unwanted. If this is checked, ESPs and ESMs not checked in the List are invisible to the game and can not be loaded.
-
+
Hide inactive ESPs/ESMs
-
+
If checked, files (i.e. esps, esms and bsas) belonging to the core game can not be disabled in the UI. (default: on)
-
+
If checked, files (i.e. esps, esms and bsas) belonging to the core game can not be disabled in the UI. (default: on)
Uncheck this if you want to use Mod Organizer with total conversions (like Nehrim) but be aware that the game will crash if required files are not enabled.
-
+
Force-enable game files
-
+
Disable this to no longer display mods installed outside MO in the mod list (left pane). Assets from those mods will then be treated as having lowest mod priority together with the original game content.
-
+
By default Mod Organizer will display esp+bsa bundles installed with foreign tools as mods (left pane). This allows you to control their priority in relation to other mods. This is particularly useful if you also use Steam Workshop to install mods.
However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly.
@@ -5300,24 +5305,24 @@ If you disable this feature, MO will only display official DLCs this way. Please
-
+
Display mods installed outside MO
-
-
+
+
For Skyrim, this can be used instead of Archive Invalidation. It should make AI redundant for all Profiles.
For the other games this is not a sufficient replacement for AI!
-
+
Back-date BSAs
-
+
These are workarounds for problems with Mod Organizer. Please make sure you read the help text before changing anything here.
@@ -5558,7 +5563,7 @@ On Windows XP:
UsvfsConnector
-
+
Preparing vfs
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 6ceefb4b..b5e5118d 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -586,6 +586,25 @@ InstallationManager *OrganizerCore::installationManager()
return &m_InstallationManager;
}
+bool OrganizerCore::createDirectory(const QString &path) {
+ if (!QDir(path).exists() && !QDir().mkpath(path)) {
+ QMessageBox::critical(nullptr, QObject::tr("Error"),
+ QObject::tr("Failed to create \"%1\". Your user "
+ "account probably lacks permission.")
+ .arg(QDir::toNativeSeparators(path)));
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool OrganizerCore::bootstrap() {
+ return createDirectory(m_Settings.getProfileDirectory()) &&
+ createDirectory(m_Settings.getModDirectory()) &&
+ createDirectory(m_Settings.getDownloadDirectory()) &&
+ createDirectory(m_Settings.getOverwriteDirectory());
+}
+
void OrganizerCore::createDefaultProfile()
{
QString profilesPath = settings().getProfileDirectory();
@@ -610,7 +629,19 @@ void OrganizerCore::setCurrentProfile(const QString &profileName)
&& (profileName == m_CurrentProfile->name())) {
return;
}
- QString profileDir = settings().getProfileDirectory() + "/" + profileName;
+
+ QDir profileBaseDir(settings().getProfileDirectory());
+ QString profileDir = profileBaseDir.absoluteFilePath(profileName);
+
+ if (!QDir(profileDir).exists()) {
+ // selected profile doesn't exist. Ensure there is at least one profile,
+ // then pick any one
+ createDefaultProfile();
+
+ profileDir = profileBaseDir.absoluteFilePath(
+ profileBaseDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot).at(0));
+ }
+
Profile *newProfile = new Profile(QDir(profileDir), managedGame());
delete m_CurrentProfile;
@@ -1870,7 +1901,7 @@ std::vector OrganizerCore::fileMapping(const QString &profileName,
result.insert(result.end(), {
QDir::toNativeSeparators(m_Settings.getOverwriteDirectory()),
- QDir::toNativeSeparators(game->dataDirectory().absolutePath()),
+ dataPath,
true,
customOverwrite.isEmpty()
});
diff --git a/src/organizercore.h b/src/organizercore.h
index ecb02d83..6c882dc9 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -135,6 +135,8 @@ public:
void loginSuccessfulUpdate(bool necessary);
void loginFailedUpdate(const QString &message);
+ static bool createAndMakeWritable(const QString &path);
+ bool bootstrap();
void createDefaultProfile();
MOBase::DelayedFileWriter &pluginsWriter() { return m_PluginListsWriter; }
@@ -228,6 +230,8 @@ private:
bool testForSteam();
+ bool createDirectory(const QString &path);
+
/**
* @brief return a descriptor of the mappings real file->virtual file
*/
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index bc6a908e..44e08023 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -237,8 +237,8 @@ void PluginList::enableAll()
{
if (QMessageBox::question(nullptr, tr("Confirm"), tr("Really enable all plugins?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- for (std::vector::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
- iter->m_Enabled = true;
+ for (ESPInfo &info : m_ESPs) {
+ info.m_Enabled = true;
}
emit writePluginsList();
}
@@ -249,9 +249,9 @@ void PluginList::disableAll()
{
if (QMessageBox::question(nullptr, tr("Confirm"), tr("Really disable all plugins?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- for (std::vector::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
- if (!iter->m_ForceEnabled) {
- iter->m_Enabled = false;
+ for (ESPInfo &info : m_ESPs) {
+ if (!info.m_ForceEnabled) {
+ info.m_Enabled = false;
}
}
emit writePluginsList();
diff --git a/src/settings.cpp b/src/settings.cpp
index 193c6a35..b86e2289 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -32,6 +32,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
#include
@@ -701,10 +702,15 @@ void Settings::PathsTab::update()
settingsKey = QString("Settings/%1").arg(settingsKey);
QString realPath = path;
- realPath.replace("%BASE_DIR%", m_parent->getBaseDirectory());
+ realPath.replace("%BASE_DIR%", m_baseDirEdit->text());
if (!QDir(realPath).exists()) {
- QDir().mkpath(realPath);
+ if (!QDir().mkpath(realPath)) {
+ QMessageBox::warning(qApp->activeWindow(), tr("Error"),
+ tr("Failed to create \"%1\", you may not have the "
+ "necessary permission. path remains unchanged.")
+ .arg(realPath));
+ }
}
if (QFileInfo(realPath)
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 082be8a1..a38530da 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -349,6 +349,13 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
+ -
+
+
+ Use %BASE_DIR% to refer to the Base Directory.
+
+
+
-
--
cgit v1.3.1
From 54fd26fee15c320c363a4be355c80e4b7ce38164 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Fri, 8 Dec 2017 11:00:57 +0200
Subject: new diagnostics settings dialog tab
---
src/settings.cpp | 37 +++++++--
src/settings.h | 25 +++++-
src/settingsdialog.ui | 225 ++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 237 insertions(+), 50 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/settings.cpp b/src/settings.cpp
index fc740302..7d90d861 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -28,6 +28,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
#include
@@ -38,6 +39,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
#include
#include
@@ -334,9 +336,18 @@ bool Settings::offlineMode() const
int Settings::logLevel() const
{
- return m_Settings.value("Settings/log_level", 0).toInt();
+ return m_Settings.value("Settings/log_level", static_cast(LogLevel::Info)).toInt();
}
+int Settings::crashDumpsType() const
+{
+ return m_Settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt();
+}
+
+int Settings::crashDumpsMax() const
+{
+ return m_Settings.value("Settings/crash_dumps_max", 5).toInt();
+}
void Settings::setNexusLogin(QString username, QString password)
{
@@ -581,6 +592,7 @@ void Settings::query(QWidget *parent)
tabs.push_back(std::unique_ptr(new GeneralTab(this, dialog)));
tabs.push_back(std::unique_ptr(new PathsTab(this, dialog)));
+ tabs.push_back(std::unique_ptr(new DiagnosticsTab(this, dialog)));
tabs.push_back(std::unique_ptr(new NexusTab(this, dialog)));
tabs.push_back(std::unique_ptr(new SteamTab(this, dialog)));
tabs.push_back(std::unique_ptr(new PluginsTab(this, dialog)));
@@ -608,7 +620,6 @@ Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
: Settings::SettingsTab(m_parent, m_dialog)
, m_languageBox(m_dialog.findChild("languageBox"))
, m_styleBox(m_dialog.findChild("styleBox"))
- , m_logLevelBox(m_dialog.findChild("logLevelBox"))
, m_compactBox(m_dialog.findChild("compactBox"))
, m_showMetaBox(m_dialog.findChild("showMetaBox"))
, m_usePrereleaseBox(m_dialog.findChild("usePrereleaseBox"))
@@ -640,7 +651,6 @@ Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
}
}
- m_logLevelBox->setCurrentIndex(m_parent->logLevel());
m_compactBox->setChecked(m_parent->compactDownloads());
m_showMetaBox->setChecked(m_parent->metaDownloads());
m_usePrereleaseBox->setChecked(m_parent->usePrereleases());
@@ -662,9 +672,6 @@ void Settings::GeneralTab::update()
emit m_parent->styleChanged(newStyle);
}
- m_Settings.setValue("Settings/log_level", m_logLevelBox->currentIndex());
-
-
m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked());
m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked());
m_Settings.setValue("Settings/use_prereleases", m_usePrereleaseBox->isChecked());
@@ -743,6 +750,24 @@ void Settings::PathsTab::update()
}
}
+Settings::DiagnosticsTab::DiagnosticsTab(Settings *m_parent, SettingsDialog &m_dialog)
+ : Settings::SettingsTab(m_parent, m_dialog)
+ , m_logLevelBox(m_dialog.findChild("logLevelBox"))
+ , m_dumpsTypeBox(m_dialog.findChild("dumpsTypeBox"))
+ , m_dumpsMaxEdit(m_dialog.findChild("dumpsMaxEdit"))
+{
+ m_logLevelBox->setCurrentIndex(m_parent->logLevel());
+ m_dumpsTypeBox->setCurrentIndex(m_parent->crashDumpsType());
+ m_dumpsMaxEdit->setValue(m_parent->crashDumpsMax());
+}
+
+void Settings::DiagnosticsTab::update()
+{
+ m_Settings.setValue("Settings/log_level", m_logLevelBox->currentIndex());
+ m_Settings.setValue("Settings/crash_dumps_type", m_dumpsTypeBox->currentIndex());
+ m_Settings.setValue("Settings/crash_dumps_max", m_dumpsMaxEdit->value());
+}
+
Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog)
: Settings::SettingsTab(parent, dialog)
, m_loginCheckBox(dialog.findChild("loginCheckBox"))
diff --git a/src/settings.h b/src/settings.h
index d316c82d..9ee29ba3 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -38,6 +38,7 @@ along with Mod Organizer. If not, see .
class QCheckBox;
class QComboBox;
class QLineEdit;
+class QSpinBox;
class QListWidget;
class QWidget;
@@ -204,6 +205,16 @@ public:
*/
int logLevel() const;
+ /**
+ * @return the configured crash dumps type
+ */
+ int crashDumpsType() const;
+
+ /**
+ * @return the configured crash dumps max
+ */
+ int crashDumpsMax() const;
+
/**
* @brief set the nexus login information
*
@@ -371,7 +382,6 @@ private:
private:
QComboBox *m_languageBox;
QComboBox *m_styleBox;
- QComboBox *m_logLevelBox;
QCheckBox *m_compactBox;
QCheckBox *m_showMetaBox;
QCheckBox *m_usePrereleaseBox;
@@ -393,6 +403,19 @@ private:
QLineEdit *m_overwriteDirEdit;
};
+ class DiagnosticsTab : public SettingsTab
+ {
+ public:
+ DiagnosticsTab(Settings *parent, SettingsDialog &dialog);
+
+ void update();
+
+ private:
+ QComboBox *m_logLevelBox;
+ QComboBox *m_dumpsTypeBox;
+ QSpinBox *m_dumpsMaxEdit;
+ };
+
/** Display/store the configuration in the 'nexus' tab of the settings dialogue */
class NexusTab : public SettingsTab
{
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index f5e37ea6..632dc6c9 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -70,48 +70,6 @@ p, li { white-space: pre-wrap; }
- -
-
-
-
-
-
- Log Level
-
-
-
- -
-
-
- Decides the amount of data printed to "ModOrganizer.log"
-
-
- Decides the amount of data printed to "ModOrganizer.log".
-"Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty.
-
-
-
-
- Debug
-
-
- -
-
- Info
-
-
- -
-
- Warning
-
-
- -
-
- Error
-
-
-
-
-
-
-
@@ -378,7 +336,188 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
-
+
+
+ Diagnostics
+
+
+ -
+
+
-
+
+
+ Log Level
+
+
+
+ -
+
+
+ Decides the amount of data printed to "ModOrganizer.log"
+
+
+
+ Decides the amount of data printed to "ModOrganizer.log".
+ "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty.
+
+
+
-
+
+ Debug
+
+
+ -
+
+ Info (recommended)
+
+
+ -
+
+ Warning
+
+
+ -
+
+ Error
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
-
+
+
+ Crash Dumps
+
+
+
+ -
+
+
+ Decides which type of crash dumps are collected when injected processes crash.
+
+
+
+ Decides which type of crash dumps are collected when injected processes crash.
+ "None" Disables the generation of crash dumps by MO.
+ "Mini" Default level which generates small dumps (only stack traces).
+ "Data" Much larger dumps with additional information which may be need (also data segments).
+ "Full" Even larger dumps with a full memory dump of the process.
+
+
+
-
+
+ None
+
+
+ -
+
+ Mini (recommended)
+
+
+ -
+
+ Data
+
+
+ -
+
+ Full
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Max Dumps To Keep
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 60
+ 20
+
+
+
+
+ -
+
+
+ Maximum number of crash dumps to keep on disk. Use 0 for unlimited.
+
+
+
+ Maximum number of crash dumps to keep on disk. Use 0 for unlimited.
+ Set "Crash Dumps" above to None to disable crash dump collection.
+
+
+
+
+
+
+ -
+
+
+
+ Dumps are stored in <a href="%LOCALAPPDATA%\modorganizer">%LOCALAPPDATA%\modorganizer</a>.
+ Sending such dumps to the developers can help solve crashes caused by MO.
+ It is recommended to compress the dumps before sending, especially on the larger settings.
+
+
+
+ true
+
+
+ Hint: right click link and copy link location
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Expanding
+
+
+
+ 20
+ 232
+
+
+
+
+
+
+
Nexus
--
cgit v1.3.1
From 4adb13c9435baade511d3ac78fb142dc73bd2e1f Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Fri, 8 Dec 2017 18:24:06 +0200
Subject: generate dumps using new diagnostics settings
---
src/main.cpp | 79 ++++++++++----------------------------------------
src/mainwindow.cpp | 2 +-
src/organizercore.cpp | 23 +++++++++++++--
src/organizercore.h | 7 ++++-
src/settings.cpp | 2 +-
src/usvfsconnector.cpp | 36 ++++++++++++++++-------
src/usvfsconnector.h | 4 ++-
7 files changed, 73 insertions(+), 80 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 526563a2..71fbc943 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,6 +48,7 @@ along with Mod Organizer. If not, see .
#include
#include
+#include
#include
#include
@@ -127,71 +128,17 @@ bool isNxmLink(const QString &link)
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
- typedef BOOL (WINAPI *FuncMiniDumpWriteDump)(HANDLE process, DWORD pid, HANDLE file, MINIDUMP_TYPE dumpType,
- const PMINIDUMP_EXCEPTION_INFORMATION exceptionParam,
- const PMINIDUMP_USER_STREAM_INFORMATION userStreamParam,
- const PMINIDUMP_CALLBACK_INFORMATION callbackParam);
- LONG result = EXCEPTION_CONTINUE_SEARCH;
-
- HMODULE dbgDLL = ::LoadLibrary(L"dbghelp.dll");
-
- static const int errorLen = 200;
- char errorBuffer[errorLen + 1];
- memset(errorBuffer, '\0', errorLen + 1);
-
- if (dbgDLL) {
- FuncMiniDumpWriteDump funcDump = (FuncMiniDumpWriteDump)::GetProcAddress(dbgDLL, "MiniDumpWriteDump");
- if (funcDump) {
- QString dataPath = qApp->property("dataPath").toString();
- QString exeName = QFileInfo(qApp->applicationFilePath()).fileName();
- QString dumpName = dataPath + "/" + exeName + ".dmp";
-
- if (QMessageBox::question(nullptr, QObject::tr("Woops"),
- QObject::tr("ModOrganizer has crashed! "
- "Should a diagnostic file be created? "
- "If you send me this file (%1) to modorganizer@gmail.com, "
- "the bug is a lot more likely to be fixed. "
- "Please include a short description of what you were "
- "doing when the crash happened"
- ).arg(dumpName),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
-
- HANDLE dumpFile = ::CreateFile(dumpName.toStdWString().c_str(),
- GENERIC_WRITE, FILE_SHARE_WRITE, nullptr,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (dumpFile != INVALID_HANDLE_VALUE) {
- _MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
- exceptionInfo.ThreadId = ::GetCurrentThreadId();
- exceptionInfo.ExceptionPointers = exceptionPtrs;
- exceptionInfo.ClientPointers = false;
-
- BOOL success = funcDump(::GetCurrentProcess(), ::GetCurrentProcessId(), dumpFile,
- MiniDumpNormal, &exceptionInfo, nullptr, nullptr);
-
- ::FlushFileBuffers(dumpFile);
- ::CloseHandle(dumpFile);
- if (success) {
- return EXCEPTION_EXECUTE_HANDLER;
- }
- _snprintf(errorBuffer, errorLen, "failed to save minidump to %ls (error %lu)",
- dumpName.toStdWString().c_str(), ::GetLastError());
- } else {
- _snprintf(errorBuffer, errorLen, "failed to create %ls (error %lu)",
- dumpName.toStdWString().c_str(), ::GetLastError());
- }
- } else {
- return result;
- }
- } else {
- _snprintf(errorBuffer, errorLen, "dbghelp.dll outdated");
- }
- } else {
- _snprintf(errorBuffer, errorLen, "dbghelp.dll not found");
+ const std::wstring& dumpPath = OrganizerCore::crashDumpsPath();
+ int dumpRes =
+ CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str());
+ if (!dumpRes) {
+ qCritical("ModOrganizer has crashed, crash dump created.");
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ else {
+ qCritical("ModOrganizer has crashed, CreateMiniDump failed (%d, error %lu).", dumpRes, GetLastError());
+ return EXCEPTION_CONTINUE_SEARCH;
}
-
- QMessageBox::critical(nullptr, QObject::tr("Woops"),
- QObject::tr("ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1").arg(errorBuffer));
- return result;
}
static bool HaveWriteAccess(const std::wstring &path)
@@ -448,6 +395,10 @@ int runApplication(MOApplication &application, SingleInstance &instance,
QSettings settings(dataPath + "/"
+ QString::fromStdWString(AppConfig::iniFileName()),
QSettings::IniFormat);
+
+ // global crashDumpType sits in OrganizerCore to make a bit less ugly to update it when the settings are changed during runtime
+ OrganizerCore::setGlobalCrashDumpsType(settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt());
+
qDebug("initializing core");
OrganizerCore organizer(settings);
if (!organizer.bootstrap()) {
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 48dfdfbd..cab4c41f 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -3296,7 +3296,7 @@ void MainWindow::on_actionSettings_triggered()
updateDownloadListDelegate();
- m_OrganizerCore.setLogLevel(settings.logLevel());
+ m_OrganizerCore.updateVFSParams(settings.logLevel(), settings.crashDumpsType());
}
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index f8a368c9..adb895ec 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -47,6 +47,7 @@
#include // for qPrintable, etc
#include
+#include
#include // for _tcsicmp
#include
@@ -66,6 +67,9 @@
using namespace MOShared;
using namespace MOBase;
+//static
+CrashDumpsType OrganizerCore::m_globalCrashDumpsType = CrashDumpsType::None;
+
static bool isOnline()
{
QList interfaces = QNetworkInterface::allInterfaces();
@@ -643,8 +647,23 @@ void OrganizerCore::prepareVFS()
m_USVFS.updateMapping(fileMapping(m_CurrentProfile->name(), QString()));
}
-void OrganizerCore::setLogLevel(int logLevel) {
- m_USVFS.setLogLevel(logLevel);
+void OrganizerCore::updateVFSParams(int logLevel, int crashDumpsType) {
+ setGlobalCrashDumpsType(crashDumpsType);
+ m_USVFS.updateParams(logLevel, crashDumpsType);
+}
+
+//static
+void OrganizerCore::setGlobalCrashDumpsType(int crashDumpsType) {
+ m_globalCrashDumpsType = ::crashDumpsType(crashDumpsType);
+}
+
+//static
+std::wstring OrganizerCore::crashDumpsPath() {
+ wchar_t appDataLocal[MAX_PATH]{ 0 };
+ ::SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataLocal);
+ std::wstring dumpPath{ appDataLocal };
+ dumpPath += L"\\modorganizer";
+ return dumpPath;
}
void OrganizerCore::setCurrentProfile(const QString &profileName)
diff --git a/src/organizercore.h b/src/organizercore.h
index 297b94f6..7bb7faa7 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -158,7 +158,11 @@ public:
void prepareVFS();
- void setLogLevel(int logLevel);
+ void updateVFSParams(int logLevel, int crashDumpsType);
+
+ static CrashDumpsType getGlobalCrashDumpsType() { return m_globalCrashDumpsType; }
+ static void setGlobalCrashDumpsType(int crashDumpsType);
+ static std::wstring crashDumpsPath();
public:
MOBase::IModRepositoryBridge *createNexusBridge() const;
@@ -319,6 +323,7 @@ private:
MOBase::DelayedFileWriter m_PluginListsWriter;
UsvfsConnector m_USVFS;
+ static CrashDumpsType m_globalCrashDumpsType;
};
#endif // ORGANIZERCORE_H
diff --git a/src/settings.cpp b/src/settings.cpp
index 7d90d861..05a62591 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -28,7 +28,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/src/usvfsconnector.cpp b/src/usvfsconnector.cpp
index 0420ddc2..b90784d9 100644
--- a/src/usvfsconnector.cpp
+++ b/src/usvfsconnector.cpp
@@ -19,6 +19,8 @@ along with Mod Organizer. If not, see .
#include "usvfsconnector.h"
#include "settings.h"
+#include "organizercore.h"
+#include "shared/util.h"
#include
#include
#include
@@ -27,6 +29,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
static const char SHMID[] = "mod_organizer_instance";
@@ -101,14 +104,33 @@ LogLevel logLevel(int level)
}
}
+CrashDumpsType crashDumpsType(int type)
+{
+ switch (type) {
+ case CrashDumpsType::Mini:
+ return CrashDumpsType::Mini;
+ case CrashDumpsType::Data:
+ return CrashDumpsType::Data;
+ case CrashDumpsType::Full:
+ return CrashDumpsType::Full;
+ default:
+ return CrashDumpsType::None;
+ }
+}
+
UsvfsConnector::UsvfsConnector()
{
USVFSParameters params;
LogLevel level = logLevel(Settings::instance().logLevel());
- USVFSInitParameters(¶ms, SHMID, false, level);
+ CrashDumpsType dumpType = crashDumpsType(Settings::instance().crashDumpsType());
+
+ std::string dumpPath = MOShared::ToString(OrganizerCore::crashDumpsPath(), true);
+ USVFSInitParameters(¶ms, SHMID, false, level, dumpType, dumpPath.c_str());
InitLogging(false);
+
+ qDebug("Initializing VFS <%s, %d, %d, %s>", params.instanceName, params.logLevel, params.crashDumpsType, params.crashDumpsPath);
+
CreateVFS(¶ms);
- SetLogLevel(level);
BlacklistExecutable(L"TSVNCache.exe");
@@ -165,12 +187,6 @@ void UsvfsConnector::updateMapping(const MappingType &mapping)
*/
}
-void UsvfsConnector::setLogLevel(int logLevel) {
- switch (logLevel) {
- case LogLevel::Debug: SetLogLevel(LogLevel::Debug); break;
- case LogLevel::Info: SetLogLevel(LogLevel::Info); break;
- case LogLevel::Warning: SetLogLevel(LogLevel::Warning); break;
- case LogLevel::Error: SetLogLevel(LogLevel::Error); break;
- default: SetLogLevel(LogLevel::Debug); break;
- }
+void UsvfsConnector::updateParams(int logLevel, int crashDumpsType) {
+ USVFSUpdateParams(::logLevel(logLevel), ::crashDumpsType(crashDumpsType));
}
diff --git a/src/usvfsconnector.h b/src/usvfsconnector.h
index 8f723a01..0935bac1 100644
--- a/src/usvfsconnector.h
+++ b/src/usvfsconnector.h
@@ -27,6 +27,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
class LogWorker : public QThread {
@@ -67,7 +68,7 @@ public:
~UsvfsConnector();
void updateMapping(const MappingType &mapping);
- void setLogLevel(int logLevel);
+ void updateParams(int logLevel, int crashDumpsType);
private:
@@ -76,5 +77,6 @@ private:
};
+CrashDumpsType crashDumpsType(int type);
#endif // USVFSCONNECTOR_H
--
cgit v1.3.1
From 240900de39aaf1562332ed88708b4b128703ad0e Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Tue, 12 Dec 2017 23:22:04 +0200
Subject: Move crash dumps to instance-dependant data folder
---
src/main.cpp | 5 +++--
src/organizercore.cpp | 9 ++++-----
src/settings.cpp | 12 ++++++++++++
src/settings.h | 2 ++
src/settingsdialog.ui | 9 +++++----
src/shared/appconfig.inc | 1 +
6 files changed, 27 insertions(+), 11 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index eed4dfd3..b4faf570 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -528,8 +528,6 @@ int runApplication(MOApplication &application, SingleInstance &instance,
int main(int argc, char *argv[])
{
- prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
-
MOApplication application(argc, argv);
QStringList arguments = application.arguments();
@@ -586,6 +584,9 @@ int main(int argc, char *argv[])
}
application.setProperty("dataPath", dataPath);
+ // initialize dump collection only after "dataPath" since the crashes are stored under it
+ prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
+
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
QString splash = dataPath + "/splash.png";
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index bc0578b3..deb0b718 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -670,11 +670,10 @@ void OrganizerCore::setGlobalCrashDumpsType(int crashDumpsType) {
//static
std::wstring OrganizerCore::crashDumpsPath() {
- wchar_t appDataLocal[MAX_PATH]{ 0 };
- ::SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataLocal);
- std::wstring dumpPath{ appDataLocal };
- dumpPath += L"\\modorganizer\\crashDumps";
- return dumpPath;
+ return (
+ qApp->property("dataPath").toString() + "/"
+ + QString::fromStdWString(AppConfig::dumpsDir())
+ ).toStdWString();
}
void OrganizerCore::setCurrentProfile(const QString &profileName)
diff --git a/src/settings.cpp b/src/settings.cpp
index 05a62591..b2fc8939 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -24,6 +24,7 @@ along with Mod Organizer. If not, see .
#include "settingsdialog.h"
#include "versioninfo.h"
#include "appconfig.h"
+#include "organizercore.h"
#include
#include
#include
@@ -48,6 +49,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include // for Qt::UserRole, etc
#include // for qDebug, qWarning
@@ -755,10 +757,20 @@ Settings::DiagnosticsTab::DiagnosticsTab(Settings *m_parent, SettingsDialog &m_d
, m_logLevelBox(m_dialog.findChild("logLevelBox"))
, m_dumpsTypeBox(m_dialog.findChild("dumpsTypeBox"))
, m_dumpsMaxEdit(m_dialog.findChild("dumpsMaxEdit"))
+ , m_diagnosticsExplainedLabel(m_dialog.findChild("diagnosticsExplainedLabel"))
{
m_logLevelBox->setCurrentIndex(m_parent->logLevel());
m_dumpsTypeBox->setCurrentIndex(m_parent->crashDumpsType());
m_dumpsMaxEdit->setValue(m_parent->crashDumpsMax());
+ QString logsPath = qApp->property("dataPath").toString()
+ + "/" + QString::fromStdWString(AppConfig::logPath());
+ m_diagnosticsExplainedLabel->setText(
+ m_diagnosticsExplainedLabel->text()
+ .replace("LOGS_FULL_PATH", logsPath)
+ .replace("LOGS_DIR", QString::fromStdWString(AppConfig::logPath()))
+ .replace("DUMPS_FULL_PATH", QString::fromStdWString(OrganizerCore::crashDumpsPath()))
+ .replace("DUMPS_DIR", QString::fromStdWString(AppConfig::dumpsDir()))
+ );
}
void Settings::DiagnosticsTab::update()
diff --git a/src/settings.h b/src/settings.h
index 9ee29ba3..ae38223f 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -41,6 +41,7 @@ class QLineEdit;
class QSpinBox;
class QListWidget;
class QWidget;
+class QLabel;
struct ServerInfo;
@@ -414,6 +415,7 @@ private:
QComboBox *m_logLevelBox;
QComboBox *m_dumpsTypeBox;
QSpinBox *m_dumpsMaxEdit;
+ QLabel *m_diagnosticsExplainedLabel;
};
/** Display/store the configuration in the 'nexus' tab of the settings dialogue */
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 6d462cfa..7a902748 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -483,12 +483,13 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
-
-
+
- Dumps are stored in <a href="%LOCALAPPDATA%\modorganizer\crashDumps">%LOCALAPPDATA%\modorganizer\crashDumps</a>.
- Sending such dumps to the developers can help solve crashes caused by MO.
- It is recommended to compress the dumps before sending, especially on the larger settings.
+ Logs and crash dumps are stored under your current instance in the <a href="LOGS_FULL_PATH">LOGS_DIR</a>
+ and <a href="DUMPS_FULL_PATH">DUMPS_DIR</a> folders.
+ Sending logs and/or crash dumps to the developers can help investigate issues.
+ It is recommended to compress large log and dmp files before sending.
diff --git a/src/shared/appconfig.inc b/src/shared/appconfig.inc
index e98757d3..e572a32b 100644
--- a/src/shared/appconfig.inc
+++ b/src/shared/appconfig.inc
@@ -8,6 +8,7 @@ APPPARAM(std::wstring, stylesheetsPath, L"stylesheets")
APPPARAM(std::wstring, cachePath, L"webcache")
APPPARAM(std::wstring, tutorialsPath, L"tutorials")
APPPARAM(std::wstring, logPath, L"logs")
+APPPARAM(std::wstring, dumpsDir, L"crashDumps")
APPPARAM(std::wstring, profileTweakIni, L"profile_tweaks.ini")
APPPARAM(std::wstring, logFileName, L"ModOrganizer.log")
APPPARAM(std::wstring, iniFileName, L"ModOrganizer.ini")
--
cgit v1.3.1
From 9c9a43ec8da94a374e4a8ea3a7a5cfd2de341162 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Tue, 26 Dec 2017 21:03:57 +0200
Subject: print settings loading and changes to log for diagnostic purposes
---
src/main.cpp | 7 +++++++
src/settings.cpp | 21 +++++++++++++++++++++
2 files changed, 28 insertions(+)
(limited to 'src/settings.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 3d315f1d..99ff641a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -389,6 +389,13 @@ int runApplication(MOApplication &application, SingleInstance &instance,
// global crashDumpType sits in OrganizerCore to make a bit less ugly to update it when the settings are changed during runtime
OrganizerCore::setGlobalCrashDumpsType(settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt());
+ qDebug("Loaded settings:");
+ settings.beginGroup("Settings");
+ for (auto k : settings.allKeys())
+ qDebug(" %s=%s", k.toUtf8().data(), settings.value(k).toString().toUtf8().data());
+ settings.endGroup();
+
+
qDebug("initializing core");
OrganizerCore organizer(settings);
if (!organizer.bootstrap()) {
diff --git a/src/settings.cpp b/src/settings.cpp
index b2fc8939..028f88da 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -601,10 +601,31 @@ void Settings::query(QWidget *parent)
tabs.push_back(std::unique_ptr(new WorkaroundsTab(this, dialog)));
if (dialog.exec() == QDialog::Accepted) {
+ // remember settings before change
+ QMap before;
+ m_Settings.beginGroup("Settings");
+ for (auto k : m_Settings.allKeys())
+ before[k] = m_Settings.value(k).toString();
+ m_Settings.endGroup();
+
// transfer modified settings to configuration file
for (std::unique_ptr const &tab: tabs) {
tab->update();
}
+
+ // print "changed" settings
+ m_Settings.beginGroup("Settings");
+ bool first_update = true;
+ for (auto k : m_Settings.allKeys())
+ if (m_Settings.value(k).toString() != before[k])
+ {
+ if (first_update) {
+ qDebug("Changed settings:");
+ first_update = false;
+ }
+ qDebug(" %s=%s", k.toUtf8().data(), m_Settings.value(k).toString().toUtf8().data());
+ }
+ m_Settings.endGroup();
}
}
--
cgit v1.3.1
From 548744d746223f0f96b33587ca41d2ed6a314f33 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Wed, 27 Dec 2017 04:18:46 +0200
Subject: Don't log username and password
---
src/main.cpp | 3 ++-
src/settings.cpp | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 5418abc2..4c5ac75c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -447,7 +447,8 @@ int runApplication(MOApplication &application, SingleInstance &instance,
qDebug("Loaded settings:");
settings.beginGroup("Settings");
for (auto k : settings.allKeys())
- qDebug(" %s=%s", k.toUtf8().data(), settings.value(k).toString().toUtf8().data());
+ if (!k.contains("username") && !k.contains("password"))
+ qDebug(" %s=%s", k.toUtf8().data(), settings.value(k).toString().toUtf8().data());
settings.endGroup();
diff --git a/src/settings.cpp b/src/settings.cpp
index 028f88da..d1130e05 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -617,7 +617,7 @@ void Settings::query(QWidget *parent)
m_Settings.beginGroup("Settings");
bool first_update = true;
for (auto k : m_Settings.allKeys())
- if (m_Settings.value(k).toString() != before[k])
+ if (m_Settings.value(k).toString() != before[k] && !k.contains("username") && !k.contains("password"))
{
if (first_update) {
qDebug("Changed settings:");
--
cgit v1.3.1
From ca54760c13fbbb6ff685e04ef11ed5592823680c Mon Sep 17 00:00:00 2001
From: matzman666
Date: Sat, 6 Jan 2018 21:36:21 +0100
Subject: Fixed nexus link handling to use gameNexusName() instead of
gameShortName().
---
src/downloadmanager.cpp | 4 ++--
src/settings.cpp | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index cb954ebe..593c754a 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -451,7 +451,7 @@ void DownloadManager::addNXMDownload(const QString &url)
{
NXMUrl nxmInfo(url);
- QString managedGame = m_ManagedGame->gameShortName();
+ QString managedGame = m_ManagedGame->gameNexusName();
qDebug("add nxm download: %s", qPrintable(url));
if (nxmInfo.game().compare(managedGame, Qt::CaseInsensitive) != 0) {
qDebug("download requested for wrong game (game: %s, url: %s)", qPrintable(managedGame), qPrintable(nxmInfo.game()));
@@ -1246,7 +1246,7 @@ int DownloadManager::startDownloadURLs(const QStringList &urls)
int DownloadManager::startDownloadNexusFile(int modID, int fileID)
{
int newID = m_ActiveDownloads.size();
- addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(m_ManagedGame->gameShortName()).arg(modID).arg(fileID));
+ addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(m_ManagedGame->gameNexusName()).arg(modID).arg(fileID));
return newID;
}
diff --git a/src/settings.cpp b/src/settings.cpp
index d1130e05..62041ca2 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -133,7 +133,7 @@ void Settings::registerAsNXMHandler(bool force)
std::wstring nxmPath = ToWString(QCoreApplication::applicationDirPath() + "/nxmhandler.exe");
std::wstring executable = ToWString(QCoreApplication::applicationFilePath());
std::wstring mode = force ? L"forcereg" : L"reg";
- std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString() + L" \"" + executable + L"\"";
+ std::wstring parameters = mode + L" " + m_GamePlugin->gameNexusName().toStdWString() + L" \"" + executable + L"\"";
HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL);
if ((int)res <= 32) {
QMessageBox::critical(nullptr, tr("Failed"),
--
cgit v1.3.1
From d6b645413c3d3f20ad0f554a1f106206886b3a83 Mon Sep 17 00:00:00 2001
From: Al12rs
Date: Sat, 27 Jan 2018 12:28:56 +0100
Subject: Revert "Fixed nexus link handling to use gameNexusName() instead of
gameShortName()."
This reverts commit ca54760c13fbbb6ff685e04ef11ed5592823680c.
---
src/downloadmanager.cpp | 4 ++--
src/settings.cpp | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
(limited to 'src/settings.cpp')
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index 593c754a..cb954ebe 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -451,7 +451,7 @@ void DownloadManager::addNXMDownload(const QString &url)
{
NXMUrl nxmInfo(url);
- QString managedGame = m_ManagedGame->gameNexusName();
+ QString managedGame = m_ManagedGame->gameShortName();
qDebug("add nxm download: %s", qPrintable(url));
if (nxmInfo.game().compare(managedGame, Qt::CaseInsensitive) != 0) {
qDebug("download requested for wrong game (game: %s, url: %s)", qPrintable(managedGame), qPrintable(nxmInfo.game()));
@@ -1246,7 +1246,7 @@ int DownloadManager::startDownloadURLs(const QStringList &urls)
int DownloadManager::startDownloadNexusFile(int modID, int fileID)
{
int newID = m_ActiveDownloads.size();
- addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(m_ManagedGame->gameNexusName()).arg(modID).arg(fileID));
+ addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(m_ManagedGame->gameShortName()).arg(modID).arg(fileID));
return newID;
}
diff --git a/src/settings.cpp b/src/settings.cpp
index 62041ca2..d1130e05 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -133,7 +133,7 @@ void Settings::registerAsNXMHandler(bool force)
std::wstring nxmPath = ToWString(QCoreApplication::applicationDirPath() + "/nxmhandler.exe");
std::wstring executable = ToWString(QCoreApplication::applicationFilePath());
std::wstring mode = force ? L"forcereg" : L"reg";
- std::wstring parameters = mode + L" " + m_GamePlugin->gameNexusName().toStdWString() + L" \"" + executable + L"\"";
+ std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString() + L" \"" + executable + L"\"";
HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL);
if ((int)res <= 32) {
QMessageBox::critical(nullptr, tr("Failed"),
--
cgit v1.3.1
From 5e5c9c07291f6b09623d31c92b1fb61c4ede576e Mon Sep 17 00:00:00 2001
From: Sandro Jäckel
Date: Thu, 22 Feb 2018 16:54:34 +0100
Subject: Applied clang-format on source
---
.clang-format | 11 +
src/aboutdialog.cpp | 95 +-
src/aboutdialog.h | 44 +-
src/activatemodsdialog.cpp | 99 +-
src/activatemodsdialog.h | 58 +-
src/bbcode.cpp | 415 +-
src/bbcode.h | 7 +-
src/browserdialog.cpp | 370 +-
src/browserdialog.h | 110 +-
src/browserview.cpp | 77 +-
src/browserview.h | 67 +-
src/categories.cpp | 516 ++-
src/categories.h | 306 +-
src/categoriesdialog.cpp | 320 +-
src/categoriesdialog.h | 46 +-
src/credentialsdialog.cpp | 32 +-
src/credentialsdialog.h | 21 +-
src/csvbuilder.cpp | 345 +-
src/csvbuilder.h | 99 +-
src/descriptionpage.h | 14 +-
src/directoryrefresher.cpp | 203 +-
src/directoryrefresher.h | 200 +-
src/downloadlist.cpp | 123 +-
src/downloadlist.h | 96 +-
src/downloadlistsortproxy.cpp | 71 +-
src/downloadlistsortproxy.h | 27 +-
src/downloadlistwidget.cpp | 482 +--
src/downloadlistwidget.h | 103 +-
src/downloadlistwidgetcompact.cpp | 455 +--
src/downloadlistwidgetcompact.h | 114 +-
src/downloadmanager.cpp | 2325 +++++------
src/downloadmanager.h | 837 ++--
src/editexecutablesdialog.cpp | 459 +--
src/editexecutablesdialog.h | 91 +-
src/eventfilter.cpp | 14 +-
src/eventfilter.h | 16 +-
src/executableslist.cpp | 253 +-
src/executableslist.h | 273 +-
src/filedialogmemory.cpp | 106 +-
src/filedialogmemory.h | 37 +-
src/gameinfoimpl.cpp | 49 +-
src/genericicondelegate.cpp | 44 +-
src/genericicondelegate.h | 45 +-
src/helper.cpp | 90 +-
src/helper.h | 13 +-
src/icondelegate.cpp | 71 +-
src/icondelegate.h | 22 +-
src/ilockedwaitingforprocess.h | 7 +-
src/installationmanager.cpp | 1334 +++---
src/installationmanager.h | 303 +-
src/instancemanager.cpp | 410 +-
src/instancemanager.h | 46 +-
src/iuserinterface.h | 35 +-
src/json.cpp | 823 ++--
src/json.h | 105 +-
src/loadmechanism.cpp | 454 +--
src/loadmechanism.h | 119 +-
src/lockeddialog.cpp | 64 +-
src/lockeddialog.h | 21 +-
src/lockeddialogbase.cpp | 65 +-
src/lockeddialogbase.h | 32 +-
src/logbuffer.cpp | 337 +-
src/logbuffer.h | 78 +-
src/loghighlighter.cpp | 47 +-
src/loghighlighter.h | 9 +-
src/main.cpp | 1052 +++--
src/mainwindow.cpp | 8136 ++++++++++++++++++-------------------
src/mainwindow.h | 691 ++--
src/messagedialog.cpp | 107 +-
src/messagedialog.h | 46 +-
src/moapplication.cpp | 175 +-
src/moapplication.h | 19 +-
src/modeltest.cpp | 496 ++-
src/modeltest.h | 62 +-
src/modflagicondelegate.cpp | 142 +-
src/modflagicondelegate.h | 17 +-
src/modinfo.cpp | 512 ++-
src/modinfo.h | 1111 +++--
src/modinfobackup.cpp | 22 +-
src/modinfobackup.h | 49 +-
src/modinfodialog.cpp | 1832 ++++-----
src/modinfodialog.h | 313 +-
src/modinfoforeign.cpp | 76 +-
src/modinfoforeign.h | 100 +-
src/modinfooverwrite.cpp | 75 +-
src/modinfooverwrite.h | 82 +-
src/modinforegular.cpp | 878 ++--
src/modinforegular.h | 622 ++-
src/modinfowithconflictinfo.cpp | 184 +-
src/modinfowithconflictinfo.h | 62 +-
src/modlist.cpp | 1891 +++++----
src/modlist.h | 432 +-
src/modlistsortproxy.cpp | 646 ++-
src/modlistsortproxy.h | 134 +-
src/modlistview.cpp | 67 +-
src/modlistview.h | 22 +-
src/moshortcut.cpp | 26 +-
src/moshortcut.h | 23 +-
src/motddialog.cpp | 27 +-
src/motddialog.h | 19 +-
src/nexusinterface.cpp | 943 ++---
src/nexusinterface.h | 700 ++--
src/noeditdelegate.cpp | 9 +-
src/noeditdelegate.h | 6 +-
src/nxmaccessmanager.cpp | 478 +--
src/nxmaccessmanager.h | 131 +-
src/organizercore.cpp | 3491 ++++++++--------
src/organizercore.h | 408 +-
src/organizerproxy.cpp | 187 +-
src/organizerproxy.h | 93 +-
src/overwriteinfodialog.cpp | 340 +-
src/overwriteinfodialog.h | 53 +-
src/persistentcookiejar.cpp | 96 +-
src/persistentcookiejar.h | 19 +-
src/plugincontainer.cpp | 502 ++-
src/plugincontainer.h | 115 +-
src/pluginlist.cpp | 1866 ++++-----
src/pluginlist.h | 501 ++-
src/pluginlistsortproxy.cpp | 137 +-
src/pluginlistsortproxy.h | 44 +-
src/pluginlistview.cpp | 66 +-
src/pluginlistview.h | 22 +-
src/previewdialog.cpp | 66 +-
src/previewdialog.h | 24 +-
src/previewgenerator.cpp | 40 +-
src/previewgenerator.h | 24 +-
src/problemsdialog.cpp | 104 +-
src/problemsdialog.h | 30 +-
src/profile.cpp | 1180 +++---
src/profile.h | 569 ++-
src/profileinputdialog.cpp | 28 +-
src/profileinputdialog.h | 19 +-
src/profilesdialog.cpp | 460 +--
src/profilesdialog.h | 81 +-
src/qtgroupingproxy.cpp | 1651 ++++----
src/qtgroupingproxy.h | 235 +-
src/queryoverwritedialog.cpp | 51 +-
src/queryoverwritedialog.h | 39 +-
src/savetextasdialog.cpp | 54 +-
src/savetextasdialog.h | 21 +-
src/selectiondialog.cpp | 107 +-
src/selectiondialog.h | 54 +-
src/selfupdater.cpp | 412 +-
src/selfupdater.h | 142 +-
src/serverinfo.h | 13 +-
src/settings.cpp | 1491 ++++---
src/settings.h | 846 ++--
src/settingsdialog.cpp | 319 +-
src/settingsdialog.h | 53 +-
src/shared/appconfig.cpp | 4 +-
src/shared/appconfig.h | 4 +-
src/shared/directoryentry.cpp | 1332 +++---
src/shared/directoryentry.h | 405 +-
src/shared/error_report.cpp | 98 +-
src/shared/leaktrace.cpp | 70 +-
src/shared/leaktrace.h | 7 +-
src/shared/stackdata.cpp | 219 +-
src/shared/stackdata.h | 43 +-
src/shared/util.cpp | 209 +-
src/shared/util.h | 23 +-
src/shared/windows_error.cpp | 43 +-
src/shared/windows_error.h | 14 +-
src/singleinstance.cpp | 125 +-
src/singleinstance.h | 79 +-
src/spawn.cpp | 244 +-
src/spawn.h | 12 +-
src/syncoverwritedialog.cpp | 215 +-
src/syncoverwritedialog.h | 31 +-
src/transfersavesdialog.cpp | 464 +--
src/transfersavesdialog.h | 81 +-
src/usvfsconnector.cpp | 251 +-
src/usvfsconnector.h | 50 +-
src/viewmarkingscrollbar.cpp | 54 +-
src/viewmarkingscrollbar.h | 20 +-
src/waitingonclosedialog.cpp | 61 +-
src/waitingonclosedialog.h | 23 +-
176 files changed, 26451 insertions(+), 30158 deletions(-)
create mode 100644 .clang-format
(limited to 'src/settings.cpp')
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..6e34f96b
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,11 @@
+---
+Language: Cpp
+BasedOnStyle: LLVM
+
+AccessModifierOffset: -4
+AlwaysBreakTemplateDeclarations: true
+ColumnLimit: 120
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+SortUsingDeclarations: true
\ No newline at end of file
diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp
index ed57a217..e79109ad 100644
--- a/src/aboutdialog.cpp
+++ b/src/aboutdialog.cpp
@@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see .
*/
-
#include "aboutdialog.h"
#include "ui_aboutdialog.h"
#include
@@ -30,65 +29,55 @@ along with Mod Organizer. If not, see .
#include
#include
-
-AboutDialog::AboutDialog(const QString &version, QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::AboutDialog)
-{
- ui->setupUi(this);
-
- m_LicenseFiles[LICENSE_LGPL3] = "lgpl-3.0.txt";
- m_LicenseFiles[LICENSE_GPL3] = "gpl-3.0.txt";
- m_LicenseFiles[LICENSE_BSD3] = "bsd3.txt";
- m_LicenseFiles[LICENSE_BOOST] = "boost.txt";
- m_LicenseFiles[LICENSE_CCBY3] = "by-sa3.txt";
- m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
- m_LicenseFiles[LICENSE_APACHE2] = "apache-license-2.0.txt";
-
- addLicense("Qt", LICENSE_LGPL3);
- addLicense("Qt Json", LICENSE_GPL3);
- addLicense("Boost Library", LICENSE_BOOST);
- addLicense("7-zip", LICENSE_LGPL3);
- addLicense("ZLib", LICENSE_ZLIB);
- addLicense("Tango Icon Theme", LICENSE_NONE);
- addLicense("RRZE Icon Set", LICENSE_CCBY3);
- addLicense("Icons by Lorc, Delapouite and sbed available on http://game-icons.net", LICENSE_CCBY3);
- addLicense("Castle Core", LICENSE_APACHE2);
- addLicense("LOOT", LICENSE_GPL3);
-
- ui->nameLabel->setText(QString("%1 %2").arg(ui->nameLabel->text()).arg(version));
+AboutDialog::AboutDialog(const QString& version, QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) {
+ ui->setupUi(this);
+
+ m_LicenseFiles[LICENSE_LGPL3] = "lgpl-3.0.txt";
+ m_LicenseFiles[LICENSE_GPL3] = "gpl-3.0.txt";
+ m_LicenseFiles[LICENSE_BSD3] = "bsd3.txt";
+ m_LicenseFiles[LICENSE_BOOST] = "boost.txt";
+ m_LicenseFiles[LICENSE_CCBY3] = "by-sa3.txt";
+ m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
+ m_LicenseFiles[LICENSE_APACHE2] = "apache-license-2.0.txt";
+
+ addLicense("Qt", LICENSE_LGPL3);
+ addLicense("Qt Json", LICENSE_GPL3);
+ addLicense("Boost Library", LICENSE_BOOST);
+ addLicense("7-zip", LICENSE_LGPL3);
+ addLicense("ZLib", LICENSE_ZLIB);
+ addLicense("Tango Icon Theme", LICENSE_NONE);
+ addLicense("RRZE Icon Set", LICENSE_CCBY3);
+ addLicense("Icons by Lorc, Delapouite and sbed available on http://game-icons.net", LICENSE_CCBY3);
+ addLicense("Castle Core", LICENSE_APACHE2);
+ addLicense("LOOT", LICENSE_GPL3);
+
+ ui->nameLabel->setText(QString("%1 %2")
+ .arg(ui->nameLabel->text())
+ .arg(version));
#if defined(HGID)
- ui->revisionLabel->setText(ui->revisionLabel->text() + " " + HGID);
+ ui->revisionLabel->setText(ui->revisionLabel->text() + " " + HGID);
#elif defined(GITID)
- ui->revisionLabel->setText(ui->revisionLabel->text() + " " + GITID);
+ ui->revisionLabel->setText(ui->revisionLabel->text() + " " + GITID);
#else
- ui->revisionLabel->setText(ui->revisionLabel->text() + " unknown");
+ ui->revisionLabel->setText(ui->revisionLabel->text() + " unknown");
#endif
}
+AboutDialog::~AboutDialog() { delete ui; }
-AboutDialog::~AboutDialog()
-{
- delete ui;
+void AboutDialog::addLicense(const QString& name, Licenses license) {
+ QListWidgetItem* item = new QListWidgetItem(name);
+ item->setData(Qt::UserRole, license);
+ ui->creditsList->addItem(item);
}
-
-void AboutDialog::addLicense(const QString &name, Licenses license)
-{
- QListWidgetItem *item = new QListWidgetItem(name);
- item->setData(Qt::UserRole, license);
- ui->creditsList->addItem(item);
-}
-
-
-void AboutDialog::on_creditsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem*)
-{
- auto iter = m_LicenseFiles.find(current->data(Qt::UserRole).toInt());
- if (iter != m_LicenseFiles.end()) {
- QString filePath = qApp->applicationDirPath() + "/license/" + iter->second;
- QString text = MOBase::readFileText(filePath);
- ui->licenseText->setText(text);
- } else {
- ui->licenseText->setText(tr("No license"));
- }
+void AboutDialog::on_creditsList_currentItemChanged(QListWidgetItem* current, QListWidgetItem*) {
+ auto iter = m_LicenseFiles.find(current->data(Qt::UserRole).toInt());
+ if (iter != m_LicenseFiles.end()) {
+ QString filePath = qApp->applicationDirPath() + "/license/" + iter->second;
+ QString text = MOBase::readFileText(filePath);
+ ui->licenseText->setText(text);
+ } else {
+ ui->licenseText->setText(tr("No license"));
+ }
}
diff --git a/src/aboutdialog.h b/src/aboutdialog.h
index 103a0d2f..a5c93834 100644
--- a/src/aboutdialog.h
+++ b/src/aboutdialog.h
@@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see .
*/
-
#define ABOUTDIALOG_H
#include
@@ -29,43 +28,38 @@ class QListWidgetItem;
#include
");
- m_TagMap["code"] = std::make_pair(QRegExp("\\[code\\](.*)\\[/code\\]"),
- "\\1
");
- m_TagMap["heading"]= std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"),
- "\\1
");
- m_TagMap["line"] = std::make_pair(QRegExp("\\[line\\]"),
- "
");
-
- // lists
- m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"),
- "");
- m_TagMap["list="] = std::make_pair(QRegExp("\\[list.*\\](.*)\\[/list\\]"),
- "\\1
");
- m_TagMap["ul"] = std::make_pair(QRegExp("\\[ul\\](.*)\\[/ul\\]"),
- "");
- m_TagMap["ol"] = std::make_pair(QRegExp("\\[ol\\](.*)\\[/ol\\]"),
- "\\1
");
- m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"),
- "\\1");
-
- // tables
- m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"),
- "");
- m_TagMap["tr"] = std::make_pair(QRegExp("\\[tr\\](.*)\\[/tr\\]"),
- "\\1
");
- m_TagMap["th"] = std::make_pair(QRegExp("\\[th\\](.*)\\[/th\\]"),
- "\\1 | ");
- m_TagMap["td"] = std::make_pair(QRegExp("\\[td\\](.*)\\[/td\\]"),
- "\\1 | ");
-
- // web content
- m_TagMap["url"] = std::make_pair(QRegExp("\\[url\\](.*)\\[/url\\]"),
- "\\1");
- m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"),
- "\\2");
- m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"),
- "
");
- m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"),
- "
");
- m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"),
- "\\2");
- m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"),
- "http://www.youtube.com/v/\\1");
-
+ BBCodeMap() : m_TagNameExp("^[a-zA-Z*]*=?") {
+ m_TagMap["b"] = std::make_pair(QRegExp("\\[b\\](.*)\\[/b\\]"), "\\1");
+ m_TagMap["i"] = std::make_pair(QRegExp("\\[i\\](.*)\\[/i\\]"), "\\1");
+ m_TagMap["u"] = std::make_pair(QRegExp("\\[u\\](.*)\\[/u\\]"), "\\1");
+ m_TagMap["s"] = std::make_pair(QRegExp("\\[s\\](.*)\\[/s\\]"), "\\1");
+ m_TagMap["sub"] = std::make_pair(QRegExp("\\[sub\\](.*)\\[/sub\\]"), "\\1");
+ m_TagMap["sup"] = std::make_pair(QRegExp("\\[sup\\](.*)\\[/sup\\]"), "\\1");
+ m_TagMap["size="] =
+ std::make_pair(QRegExp("\\[size=([^\\]]*)\\](.*)\\[/size\\]"), "\\2");
+ m_TagMap["color="] = std::make_pair(QRegExp("\\[color=([^\\]]*)\\](.*)\\[/color\\]"), "");
+ m_TagMap["font="] = std::make_pair(QRegExp("\\[font=([^\\]]*)\\](.*)\\[/font\\]"),
+ "\\2");
+ m_TagMap["center"] =
+ std::make_pair(QRegExp("\\[center\\](.*)\\[/center\\]"), "\\1
");
+ m_TagMap["quote"] = std::make_pair(QRegExp("\\[quote\\](.*)\\[/quote\\]"), "\"\\1\"
");
+ m_TagMap["quote="] = std::make_pair(QRegExp("\\[quote=([^\\]]*)\\](.*)\\[/quote\\]"),
+ "\"\\2\"
--\\1
");
+ m_TagMap["code"] = std::make_pair(QRegExp("\\[code\\](.*)\\[/code\\]"), "\\1
");
+ m_TagMap["heading"] =
+ std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"), "\\1
");
+ m_TagMap["line"] = std::make_pair(QRegExp("\\[line\\]"), "
");
+
+ // lists
+ m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"), "");
+ m_TagMap["list="] = std::make_pair(QRegExp("\\[list.*\\](.*)\\[/list\\]"), "\\1
");
+ m_TagMap["ul"] = std::make_pair(QRegExp("\\[ul\\](.*)\\[/ul\\]"), "");
+ m_TagMap["ol"] = std::make_pair(QRegExp("\\[ol\\](.*)\\[/ol\\]"), "\\1
");
+ m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"), "\\1");
+
+ // tables
+ m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"), "");
+ m_TagMap["tr"] = std::make_pair(QRegExp("\\[tr\\](.*)\\[/tr\\]"), "\\1
");
+ m_TagMap["th"] = std::make_pair(QRegExp("\\[th\\](.*)\\[/th\\]"), "\\1 | ");
+ m_TagMap["td"] = std::make_pair(QRegExp("\\[td\\](.*)\\[/td\\]"), "\\1 | ");
+
+ // web content
+ m_TagMap["url"] = std::make_pair(QRegExp("\\[url\\](.*)\\[/url\\]"), "\\1");
+ m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"), "\\2");
+ m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), "
");
+ m_TagMap["img="] =
+ std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), "
");
+ m_TagMap["email="] =
+ std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"), "\\2");
+ m_TagMap["youtube"] =
+ std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"),
+ "http://www.youtube.com/v/\\1");
+
+ // make all patterns non-greedy and case-insensitive
+ for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
+ iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
+ iter->second.first.setMinimal(true);
+ }
- // make all patterns non-greedy and case-insensitive
- for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
- iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
- iter->second.first.setMinimal(true);
+ // this tag is in fact greedy
+ m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)"), "\\1");
+
+ m_ColorMap.insert(std::make_pair("red", "FF0000"));
+ m_ColorMap.insert(std::make_pair("green", "00FF00"));
+ m_ColorMap.insert(std::make_pair("blue", "0000FF"));
+ m_ColorMap.insert(std::make_pair("black", "000000"));
+ m_ColorMap.insert(std::make_pair("gray", "7F7F7F"));
+ m_ColorMap.insert(std::make_pair("white", "FFFFFF"));
+ m_ColorMap.insert(std::make_pair("yellow", "FFFF00"));
+ m_ColorMap.insert(std::make_pair("cyan", "00FFFF"));
+ m_ColorMap.insert(std::make_pair("magenta", "FF00FF"));
+ m_ColorMap.insert(std::make_pair("brown", "A52A2A"));
+ m_ColorMap.insert(std::make_pair("orange", "FFA500"));
+ m_ColorMap.insert(std::make_pair("gold", "FFD700"));
+ m_ColorMap.insert(std::make_pair("deepskyblue", "00BFFF"));
+ m_ColorMap.insert(std::make_pair("salmon", "FA8072"));
+ m_ColorMap.insert(std::make_pair("dodgerblue", "1E90FF"));
+ m_ColorMap.insert(std::make_pair("greenyellow", "ADFF2F"));
+ m_ColorMap.insert(std::make_pair("peru", "CD853F"));
}
- // this tag is in fact greedy
- m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)"),
- "\\1");
-
- m_ColorMap.insert(std::make_pair("red", "FF0000"));
- m_ColorMap.insert(std::make_pair("green", "00FF00"));
- m_ColorMap.insert(std::make_pair("blue", "0000FF"));
- m_ColorMap.insert(std::make_pair("black", "000000"));
- m_ColorMap.insert(std::make_pair("gray", "7F7F7F"));
- m_ColorMap.insert(std::make_pair("white", "FFFFFF"));
- m_ColorMap.insert(std::make_pair("yellow", "FFFF00"));
- m_ColorMap.insert(std::make_pair("cyan", "00FFFF"));
- m_ColorMap.insert(std::make_pair("magenta", "FF00FF"));
- m_ColorMap.insert(std::make_pair("brown", "A52A2A"));
- m_ColorMap.insert(std::make_pair("orange", "FFA500"));
- m_ColorMap.insert(std::make_pair("gold", "FFD700"));
- m_ColorMap.insert(std::make_pair("deepskyblue", "00BFFF"));
- m_ColorMap.insert(std::make_pair("salmon", "FA8072"));
- m_ColorMap.insert(std::make_pair("dodgerblue", "1E90FF"));
- m_ColorMap.insert(std::make_pair("greenyellow", "ADFF2F"));
- m_ColorMap.insert(std::make_pair("peru", "CD853F"));
- }
-
private:
-
- QRegExp m_TagNameExp;
- TagMap m_TagMap;
- std::map m_ColorMap;
+ QRegExp m_TagNameExp;
+ TagMap m_TagMap;
+ std::map m_ColorMap;
};
-
-QString convertToHTML(const QString &inputParam)
-{
- // this code goes over the input string once and replaces all bbtags
- // it encounters. This function is called recursively for every replaced
- // string to convert nested tags.
- //
- // This could be implemented simpler by applying a set of regular expressions
- // for each recognized bb-tag one after the other but that would probably be
- // very inefficient (O(n^2)).
-
- QString input = inputParam.mid(0).replace("\r\n", "
");
- input.replace("\\\"", "\"").replace("\\'", "'");
- QString result;
- int lastBlock = 0;
- int pos = 0;
-
- // iterate over the input buffer
- while ((pos = input.indexOf('[', lastBlock)) != -1) {
- // append everything between the previous tag-block and the current one
- result.append(input.midRef(lastBlock, pos - lastBlock));
-
- if ((pos < (input.size() - 1)) && (input.at(pos + 1) == '/')) {
- // skip invalid end tag
- int tagEnd = input.indexOf(']', pos) + 1;
- pos = tagEnd;
- } else {
- // convert the tag and content if necessary
- int length = -1;
- QString replacement = BBCodeMap::instance().convertTag(input.mid(pos), length);
- if (length != 0) {
- result.append(convertToHTML(replacement));
- // length contains the number of characters in the original tag
- pos += length;
- } else {
- // nothing replaced
- result.append('[');
- ++pos;
- }
+QString convertToHTML(const QString& inputParam) {
+ // this code goes over the input string once and replaces all bbtags
+ // it encounters. This function is called recursively for every replaced
+ // string to convert nested tags.
+ //
+ // This could be implemented simpler by applying a set of regular expressions
+ // for each recognized bb-tag one after the other but that would probably be
+ // very inefficient (O(n^2)).
+
+ QString input = inputParam.mid(0).replace("\r\n", "
");
+ input.replace("\\\"", "\"").replace("\\'", "'");
+ QString result;
+ int lastBlock = 0;
+ int pos = 0;
+
+ // iterate over the input buffer
+ while ((pos = input.indexOf('[', lastBlock)) != -1) {
+ // append everything between the previous tag-block and the current one
+ result.append(input.midRef(lastBlock, pos - lastBlock));
+
+ if ((pos < (input.size() - 1)) && (input.at(pos + 1) == '/')) {
+ // skip invalid end tag
+ int tagEnd = input.indexOf(']', pos) + 1;
+ pos = tagEnd;
+ } else {
+ // convert the tag and content if necessary
+ int length = -1;
+ QString replacement = BBCodeMap::instance().convertTag(input.mid(pos), length);
+ if (length != 0) {
+ result.append(convertToHTML(replacement));
+ // length contains the number of characters in the original tag
+ pos += length;
+ } else {
+ // nothing replaced
+ result.append('[');
+ ++pos;
+ }
+ }
+ lastBlock = pos;
}
- lastBlock = pos;
- }
- // append the remainder (everything after the last tag)
- result.append(input.midRef(lastBlock));
- return result;
+ // append the remainder (everything after the last tag)
+ result.append(input.midRef(lastBlock));
+ return result;
}
} // namespace BBCode
-
diff --git a/src/bbcode.h b/src/bbcode.h
index 708dfe71..d8a10337 100644
--- a/src/bbcode.h
+++ b/src/bbcode.h
@@ -20,10 +20,8 @@ along with Mod Organizer. If not, see .
#ifndef BBCODE_H
#define BBCODE_H
-
#include
-
namespace BBCode {
/**
@@ -32,9 +30,8 @@ namespace BBCode {
* @param replaceOccured if not nullptr, this parameter will be set to true if any bb tags were replaced
* @return the same string in html representation
**/
-QString convertToHTML(const QString &input);
-
-}
+QString convertToHTML(const QString& input);
+} // namespace BBCode
#endif // BBCODE_H
diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp
index c2c65acc..d5a43332 100644
--- a/src/browserdialog.cpp
+++ b/src/browserdialog.cpp
@@ -19,276 +19,228 @@ along with Mod Organizer. If not, see .
#include "browserdialog.h"
-#include "ui_browserdialog.h"
#include "browserview.h"
#include "messagedialog.h"
-#include "report.h"
#include "persistentcookiejar.h"
+#include "report.h"
+#include "ui_browserdialog.h"
-#include
#include "settings.h"
+#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+BrowserDialog::BrowserDialog(QWidget* parent)
+ : QDialog(parent), ui(new Ui::BrowserDialog), m_AccessManager(new QNetworkAccessManager(this)) {
+ ui->setupUi(this);
+ m_AccessManager->setCookieJar(
+ new PersistentCookieJar(QDir::fromNativeSeparators(Settings::instance().getCacheDirectory() + "/cookies.dat")));
-BrowserDialog::BrowserDialog(QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::BrowserDialog)
- , m_AccessManager(new QNetworkAccessManager(this))
-{
- ui->setupUi(this);
-
- m_AccessManager->setCookieJar(new PersistentCookieJar(
- QDir::fromNativeSeparators(Settings::instance().getCacheDirectory() + "/cookies.dat")));
-
- Qt::WindowFlags flags = windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint;
- Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint;
- flags = flags & (~helpFlag);
- setWindowFlags(flags);
+ Qt::WindowFlags flags = windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint;
+ Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint;
+ flags = flags & (~helpFlag);
+ setWindowFlags(flags);
- m_Tabs = this->findChild("browserTabWidget");
+ m_Tabs = this->findChild("browserTabWidget");
- installEventFilter(this);
+ installEventFilter(this);
- connect(m_Tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)));
+ connect(m_Tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)));
- ui->urlEdit->setVisible(false);
+ ui->urlEdit->setVisible(false);
}
-BrowserDialog::~BrowserDialog()
-{
- delete ui;
-}
+BrowserDialog::~BrowserDialog() { delete ui; }
-void BrowserDialog::closeEvent(QCloseEvent *event)
-{
-// m_AccessManager->showCookies();
- QDialog::closeEvent(event);
+void BrowserDialog::closeEvent(QCloseEvent* event) {
+ // m_AccessManager->showCookies();
+ QDialog::closeEvent(event);
}
-void BrowserDialog::initTab(BrowserView *newView)
-{
- //newView->page()->setNetworkAccessManager(m_AccessManager);
- //newView->page()->setForwardUnsupportedContent(true);
-
- connect(newView, SIGNAL(loadProgress(int)), this, SLOT(progress(int)));
- connect(newView, SIGNAL(titleChanged(QString)), this, SLOT(titleChanged(QString)));
- connect(newView, SIGNAL(initTab(BrowserView*)), this, SLOT(initTab(BrowserView*)));
- connect(newView, SIGNAL(startFind()), this, SLOT(startSearch()));
- connect(newView, SIGNAL(urlChanged(QUrl)), this, SLOT(urlChanged(QUrl)));
- connect(newView, SIGNAL(openUrlInNewTab(QUrl)), this, SLOT(openInNewTab(QUrl)));
- connect(newView, SIGNAL(downloadRequested(QNetworkRequest)), this, SLOT(downloadRequested(QNetworkRequest)));
- connect(newView, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
-
- ui->backBtn->setEnabled(false);
- ui->fwdBtn->setEnabled(false);
- m_Tabs->addTab(newView, tr("new"));
- newView->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
- newView->settings()->setAttribute(QWebEngineSettings::AutoLoadImages, true);
-}
+void BrowserDialog::initTab(BrowserView* newView) {
+ // newView->page()->setNetworkAccessManager(m_AccessManager);
+ // newView->page()->setForwardUnsupportedContent(true);
+ connect(newView, SIGNAL(loadProgress(int)), this, SLOT(progress(int)));
+ connect(newView, SIGNAL(titleChanged(QString)), this, SLOT(titleChanged(QString)));
+ connect(newView, SIGNAL(initTab(BrowserView*)), this, SLOT(initTab(BrowserView*)));
+ connect(newView, SIGNAL(startFind()), this, SLOT(startSearch()));
+ connect(newView, SIGNAL(urlChanged(QUrl)), this, SLOT(urlChanged(QUrl)));
+ connect(newView, SIGNAL(openUrlInNewTab(QUrl)), this, SLOT(openInNewTab(QUrl)));
+ connect(newView, SIGNAL(downloadRequested(QNetworkRequest)), this, SLOT(downloadRequested(QNetworkRequest)));
+ connect(newView, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
-void BrowserDialog::openInNewTab(const QUrl &url)
-{
- BrowserView *newView = new BrowserView(this);
- initTab(newView);
- newView->setUrl(url);
+ ui->backBtn->setEnabled(false);
+ ui->fwdBtn->setEnabled(false);
+ m_Tabs->addTab(newView, tr("new"));
+ newView->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
+ newView->settings()->setAttribute(QWebEngineSettings::AutoLoadImages, true);
}
-
-BrowserView *BrowserDialog::getCurrentView()
-{
- return qobject_cast(m_Tabs->currentWidget());
+void BrowserDialog::openInNewTab(const QUrl& url) {
+ BrowserView* newView = new BrowserView(this);
+ initTab(newView);
+ newView->setUrl(url);
}
+BrowserView* BrowserDialog::getCurrentView() { return qobject_cast(m_Tabs->currentWidget()); }
-void BrowserDialog::urlChanged(const QUrl &url)
-{
- BrowserView *currentView = getCurrentView();
- if (currentView != nullptr) {
- ui->backBtn->setEnabled(currentView->history()->canGoBack());
- ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
- }
- ui->urlEdit->setText(url.toString());
+void BrowserDialog::urlChanged(const QUrl& url) {
+ BrowserView* currentView = getCurrentView();
+ if (currentView != nullptr) {
+ ui->backBtn->setEnabled(currentView->history()->canGoBack());
+ ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
+ }
+ ui->urlEdit->setText(url.toString());
}
-
-void BrowserDialog::openUrl(const QUrl &url)
-{
- if (isHidden()) {
- show();
- }
- openInNewTab(url);
+void BrowserDialog::openUrl(const QUrl& url) {
+ if (isHidden()) {
+ show();
+ }
+ openInNewTab(url);
}
+void BrowserDialog::maximizeWidth() {
+ int viewportWidth = getCurrentView()->page()->contentsSize().width();
+ int frameWidth = width() - viewportWidth;
-void BrowserDialog::maximizeWidth()
-{
- int viewportWidth = getCurrentView()->page()->contentsSize ().width();
- int frameWidth = width() - viewportWidth;
-
- int contentWidth = getCurrentView()->page()->contentsSize().width();
-
- QDesktopWidget screen;
- int currentScreen = screen.screenNumber(this);
- int screenWidth = screen.screenGeometry(currentScreen).size().width();
-
- int targetWidth = std::min(std::max(viewportWidth, contentWidth) + frameWidth, screenWidth);
- this->resize(targetWidth, height());
-}
+ int contentWidth = getCurrentView()->page()->contentsSize().width();
+ QDesktopWidget screen;
+ int currentScreen = screen.screenNumber(this);
+ int screenWidth = screen.screenGeometry(currentScreen).size().width();
-void BrowserDialog::progress(int value)
-{
- ui->loadProgress->setValue(value);
- if (value == 100) {
- maximizeWidth();
- ui->loadProgress->setVisible(false);
- } else {
- ui->loadProgress->setVisible(true);
- }
+ int targetWidth = std::min(std::max(viewportWidth, contentWidth) + frameWidth, screenWidth);
+ this->resize(targetWidth, height());
}
-
-void BrowserDialog::titleChanged(const QString &title)
-{
- BrowserView *view = qobject_cast(sender());
- for (int i = 0; i < m_Tabs->count(); ++i) {
- if (m_Tabs->widget(i) == view) {
- m_Tabs->setTabText(i, title.mid(0, 15));
- m_Tabs->setTabToolTip(i, title);
+void BrowserDialog::progress(int value) {
+ ui->loadProgress->setValue(value);
+ if (value == 100) {
+ maximizeWidth();
+ ui->loadProgress->setVisible(false);
+ } else {
+ ui->loadProgress->setVisible(true);
}
- }
}
-
-QString BrowserDialog::guessFileName(const QString &url)
-{
- QRegExp uploadsExp(QString("http://.+/uploads/([^/]+)$"));
- if (uploadsExp.indexIn(url) != -1) {
- // these seem to be premium downloads
- return uploadsExp.cap(1);
- }
-
- QRegExp filesExp(QString("http://.+\\?file=([^&]+)"));
- if (filesExp.indexIn(url) != -1) {
- // a regular manual download?
- return filesExp.cap(1);
- }
- return "unknown";
+void BrowserDialog::titleChanged(const QString& title) {
+ BrowserView* view = qobject_cast(sender());
+ for (int i = 0; i < m_Tabs->count(); ++i) {
+ if (m_Tabs->widget(i) == view) {
+ m_Tabs->setTabText(i, title.mid(0, 15));
+ m_Tabs->setTabToolTip(i, title);
+ }
+ }
}
-void BrowserDialog::unsupportedContent(QNetworkReply *reply)
-{
- try {
- QWebEnginePage *page = qobject_cast(sender());
- if (page == nullptr) {
- qCritical("sender not a page");
- return;
- }
- BrowserView *view = qobject_cast(page->view());
- if (view == nullptr) {
- qCritical("no view?");
- return;
+QString BrowserDialog::guessFileName(const QString& url) {
+ QRegExp uploadsExp(QString("http://.+/uploads/([^/]+)$"));
+ if (uploadsExp.indexIn(url) != -1) {
+ // these seem to be premium downloads
+ return uploadsExp.cap(1);
}
- emit requestDownload(view->url(), reply);
- } catch (const std::exception &e) {
- if (isVisible()) {
- MessageDialog::showMessage(tr("failed to start download"), this);
+ QRegExp filesExp(QString("http://.+\\?file=([^&]+)"));
+ if (filesExp.indexIn(url) != -1) {
+ // a regular manual download?
+ return filesExp.cap(1);
+ }
+ return "unknown";
+}
+
+void BrowserDialog::unsupportedContent(QNetworkReply* reply) {
+ try {
+ QWebEnginePage* page = qobject_cast(sender());
+ if (page == nullptr) {
+ qCritical("sender not a page");
+ return;
+ }
+ BrowserView* view = qobject_cast(page->view());
+ if (view == nullptr) {
+ qCritical("no view?");
+ return;
+ }
+
+ emit requestDownload(view->url(), reply);
+ } catch (const std::exception& e) {
+ if (isVisible()) {
+ MessageDialog::showMessage(tr("failed to start download"), this);
+ }
+ qCritical("exception downloading unsupported content: %s", e.what());
}
- qCritical("exception downloading unsupported content: %s", e.what());
- }
-}
-
-
-void BrowserDialog::downloadRequested(const QNetworkRequest &request)
-{
- qCritical("download request %s ignored", request.url().toString().toUtf8().constData());
}
-
-void BrowserDialog::tabCloseRequested(int index)
-{
- if (m_Tabs->count() == 1) {
- this->close();
- } else {
- m_Tabs->widget(index)->deleteLater();
- m_Tabs->removeTab(index);
- }
+void BrowserDialog::downloadRequested(const QNetworkRequest& request) {
+ qCritical("download request %s ignored", request.url().toString().toUtf8().constData());
}
-void BrowserDialog::on_backBtn_clicked()
-{
- BrowserView *currentView = getCurrentView();
- if (currentView != nullptr) {
- currentView->back();
- }
+void BrowserDialog::tabCloseRequested(int index) {
+ if (m_Tabs->count() == 1) {
+ this->close();
+ } else {
+ m_Tabs->widget(index)->deleteLater();
+ m_Tabs->removeTab(index);
+ }
}
-void BrowserDialog::on_fwdBtn_clicked()
-{
- BrowserView *currentView = getCurrentView();
- if (currentView != nullptr) {
- currentView->forward();
- }
+void BrowserDialog::on_backBtn_clicked() {
+ BrowserView* currentView = getCurrentView();
+ if (currentView != nullptr) {
+ currentView->back();
+ }
}
-
-void BrowserDialog::startSearch()
-{
- ui->searchEdit->setFocus();
+void BrowserDialog::on_fwdBtn_clicked() {
+ BrowserView* currentView = getCurrentView();
+ if (currentView != nullptr) {
+ currentView->forward();
+ }
}
+void BrowserDialog::startSearch() { ui->searchEdit->setFocus(); }
-void BrowserDialog::on_searchEdit_returnPressed()
-{
-// BrowserView *currentView = getCurrentView();
-// if (currentView != nullptr) {
-// currentView->findText(ui->searchEdit->text(), QWebEnginePage::FindWrapsAroundDocument);
-// }
+void BrowserDialog::on_searchEdit_returnPressed() {
+ // BrowserView *currentView = getCurrentView();
+ // if (currentView != nullptr) {
+ // currentView->findText(ui->searchEdit->text(), QWebEnginePage::FindWrapsAroundDocument);
+ // }
}
-void BrowserDialog::on_refreshBtn_clicked()
-{
- getCurrentView()->reload();
-}
+void BrowserDialog::on_refreshBtn_clicked() { getCurrentView()->reload(); }
-void BrowserDialog::on_browserTabWidget_currentChanged(int index)
-{
- BrowserView *currentView = qobject_cast(ui->browserTabWidget->widget(index));
- if (currentView != nullptr) {
- ui->backBtn->setEnabled(currentView->history()->canGoBack());
- ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
- }
+void BrowserDialog::on_browserTabWidget_currentChanged(int index) {
+ BrowserView* currentView = qobject_cast(ui->browserTabWidget->widget(index));
+ if (currentView != nullptr) {
+ ui->backBtn->setEnabled(currentView->history()->canGoBack());
+ ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
+ }
}
-void BrowserDialog::on_urlEdit_returnPressed()
-{
- QWebEngineView *currentView = getCurrentView();
- if (currentView != nullptr) {
- currentView->setUrl(QUrl(ui->urlEdit->text()));
- }
+void BrowserDialog::on_urlEdit_returnPressed() {
+ QWebEngineView* currentView = getCurrentView();
+ if (currentView != nullptr) {
+ currentView->setUrl(QUrl(ui->urlEdit->text()));
+ }
}
-bool BrowserDialog::eventFilter(QObject *object, QEvent *event)
-{
- if (event->type() == QEvent::KeyPress) {
- QKeyEvent *keyEvent = reinterpret_cast(event);
- if ((keyEvent->modifiers() & Qt::ControlModifier)
- && (keyEvent->key() == Qt::Key_U)) {
- ui->urlEdit->setVisible(!ui->urlEdit->isVisible());
- return true;
+bool BrowserDialog::eventFilter(QObject* object, QEvent* event) {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent* keyEvent = reinterpret_cast(event);
+ if ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->key() == Qt::Key_U)) {
+ ui->urlEdit->setVisible(!ui->urlEdit->isVisible());
+ return true;
+ }
}
- }
- return QDialog::eventFilter(object, event);
+ return QDialog::eventFilter(object, event);
}
diff --git a/src/browserdialog.h b/src/browserdialog.h
index 354a377b..6947cc43 100644
--- a/src/browserdialog.h
+++ b/src/browserdialog.h
@@ -20,18 +20,17 @@ along with Mod Organizer. If not, see .
#ifndef BROWSERDIALOG_H
#define BROWSERDIALOG_H
+#include
#include
-#include
#include
-#include
-#include
+#include
#include
#include
-#include
-
+#include
+#include
namespace Ui {
- class BrowserDialog;
+class BrowserDialog;
}
class BrowserView;
@@ -39,88 +38,81 @@ class BrowserView;
/**
* @brief a dialog containing a webbrowser that is intended to browse the nexus network
**/
-class BrowserDialog : public QDialog
-{
+class BrowserDialog : public QDialog {
Q_OBJECT
public:
-
- /**
- * @brief constructor
- *
- * @param accessManager the access manager to use for network requests
- * @param parent parent widget
- **/
- explicit BrowserDialog(QWidget *parent = 0);
- ~BrowserDialog();
-
- /**
- * @brief set the url to open. If automatic login is enabled, the url is opened after login
- *
- * @param url the url to open
- **/
- void openUrl(const QUrl &url);
-
- virtual bool eventFilter(QObject *object, QEvent *event);
+ /**
+ * @brief constructor
+ *
+ * @param accessManager the access manager to use for network requests
+ * @param parent parent widget
+ **/
+ explicit BrowserDialog(QWidget* parent = 0);
+ ~BrowserDialog();
+
+ /**
+ * @brief set the url to open. If automatic login is enabled, the url is opened after login
+ *
+ * @param url the url to open
+ **/
+ void openUrl(const QUrl& url);
+
+ virtual bool eventFilter(QObject* object, QEvent* event);
signals:
- /**
- * @brief emitted when the user starts a download
- * @param pageUrl url of the current web site from which the download was started
- * @param reply network reply of the started download
- */
- void requestDownload(const QUrl &pageUrl, QNetworkReply *reply);
+ /**
+ * @brief emitted when the user starts a download
+ * @param pageUrl url of the current web site from which the download was started
+ * @param reply network reply of the started download
+ */
+ void requestDownload(const QUrl& pageUrl, QNetworkReply* reply);
protected:
-
- virtual void closeEvent(QCloseEvent *);
+ virtual void closeEvent(QCloseEvent*);
private slots:
- void initTab(BrowserView *newView);
- void openInNewTab(const QUrl &url);
+ void initTab(BrowserView* newView);
+ void openInNewTab(const QUrl& url);
- void progress(int value);
+ void progress(int value);
- void titleChanged(const QString &title);
- void unsupportedContent(QNetworkReply *reply);
- void downloadRequested(const QNetworkRequest &request);
+ void titleChanged(const QString& title);
+ void unsupportedContent(QNetworkReply* reply);
+ void downloadRequested(const QNetworkRequest& request);
- void tabCloseRequested(int index);
+ void tabCloseRequested(int index);
- void urlChanged(const QUrl &url);
+ void urlChanged(const QUrl& url);
- void on_backBtn_clicked();
+ void on_backBtn_clicked();
- void on_fwdBtn_clicked();
+ void on_fwdBtn_clicked();
- void on_searchEdit_returnPressed();
+ void on_searchEdit_returnPressed();
- void startSearch();
+ void startSearch();
- void on_refreshBtn_clicked();
+ void on_refreshBtn_clicked();
- void on_browserTabWidget_currentChanged(int index);
+ void on_browserTabWidget_currentChanged(int index);
- void on_urlEdit_returnPressed();
+ void on_urlEdit_returnPressed();
private:
+ QString guessFileName(const QString& url);
- QString guessFileName(const QString &url);
-
- BrowserView *getCurrentView();
+ BrowserView* getCurrentView();
- void maximizeWidth();
+ void maximizeWidth();
private:
+ Ui::BrowserDialog* ui;
- Ui::BrowserDialog *ui;
-
- QNetworkAccessManager *m_AccessManager;
-
- QTabWidget *m_Tabs;
-
+ QNetworkAccessManager* m_AccessManager;
+ QTabWidget* m_Tabs;
};
#endif // BROWSERDIALOG_H
diff --git a/src/browserview.cpp b/src/browserview.cpp
index 0b871e23..a44792b2 100644
--- a/src/browserview.cpp
+++ b/src/browserview.cpp
@@ -19,58 +19,53 @@ along with Mod Organizer. If not, see .
#include "browserview.h"
+#include "utility.h"
#include
#include
+#include
#include
#include
#include
-#include
#include
-#include "utility.h"
-
-BrowserView::BrowserView(QWidget *parent)
- : QWebEngineView(parent)
-{
- installEventFilter(this);
+BrowserView::BrowserView(QWidget* parent) : QWebEngineView(parent) {
+ installEventFilter(this);
- //page()->settings()->setMaximumPagesInCache(10);
+ // page()->settings()->setMaximumPagesInCache(10);
}
-QWebEngineView *BrowserView::createWindow(QWebEnginePage::WebWindowType)
-{
- BrowserView *newView = new BrowserView(parentWidget());
- emit initTab(newView);
- return newView;
+QWebEngineView* BrowserView::createWindow(QWebEnginePage::WebWindowType) {
+ BrowserView* newView = new BrowserView(parentWidget());
+ emit initTab(newView);
+ return newView;
}
-bool BrowserView::eventFilter(QObject *obj, QEvent *event)
-{
- if (event->type() == QEvent::ShortcutOverride) {
- QKeyEvent *keyEvent = static_cast(event);
- if (keyEvent->matches(QKeySequence::Find)) {
- emit startFind();
- } else if (keyEvent->matches(QKeySequence::FindNext)) {
- emit findAgain();
- }
- } else if (event->type() == QEvent::MouseButtonPress) {
- QMouseEvent *mouseEvent = static_cast(event);
- if (mouseEvent->button() == Qt::MidButton) {
- mouseEvent->ignore();
- return true;
+bool BrowserView::eventFilter(QObject* obj, QEvent* event) {
+ if (event->type() == QEvent::ShortcutOverride) {
+ QKeyEvent* keyEvent = static_cast(event);
+ if (keyEvent->matches(QKeySequence::Find)) {
+ emit startFind();
+ } else if (keyEvent->matches(QKeySequence::FindNext)) {
+ emit findAgain();
+ }
+ } else if (event->type() == QEvent::MouseButtonPress) {
+ QMouseEvent* mouseEvent = static_cast(event);
+ if (mouseEvent->button() == Qt::MidButton) {
+ mouseEvent->ignore();
+ return true;
+ }
+ // TODO This is due to that QTWebEnginePage doesn't support QWebFrame anymore
+ // } else if (event->type() == QEvent::MouseButtonRelease) {
+ // QMouseEvent *mouseEvent = static_cast(event);
+ // if (mouseEvent->button() == Qt::MidButton) {
+ // QWebEngineContextMenuData hitTest = page()->hitTestContent(mouseEvent->pos());
+ // if (hitTest.linkUrl().isValid()) {
+ // emit openUrlInNewTab(hitTest.linkUrl());
+ // }
+ // mouseEvent->ignore();
+ //
+ // return true;
+ // }
}
-// TODO This is due to that QTWebEnginePage doesn't support QWebFrame anymore
-// } else if (event->type() == QEvent::MouseButtonRelease) {
-// QMouseEvent *mouseEvent = static_cast(event);
-// if (mouseEvent->button() == Qt::MidButton) {
-// QWebEngineContextMenuData hitTest = page()->hitTestContent(mouseEvent->pos());
-// if (hitTest.linkUrl().isValid()) {
-// emit openUrlInNewTab(hitTest.linkUrl());
-// }
-// mouseEvent->ignore();
-//
-// return true;
-// }
- }
- return QWebEngineView::eventFilter(obj, event);
+ return QWebEngineView::eventFilter(obj, event);
}
diff --git a/src/browserview.h b/src/browserview.h
index 24be21c1..b390ed4e 100644
--- a/src/browserview.h
+++ b/src/browserview.h
@@ -20,62 +20,55 @@ along with Mod Organizer. If not, see .
#ifndef NEXUSVIEW_H
#define NEXUSVIEW_H
-
class QEvent;
class QUrl;
class QWidget;
-#include
#include
+#include
/**
* @brief web view used to display a nexus page
**/
-class BrowserView : public QWebEngineView
-{
+class BrowserView : public QWebEngineView {
Q_OBJECT
public:
-
- explicit BrowserView(QWidget *parent = 0);
+ explicit BrowserView(QWidget* parent = 0);
signals:
- /**
- * @brief emitted when the user opens a new window to be displayed in another tab
- *
- * @param newView the view for the newly opened window
- **/
- void initTab(BrowserView *newView);
-
- /**
- * @brief emitted when the user requests a link to be opened in a new tab by middle-clicking
- *
- * @param url the url to open
- */
- void openUrlInNewTab(const QUrl &url);
-
- /**
- * @brief Ctrl-f was clicked. The containing dialog should activate its find-facility
- */
- void startFind();
-
- /**
- * @brief F3 was pressed. The containing dialog should search again
- */
- void findAgain();
+ /**
+ * @brief emitted when the user opens a new window to be displayed in another tab
+ *
+ * @param newView the view for the newly opened window
+ **/
+ void initTab(BrowserView* newView);
+
+ /**
+ * @brief emitted when the user requests a link to be opened in a new tab by middle-clicking
+ *
+ * @param url the url to open
+ */
+ void openUrlInNewTab(const QUrl& url);
+
+ /**
+ * @brief Ctrl-f was clicked. The containing dialog should activate its find-facility
+ */
+ void startFind();
+
+ /**
+ * @brief F3 was pressed. The containing dialog should search again
+ */
+ void findAgain();
protected:
+ virtual QWebEngineView* createWindow(QWebEnginePage::WebWindowType type);
- virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type);
-
- virtual bool eventFilter(QObject *obj, QEvent *event);
-
+ virtual bool eventFilter(QObject* obj, QEvent* event);
private:
-
- QString m_FindPattern;
- bool m_MiddleClick;
-
+ QString m_FindPattern;
+ bool m_MiddleClick;
};
#endif // NEXUSVIEW_H
diff --git a/src/categories.cpp b/src/categories.cpp
index d8cd49fb..c88227e6 100644
--- a/src/categories.cpp
+++ b/src/categories.cpp
@@ -19,350 +19,302 @@ along with Mod Organizer. If not, see .
#include "categories.h"
-#include
#include
+#include
-#include
-#include
+#include
#include
+#include
#include
-#include
-
+#include
using namespace MOBase;
-
CategoryFactory* CategoryFactory::s_Instance = nullptr;
+QString CategoryFactory::categoriesFilePath() { return qApp->property("dataPath").toString() + "/categories.dat"; }
-QString CategoryFactory::categoriesFilePath()
-{
- return qApp->property("dataPath").toString() + "/categories.dat";
-}
+CategoryFactory::CategoryFactory() { atexit(&cleanup); }
+void CategoryFactory::loadCategories() {
+ reset();
-CategoryFactory::CategoryFactory()
-{
- atexit(&cleanup);
-}
+ QFile categoryFile(categoriesFilePath());
-void CategoryFactory::loadCategories()
-{
- reset();
-
- QFile categoryFile(categoriesFilePath());
-
- if (!categoryFile.open(QIODevice::ReadOnly)) {
- loadDefaultCategories();
- } else {
- int lineNum = 0;
- while (!categoryFile.atEnd()) {
- QByteArray line = categoryFile.readLine();
- ++lineNum;
- QList cells = line.split('|');
- if (cells.count() != 4) {
- qCritical("invalid category line %d: %s (%d cells)",
- lineNum, line.constData(), cells.count());
- } else {
- std::vector nexusIDs;
- if (cells[2].length() > 0) {
- QList nexusIDStrings = cells[2].split(',');
- for (QList::iterator iter = nexusIDStrings.begin();
- iter != nexusIDStrings.end(); ++iter) {
- bool ok = false;
- int temp = iter->toInt(&ok);
- if (!ok) {
- qCritical("invalid id %s", iter->constData());
+ if (!categoryFile.open(QIODevice::ReadOnly)) {
+ loadDefaultCategories();
+ } else {
+ int lineNum = 0;
+ while (!categoryFile.atEnd()) {
+ QByteArray line = categoryFile.readLine();
+ ++lineNum;
+ QList cells = line.split('|');
+ if (cells.count() != 4) {
+ qCritical("invalid category line %d: %s (%d cells)", lineNum, line.constData(), cells.count());
+ } else {
+ std::vector nexusIDs;
+ if (cells[2].length() > 0) {
+ QList nexusIDStrings = cells[2].split(',');
+ for (QList::iterator iter = nexusIDStrings.begin(); iter != nexusIDStrings.end();
+ ++iter) {
+ bool ok = false;
+ int temp = iter->toInt(&ok);
+ if (!ok) {
+ qCritical("invalid id %s", iter->constData());
+ }
+ nexusIDs.push_back(temp);
+ }
+ }
+ bool cell0Ok = true;
+ bool cell3Ok = true;
+ int id = cells[0].toInt(&cell0Ok);
+ int parentID = cells[3].trimmed().toInt(&cell3Ok);
+ if (!cell0Ok || !cell3Ok) {
+ qCritical("invalid category line %d: %s", lineNum, line.constData());
+ }
+ addCategory(id, QString::fromUtf8(cells[1].constData()), nexusIDs, parentID);
}
- nexusIDs.push_back(temp);
- }
- }
- bool cell0Ok = true;
- bool cell3Ok = true;
- int id = cells[0].toInt(&cell0Ok);
- int parentID = cells[3].trimmed().toInt(&cell3Ok);
- if (!cell0Ok || !cell3Ok) {
- qCritical("invalid category line %d: %s",
- lineNum, line.constData());
}
- addCategory(id, QString::fromUtf8(cells[1].constData()), nexusIDs, parentID);
- }
+ categoryFile.close();
}
- categoryFile.close();
- }
- std::sort(m_Categories.begin(), m_Categories.end());
- setParents();
+ std::sort(m_Categories.begin(), m_Categories.end());
+ setParents();
}
-
-CategoryFactory &CategoryFactory::instance()
-{
- if (s_Instance == nullptr) {
- s_Instance = new CategoryFactory;
- }
- return *s_Instance;
+CategoryFactory& CategoryFactory::instance() {
+ if (s_Instance == nullptr) {
+ s_Instance = new CategoryFactory;
+ }
+ return *s_Instance;
}
-
-void CategoryFactory::reset()
-{
- m_Categories.clear();
- m_IDMap.clear();
- // 28 =
- // 43 = Savegames (makes no sense to install them through MO)
- // 45 = Videos and trailers
- // 87 = Miscelanous
- addCategory(0, "None", MakeVector(4, 28, 43, 45, 87), 0);
+void CategoryFactory::reset() {
+ m_Categories.clear();
+ m_IDMap.clear();
+ // 28 =
+ // 43 = Savegames (makes no sense to install them through MO)
+ // 45 = Videos and trailers
+ // 87 = Miscelanous
+ addCategory(0, "None", MakeVector(4, 28, 43, 45, 87), 0);
}
+void CategoryFactory::setParents() {
+ for (std::vector::iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) {
+ iter->m_HasChildren = false;
+ }
-void CategoryFactory::setParents()
-{
- for (std::vector::iterator iter = m_Categories.begin();
- iter != m_Categories.end(); ++iter) {
- iter->m_HasChildren = false;
- }
-
- for (std::vector::const_iterator categoryIter = m_Categories.begin();
- categoryIter != m_Categories.end(); ++categoryIter) {
- if (categoryIter->m_ParentID != 0) {
- std::map::const_iterator iter = m_IDMap.find(categoryIter->m_ParentID);
- if (iter != m_IDMap.end()) {
- m_Categories[iter->second].m_HasChildren = true;
- }
+ for (std::vector::const_iterator categoryIter = m_Categories.begin(); categoryIter != m_Categories.end();
+ ++categoryIter) {
+ if (categoryIter->m_ParentID != 0) {
+ std::map::const_iterator iter = m_IDMap.find(categoryIter->m_ParentID);
+ if (iter != m_IDMap.end()) {
+ m_Categories[iter->second].m_HasChildren = true;
+ }
+ }
}
- }
}
-void CategoryFactory::cleanup()
-{
- delete s_Instance;
- s_Instance = nullptr;
+void CategoryFactory::cleanup() {
+ delete s_Instance;
+ s_Instance = nullptr;
}
+void CategoryFactory::saveCategories() {
+ QFile categoryFile(categoriesFilePath());
-void CategoryFactory::saveCategories()
-{
- QFile categoryFile(categoriesFilePath());
-
- if (!categoryFile.open(QIODevice::WriteOnly)) {
- reportError(QObject::tr("Failed to save custom categories"));
- return;
- }
+ if (!categoryFile.open(QIODevice::WriteOnly)) {
+ reportError(QObject::tr("Failed to save custom categories"));
+ return;
+ }
- categoryFile.resize(0);
- for (std::vector::const_iterator iter = m_Categories.begin();
- iter != m_Categories.end(); ++iter) {
- if (iter->m_ID == 0) {
- continue;
+ categoryFile.resize(0);
+ for (std::vector::const_iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) {
+ if (iter->m_ID == 0) {
+ continue;
+ }
+ QByteArray line;
+ line.append(QByteArray::number(iter->m_ID))
+ .append("|")
+ .append(iter->m_Name.toUtf8())
+ .append("|")
+ .append(VectorJoin(iter->m_NexusIDs, ","))
+ .append("|")
+ .append(QByteArray::number(iter->m_ParentID))
+ .append("\n");
+ categoryFile.write(line);
}
- QByteArray line;
- line.append(QByteArray::number(iter->m_ID)).append("|")
- .append(iter->m_Name.toUtf8()).append("|")
- .append(VectorJoin(iter->m_NexusIDs, ",")).append("|")
- .append(QByteArray::number(iter->m_ParentID)).append("\n");
- categoryFile.write(line);
- }
- categoryFile.close();
+ categoryFile.close();
}
-
-unsigned int CategoryFactory::countCategories(std::tr1::function filter)
-{
- unsigned int result = 0;
- for (const Category &cat : m_Categories) {
- if (filter(cat)) {
- ++result;
+unsigned int CategoryFactory::countCategories(std::tr1::function filter) {
+ unsigned int result = 0;
+ for (const Category& cat : m_Categories) {
+ if (filter(cat)) {
+ ++result;
+ }
}
- }
- return result;
+ return result;
}
-int CategoryFactory::addCategory(const QString &name, const std::vector &nexusIDs, int parentID)
-{
- int id = 1;
- while (m_IDMap.find(id) != m_IDMap.end()) {
- ++id;
- }
- addCategory(id, name, nexusIDs, parentID);
-
- saveCategories();
- return id;
-}
+int CategoryFactory::addCategory(const QString& name, const std::vector& nexusIDs, int parentID) {
+ int id = 1;
+ while (m_IDMap.find(id) != m_IDMap.end()) {
+ ++id;
+ }
+ addCategory(id, name, nexusIDs, parentID);
-void CategoryFactory::addCategory(int id, const QString &name, const std::vector &nexusIDs, int parentID)
-{
- int index = static_cast(m_Categories.size());
- m_Categories.push_back(Category(index, id, name, nexusIDs, parentID));
- for (int nexusID : nexusIDs) {
- m_NexusMap[nexusID] = index;
- }
- m_IDMap[id] = index;
+ saveCategories();
+ return id;
}
-
-void CategoryFactory::loadDefaultCategories()
-{
- // the order here is relevant as it defines the order in which the
- // mods appear in the combo box
- addCategory(1, "Animations", MakeVector(2, 4, 51), 0);
- addCategory(52, "Poses", MakeVector(1, 29), 1);
- addCategory(2, "Armour", MakeVector(2, 5, 54), 0);
- addCategory(53, "Power Armor", MakeVector(1, 53), 2);
- addCategory(3, "Audio", MakeVector(3, 33, 35, 106), 0);
- addCategory(38, "Music", MakeVector(2, 34, 61), 0);
- addCategory(39, "Voice", MakeVector(2, 36, 107), 0);
- addCategory(5, "Clothing", MakeVector(2, 9, 60), 0);
- addCategory(41, "Jewelry", MakeVector(1, 102), 5);
- addCategory(42, "Backpacks", MakeVector(1, 49), 5);
- addCategory(6, "Collectables", MakeVector(2, 10, 92), 0);
- addCategory(28, "Companions", MakeVector(3, 11, 66, 96), 0);
- addCategory(7, "Creatures, Mounts, & Vehicles", MakeVector(4, 12, 65, 83, 101), 0);
- addCategory(8, "Factions", MakeVector(2, 16, 25), 0);
- addCategory(9, "Gameplay", MakeVector(2, 15, 24), 0);
- addCategory(27, "Combat", MakeVector(1, 77), 9);
- addCategory(43, "Crafting", MakeVector(2, 50, 100), 9);
- addCategory(48, "Overhauls", MakeVector(2, 24, 79), 9);
- addCategory(49, "Perks", MakeVector(1, 27), 9);
- addCategory(54, "Radio", MakeVector(1, 31), 9);
- addCategory(55, "Shouts", MakeVector(1, 104), 9);
- addCategory(22, "Skills & Levelling", MakeVector(2, 46, 73), 9);
- addCategory(58, "Weather & Lighting", MakeVector(1, 56), 9);
- addCategory(44, "Equipment", MakeVector(1, 44), 43);
- addCategory(45, "Home/Settlement", MakeVector(1, 45), 43);
- addCategory(10, "Body, Face, & Hair", MakeVector(2, 17, 26), 0);
- addCategory(39, "Tattoos", MakeVector(1, 57), 10);
- addCategory(40, "Character Presets", MakeVector(1, 58), 0);
- addCategory(11, "Items", MakeVector(2, 27, 85), 0);
- addCategory(32, "Mercantile", MakeVector(2, 23, 69), 0);
- addCategory(37, "Ammo", MakeVector(1, 3), 11);
- addCategory(19, "Weapons", MakeVector(2, 41, 55), 11);
- addCategory(36, "Weapon & Armour Sets", MakeVector(1, 42), 11);
- addCategory(23, "Player Homes", MakeVector(2, 28, 67), 0);
- addCategory(25, "Castles & Mansions", MakeVector(1, 68), 23);
- addCategory(51, "Settlements", MakeVector(1, 48), 23);
- addCategory(12, "Locations", MakeVector(10, 20, 21, 22, 30, 47, 70, 88, 89, 90, 91), 0);
- addCategory(4, "Cities", MakeVector(1, 53), 12);
- addCategory(31, "Landscape Changes", MakeVector(1, 58), 0);
- addCategory(29, "Environment", MakeVector(2, 14, 74), 0);
- addCategory(30, "Immersion", MakeVector(2, 51, 78), 0);
- addCategory(20, "Magic", MakeVector(3, 75, 93, 94), 0);
- addCategory(21, "Models & Textures", MakeVector(2, 19, 29), 0);
- addCategory(33, "Modders resources", MakeVector(2, 18, 82), 0);
- addCategory(13, "NPCs", MakeVector(3, 22, 33, 99), 0);
- addCategory(24, "Bugfixes", MakeVector(2, 6, 95), 0);
- addCategory(14, "Patches", MakeVector(2, 25, 84), 24);
- addCategory(35, "Utilities", MakeVector(2, 38, 39), 0);
- addCategory(26, "Cheats", MakeVector(1, 8), 0);
- addCategory(15, "Quests", MakeVector(2, 30, 35), 0);
- addCategory(16, "Races & Classes", MakeVector(1, 34), 0);
- addCategory(34, "Stealth", MakeVector(1, 76), 0);
- addCategory(17, "UI", MakeVector(2, 37, 42), 0);
- addCategory(18, "Visuals", MakeVector(2, 40, 62), 0);
- addCategory(50, "Pip-Boy", MakeVector(1, 52), 18);
- addCategory(46, "Shader Presets", MakeVector(3, 13, 97, 105), 0);
- addCategory(47, "Miscellaneous", MakeVector(2, 2, 28), 0);
+void CategoryFactory::addCategory(int id, const QString& name, const std::vector& nexusIDs, int parentID) {
+ int index = static_cast(m_Categories.size());
+ m_Categories.push_back(Category(index, id, name, nexusIDs, parentID));
+ for (int nexusID : nexusIDs) {
+ m_NexusMap[nexusID] = index;
+ }
+ m_IDMap[id] = index;
}
-
-int CategoryFactory::getParentID(unsigned int index) const
-{
- if (index >= m_Categories.size()) {
- throw MyException(QObject::tr("invalid index %1").arg(index));
- }
-
- return m_Categories[index].m_ParentID;
+void CategoryFactory::loadDefaultCategories() {
+ // the order here is relevant as it defines the order in which the
+ // mods appear in the combo box
+ addCategory(1, "Animations", MakeVector(2, 4, 51), 0);
+ addCategory(52, "Poses", MakeVector(1, 29), 1);
+ addCategory(2, "Armour", MakeVector(2, 5, 54), 0);
+ addCategory(53, "Power Armor", MakeVector(1, 53), 2);
+ addCategory(3, "Audio", MakeVector(3, 33, 35, 106), 0);
+ addCategory(38, "Music", MakeVector(2, 34, 61), 0);
+ addCategory(39, "Voice", MakeVector(2, 36, 107), 0);
+ addCategory(5, "Clothing", MakeVector(2, 9, 60), 0);
+ addCategory(41, "Jewelry", MakeVector(1, 102), 5);
+ addCategory(42, "Backpacks", MakeVector(1, 49), 5);
+ addCategory(6, "Collectables", MakeVector(2, 10, 92), 0);
+ addCategory(28, "Companions", MakeVector(3, 11, 66, 96), 0);
+ addCategory(7, "Creatures, Mounts, & Vehicles", MakeVector(4, 12, 65, 83, 101), 0);
+ addCategory(8, "Factions", MakeVector(2, 16, 25), 0);
+ addCategory(9, "Gameplay", MakeVector(2, 15, 24), 0);
+ addCategory(27, "Combat", MakeVector(1, 77), 9);
+ addCategory(43, "Crafting", MakeVector(2, 50, 100), 9);
+ addCategory(48, "Overhauls", MakeVector(2, 24, 79), 9);
+ addCategory(49, "Perks", MakeVector(1, 27), 9);
+ addCategory(54, "Radio", MakeVector(1, 31), 9);
+ addCategory(55, "Shouts", MakeVector(1, 104), 9);
+ addCategory(22, "Skills & Levelling", MakeVector(2, 46, 73), 9);
+ addCategory(58, "Weather & Lighting", MakeVector(1, 56), 9);
+ addCategory(44, "Equipment", MakeVector(1, 44), 43);
+ addCategory(45, "Home/Settlement", MakeVector(1, 45), 43);
+ addCategory(10, "Body, Face, & Hair", MakeVector(2, 17, 26), 0);
+ addCategory(39, "Tattoos", MakeVector(1, 57), 10);
+ addCategory(40, "Character Presets", MakeVector(1, 58), 0);
+ addCategory(11, "Items", MakeVector(2, 27, 85), 0);
+ addCategory(32, "Mercantile", MakeVector(2, 23, 69), 0);
+ addCategory(37, "Ammo", MakeVector(1, 3), 11);
+ addCategory(19, "Weapons", MakeVector(2, 41, 55), 11);
+ addCategory(36, "Weapon & Armour Sets", MakeVector(1, 42), 11);
+ addCategory(23, "Player Homes", MakeVector(2, 28, 67), 0);
+ addCategory(25, "Castles & Mansions", MakeVector(1, 68), 23);
+ addCategory(51, "Settlements", MakeVector(1, 48), 23);
+ addCategory(12, "Locations", MakeVector(10, 20, 21, 22, 30, 47, 70, 88, 89, 90, 91), 0);
+ addCategory(4, "Cities", MakeVector(1, 53), 12);
+ addCategory(31, "Landscape Changes", MakeVector(1, 58), 0);
+ addCategory(29, "Environment", MakeVector(2, 14, 74), 0);
+ addCategory(30, "Immersion", MakeVector(2, 51, 78), 0);
+ addCategory(20, "Magic", MakeVector(3, 75, 93, 94), 0);
+ addCategory(21, "Models & Textures", MakeVector(2, 19, 29), 0);
+ addCategory(33, "Modders resources", MakeVector(2, 18, 82), 0);
+ addCategory(13, "NPCs", MakeVector(3, 22, 33, 99), 0);
+ addCategory(24, "Bugfixes", MakeVector(2, 6, 95), 0);
+ addCategory(14, "Patches", MakeVector(2, 25, 84), 24);
+ addCategory(35, "Utilities", MakeVector(2, 38, 39), 0);
+ addCategory(26, "Cheats", MakeVector(1, 8), 0);
+ addCategory(15, "Quests", MakeVector(2, 30, 35), 0);
+ addCategory(16, "Races & Classes", MakeVector(1, 34), 0);
+ addCategory(34, "Stealth", MakeVector(1, 76), 0);
+ addCategory(17, "UI", MakeVector(2, 37, 42), 0);
+ addCategory(18, "Visuals", MakeVector(2, 40, 62), 0);
+ addCategory(50, "Pip-Boy", MakeVector(1, 52), 18);
+ addCategory(46, "Shader Presets", MakeVector(3, 13, 97, 105), 0);
+ addCategory(47, "Miscellaneous", MakeVector(2, 2, 28), 0);
}
+int CategoryFactory::getParentID(unsigned int index) const {
+ if (index >= m_Categories.size()) {
+ throw MyException(QObject::tr("invalid index %1").arg(index));
+ }
-bool CategoryFactory::categoryExists(int id) const
-{
- return m_IDMap.find(id) != m_IDMap.end();
+ return m_Categories[index].m_ParentID;
}
-
-bool CategoryFactory::isDecendantOf(int id, int parentID) const
-{
- std::map