mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1439347def | ||
|
|
a9a51f5085 | ||
|
|
2aae65d6f6 |
+12
-10
@@ -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
|
||||
|
||||
+9
-14
@@ -693,19 +693,14 @@ void DownloadManager::queryInfo(int index)
|
||||
QString ignore;
|
||||
NexusInterface::interpretNexusFileName(fileName, ignore, info->m_FileInfo->modID, true);
|
||||
if (info->m_FileInfo->modID < 0) {
|
||||
QString modIDString;
|
||||
while (modIDString.isEmpty()) {
|
||||
modIDString = QInputDialog::getText(nullptr, tr("Please enter the nexus mod id"), tr("Mod ID:"), QLineEdit::Normal,
|
||||
QString(), nullptr, 0, Qt::ImhFormattedNumbersOnly);
|
||||
if (modIDString.isNull()) {
|
||||
// canceled
|
||||
return;
|
||||
} else if (modIDString.contains(QRegExp("[^0-9]"))) {
|
||||
qDebug("illegal character in mod-id");
|
||||
modIDString.clear();
|
||||
}
|
||||
}
|
||||
info->m_FileInfo->modID = modIDString.toInt(nullptr, 10);
|
||||
bool ok = false;
|
||||
int modId = QInputDialog::getInt(
|
||||
nullptr, tr("Please enter the nexus mod id"), tr("Mod ID:"), 1, 1,
|
||||
std::numeric_limits<int>::max(), 1, &ok);
|
||||
// careful now: while the dialog was displayed, events were processed.
|
||||
// the download list might have changed and our info-ptr invalidated.
|
||||
m_ActiveDownloads[index]->m_FileInfo->modID = modId;
|
||||
return;
|
||||
}
|
||||
}
|
||||
info->m_ReQueried = true;
|
||||
@@ -1247,7 +1242,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->getGameShortName()).arg(modID).arg(fileID));
|
||||
addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(m_ManagedGame->gameShortName()).arg(modID).arg(fileID));
|
||||
return newID;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "instancemanager.h"
|
||||
#include "selectiondialog.h"
|
||||
#include <utility.h>
|
||||
#include <appconfig.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
+64
-56
@@ -26,37 +26,33 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QDateTime>
|
||||
#include <Windows.h>
|
||||
|
||||
|
||||
using MOBase::reportError;
|
||||
|
||||
QScopedPointer<LogBuffer> 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);
|
||||
}
|
||||
|
||||
+162
-163
@@ -45,6 +45,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "moapplication.h"
|
||||
#include "tutorialmanager.h"
|
||||
#include "nxmaccessmanager.h"
|
||||
#include "instancemanager.h"
|
||||
|
||||
#include <eh.h>
|
||||
#include <windows_error.h>
|
||||
|
||||
@@ -84,6 +86,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
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()));
|
||||
qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(
|
||||
QCoreApplication::applicationDirPath())));
|
||||
|
||||
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;
|
||||
}
|
||||
boost::scoped_array<TCHAR> 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);
|
||||
|
||||
QString dataPath = application.property("dataPath").toString();
|
||||
qDebug("data path: %s", qPrintable(dataPath));
|
||||
|
||||
if (!bootstrap()) {
|
||||
reportError("failed to set up data path");
|
||||
return 1;
|
||||
}
|
||||
|
||||
QStringList arguments = application.arguments();
|
||||
|
||||
try {
|
||||
if (!bootstrap()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
|
||||
|
||||
#if QT_VERSION >= 0x050000 && !defined(QT_NO_SSL)
|
||||
qDebug("ssl support: %d", QSslSocket::supportsSsl());
|
||||
#endif
|
||||
|
||||
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<TCHAR> 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);
|
||||
}
|
||||
|
||||
+17
-9
@@ -74,6 +74,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <taskprogressmanager.h>
|
||||
#include <util.h>
|
||||
#include <scopeguard.h>
|
||||
#include <usvfs.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QInputDialog>
|
||||
@@ -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("<Manage...>"));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+3
-4
@@ -26,7 +26,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QTreeWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QProcess>
|
||||
#include <QThread>
|
||||
#include <QProgressBar>
|
||||
#include <QTranslator>
|
||||
#include <QPluginLoader>
|
||||
@@ -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<QString> m_ModNameList; // the mod-list to go with the directory structure
|
||||
|
||||
@@ -193,7 +193,7 @@ void NexusInterface::loginCompleted()
|
||||
void NexusInterface::interpretNexusFileName(const QString &fileName, QString &modName, int &modID, bool query)
|
||||
{
|
||||
//Look for something along the lines of modulename-Vn-m + any old rubbish.
|
||||
static std::regex exp("^([a-zA-Z0-9_'\"\\- ]*?)([-_ ][VvRr]?[0-9_]+)?-([1-9][0-9]+).*");
|
||||
static std::regex exp("^([a-zA-Z0-9_'\"\\-.() ]*?)([-_ ][VvRr]?[0-9_]+)?-([1-9][0-9]+).*\.(zip|rar|7z)");
|
||||
static std::regex simpleexp("^([a-zA-Z0-9_]+)");
|
||||
|
||||
QByteArray fileNameUTF8 = fileName.toUtf8();
|
||||
|
||||
+10
-12
@@ -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<Mapping> OrganizerCore::fileMapping()
|
||||
|
||||
int overwriteId = m_DirectoryStructure->getOriginByName(L"Overwrite").getID();
|
||||
|
||||
const IPluginGame *game = qApp->property("managed_game").value<const IPluginGame *>();
|
||||
IPluginGame *game = qApp->property("managed_game").value<IPluginGame *>();
|
||||
MappingType result = fileMapping(
|
||||
QDir::toNativeSeparators(game->dataDirectory().absolutePath()),
|
||||
"\\",
|
||||
|
||||
@@ -201,6 +201,8 @@ signals:
|
||||
|
||||
void managedGameChanged(MOBase::IPluginGame const *gamePlugin);
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
||||
void storeSettings();
|
||||
|
||||
+4
-3
@@ -22,6 +22,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "windows_error.h"
|
||||
#include "modinfo.h"
|
||||
#include "safewritefile.h"
|
||||
#include "settings.h"
|
||||
#include <utility.h>
|
||||
#include <util.h>
|
||||
#include <error_report.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "profileinputdialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "settings.h"
|
||||
#include <iplugingame.h>
|
||||
#include <bsainvalidation.h>
|
||||
#include <appconfig.h>
|
||||
@@ -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<QListWidget*>("profilesList");
|
||||
|
||||
@@ -187,8 +188,7 @@ void ProfilesDialog::on_removeProfileButton_clicked()
|
||||
Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value<Profile::Ptr>();
|
||||
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. "
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -53,6 +53,8 @@ public:
|
||||
QVariant getChoiceData();
|
||||
QString getChoiceString();
|
||||
|
||||
void disableCancel();
|
||||
|
||||
private slots:
|
||||
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
||||
+1
-1
@@ -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()));
|
||||
}
|
||||
|
||||
+162
-118
@@ -125,7 +125,7 @@ void Settings::registerPlugin(IPlugin *plugin)
|
||||
m_Plugins.push_back(plugin);
|
||||
m_PluginSettings.insert(plugin->name(), QMap<QString, QVariant>());
|
||||
m_PluginDescriptions.insert(plugin->name(), QMap<QString, QVariant>());
|
||||
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<QString, int> Settings::getPreferredServers()
|
||||
std::map<QString, int> 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<ServerInfo> &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<ServerInfo> &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<std::unique_ptr<SettingsTab>> tabs;
|
||||
|
||||
tabs.push_back(std::unique_ptr<SettingsTab>(new GeneralTab(this, dialog)));
|
||||
tabs.push_back(std::unique_ptr<SettingsTab>(new PathsTab(this, dialog)));
|
||||
tabs.push_back(std::unique_ptr<SettingsTab>(new NexusTab(this, dialog)));
|
||||
tabs.push_back(std::unique_ptr<SettingsTab>(new SteamTab(this, dialog)));
|
||||
tabs.push_back(std::unique_ptr<SettingsTab>(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<QComboBox*>("languageBox")),
|
||||
m_styleBox(m_dialog.findChild<QComboBox*>("styleBox")),
|
||||
m_logLevelBox(m_dialog.findChild<QComboBox*>("logLevelBox")),
|
||||
m_downloadDirEdit(m_dialog.findChild<QLineEdit*>("downloadDirEdit")),
|
||||
m_modDirEdit(m_dialog.findChild<QLineEdit*>("modDirEdit")),
|
||||
m_cacheDirEdit(m_dialog.findChild<QLineEdit*>("cacheDirEdit")),
|
||||
m_compactBox(m_dialog.findChild<QCheckBox*>("compactBox")),
|
||||
m_showMetaBox(m_dialog.findChild<QCheckBox*>("showMetaBox"))
|
||||
Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog)
|
||||
: Settings::SettingsTab(m_parent, m_dialog)
|
||||
, m_languageBox(m_dialog.findChild<QComboBox *>("languageBox"))
|
||||
, m_styleBox(m_dialog.findChild<QComboBox *>("styleBox"))
|
||||
, m_logLevelBox(m_dialog.findChild<QComboBox *>("logLevelBox"))
|
||||
, m_compactBox(m_dialog.findChild<QCheckBox *>("compactBox"))
|
||||
, m_showMetaBox(m_dialog.findChild<QCheckBox *>("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));
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
if (currentID != -1) {
|
||||
m_languageBox->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());
|
||||
// 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_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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked());
|
||||
m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked());
|
||||
}
|
||||
|
||||
Settings::NexusTab::NexusTab(Settings *m_parent, SettingsDialog &m_dialog) :
|
||||
Settings::SettingsTab(m_parent, m_dialog),
|
||||
m_loginCheckBox(m_dialog.findChild<QCheckBox*>("loginCheckBox")),
|
||||
m_usernameEdit(m_dialog.findChild<QLineEdit*>("usernameEdit")),
|
||||
m_passwordEdit(m_dialog.findChild<QLineEdit*>("passwordEdit")),
|
||||
m_offlineBox(m_dialog.findChild<QCheckBox*>("offlineBox")),
|
||||
m_proxyBox(m_dialog.findChild<QCheckBox*>("proxyBox")),
|
||||
m_knownServersList(m_dialog.findChild<QListWidget*>("knownServersList")),
|
||||
m_preferredServersList(m_dialog.findChild<QListWidget*>("preferredServersList"))
|
||||
Settings::PathsTab::PathsTab(Settings *parent, SettingsDialog &dialog)
|
||||
: SettingsTab(parent, dialog)
|
||||
, m_downloadDirEdit(m_dialog.findChild<QLineEdit *>("downloadDirEdit"))
|
||||
, m_modDirEdit(m_dialog.findChild<QLineEdit *>("modDirEdit"))
|
||||
, m_cacheDirEdit(m_dialog.findChild<QLineEdit *>("cacheDirEdit"))
|
||||
, m_profilesDirEdit(m_dialog.findChild<QLineEdit *>("profilesDirEdit"))
|
||||
{
|
||||
if (m_parent->automaticLoginEnabled()) {
|
||||
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_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)
|
||||
: Settings::SettingsTab(parent, dialog)
|
||||
, m_loginCheckBox(dialog.findChild<QCheckBox *>("loginCheckBox"))
|
||||
, m_usernameEdit(dialog.findChild<QLineEdit *>("usernameEdit"))
|
||||
, m_passwordEdit(dialog.findChild<QLineEdit *>("passwordEdit"))
|
||||
, m_offlineBox(dialog.findChild<QCheckBox *>("offlineBox"))
|
||||
, m_proxyBox(dialog.findChild<QCheckBox *>("proxyBox"))
|
||||
, m_knownServersList(dialog.findChild<QListWidget *>("knownServersList"))
|
||||
, m_preferredServersList(
|
||||
dialog.findChild<QListWidget *>("preferredServersList"))
|
||||
{
|
||||
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<QLineEdit*>("steamUserEdit")),
|
||||
m_steamPassEdit(m_dialog.findChild<QLineEdit*>("steamPassEdit"))
|
||||
Settings::SteamTab::SteamTab(Settings *m_parent, SettingsDialog &m_dialog)
|
||||
: Settings::SettingsTab(m_parent, m_dialog)
|
||||
, m_steamUserEdit(m_dialog.findChild<QLineEdit *>("steamUserEdit"))
|
||||
, m_steamPassEdit(m_dialog.findChild<QLineEdit *>("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<QListWidget*>("pluginsList")),
|
||||
m_pluginBlacklistList(m_dialog.findChild<QListWidget*>("pluginBlacklist"))
|
||||
Settings::PluginsTab::PluginsTab(Settings *m_parent, SettingsDialog &m_dialog)
|
||||
: Settings::SettingsTab(m_parent, m_dialog)
|
||||
, m_pluginsList(m_dialog.findChild<QListWidget *>("pluginsList"))
|
||||
, m_pluginBlacklistList(m_dialog.findChild<QListWidget *>("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<QLineEdit*>("appIDEdit")),
|
||||
m_mechanismBox(m_dialog.findChild<QComboBox*>("mechanismBox")),
|
||||
m_nmmVersionEdit(m_dialog.findChild<QLineEdit*>("nmmVersionEdit")),
|
||||
m_hideUncheckedBox(m_dialog.findChild<QCheckBox*>("hideUncheckedBox")),
|
||||
m_forceEnableBox(m_dialog.findChild<QCheckBox*>("forceEnableBox")),
|
||||
m_displayForeignBox(m_dialog.findChild<QCheckBox*>("displayForeignBox"))
|
||||
Settings::WorkaroundsTab::WorkaroundsTab(Settings *m_parent,
|
||||
SettingsDialog &m_dialog)
|
||||
: Settings::SettingsTab(m_parent, m_dialog)
|
||||
, m_appIDEdit(m_dialog.findChild<QLineEdit *>("appIDEdit"))
|
||||
, m_mechanismBox(m_dialog.findChild<QComboBox *>("mechanismBox"))
|
||||
, m_nmmVersionEdit(m_dialog.findChild<QLineEdit *>("nmmVersionEdit"))
|
||||
, m_hideUncheckedBox(m_dialog.findChild<QCheckBox *>("hideUncheckedBox"))
|
||||
, m_forceEnableBox(m_dialog.findChild<QCheckBox *>("forceEnableBox"))
|
||||
, m_displayForeignBox(m_dialog.findChild<QCheckBox *>("displayForeignBox"))
|
||||
{
|
||||
m_appIDEdit->setText(m_parent->getSteamAppID());
|
||||
|
||||
|
||||
+18
-2
@@ -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 */
|
||||
|
||||
+20
-4
@@ -25,6 +25,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "noeditdelegate.h"
|
||||
#include "iplugingame.h"
|
||||
#include "settings.h"
|
||||
#include "instancemanager.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFileDialog>
|
||||
@@ -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<IPlugin*> &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 *>();
|
||||
IPluginGame const *game
|
||||
= qApp->property("managed_game").value<IPluginGame *>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user