From 4ff751fb7e592376de5faab44ab7dd6fe70dbdd0 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Thu, 19 Nov 2015 19:09:34 +0100
Subject: some fixes/disabled code required since hook.dll is gone
---
src/main.cpp | 14 --------------
1 file changed, 14 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 773bfc16..07d6fa19 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -131,19 +131,6 @@ bool bootstrap()
createAndMakeWritable(AppConfig::overwritePath());
createAndMakeWritable(AppConfig::logPath());
- // verify the hook-dll exists
- QString dllName = qApp->applicationDirPath() + "/" + ToQString(AppConfig::hookDLLName());
-
- if (::GetModuleHandleW(ToWString(dllName).c_str()) != nullptr) {
- throw std::runtime_error("hook.dll already loaded! You can't start Mod Organizer from within itself (not even indirectly)");
- }
-
- HMODULE dllMod = ::LoadLibraryW(ToWString(dllName).c_str());
- if (dllMod == nullptr) {
- throw windows_error("hook.dll is missing or invalid");
- }
- ::FreeLibrary(dllMod);
-
return true;
}
@@ -516,7 +503,6 @@ 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(gamePath)));
--
cgit v1.3.1
From fe8c3aaea58400425b9195bb670a1b4e8c9db10d Mon Sep 17 00:00:00 2001
From: Tannin
Date: Mon, 23 Nov 2015 21:44:47 +0100
Subject: some fixes and removed obsolete code
---
src/main.cpp | 2 +-
src/mainwindow.cpp | 184 ++-----------------------------------------------
src/mainwindow.h | 5 --
src/mainwindow.ui | 101 ---------------------------
src/usvfsconnector.cpp | 8 ++-
5 files changed, 12 insertions(+), 288 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 07d6fa19..7061a6e3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -123,7 +123,7 @@ bool bootstrap()
// cycle logfile
removeOldFiles(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()),
- "ModOrganizer*.log", 5, QDir::Name);
+ "usvfs*.log", 5, QDir::Name);
createAndMakeWritable(AppConfig::profilesPath());
createAndMakeWritable(AppConfig::modsPath());
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index e34d8b03..71013c3c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -186,6 +186,7 @@ MainWindow::MainWindow(const QString &exeName
m_RefreshProgress->setVisible(false);
statusBar()->addWidget(m_RefreshProgress, 1000);
statusBar()->clearMessage();
+ statusBar()->hide();
ui->actionEndorseMO->setVisible(false);
@@ -233,8 +234,6 @@ MainWindow::MainWindow(const QString &exeName
}
ui->espList->installEventFilter(m_OrganizerCore.pluginList());
- ui->bsaList->setLocalMoveOnly(true);
-
ui->splitter->setStretchFactor(0, 3);
ui->splitter->setStretchFactor(1, 2);
@@ -302,9 +301,6 @@ MainWindow::MainWindow(const QString &exeName
connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString)));
- m_CheckBSATimer.setSingleShot(true);
- connect(&m_CheckBSATimer, SIGNAL(timeout()), this, SLOT(checkBSAList()));
-
m_UpdateProblemsTimer.setSingleShot(true);
connect(&m_UpdateProblemsTimer, SIGNAL(timeout()), this, SLOT(updateProblemsButton()));
@@ -1317,157 +1313,6 @@ static QStringList toStringList(InputIterator current, InputIterator end)
return result;
}
-void MainWindow::updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives)
-{
- m_DefaultArchives = defaultArchives;
- ui->bsaList->clear();
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
- ui->bsaList->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
-#else
- ui->bsaList->header()->setResizeMode(QHeaderView::ResizeToContents);
-#endif
-
- std::vector> items;
-
- IPluginGame *gamePlugin = qApp->property("managed_game").value();
- BSAInvalidation *invalidation = gamePlugin->feature();
- std::vector files = m_OrganizerCore.directoryStructure()->getFiles();
-
- QStringList plugins = m_OrganizerCore.findFiles("", [] (const QString &fileName) -> bool {
- return fileName.endsWith(".esp", Qt::CaseInsensitive)
- || fileName.endsWith(".esm", Qt::CaseInsensitive);
- });
-
- auto hasAssociatedPlugin = [&](const QString &bsaName) -> bool {
- for (const QString &pluginName : plugins) {
- QFileInfo pluginInfo(pluginName);
- if (bsaName.startsWith(QFileInfo(pluginName).baseName(), Qt::CaseInsensitive)
- && (m_OrganizerCore.pluginList()->state(pluginInfo.fileName()) == IPluginList::STATE_ACTIVE)) {
- return true;
- }
- }
- return false;
- };
-
- for (FileEntry::Ptr current : files) {
- QFileInfo fileInfo(ToQString(current->getName().c_str()));
-
- if (fileInfo.suffix().toLower() == "bsa") {
- int index = activeArchives.indexOf(fileInfo.fileName());
- if (index == -1) {
- index = 0xFFFF;
- } else {
- index += 2;
- }
-
- if ((invalidation != nullptr) && invalidation->isInvalidationBSA(fileInfo.fileName())) {
- index = 1;
- }
-
- int originId = current->getOrigin();
- FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByID(originId);
-
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList()
- << fileInfo.fileName()
- << ToQString(origin.getName()));
- newItem->setData(0, Qt::UserRole, index);
- newItem->setData(1, Qt::UserRole, originId);
- newItem->setFlags(newItem->flags() & ~Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable);
- newItem->setCheckState(0, (index != -1) ? Qt::Checked : Qt::Unchecked);
- newItem->setData(0, Qt::UserRole, false);
- if (m_OrganizerCore.settings().forceEnableCoreFiles()
- && defaultArchives.contains(fileInfo.fileName())) {
- newItem->setCheckState(0, Qt::Checked);
- newItem->setDisabled(true);
- newItem->setData(0, Qt::UserRole, true);
- } else if (fileInfo.fileName().compare("update.bsa", Qt::CaseInsensitive) == 0) {
- newItem->setCheckState(0, Qt::Checked);
- newItem->setDisabled(true);
- } else if (hasAssociatedPlugin(fileInfo.fileName())) {
- newItem->setCheckState(0, Qt::Checked);
- newItem->setDisabled(true);
- }
-
- if (index < 0) index = 0;
-
- UINT32 sortValue = ((origin.getPriority() & 0xFFFF) << 16) | (index & 0xFFFF);
- items.push_back(std::make_pair(sortValue, newItem));
- }
- }
-
- std::sort(items.begin(), items.end(), BySortValue);
-
- for (auto iter = items.begin(); iter != items.end(); ++iter) {
- int originID = iter->second->data(1, Qt::UserRole).toInt();
-
- FilesOrigin origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID);
- QString modName("data");
- unsigned int modIndex = ModInfo::getIndex(ToQString(origin.getName()));
- if (modIndex != UINT_MAX) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
- modName = modInfo->name();
- }
- QList items = ui->bsaList->findItems(modName, Qt::MatchFixedString);
- QTreeWidgetItem *subItem = nullptr;
- if (items.length() > 0) {
- subItem = items.at(0);
- } else {
- subItem = new QTreeWidgetItem(QStringList(modName));
- subItem->setFlags(subItem->flags() & ~Qt::ItemIsDragEnabled);
- ui->bsaList->addTopLevelItem(subItem);
- }
- subItem->addChild(iter->second);
- subItem->setExpanded(true);
- }
-
- checkBSAList();
-}
-
-
-void MainWindow::checkBSAList()
-{
- DataArchives *archives = m_OrganizerCore.managedGame()->feature();
-
- if (archives != nullptr) {
- ui->bsaList->blockSignals(true);
- ON_BLOCK_EXIT([&] () { ui->bsaList->blockSignals(false); });
-
- QStringList defaultArchives = archives->archives(m_OrganizerCore.currentProfile());
-
- bool warning = false;
-
- for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
- bool modWarning = false;
- QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i);
- for (int j = 0; j < tlItem->childCount(); ++j) {
- QTreeWidgetItem *item = tlItem->child(j);
- QString filename = item->text(0);
- item->setIcon(0, QIcon());
- item->setToolTip(0, QString());
-
- if (item->checkState(0) == Qt::Unchecked) {
- if (defaultArchives.contains(filename)) {
- item->setIcon(0, QIcon(":/MO/gui/warning"));
- item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!"));
- modWarning = true;
- }
- }
- }
- if (modWarning) {
- ui->bsaList->expandItem(ui->bsaList->topLevelItem(i));
- warning = true;
- }
- }
-
- if (warning) {
- ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/warning"));
- } else {
- ui->tabWidget->setTabIcon(1, QIcon());
- }
- }
-}
-
-
void MainWindow::saveModMetas()
{
for (unsigned int i = 0; i < ModInfo::getNumMods(); ++i) {
@@ -1476,7 +1321,6 @@ void MainWindow::saveModMetas()
}
}
-
void MainWindow::fixCategories()
{
for (unsigned int i = 0; i < ModInfo::getNumMods(); ++i) {
@@ -1856,8 +1700,10 @@ void MainWindow::setESPListSorting(int index)
void MainWindow::refresher_progress(int percent)
{
if (percent == 100) {
-// m_RefreshProgress->setVisible(false);
+ m_RefreshProgress->setVisible(false);
+ statusBar()->hide();
} else if (!m_RefreshProgress->isVisible()) {
+ statusBar()->show();
m_RefreshProgress->setVisible(true);
m_RefreshProgress->setRange(0, 100);
m_RefreshProgress->setValue(percent);
@@ -3815,8 +3661,7 @@ void MainWindow::updateDownloadListDelegate()
void MainWindow::modDetailsUpdated(bool)
{
- --m_ModsToUpdate;
- if (m_ModsToUpdate == 0) {
+ if (--m_ModsToUpdate == 0) {
statusBar()->hide();
m_ModListSortProxy->setCategoryFilter(boost::assign::list_of(CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE));
for (int i = 0; i < ui->categoriesList->topLevelItemCount(); ++i) {
@@ -4022,19 +3867,6 @@ void MainWindow::displayColumnSelection(const QPoint &pos)
}
}
-
-void MainWindow::on_bsaList_customContextMenuRequested(const QPoint &pos)
-{
- m_ContextItem = ui->bsaList->itemAt(pos);
-
-// m_ContextRow = ui->bsaList->indexOfTopLevelItem(ui->bsaList->itemAt(pos));
-
- QMenu menu;
- menu.addAction(tr("Extract..."), this, SLOT(extractBSATriggered()));
-
- menu.exec(ui->bsaList->mapToGlobal(pos));
-}
-
void MainWindow::on_actionProblems_triggered()
{
ProblemsDialog problems(m_PluginContainer.plugins(), this);
@@ -4610,12 +4442,6 @@ void MainWindow::on_categoriesOrBtn_toggled(bool checked)
}
}
-void MainWindow::on_managedArchiveLabel_linkHovered(const QString&)
-{
- QToolTip::showText(QCursor::pos(),
- ui->managedArchiveLabel->toolTip());
-}
-
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
//Accept copy or move drags to the download window. Link drags are not
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 279c8922..44f46f4b 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -88,7 +88,6 @@ public:
virtual bool unlockClicked() override;
bool addProfile();
- void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives);
void refreshDataTree();
void refreshSaveList();
@@ -439,8 +438,6 @@ private slots:
void startExeAction();
- void checkBSAList();
-
void updateProblemsButton();
void saveModMetas();
@@ -494,7 +491,6 @@ private slots: // ui slots
void on_actionUpdate_triggered();
void on_actionEndorseMO_triggered();
- void on_bsaList_customContextMenuRequested(const QPoint &pos);
void on_btnRefreshData_clicked();
void on_categoriesList_customContextMenuRequested(const QPoint &pos);
void on_conflictsCheckBox_toggled(bool checked);
@@ -522,7 +518,6 @@ private slots: // ui slots
void on_actionCopy_Log_to_Clipboard_triggered();
void on_categoriesAndBtn_toggled(bool checked);
void on_categoriesOrBtn_toggled(bool checked);
- void on_managedArchiveLabel_linkHovered(const QString &link);
};
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 7d7eeca8..02319bee 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -884,102 +884,6 @@ p, li { white-space: pre-wrap; }
-
-
- Archives
-
-
-
- 6
-
-
- 6
-
-
- 6
-
-
- 6
-
- -
-
-
-
-
-
- <html><head/><body><p>BSAs are bundles of game assets (textures, scripts, ...). By default, the engine loads these bundles in a separate step from loose files. MO can manage those archives to align their load order with that of loose files:</p><p>If archives are <span style=" font-weight:600;">managed</span>, their load order is specified by the priority of the corresponding mod (left pane), the same as the loose files. You can manually enable any BSA that has no corresponding plugin active.<br/></p><p>If archives are <span style=" font-weight:600;">not managed</span> their load order is specified by the priority of the corresponding plugin (right pane, plugins tab). You can then not manually enable BSAs where the plugin isn't active.</p><p>In either case you can not disable archives if there is a matching plugin, the game will load them no matter what.</p></body></html>
-
-
- <html><head/><body><p>Archive order follows Plugin order.</p></body></html>
-
-
- true
-
-
-
-
-
- -
-
-
- Qt::CustomContextMenu
-
-
- List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order.
-
-
- BSA files are archives (comparable to .zip files) that contain data assets (meshes, textures, ...) to be used by the game. As such they "compete" with loose files in your data directory over which is loaded.
-By default, BSAs that share their base name with an enabled ESP (i.e. plugin.esp and plugin.bsa) are automatically loaded and will have precedence over all loose files, the installation order you set up to the left is then ignored!
-
-BSAs checked here are loaded in such a way that your installation order is obeyed properly.
-
-
- QAbstractItemView::NoEditTriggers
-
-
- true
-
-
- false
-
-
- false
-
-
- QAbstractItemView::DragDrop
-
-
- Qt::MoveAction
-
-
- QAbstractItemView::SingleSelection
-
-
- QAbstractItemView::SelectRows
-
-
- 20
-
-
- true
-
-
- 1
-
-
- false
-
-
- 200
-
-
-
- File
-
-
-
-
-
-
Data
@@ -1477,11 +1381,6 @@ Right now this has very limited functionality
QTreeView
-
- MOBase::SortableTreeWidget
- QTreeWidget
-
-
diff --git a/src/usvfsconnector.cpp b/src/usvfsconnector.cpp
index 62145475..a29d806e 100644
--- a/src/usvfsconnector.cpp
+++ b/src/usvfsconnector.cpp
@@ -22,6 +22,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
@@ -53,10 +54,13 @@ extern "C" DLLEXPORT void __cdecl InitHooks(LPVOID userData, size_t userDataSize
LogWorker::LogWorker()
: m_Buffer(1024, '\0')
, m_QuitRequested(false)
- , m_LogFile(qApp->property("dataPath").toString() + "/logs/usvfs.log")
+ , m_LogFile(qApp->property("dataPath").toString()
+ + QString("/logs/usvfs-%1.log").arg(
+ QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd_hh-mm-ss")))
{
m_LogFile.open(QIODevice::WriteOnly);
- qDebug("usvfs log messages are written to %s", qPrintable(m_LogFile.fileName()));
+ qDebug("usvfs log messages are written to %s",
+ qPrintable(m_LogFile.fileName()));
}
LogWorker::~LogWorker()
--
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/main.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 53d978974040c34f6818e03e6dbf0d8d6f8acb3f Mon Sep 17 00:00:00 2001
From: Tannin
Date: Wed, 2 Mar 2016 21:20:38 +0100
Subject: updated icon and splash screen. MO can now use custom instance
specific splash screens and splashes stored in game plugins
---
src/main.cpp | 24 ++++++++++++++++++++----
src/mo_icon.ico | Bin 96367 -> 45874 bytes
src/mo_icon.psd | Bin 979131 -> 0 bytes
src/splash.png | Bin 273418 -> 74041 bytes
4 files changed, 20 insertions(+), 4 deletions(-)
delete mode 100644 src/mo_icon.psd
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index a262d031..eb3a7248 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -434,11 +434,11 @@ void setupPath()
::SetEnvironmentVariableW(L"PATH", newPath.c_str());
}
-
-int runApplication(MOApplication &application, SingleInstance &instance)
+int runApplication(MOApplication &application, SingleInstance &instance,
+ const QString &splashPath)
{
qDebug("start main application");
- QPixmap pixmap(":/MO/gui/splash");
+ QPixmap pixmap(splashPath);
QSplashScreen splash(pixmap);
QString dataPath = application.property("dataPath").toString();
@@ -474,6 +474,17 @@ int runApplication(MOApplication &application, SingleInstance &instance)
if (game == nullptr) {
return 1;
}
+ if (splashPath.startsWith(':')) {
+ // currently using MO splash, see if the plugin contains one
+ QString pluginSplash
+ = QString(":/%1/splash").arg(game->gameShortName());
+ QImage image(pluginSplash);
+ if (!image.isNull()) {
+ image.save(dataPath + "/splash.png");
+ } else {
+ qDebug("no plugin splash");
+ }
+ }
organizer.setManagedGame(game);
organizer.createDefaultProfile();
@@ -630,7 +641,12 @@ int main(int argc, char *argv[])
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
- int result = runApplication(application, instance);
+ QString splash = dataPath + "/splash.png";
+ if (!QFile::exists(dataPath + "/splash.png")) {
+ splash = ":/MO/gui/splash";
+ }
+
+ int result = runApplication(application, instance, splash);
if (result != INT_MAX) {
return result;
diff --git a/src/mo_icon.ico b/src/mo_icon.ico
index 59da6c2d..ba54d4dc 100644
Binary files a/src/mo_icon.ico and b/src/mo_icon.ico differ
diff --git a/src/mo_icon.psd b/src/mo_icon.psd
deleted file mode 100644
index 1f7b40c9..00000000
Binary files a/src/mo_icon.psd and /dev/null differ
diff --git a/src/splash.png b/src/splash.png
index 4f1f1a3d..d29a6711 100644
Binary files a/src/splash.png and b/src/splash.png differ
--
cgit v1.3.1
From eb97c46ed68a965d6ddf44fa6741fa929fd7d278 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Sat, 7 May 2016 00:03:38 +0200
Subject: cleanup
---
src/CMakeLists.txt | 12 ++++-
src/aboutdialog.cpp | 5 ++-
src/aboutdialog.ui | 50 +++++++++++++++++++--
src/categories.cpp | 2 +-
src/directoryrefresher.cpp | 2 +-
src/downloadmanager.cpp | 47 +++++++++----------
src/editexecutablesdialog.cpp | 8 ++--
src/editexecutablesdialog.ui | 4 +-
src/executableslist.h | 3 +-
src/installationmanager.cpp | 3 +-
src/logbuffer.cpp | 22 +++++----
src/main.cpp | 6 +--
src/mainwindow.cpp | 14 +++---
src/mainwindow.ui | 40 +++++++++++------
src/modflagicondelegate.cpp | 6 +--
src/modinfo.cpp | 6 +--
src/modinfodialog.cpp | 10 +++--
src/nexusinterface.cpp | 11 ++---
src/organizercore.cpp | 12 +++--
src/persistentcookiejar.cpp | 2 +-
src/plugincontainer.cpp | 4 +-
src/profile.cpp | 17 +++----
src/profile.h | 2 +-
src/profilesdialog.cpp | 102 ++++++++++++++++++++----------------------
src/profilesdialog.ui | 4 +-
src/shared/util.cpp | 8 +++-
src/usvfsconnector.cpp | 9 +++-
src/version.rc | 4 +-
28 files changed, 248 insertions(+), 167 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 02c63ad2..a8b43c59 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -272,14 +272,22 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src
${project_path}/archive/src
${project_path}/../usvfs/usvfs
${project_path}/game_gamebryo/src
- ${project_path}/game_features/src)
+ ${project_path}/game_features/src
+ ${project_path}/githubpp/src)
INCLUDE_DIRECTORIES(shared ${ZLIB_INCLUDE_DIRS})
LINK_DIRECTORIES(${lib_path}
${project_path}/../zlib/lib)
-ADD_DEFINITIONS(-D_UNICODE -DUNICODE -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
+EXECUTE_PROCESS(
+ COMMAND git log -1 --format=%h
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_VARIABLE GIT_COMMIT_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+ADD_DEFINITIONS(-D_UNICODE -DUNICODE -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -DGITID="${GIT_COMMIT_HASH}")
IF("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
SET(usvfs_name usvfs_x64)
diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp
index 3657a10d..ed57a217 100644
--- a/src/aboutdialog.cpp
+++ b/src/aboutdialog.cpp
@@ -54,10 +54,13 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent)
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));
-#ifdef HGID
+#if defined(HGID)
ui->revisionLabel->setText(ui->revisionLabel->text() + " " + HGID);
+#elif defined(GITID)
+ ui->revisionLabel->setText(ui->revisionLabel->text() + " " + GITID);
#else
ui->revisionLabel->setText(ui->revisionLabel->text() + " unknown");
#endif
diff --git a/src/aboutdialog.ui b/src/aboutdialog.ui
index ea5d2141..8d560f2b 100644
--- a/src/aboutdialog.ui
+++ b/src/aboutdialog.ui
@@ -6,8 +6,8 @@
0
0
- 508
- 335
+ 746
+ 369
@@ -18,13 +18,50 @@
-
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
-
+
+
+ 0
+ 0
+
+
+
+
+ 250
+ 250
+
+
+
+
+ 250
+ 250
+
+
- :/MO/gui/mo_icon.ico
+ :/MO/gui/splash
+
+
+ true
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
@@ -83,7 +120,7 @@
-
- Copyright 2011-2015 Sebastian Herbord
+ Copyright 2011-2016 Sebastian Herbord
@@ -265,6 +302,11 @@
thosrtanner
+ -
+
+ ogrotten
+
+
diff --git a/src/categories.cpp b/src/categories.cpp
index 7539d3fd..50ba5271 100644
--- a/src/categories.cpp
+++ b/src/categories.cpp
@@ -188,7 +188,7 @@ int CategoryFactory::addCategory(const QString &name, const std::vector &ne
void CategoryFactory::addCategory(int id, const QString &name, const std::vector &nexusIDs, int parentID)
{
- int index = m_Categories.size();
+ 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;
diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp
index 4eac4103..0a8b82be 100644
--- a/src/directoryrefresher.cpp
+++ b/src/directoryrefresher.cpp
@@ -159,7 +159,7 @@ void DirectoryRefresher::refresh()
} catch (const std::exception &e) {
emit error(tr("failed to read mod (%1): %2").arg(iter->modName, e.what()));
}
- emit progress((i * 100) / m_Mods.size() + 1);
+ emit progress((i * 100) / static_cast(m_Mods.size()) + 1);
}
emit progress(100);
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index 6b4628cc..b92e171e 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -88,7 +88,8 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con
QString fileName = QFileInfo(filePath).fileName();
if (fileName.endsWith(UNFINISHED)) {
- info->m_FileName = fileName.mid(0, fileName.length() - strlen(UNFINISHED));
+ info->m_FileName = fileName.mid(
+ 0, fileName.length() - static_cast(strlen(UNFINISHED)));
info->m_State = STATE_PAUSED;
} else {
info->m_FileName = fileName;
@@ -471,7 +472,7 @@ void DownloadManager::addNXMDownload(const QString &url)
void DownloadManager::removeFile(int index, bool deleteFile)
{
if (index >= m_ActiveDownloads.size()) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("remove: invalid download index %1").arg(index));
}
DownloadInfo *download = m_ActiveDownloads.at(index);
@@ -538,7 +539,7 @@ void DownloadManager::refreshAlphabeticalTranslation()
void DownloadManager::restoreDownload(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("restore: invalid download index: %1").arg(index));
}
DownloadInfo *download = m_ActiveDownloads.at(index);
@@ -571,7 +572,7 @@ void DownloadManager::removeDownload(int index, bool deleteFile)
}
} else {
if (index >= m_ActiveDownloads.size()) {
- reportError(tr("invalid index %1").arg(index));
+ reportError(tr("remove: invalid download index %1").arg(index));
return;
}
@@ -589,7 +590,7 @@ void DownloadManager::removeDownload(int index, bool deleteFile)
void DownloadManager::cancelDownload(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- reportError(tr("invalid index %1").arg(index));
+ reportError(tr("cancel: invalid download index %1").arg(index));
return;
}
@@ -602,7 +603,7 @@ void DownloadManager::cancelDownload(int index)
void DownloadManager::pauseDownload(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- reportError(tr("invalid index %1").arg(index));
+ reportError(tr("pause: invalid download index %1").arg(index));
return;
}
@@ -622,7 +623,7 @@ void DownloadManager::pauseDownload(int index)
void DownloadManager::resumeDownload(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- reportError(tr("invalid index %1").arg(index));
+ reportError(tr("resume: invalid download index %1").arg(index));
return;
}
DownloadInfo *info = m_ActiveDownloads[index];
@@ -633,7 +634,7 @@ void DownloadManager::resumeDownload(int index)
void DownloadManager::resumeDownloadInt(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- reportError(tr("invalid index %1").arg(index));
+ reportError(tr("resume (int): invalid download index %1").arg(index));
return;
}
DownloadInfo *info = m_ActiveDownloads[index];
@@ -673,7 +674,7 @@ DownloadManager::DownloadInfo *DownloadManager::downloadInfoByID(unsigned int id
void DownloadManager::queryInfo(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- reportError(tr("invalid index %1").arg(index));
+ reportError(tr("query: invalid download index %1").arg(index));
return;
}
DownloadInfo *info = m_ActiveDownloads[index];
@@ -721,7 +722,7 @@ int DownloadManager::numPendingDownloads() const
std::pair DownloadManager::getPendingDownload(int index)
{
if ((index < 0) || (index >= m_PendingDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("get pending: invalid download index %1").arg(index));
}
return m_PendingDownloads.at(index);
@@ -730,7 +731,7 @@ std::pair DownloadManager::getPendingDownload(int index)
QString DownloadManager::getFilePath(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("get path: invalid download index %1").arg(index));
}
return m_OutputDirectory + "/" + m_ActiveDownloads.at(index)->m_FileName;
@@ -751,7 +752,7 @@ QString DownloadManager::getFileTypeString(int fileType)
QString DownloadManager::getDisplayName(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("display name: invalid download index %1").arg(index));
}
DownloadInfo *info = m_ActiveDownloads.at(index);
@@ -768,7 +769,7 @@ QString DownloadManager::getDisplayName(int index) const
QString DownloadManager::getFileName(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("file name: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_FileName;
@@ -777,7 +778,7 @@ QString DownloadManager::getFileName(int index) const
QDateTime DownloadManager::getFileTime(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("file time: invalid download index %1").arg(index));
}
DownloadInfo *info = m_ActiveDownloads.at(index);
@@ -791,7 +792,7 @@ QDateTime DownloadManager::getFileTime(int index) const
qint64 DownloadManager::getFileSize(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("file size: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_TotalSize;
@@ -801,7 +802,7 @@ qint64 DownloadManager::getFileSize(int index) const
int DownloadManager::getProgress(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("progress: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_Progress;
@@ -811,7 +812,7 @@ int DownloadManager::getProgress(int index) const
DownloadManager::DownloadState DownloadManager::getState(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("state: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_State;
@@ -821,7 +822,7 @@ DownloadManager::DownloadState DownloadManager::getState(int index) const
bool DownloadManager::isInfoIncomplete(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("infocomplete: invalid download index %1").arg(index));
}
DownloadInfo *info = m_ActiveDownloads.at(index);
@@ -836,7 +837,7 @@ bool DownloadManager::isInfoIncomplete(int index) const
int DownloadManager::getModID(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("mod id: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_FileInfo->modID;
}
@@ -844,7 +845,7 @@ int DownloadManager::getModID(int index) const
bool DownloadManager::isHidden(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("ishidden: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_Hidden;
}
@@ -853,7 +854,7 @@ bool DownloadManager::isHidden(int index) const
const ModRepositoryFileInfo *DownloadManager::getFileInfo(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("file info: invalid download index %1").arg(index));
}
return m_ActiveDownloads.at(index)->m_FileInfo;
@@ -863,7 +864,7 @@ const ModRepositoryFileInfo *DownloadManager::getFileInfo(int index) const
void DownloadManager::markInstalled(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("mark installed: invalid download index %1").arg(index));
}
DownloadInfo *info = m_ActiveDownloads.at(index);
@@ -878,7 +879,7 @@ void DownloadManager::markInstalled(int index)
void DownloadManager::markUninstalled(int index)
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
- throw MyException(tr("invalid index"));
+ throw MyException(tr("mark uninstalled: invalid download index %1").arg(index));
}
DownloadInfo *info = m_ActiveDownloads.at(index);
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp
index 1b2d5a48..05a7603d 100644
--- a/src/editexecutablesdialog.cpp
+++ b/src/editexecutablesdialog.cpp
@@ -126,15 +126,17 @@ void EditExecutablesDialog::on_addButton_clicked()
void EditExecutablesDialog::on_browseButton_clicked()
{
- QString binaryName = FileDialogMemory::getOpenFileName("editExecutableBinary", this,
- tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat *.jar"));
+ QString binaryName = FileDialogMemory::getOpenFileName(
+ "editExecutableBinary", this, tr("Select a binary"), QString(),
+ tr("Executable (%1)").arg("*.exe *.bat *.jar"));
if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) {
QString binaryPath;
{ // try to find java automatically
std::wstring binaryNameW = ToWString(binaryName);
WCHAR buffer[MAX_PATH];
- if (::FindExecutableW(binaryNameW.c_str(), nullptr, buffer) > (HINSTANCE)32) {
+ if (::FindExecutableW(binaryNameW.c_str(), nullptr, buffer)
+ > reinterpret_cast(32)) {
DWORD binaryType = 0UL;
if (!::GetBinaryTypeW(binaryNameW.c_str(), &binaryType)) {
qDebug("failed to determine binary type of \"%ls\": %lu", binaryNameW.c_str(), ::GetLastError());
diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui
index a2aad19a..2640bb15 100644
--- a/src/editexecutablesdialog.ui
+++ b/src/editexecutablesdialog.ui
@@ -6,8 +6,8 @@
0
0
- 384
- 446
+ 426
+ 460
diff --git a/src/executableslist.h b/src/executableslist.h
index eb7d2d6f..0534c09e 100644
--- a/src/executableslist.h
+++ b/src/executableslist.h
@@ -133,7 +133,8 @@ public:
const QString &steamAppID,
Executable::Flags flags)
{
- updateExecutable(title, executableName, arguments, workingDirectory, steamAppID, Executable::AllFlags, flags);
+ updateExecutable(title, executableName, arguments, workingDirectory,
+ steamAppID, Executable::AllFlags, flags);
}
/**
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index 8ab27124..bf5ee91a 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -346,7 +346,8 @@ DirectoryTree *InstallationManager::createFilesTree()
// to uncheck all files in a directory while keeping the dir checked. Those directories are
// currently not installed.
DirectoryTree::Node *newNode = new DirectoryTree::Node;
- newNode->setData(DirectoryTreeInformation(*componentIter, i));
+ newNode->setData(
+ DirectoryTreeInformation(*componentIter, static_cast(i)));
currentNode->addNode(newNode, false);
currentNode = newNode;
} else {
diff --git a/src/logbuffer.cpp b/src/logbuffer.cpp
index 8207dcbb..522ce3c8 100644
--- a/src/logbuffer.cpp
+++ b/src/logbuffer.cpp
@@ -53,13 +53,15 @@ void LogBuffer::logMessage(QtMsgType type, const QString &message)
if (type >= m_MinMsgType) {
Message msg = {type, QTime::currentTime(), message};
if (m_NumMessages < m_Messages.size()) {
- beginInsertRows(QModelIndex(), m_NumMessages, m_NumMessages + 1);
+ beginInsertRows(QModelIndex(), static_cast(m_NumMessages),
+ static_cast(m_NumMessages) + 1);
}
m_Messages.at(m_NumMessages % m_Messages.size()) = msg;
if (m_NumMessages < m_Messages.size()) {
endInsertRows();
} else {
- emit dataChanged(createIndex(0, 0), createIndex(m_Messages.size(), 0));
+ emit dataChanged(createIndex(0, 0),
+ createIndex(static_cast(m_Messages.size()), 0));
}
++m_NumMessages;
if (type >= QtCriticalMsg) {
@@ -84,9 +86,10 @@ void LogBuffer::write() const
return;
}
- unsigned int i = (m_NumMessages > m_Messages.size())
- ? m_NumMessages - m_Messages.size()
- : 0U;
+ unsigned int i
+ = (m_NumMessages > m_Messages.size())
+ ? static_cast(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");
@@ -165,7 +168,7 @@ int LogBuffer::rowCount(const QModelIndex &parent) const
if (parent.isValid())
return 0;
else
- return std::min(m_NumMessages, m_Messages.size());
+ return static_cast(std::min(m_NumMessages, m_Messages.size()));
}
int LogBuffer::columnCount(const QModelIndex &) const
@@ -175,9 +178,10 @@ int LogBuffer::columnCount(const QModelIndex &) const
QVariant LogBuffer::data(const QModelIndex &index, int role) const
{
- unsigned offset = m_NumMessages < m_Messages.size()
- ? 0
- : m_NumMessages - m_Messages.size();
+ unsigned int offset
+ = m_NumMessages < m_Messages.size()
+ ? 0
+ : static_cast(m_NumMessages - m_Messages.size());
unsigned int msgIndex = (offset + index.row() + 1) % m_Messages.size();
switch (role) {
case Qt::DisplayRole: {
diff --git a/src/main.cpp b/src/main.cpp
index eb3a7248..6db5a50e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -161,9 +161,9 @@ 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";
+ 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! "
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 24391999..e174a17c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -144,15 +144,10 @@ along with Mod Organizer. If not, see .
#include
#include
-#include
+#include
#include
-
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include
-#else
-#include
-#endif
#ifndef Q_MOC_RUN
#include
@@ -4198,7 +4193,12 @@ void MainWindow::on_bossButton_clicked()
HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
HANDLE stdOutRead = INVALID_HANDLE_VALUE;
createStdoutPipe(&stdOutRead, &stdOutWrite);
- m_OrganizerCore.prepareVFS();
+ try {
+ m_OrganizerCore.prepareVFS();
+ } catch (const std::exception &e) {
+ QMessageBox::warning(qApp->activeWindow(), tr("Error"), e.what());
+ return;
+ }
HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"),
parameters.join(" "),
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 7d23cde5..f504994a 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -45,7 +45,10 @@
Categories
-
+
+
+ 0
+
3
@@ -92,25 +95,34 @@
-
-
-
- false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 25
+
- Click blank area to deselect
+ Clear
+
+
+ true
-
-
-
-
-
-
- false
-
-
- false
+
+
+
+ 0
+ 0
+
-
diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp
index d66c3ac5..5c4167ad 100644
--- a/src/modflagicondelegate.cpp
+++ b/src/modflagicondelegate.cpp
@@ -58,7 +58,7 @@ size_t ModFlagIconDelegate::getNumIcons(const QModelIndex &index) const
if (modIdx < ModInfo::getNumMods()) {
ModInfo::Ptr info = ModInfo::getByIndex(modIdx);
std::vector flags = info->getFlags();
- int count = flags.size();
+ size_t count = flags.size();
if (std::find_first_of(flags.begin(), flags.end(), m_ConflictFlags, m_ConflictFlags + 4) == flags.end()) {
++count;
}
@@ -71,11 +71,11 @@ size_t ModFlagIconDelegate::getNumIcons(const QModelIndex &index) const
QSize ModFlagIconDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &modelIndex) const
{
- int count = getNumIcons(modelIndex);
+ size_t count = getNumIcons(modelIndex);
unsigned int index = modelIndex.data(Qt::UserRole + 1).toInt();
QSize result;
if (index < ModInfo::getNumMods()) {
- result = QSize(count * 40, 20);
+ result = QSize(static_cast(count) * 40, 20);
} else {
result = QSize(1, 20);
}
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index 5593b0f0..3c97ca85 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -112,7 +112,7 @@ void ModInfo::createFromOverwrite()
unsigned int ModInfo::getNumMods()
{
QMutexLocker locker(&s_Mutex);
- return s_Collection.size();
+ return static_cast(s_Collection.size());
}
@@ -121,7 +121,7 @@ ModInfo::Ptr ModInfo::getByIndex(unsigned int index)
QMutexLocker locker(&s_Mutex);
if (index >= s_Collection.size()) {
- throw MyException(tr("invalid index %1").arg(index));
+ throw MyException(tr("invalid mod index %1").arg(index));
}
return s_Collection[index];
}
@@ -150,7 +150,7 @@ bool ModInfo::removeMod(unsigned int index)
QMutexLocker locker(&s_Mutex);
if (index >= s_Collection.size()) {
- throw MyException(tr("invalid index %1").arg(index));
+ throw MyException(tr("remove: invalid mod index %1").arg(index));
}
// update the indices first
ModInfo::Ptr modInfo = s_Collection[index];
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index feaac2d4..e1a2183c 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -351,14 +351,18 @@ void ModInfoDialog::refreshLists()
void ModInfoDialog::addCategories(const CategoryFactory &factory, const std::set &enabledCategories, QTreeWidgetItem *root, int rootLevel)
{
- for (size_t i = 0; i < factory.numCategories(); ++i) {
+ for (int i = 0; i < static_cast(factory.numCategories()); ++i) {
if (factory.getParentID(i) != rootLevel) {
continue;
}
int categoryID = factory.getCategoryID(i);
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(factory.getCategoryName(i)));
+ QTreeWidgetItem *newItem
+ = new QTreeWidgetItem(QStringList(factory.getCategoryName(i)));
newItem->setFlags(newItem->flags() | Qt::ItemIsUserCheckable);
- newItem->setCheckState(0, enabledCategories.find(categoryID) != enabledCategories.end() ? Qt::Checked : Qt::Unchecked);
+ newItem->setCheckState(0, enabledCategories.find(categoryID)
+ != enabledCategories.end()
+ ? Qt::Checked
+ : Qt::Unchecked);
newItem->setData(0, Qt::UserRole, categoryID);
if (factory.hasChildren(i)) {
addCategories(factory, enabledCategories, newItem, categoryID);
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index c689501f..4a44c067 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -206,11 +206,12 @@ void NexusInterface::interpretNexusFileName(const QString &fileName, QString &mo
std::string candidate2 = result[2].str();
if (candidate2.length() != 0 && (candidate2.find_last_of("VvRr") == std::string::npos)) {
// well, that second match might be an id too...
- unsigned offset = strspn(candidate2.c_str(), "-_ ");
+ size_t offset = strspn(candidate2.c_str(), "-_ ");
if (offset < candidate2.length() && query) {
SelectionDialog selection(tr("Failed to guess mod id for \"%1\", please pick the correct one").arg(fileName));
QString r2Highlight(fileName);
- r2Highlight.insert(result.position(2) + result.length(2), "* ").insert(result.position(2) + offset, " *");
+ r2Highlight.insert(result.position(2) + result.length(2), "* ")
+ .insert(result.position(2) + static_cast(offset), " *");
QString r3Highlight(fileName);
r3Highlight.insert(result.position(3) + result.length(3), "* ").insert(result.position(3), " *");
@@ -264,14 +265,14 @@ QString NexusInterface::getModURL(int modID) const
return QString("%1/mods/%2").arg(getGameURL()).arg(modID);
}
-bool NexusInterface::isModURL(int modID, QString const &url) const
+bool NexusInterface::isModURL(int modID, const QString &url) const
{
- if (url == getModURL(modID)) {
+ if (QUrl(url) == QUrl(getModURL(modID))) {
return true;
}
//Try the alternate (old style) mod name
QString alt = QString("%1/%2").arg(getOldModsURL()).arg(modID);
- return alt == url;
+ return QUrl(alt) == QUrl(url);
}
int NexusInterface::requestDescription(int modID, QObject *receiver, QVariant userData,
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index f6196aa7..b1eaaef3 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -1345,8 +1345,6 @@ void OrganizerCore::refreshESPList()
// clear list
try {
m_PluginList.refresh(m_CurrentProfile->name(), *m_DirectoryStructure,
- m_CurrentProfile->getPluginsFileName(),
- m_CurrentProfile->getLoadOrderFileName(),
m_CurrentProfile->getLockedOrderFileName());
} catch (const std::exception &e) {
reportError(tr("Failed to refresh list of esps: %1").arg(e.what()));
@@ -1621,7 +1619,7 @@ void OrganizerCore::loginSuccessful(bool necessary)
if (necessary) {
MessageDialog::showMessage(tr("login successful"), qApp->activeWindow());
}
- foreach (QString url, m_PendingDownloads) {
+ for (QString url : m_PendingDownloads) {
downloadRequestedNXM(url);
}
m_PendingDownloads.clear();
@@ -1765,9 +1763,7 @@ void OrganizerCore::savePluginList()
m_PostRefreshTasks.append([&]() { this->savePluginList(); });
return;
}
- m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(),
- m_CurrentProfile->getLoadOrderFileName(),
- m_CurrentProfile->getLockedOrderFileName(),
+ m_PluginList.saveTo(m_CurrentProfile->getLockedOrderFileName(),
m_CurrentProfile->getDeleterFileName(),
m_Settings.hideUncheckedPlugins());
m_PluginList.saveLoadOrder(*m_DirectoryStructure);
@@ -1825,6 +1821,7 @@ std::vector OrganizerCore::fileMapping()
return result;
}
+
std::vector OrganizerCore::fileMapping(
const QString &dataPath, const QString &relPath, const DirectoryEntry *base,
const DirectoryEntry *directoryEntry, int createDestination)
@@ -1841,8 +1838,9 @@ std::vector OrganizerCore::fileMapping(
QString originPath
= QString::fromStdWString(base->getOriginByID(origin).getPath());
QString fileName = QString::fromStdWString(current->getName());
+// QString fileName = ToQString(current->getName());
QString source = originPath + relPath + fileName;
- QString target = dataPath + relPath + fileName;
+ QString target = dataPath + relPath + fileName;
if (source != target) {
result.push_back({source, target, false, false});
}
diff --git a/src/persistentcookiejar.cpp b/src/persistentcookiejar.cpp
index 6ca0de39..44537491 100644
--- a/src/persistentcookiejar.cpp
+++ b/src/persistentcookiejar.cpp
@@ -26,7 +26,7 @@ void PersistentCookieJar::save() {
QList cookies = allCookies();
data << static_cast(cookies.size());
- foreach (const QNetworkCookie &cookie, allCookies()) {
+ for (const QNetworkCookie &cookie : allCookies()) {
data << cookie.toRawForm();
}
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp
index a594f703..c4976d2c 100644
--- a/src/plugincontainer.cpp
+++ b/src/plugincontainer.cpp
@@ -200,7 +200,7 @@ void PluginContainer::unloadPlugins()
bf::for_each(m_Plugins, clearPlugins());
- foreach (const boost::signals2::connection &connection, m_DiagnosisConnections) {
+ for (const boost::signals2::connection &connection : m_DiagnosisConnections) {
connection.disconnect();
}
m_DiagnosisConnections.clear();
@@ -283,7 +283,7 @@ void PluginContainer::loadPlugins()
m_PluginLoaders.push_back(pluginLoader.release());
} else {
m_FailedPlugins.push_back(pluginName);
- qWarning("plugin \"%s\" failed to load", qPrintable(pluginName));
+ qWarning("plugin \"%s\" failed to load (may be outdated)", qPrintable(pluginName));
}
}
}
diff --git a/src/profile.cpp b/src/profile.cpp
index 8cc60cc0..d71b5a0f 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -163,7 +163,7 @@ void Profile::writeModlistNow()
return;
}
- for (int i = m_ModStatus.size() - 1; i >= 0; --i) {
+ for (int i = static_cast(m_ModStatus.size()) - 1; i >= 0; --i) {
// the priority order was inverted on load so it has to be inverted again
unsigned int index = m_ModIndexByPriority[i];
if (index != UINT_MAX) {
@@ -311,7 +311,7 @@ void Profile::refreshModStatus()
// invert priority order to match that of the pluginlist. Also
// give priorities to mods not referenced in the profile
for (size_t i = 0; i < m_ModStatus.size(); ++i) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(static_cast(i));
if (modInfo->alwaysEnabled()) {
m_ModStatus[i].m_Enabled = true;
}
@@ -340,7 +340,7 @@ void Profile::refreshModStatus()
if (topInsert < 0) {
int offset = topInsert * -1;
for (size_t i = 0; i < m_ModStatus.size(); ++i) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(static_cast(i));
if (modInfo->getFixedPriority() == INT_MAX) {
continue;
}
@@ -636,11 +636,12 @@ bool Profile::enableLocalSaves(bool enable)
m_Directory.mkdir("saves");
}
} else {
- QMessageBox::StandardButton res = QMessageBox::question(QApplication::activeModalWidget(), tr("Delete savegames?"),
- tr("Do you want to delete local savegames? (If you select \"No\", the save games "
- "will show up again if you re-enable local savegames)"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel);
+ QMessageBox::StandardButton res = QMessageBox::question(
+ QApplication::activeModalWidget(), tr("Delete savegames?"),
+ tr("Do you want to delete local savegames? (If you select \"No\", the "
+ "save games will show up again if you re-enable local savegames)"),
+ QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
+ QMessageBox::Cancel);
if (res == QMessageBox::Yes) {
shellDelete(QStringList(m_Directory.absoluteFilePath("saves")));
} else if (res == QMessageBox::No) {
diff --git a/src/profile.h b/src/profile.h
index ece23ef9..87dd91a5 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -174,7 +174,7 @@ public:
/**
* @return path to this profile
**/
- QString absolutePath() const;
+ virtual QString absolutePath() const override;
/**
* @return path to this profile's save games
diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp
index 1a47cf74..40f01f0e 100644
--- a/src/profilesdialog.cpp
+++ b/src/profilesdialog.cpp
@@ -66,17 +66,15 @@ ProfilesDialog::ProfilesDialog(const QString &profileName, MOBase::IPluginGame c
profileIter.next();
QListWidgetItem *item = addItem(profileIter.filePath());
if (profileName == profileIter.fileName()) {
- m_ProfilesList->setCurrentItem(item);
+ ui->profilesList->setCurrentItem(item);
}
}
- QCheckBox *invalidationBox = findChild("invalidationBox");
-
BSAInvalidation *invalidation = game->feature();
if (invalidation == nullptr) {
- invalidationBox->setToolTip(tr("Archive invalidation isn't required for this game."));
- invalidationBox->setEnabled(false);
+ ui->invalidationBox->setToolTip(tr("Archive invalidation isn't required for this game."));
+ ui->invalidationBox->setEnabled(false);
}
}
@@ -89,13 +87,13 @@ void ProfilesDialog::showEvent(QShowEvent *event)
{
TutorableDialog::showEvent(event);
- if (m_ProfilesList->count() == 0) {
- QPoint pos = m_ProfilesList->mapToGlobal(QPoint(0, 0));
- pos.rx() += m_ProfilesList->width() / 2;
- pos.ry() += (m_ProfilesList->height() / 2) - 20;
+ if (ui->profilesList->count() == 0) {
+ QPoint pos = ui->profilesList->mapToGlobal(QPoint(0, 0));
+ pos.rx() += ui->profilesList->width() / 2;
+ pos.ry() += (ui->profilesList->height() / 2) - 20;
QWhatsThis::showText(pos,
QObject::tr("Before you can use ModOrganizer, you need to create at least one profile. "
- "ATTENTION: Run the game at least once before creating a profile!"), m_ProfilesList);
+ "ATTENTION: Run the game at least once before creating a profile!"), ui->profilesList);
}
}
@@ -108,7 +106,7 @@ void ProfilesDialog::on_closeButton_clicked()
QListWidgetItem *ProfilesDialog::addItem(const QString &name)
{
QDir profileDir(name);
- QListWidgetItem *newItem = new QListWidgetItem(profileDir.dirName(), m_ProfilesList);
+ QListWidgetItem *newItem = new QListWidgetItem(profileDir.dirName(), ui->profilesList);
try {
newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(profileDir, m_Game))));
m_FailState = false;
@@ -121,10 +119,9 @@ QListWidgetItem *ProfilesDialog::addItem(const QString &name)
void ProfilesDialog::createProfile(const QString &name, bool useDefaultSettings)
{
try {
- QListWidget *profilesList = findChild("profilesList");
- QListWidgetItem *newItem = new QListWidgetItem(name, profilesList);
+ QListWidgetItem *newItem = new QListWidgetItem(name, ui->profilesList);
newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(name, m_Game, useDefaultSettings))));
- profilesList->addItem(newItem);
+ ui->profilesList->addItem(newItem);
m_FailState = false;
} catch (const std::exception&) {
m_FailState = true;
@@ -135,10 +132,9 @@ void ProfilesDialog::createProfile(const QString &name, bool useDefaultSettings)
void ProfilesDialog::createProfile(const QString &name, const Profile &reference)
{
try {
- QListWidget *profilesList = findChild("profilesList");
- QListWidgetItem *newItem = new QListWidgetItem(name, profilesList);
+ QListWidgetItem *newItem = new QListWidgetItem(name, ui->profilesList);
newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(Profile::createPtrFrom(name, reference, m_Game))));
- profilesList->addItem(newItem);
+ ui->profilesList->addItem(newItem);
m_FailState = false;
} catch (const std::exception&) {
m_FailState = true;
@@ -164,20 +160,23 @@ void ProfilesDialog::on_addProfileButton_clicked()
void ProfilesDialog::on_copyProfileButton_clicked()
{
bool okClicked;
- QString name = QInputDialog::getText(this, tr("Name"), tr("Please enter a name for the new profile"), QLineEdit::Normal, QString(), &okClicked);
+ QString name = QInputDialog::getText(
+ this, tr("Name"), tr("Please enter a name for the new profile"),
+ QLineEdit::Normal, QString(), &okClicked);
fixDirectoryName(name);
if (okClicked) {
if (name.size() > 0) {
- QListWidget *profilesList = findChild("profilesList");
-
try {
- const Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value();
+ const Profile::Ptr currentProfile = ui->profilesList->currentItem()
+ ->data(Qt::UserRole)
+ .value();
createProfile(name, *currentProfile);
} catch (const std::exception &e) {
reportError(tr("failed to copy profile: %1").arg(e.what()));
}
} else {
- QMessageBox::warning(this, tr("Invalid name"), tr("Invalid profile name"));
+ QMessageBox::warning(this, tr("Invalid name"),
+ tr("Invalid profile name"));
}
}
}
@@ -188,13 +187,11 @@ void ProfilesDialog::on_removeProfileButton_clicked()
QMessageBox::Yes | QMessageBox::No);
if (confirmBox.exec() == QMessageBox::Yes) {
- QListWidget *profilesList = findChild("profilesList");
-
- Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value();
+ Profile::Ptr currentProfile = ui->profilesList->currentItem()->data(Qt::UserRole).value();
QString profilePath;
if (currentProfile.get() == nullptr) {
profilePath = Settings::instance().getProfileDirectory()
- + "/" + profilesList->currentItem()->text();
+ + "/" + ui->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. "
"I'm about to delete the following folder: \"%1\". Proceed?").arg(profilePath), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
@@ -205,7 +202,7 @@ void ProfilesDialog::on_removeProfileButton_clicked()
// we have to get rid of the it before deleting the directory
profilePath = currentProfile->absolutePath();
}
- QListWidgetItem* item = profilesList->takeItem(profilesList->currentRow());
+ QListWidgetItem* item = ui->profilesList->takeItem(ui->profilesList->currentRow());
if (item != nullptr) {
delete item;
}
@@ -270,53 +267,50 @@ void ProfilesDialog::on_invalidationBox_stateChanged(int state)
void ProfilesDialog::on_profilesList_currentItemChanged(QListWidgetItem *current, QListWidgetItem*)
{
- QCheckBox *invalidationBox = findChild("invalidationBox");
- QCheckBox *localSavesBox = findChild("localSavesBox");
- QPushButton *copyButton = findChild("copyProfileButton");
- QPushButton *removeButton = findChild("removeProfileButton");
- QPushButton *transferButton = findChild("transferButton");
- QPushButton *renameButton = findChild("renameButton");
-
if (current != nullptr) {
if (!current->data(Qt::UserRole).isValid()) return;
const Profile::Ptr currentProfile = current->data(Qt::UserRole).value();
try {
bool invalidationSupported = false;
- invalidationBox->blockSignals(true);
- invalidationBox->setChecked(currentProfile->invalidationActive(&invalidationSupported));
- invalidationBox->setEnabled(invalidationSupported);
- invalidationBox->blockSignals(false);
+ ui->invalidationBox->blockSignals(true);
+ ui->invalidationBox->setChecked(currentProfile->invalidationActive(&invalidationSupported));
+ ui->invalidationBox->setEnabled(invalidationSupported);
+ ui->invalidationBox->blockSignals(false);
bool localSaves = currentProfile->localSavesEnabled();
- transferButton->setEnabled(localSaves);
+ ui->transferButton->setEnabled(localSaves);
// prevent the stateChanged-event for the saves-box from triggering, otherwise it may think local saves
// were disabled and delete the files/rename the dir
- localSavesBox->blockSignals(true);
- localSavesBox->setChecked(localSaves);
- localSavesBox->blockSignals(false);
+ ui->localSavesBox->blockSignals(true);
+ ui->localSavesBox->setChecked(localSaves);
+ ui->localSavesBox->blockSignals(false);
+
+ ui->copyProfileButton->setEnabled(true);
+ ui->removeProfileButton->setEnabled(true);
+ ui->renameButton->setEnabled(true);
- copyButton->setEnabled(true);
- removeButton->setEnabled(true);
- renameButton->setEnabled(true);
+ ui->localIniFilesBox->blockSignals(true);
+ ui->localIniFilesBox->setChecked(currentProfile->localSettingsEnabled());
+ ui->localIniFilesBox->blockSignals(false);
} catch (const std::exception& E) {
reportError(tr("failed to determine if invalidation is active: %1").arg(E.what()));
- copyButton->setEnabled(false);
- removeButton->setEnabled(false);
- renameButton->setEnabled(false);
- invalidationBox->setChecked(false);
+ ui->copyProfileButton->setEnabled(false);
+ ui->removeProfileButton->setEnabled(false);
+ ui->renameButton->setEnabled(false);
+ ui->invalidationBox->setChecked(false);
}
} else {
- invalidationBox->setChecked(false);
- copyButton->setEnabled(false);
- removeButton->setEnabled(false);
- renameButton->setEnabled(false);
+ ui->invalidationBox->setChecked(false);
+ ui->copyProfileButton->setEnabled(false);
+ ui->removeProfileButton->setEnabled(false);
+ ui->renameButton->setEnabled(false);
}
}
void ProfilesDialog::on_localSavesBox_stateChanged(int state)
{
- Profile::Ptr currentProfile = m_ProfilesList->currentItem()->data(Qt::UserRole).value();
+ Profile::Ptr currentProfile = ui->profilesList->currentItem()->data(Qt::UserRole).value();
if (currentProfile->enableLocalSaves(state == Qt::Checked)) {
ui->transferButton->setEnabled(state == Qt::Checked);
diff --git a/src/profilesdialog.ui b/src/profilesdialog.ui
index 0c952877..fe03f466 100644
--- a/src/profilesdialog.ui
+++ b/src/profilesdialog.ui
@@ -6,8 +6,8 @@
0
0
- 471
- 318
+ 482
+ 332
diff --git a/src/shared/util.cpp b/src/shared/util.cpp
index 3692aae1..5491a9e6 100644
--- a/src/shared/util.cpp
+++ b/src/shared/util.cpp
@@ -81,12 +81,16 @@ std::wstring ToWString(const std::string &source, bool utf8)
if (!utf8) {
codepage = AreFileApisANSI() ? GetACP() : GetOEMCP();
}
- int sizeRequired = ::MultiByteToWideChar(codepage, 0, source.c_str(), source.length(), nullptr, 0);
+ int sizeRequired
+ = ::MultiByteToWideChar(codepage, 0, source.c_str(),
+ static_cast(source.length()), nullptr, 0);
if (sizeRequired == 0) {
throw windows_error("failed to convert string to wide character");
}
result.resize(sizeRequired, L'\0');
- ::MultiByteToWideChar(codepage, 0, source.c_str(), source.length(), &result[0], sizeRequired);
+ ::MultiByteToWideChar(codepage, 0, source.c_str(),
+ static_cast(source.length()), &result[0],
+ sizeRequired);
}
return result;
diff --git a/src/usvfsconnector.cpp b/src/usvfsconnector.cpp
index db20a54f..bc818685 100644
--- a/src/usvfsconnector.cpp
+++ b/src/usvfsconnector.cpp
@@ -76,13 +76,16 @@ LogWorker::~LogWorker()
void LogWorker::process()
{
+ int noLogCycles = 0;
while (!m_QuitRequested) {
if (GetLogMessages(&m_Buffer[0], m_Buffer.size(), false)) {
m_LogFile.write(m_Buffer.c_str());
m_LogFile.write("\n");
m_LogFile.flush();
+ noLogCycles = 0;
} else {
- QThread::sleep(1);
+ QThread::msleep(std::min(40, noLogCycles) * 5);
+ ++noLogCycles;
}
}
emit finished();
@@ -148,11 +151,13 @@ void UsvfsConnector::updateMapping(const MappingType &mapping)
if (value % 10 == 0) {
QCoreApplication::processEvents();
}
+
if (map.isDirectory) {
VirtualLinkDirectoryStatic(map.source.toStdWString().c_str(),
map.destination.toStdWString().c_str(),
(map.createTarget ? LINKFLAG_CREATETARGET : 0)
- | LINKFLAG_RECURSIVE);
+ | LINKFLAG_RECURSIVE
+ );
} else {
VirtualLinkFile(map.source.toStdWString().c_str(),
map.destination.toStdWString().c_str(), 0);
diff --git a/src/version.rc b/src/version.rc
index 028912d7..872c65d7 100644
--- a/src/version.rc
+++ b/src/version.rc
@@ -1,7 +1,7 @@
#include "Winver.h"
-#define VER_FILEVERSION 2,0,4
-#define VER_FILEVERSION_STR "2,0,4alpha\0"
+#define VER_FILEVERSION 2,0,5
+#define VER_FILEVERSION_STR "2.0.5beta\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
--
cgit v1.3.1
From 5665be7fd126c435ed4ad4ceb8c01f0e6eb16975 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Sun, 15 May 2016 14:58:54 +0200
Subject: fixed calls to helper.exe using wrong path
---
src/helper.cpp | 10 +++++-----
src/helper.h | 8 ++++----
src/main.cpp | 3 ++-
src/settingsdialog.cpp | 2 +-
src/version.rc | 4 ++--
5 files changed, 14 insertions(+), 13 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/helper.cpp b/src/helper.cpp
index 41784fe5..b7fc866c 100644
--- a/src/helper.cpp
+++ b/src/helper.cpp
@@ -62,7 +62,7 @@ static bool helperExec(LPCWSTR moDirectory, LPCWSTR commandLine)
}
-bool init(const std::wstring &moDirectory)
+bool init(const std::wstring &moPath, const std::wstring &dataPath)
{
DWORD userNameLen = UNLEN + 1;
wchar_t userName[UNLEN + 1];
@@ -74,22 +74,22 @@ bool init(const std::wstring &moDirectory)
wchar_t *commandLine = new wchar_t[32768];
_snwprintf(commandLine, 32768, L"init \"%ls\" \"%ls\"",
- moDirectory.c_str(), userName);
+ dataPath.c_str(), userName);
- bool res = helperExec(moDirectory.c_str(), commandLine);
+ bool res = helperExec(moPath.c_str(), commandLine);
delete [] commandLine;
return res;
}
-bool backdateBSAs(const std::wstring &moDirectory, const std::wstring &dataPath)
+bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath)
{
wchar_t *commandLine = new wchar_t[32768];
_snwprintf(commandLine, 32768, L"backdateBSA \"%ls\"",
dataPath.c_str());
- bool res = helperExec(moDirectory.c_str(), commandLine);
+ bool res = helperExec(moPath.c_str(), commandLine);
delete [] commandLine;
return res;
diff --git a/src/helper.h b/src/helper.h
index 410e2527..cd4b7883 100644
--- a/src/helper.h
+++ b/src/helper.h
@@ -38,17 +38,17 @@ namespace Helper {
* This will create all required sub-directories and give the user running ModOrganizer
* write-access
*
- * @param moDirectory absolute path to the ModOrganizer base directory
+ * @param moPath absolute path to the ModOrganizer base directory
* @return true on success
**/
-bool init(const std::wstring &moDirectory);
+bool init(const std::wstring &moPath, const std::wstring &dataPath);
/**
* @brief sets the last modified time for all .bsa-files in the target directory well into the past
- * @param moDirectory absolute path to the modOrganizer base directory
+ * @param moPath absolute path to the modOrganizer base directory
* @param dataPath the path taht contains the .bsa-files, usually the data directory of the game
**/
-bool backdateBSAs(const std::wstring &moDirectory, const std::wstring &dataPath);
+bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath);
}
diff --git a/src/main.cpp b/src/main.cpp
index 6db5a50e..3cced2a1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -104,7 +104,8 @@ bool createAndMakeWritable(const std::wstring &subPath)
"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(dataPath.toStdWString())) {
+ if (!Helper::init(qApp->applicationDirPath().toStdWString(),
+ dataPath.toStdWString())) {
return false;
}
} else {
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index d354b29b..e528f478 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -96,7 +96,7 @@ void SettingsDialog::on_bsaDateBtn_clicked()
= qApp->property("managed_game").value();
QDir dir = game->dataDirectory();
- Helper::backdateBSAs(qApp->property("dataPath").toString().toStdWString(),
+ Helper::backdateBSAs(qApp->applicationDirPath().toStdWString(),
dir.absolutePath().toStdWString());
}
diff --git a/src/version.rc b/src/version.rc
index 872c65d7..445f7c19 100644
--- a/src/version.rc
+++ b/src/version.rc
@@ -1,7 +1,7 @@
#include "Winver.h"
-#define VER_FILEVERSION 2,0,5
-#define VER_FILEVERSION_STR "2.0.5beta\0"
+#define VER_FILEVERSION 2,0,6
+#define VER_FILEVERSION_STR "2.0.6beta\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
--
cgit v1.3.1
From 986330a3bd8e0a4717a0a1aa26f4acd2c04de1ac Mon Sep 17 00:00:00 2001
From: Tannin
Date: Mon, 16 May 2016 16:03:36 +0200
Subject: removed obsolete stuff
---
src/main.cpp | 1 -
src/pluginlist.cpp | 1 -
src/shared/fallout3info.cpp | 71 ------------------
src/shared/fallout3info.h | 55 --------------
src/shared/fallout4info.cpp | 100 --------------------------
src/shared/fallout4info.h | 75 -------------------
src/shared/falloutnvinfo.cpp | 71 ------------------
src/shared/falloutnvinfo.h | 53 --------------
src/shared/gameinfo.cpp | 167 -------------------------------------------
src/shared/gameinfo.h | 89 -----------------------
src/shared/oblivioninfo.cpp | 71 ------------------
src/shared/oblivioninfo.h | 54 --------------
src/shared/skyriminfo.cpp | 81 ---------------------
src/shared/skyriminfo.h | 58 ---------------
src/spawn.cpp | 1 -
15 files changed, 948 deletions(-)
delete mode 100644 src/shared/fallout3info.cpp
delete mode 100644 src/shared/fallout3info.h
delete mode 100644 src/shared/fallout4info.cpp
delete mode 100644 src/shared/fallout4info.h
delete mode 100644 src/shared/falloutnvinfo.cpp
delete mode 100644 src/shared/falloutnvinfo.h
delete mode 100644 src/shared/gameinfo.cpp
delete mode 100644 src/shared/gameinfo.h
delete mode 100644 src/shared/oblivioninfo.cpp
delete mode 100644 src/shared/oblivioninfo.h
delete mode 100644 src/shared/skyriminfo.cpp
delete mode 100644 src/shared/skyriminfo.h
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 3cced2a1..6940e288 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -27,7 +27,6 @@ along with Mod Organizer. If not, see .
#include
#include
-#include
#include
#include
#include
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 5c21d0c8..8d37ab82 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -18,7 +18,6 @@ along with Mod Organizer. If not, see .
*/
#include "pluginlist.h"
-#include "inject.h"
#include "settings.h"
#include "scopeguard.h"
#include "modinfo.h"
diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp
deleted file mode 100644
index 446d4afe..00000000
--- a/src/shared/fallout3info.cpp
+++ /dev/null
@@ -1,71 +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 .
-*/
-
-#include "fallout3info.h"
-#include "util.h"
-#include
-#include
-#include
-#include "windows_error.h"
-#include "error_report.h"
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-
-namespace MOShared {
-
-Fallout3Info::Fallout3Info(const std::wstring &gameDirectory)
- : GameInfo(gameDirectory)
-{
- identifyMyGamesDirectory(L"fallout3");
-}
-
-bool Fallout3Info::identifyGame(const std::wstring &searchPath)
-{
- return FileExists(searchPath, L"Fallout3.exe") &&
- FileExists(searchPath, L"FalloutLauncher.exe");
-}
-
-std::wstring Fallout3Info::getRegPathStatic()
-{
- HKEY key;
- LONG errorcode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout3",
- 0, KEY_QUERY_VALUE, &key);
-
- if (errorcode != ERROR_SUCCESS) {
- return std::wstring();
- }
-
- WCHAR temp[MAX_PATH];
- DWORD bufferSize = MAX_PATH;
-
- if (::RegQueryValueExW(key, L"Installed Path", nullptr, nullptr, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
- return std::wstring(temp);
- } else {
- return std::wstring();
- }
-}
-
-
-std::vector Fallout3Info::getIniFileNames() const
-{
- return boost::assign::list_of(L"fallout.ini")(L"falloutprefs.ini");
-}
-
-} // namespace MOShared
diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h
deleted file mode 100644
index 601fc346..00000000
--- a/src/shared/fallout3info.h
+++ /dev/null
@@ -1,55 +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 FALLOUT3INFO_H
-#define FALLOUT3INFO_H
-
-#include "gameinfo.h"
-
-namespace MOShared {
-
-
-class Fallout3Info : public GameInfo
-{
-
- friend class GameInfo;
-
-public:
-
- virtual ~Fallout3Info() {}
-
- static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() const { return getRegPathStatic(); }
-
- // file name of this games ini (no path)
- virtual std::vector getIniFileNames() const;
-
- virtual std::wstring archiveListKey() const { return L"SArchiveList"; }
-
-private:
-
- Fallout3Info(const std::wstring &gameDirectory);
-
- static bool identifyGame(const std::wstring &searchPath);
-
-};
-
-} // namespace MOShared
-
-#endif // FALLOUT3INFO_H
diff --git a/src/shared/fallout4info.cpp b/src/shared/fallout4info.cpp
deleted file mode 100644
index aab431ad..00000000
--- a/src/shared/fallout4info.cpp
+++ /dev/null
@@ -1,100 +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 .
-*/
-
-#include "fallout4info.h"
-#include "util.h"
-#include
-#include
-#include
-#include "windows_error.h"
-#include "error_report.h"
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-
-namespace MOShared {
-
-Fallout4Info::Fallout4Info(const std::wstring &gameDirectory)
- : GameInfo(gameDirectory)
-{
- identifyMyGamesDirectory(L"fallout4");
-}
-
-bool Fallout4Info::identifyGame(const std::wstring &searchPath)
-{
- return FileExists(searchPath, L"Fallout4.exe") &&
- FileExists(searchPath, L"Fallout4Launcher.exe");
-}
-
-std::wstring Fallout4Info::getRegPathStatic()
-{
- HKEY key;
- LONG errorcode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4",
- 0, KEY_QUERY_VALUE, &key);
-
- if (errorcode != ERROR_SUCCESS) {
- return std::wstring();
- }
-
- WCHAR temp[MAX_PATH];
- DWORD bufferSize = MAX_PATH;
-
- if (::RegQueryValueExW(key, L"Installed Path", nullptr, nullptr, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
- return std::wstring(temp);
- } else {
- return std::wstring();
- }
-}
-
-
-std::vector Fallout4Info::getDLCPlugins()
-{
- return std::vector();
-}
-
-std::vector Fallout4Info::getSavegameAttachmentExtensions()
-{
- return std::vector();
-}
-
-std::vector Fallout4Info::getIniFileNames() const
-{
- return boost::assign::list_of(L"fallout4.ini")(L"fallout4prefs.ini");
-}
-
-std::wstring Fallout4Info::getNexusPage(bool nmmScheme)
-{
- if (nmmScheme) {
- return L"http://nmm.nexusmods.com/fallout4";
- } else {
- return L"http://www.nexusmods.com/fallout4";
- }
-}
-
-std::wstring Fallout4Info::getNexusInfoUrlStatic()
-{
- return L"http://nmm.nexusmods.com/fallout4";
-}
-
-int Fallout4Info::getNexusModIDStatic()
-{
- return 377160;
-}
-
-} // namespace MOShared
diff --git a/src/shared/fallout4info.h b/src/shared/fallout4info.h
deleted file mode 100644
index 70c9b7d3..00000000
--- a/src/shared/fallout4info.h
+++ /dev/null
@@ -1,75 +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 FALLOUT4INFO_H
-#define FALLOUT4INFO_H
-
-
-#include "gameinfo.h"
-
-namespace MOShared {
-
-
-class Fallout4Info : public GameInfo
-{
-
- friend class GameInfo;
-
-public:
-
- virtual ~Fallout4Info() {}
-
- static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() const { return getRegPathStatic(); }
- virtual std::wstring getBinaryName() { return L"Fallout4.exe"; }
-
- virtual std::wstring getGameName() const { return L"Fallout 4"; }
- virtual std::wstring getGameShortName() const { return L"Fallout4"; }
-
- virtual std::vector getDLCPlugins();
- virtual std::vector getSavegameAttachmentExtensions();
-
- // file name of this games ini (no path)
- virtual std::vector getIniFileNames() const;
-
- virtual std::wstring getNexusPage(bool nmmScheme = true);
- static std::wstring getNexusInfoUrlStatic();
- virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); }
- static int getNexusModIDStatic();
- virtual int getNexusModID() { return getNexusModIDStatic(); }
- virtual int getNexusGameID() { return 1151; }
-
- // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
- // the game directory
- //virtual std::vector getExecutables();
-
- virtual std::wstring archiveListKey() { return L"SArchiveList"; }
-
-private:
-
- Fallout4Info(const std::wstring &gameDirectory);
-
- static bool identifyGame(const std::wstring &searchPath);
-
-
-};
-
-} // namespace MOShared
-
-#endif // FALLOUT3INFO_H
diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp
deleted file mode 100644
index 510dfa01..00000000
--- a/src/shared/falloutnvinfo.cpp
+++ /dev/null
@@ -1,71 +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 .
-*/
-
-#include "falloutnvinfo.h"
-#include "util.h"
-#include
-#include
-#include
-#include "windows_error.h"
-#include "error_report.h"
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-
-namespace MOShared {
-
-
-FalloutNVInfo::FalloutNVInfo(const std::wstring &gameDirectory)
- : GameInfo(gameDirectory)
-{
- identifyMyGamesDirectory(L"falloutnv");
-}
-
-bool FalloutNVInfo::identifyGame(const std::wstring &searchPath)
-{
- return FileExists(searchPath, L"FalloutNV.exe") &&
- FileExists(searchPath, L"FalloutNVLauncher.exe");
-}
-
-std::wstring FalloutNVInfo::getRegPathStatic()
-{
- HKEY key;
- LONG errorcode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\FalloutNV",
- 0, KEY_QUERY_VALUE, &key);
-
- if (errorcode != ERROR_SUCCESS) {
- return std::wstring();
- }
-
- WCHAR temp[MAX_PATH];
- DWORD bufferSize = MAX_PATH;
-
- if (::RegQueryValueExW(key, L"Installed Path", nullptr, nullptr, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
- return std::wstring(temp);
- } else {
- return std::wstring();
- }
-}
-
-std::vector FalloutNVInfo::getIniFileNames() const
-{
- return boost::assign::list_of(L"fallout.ini")(L"falloutprefs.ini");
-}
-
-} // namespace MOShared
diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h
deleted file mode 100644
index a9b3b9ec..00000000
--- a/src/shared/falloutnvinfo.h
+++ /dev/null
@@ -1,53 +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 FALLOUTNVINFO_H
-#define FALLOUTNVINFO_H
-
-
-#include "gameinfo.h"
-
-namespace MOShared {
-
-
-class FalloutNVInfo : public GameInfo
-{
-
- friend class GameInfo;
-
-public:
-
- virtual ~FalloutNVInfo() {}
-
- static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() const { return getRegPathStatic(); }
-
- // file name of this games ini (no path)
- virtual std::vector getIniFileNames() const;
-
-private:
-
- FalloutNVInfo(const std::wstring &gameDirectory);
-
- static bool identifyGame(const std::wstring &searchPath);
-};
-
-} // namespace MOShared
-
-#endif // FALLOUTNVINFO_H
diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp
deleted file mode 100644
index 9b097053..00000000
--- a/src/shared/gameinfo.cpp
+++ /dev/null
@@ -1,167 +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 .
-*/
-
-#include "gameinfo.h"
-
-#include "windows_error.h"
-
-#include "oblivioninfo.h"
-#include "fallout3info.h"
-#include "fallout4info.h"
-#include "falloutnvinfo.h"
-#include "skyriminfo.h"
-#include "util.h"
-
-#include
-#include
-
-#include
-#include
-#include
-
-namespace MOShared {
-
-
-GameInfo* GameInfo::s_Instance = nullptr;
-
-
-GameInfo::GameInfo(const std::wstring &gameDirectory)
- : m_GameDirectory(gameDirectory)
-{
- atexit(&cleanup);
-}
-
-
-void GameInfo::cleanup() {
- delete GameInfo::s_Instance;
- GameInfo::s_Instance = nullptr;
-}
-
-
-void GameInfo::identifyMyGamesDirectory(const std::wstring &file)
-{
- // this function attempts 3 (three!) ways to determine the correct "My Games" folder.
- wchar_t myDocuments[MAX_PATH];
- memset(myDocuments, '\0', MAX_PATH * sizeof(wchar_t));
-
- m_MyGamesDirectory.clear();
-
- // a) this is the way it should work. get the configured My Documents\My Games directory
- if (::SHGetFolderPathW(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_CURRENT, myDocuments) == S_OK) {
- m_MyGamesDirectory = std::wstring(myDocuments) + L"\\My Games";
- }
-
- // b) if there is no directory there, look in the default directory
- if (m_MyGamesDirectory.empty()
- || !FileExists(m_MyGamesDirectory + L"\\" + file)) {
- if (::SHGetFolderPathW(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_DEFAULT, myDocuments) == S_OK) {
- std::wstring fromDefault = std::wstring(myDocuments) + L"\\My Games";
- if (FileExists(fromDefault + L"\\" + file)) {
- m_MyGamesDirectory = fromDefault;
- }
- }
- }
- // c) finally, look in the registry. This is discouraged
- if (m_MyGamesDirectory.empty()
- || !FileExists(m_MyGamesDirectory + L"\\" + file)) {
- std::wstring fromRegistry = getSpecialPath(L"Personal") + L"\\My Games";
- if (FileExists(fromRegistry + L"\\" + file)) {
- m_MyGamesDirectory = fromRegistry;
- }
- }
-}
-
-bool GameInfo::identifyGame(const std::wstring &searchPath)
-{
- if (OblivionInfo::identifyGame(searchPath)) {
- s_Instance = new OblivionInfo(searchPath);
- } else if (Fallout3Info::identifyGame(searchPath)) {
- s_Instance = new Fallout3Info(searchPath);
- } else if (FalloutNVInfo::identifyGame(searchPath)) {
- s_Instance = new FalloutNVInfo(searchPath);
- } else if (SkyrimInfo::identifyGame(searchPath)) {
- s_Instance = new SkyrimInfo(searchPath);
- } else if (Fallout4Info::identifyGame(searchPath)) {
- s_Instance = new Fallout4Info(searchPath);
- }
-
- return s_Instance != nullptr;
-}
-
-
-bool GameInfo::init(const std::wstring &moDirectory, const std::wstring &gamePath)
-{
- if (s_Instance == nullptr) {
- if (gamePath.length() == 0) {
- // search upward in the directory until a recognized game-binary is found
- std::wstring searchPath(moDirectory);
- while (!identifyGame(searchPath)) {
- size_t lastSep = searchPath.find_last_of(L"/\\");
- if (lastSep == std::string::npos) {
- return false;
- }
- searchPath.erase(lastSep);
- }
- } else if (!identifyGame(gamePath)) {
- return false;
- }
- }
- return true;
-}
-
-
-GameInfo &GameInfo::instance()
-{
- assert(s_Instance != nullptr && "gameinfo not yet initialized");
- return *s_Instance;
-}
-
-std::wstring GameInfo::getGameDirectory() const
-{
- return m_GameDirectory;
-}
-
-std::wstring GameInfo::getSpecialPath(LPCWSTR name) const
-{
- HKEY key;
- LONG errorcode = ::RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
- 0, KEY_QUERY_VALUE, &key);
-
- if (errorcode != ERROR_SUCCESS) {
- throw windows_error("failed to look up special folder (path)", errorcode);
- }
-
- WCHAR temp[MAX_PATH];
- DWORD bufferSize = MAX_PATH;
-
- errorcode = ::RegQueryValueExW(key, name, nullptr, nullptr, (LPBYTE)temp, &bufferSize);
- if (errorcode != ERROR_SUCCESS) {
- throw windows_error((boost::format("failed to look up special folder (%1%)") % ToString(name, true)).str(), errorcode);
- }
-
- WCHAR temp2[MAX_PATH];
- // try to expand variables in the path, if any
- if (::ExpandEnvironmentStringsW(temp, temp2, MAX_PATH) != 0) {
- return temp2;
- } else {
- return temp;
- }
-}
-
-} // namespace MOShared
diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h
deleted file mode 100644
index c99ebef7..00000000
--- a/src/shared/gameinfo.h
+++ /dev/null
@@ -1,89 +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 GAMEINFO_H
-#define GAMEINFO_H
-
-#include
-#include
-#include
-
-#define WIN32_LEAN_AND_MEAN
-#include
-
-namespace MOShared {
-
-
-/**
- Class to manage information that depends on the used game type. The intention is to keep
- as much of the rest of omo is game-agnostic. It is mostly concerned with figuring out the
- correct paths, filenames and data types.
-*/
-class GameInfo
-{
-
-public:
-
- virtual ~GameInfo() {}
-
- //**USED IN HOOKDLL and at startup to set up for hookdll to work
- // initialise with the path to the mo directory (needs to be where hook.dll is stored). This
- // needs to be called before the instance can be retrieved
- static bool init(const std::wstring &moDirectory, const std::wstring &gamePath = L"");
-
- //**USED ONLY IN HOOKDLL
- static GameInfo& instance();
-
- //**USED ONLY IN HOOKDLL
- virtual std::wstring getGameDirectory() const;
-
- //**USED ONLY IN HOOKDLL
- virtual std::wstring getRegPath() const = 0;
-
- //**USED ONLY IN HOOKDLL
- // file name of this games ini file(s)
- virtual std::vector getIniFileNames() const = 0;
-
-protected:
-
- GameInfo(const std::wstring &gameDirectory);
-
- void identifyMyGamesDirectory(const std::wstring &file);
-
-private:
-
- static bool identifyGame(const std::wstring &searchPath);
- std::wstring getSpecialPath(LPCWSTR name) const;
-
- static void cleanup();
-
-private:
-
- static GameInfo *s_Instance;
-
- std::wstring m_MyGamesDirectory;
-
- std::wstring m_GameDirectory;
-
-};
-
-
-} // namespace MOShared
-
-#endif // GAMEINFO_H
diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp
deleted file mode 100644
index b290fb36..00000000
--- a/src/shared/oblivioninfo.cpp
+++ /dev/null
@@ -1,71 +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 .
-*/
-
-#include "oblivioninfo.h"
-#include
-#include
-#include "util.h"
-#include
-#include "windows_error.h"
-#include "error_report.h"
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-
-namespace MOShared {
-
-
-OblivionInfo::OblivionInfo(const std::wstring &gameDirectory)
- : GameInfo(gameDirectory)
-{
- identifyMyGamesDirectory(L"oblivion");
-}
-
-bool OblivionInfo::identifyGame(const std::wstring &searchPath)
-{
- return FileExists(searchPath, L"Oblivion.exe") &&
- FileExists(searchPath, L"OblivionLauncher.exe");
-}
-
-std::wstring OblivionInfo::getRegPathStatic()
-{
- HKEY key;
- LONG errorcode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Oblivion",
- 0, KEY_QUERY_VALUE, &key);
-
- if (errorcode != ERROR_SUCCESS) {
- return std::wstring();
- }
-
- WCHAR temp[MAX_PATH];
- DWORD bufferSize = MAX_PATH;
-
- if (::RegQueryValueExW(key, L"Installed Path", nullptr, nullptr, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
- return std::wstring(temp);
- } else {
- return std::wstring();
- }
-}
-
-std::vector OblivionInfo::getIniFileNames() const
-{
- return boost::assign::list_of(L"oblivion.ini")(L"oblivionprefs.ini");
-}
-
-} // namespace MOShared
diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h
deleted file mode 100644
index 6609921a..00000000
--- a/src/shared/oblivioninfo.h
+++ /dev/null
@@ -1,54 +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 OBLIVIONINFO_H
-#define OBLIVIONINFO_H
-
-#include "gameinfo.h"
-
-namespace MOShared {
-
-class OblivionInfo : public GameInfo
-{
-
- friend class GameInfo;
-
-public:
-
- virtual ~OblivionInfo() {}
-
- static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() const { return getRegPathStatic(); }
-
- // file name of this games ini (no path)
- virtual std::vector getIniFileNames() const;
-
- virtual std::wstring archiveListKey() const { return L"SArchiveList"; }
-
-private:
-
- OblivionInfo(const std::wstring &gameDirectory);
-
- static bool identifyGame(const std::wstring &searchPath);
-
-};
-
-} // namespace MOShared
-
-#endif // OBLIVIONINFO_H
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp
deleted file mode 100644
index fbe13ae0..00000000
--- a/src/shared/skyriminfo.cpp
+++ /dev/null
@@ -1,81 +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 .
-*/
-
-#include "skyriminfo.h"
-
-#include "util.h"
-#include
-#include
-#include
-#include "windows_error.h"
-#include "error_report.h"
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-#include
-
-namespace MOShared {
-
-
-SkyrimInfo::SkyrimInfo(const std::wstring &gameDirectory)
- : GameInfo(gameDirectory)
-{
- identifyMyGamesDirectory(L"skyrim");
-
- wchar_t appDataPath[MAX_PATH];
- if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appDataPath))) {
- m_AppData = appDataPath;
- }
-}
-
-bool SkyrimInfo::identifyGame(const std::wstring &searchPath)
-{
- return FileExists(searchPath, L"TESV.exe") &&
- FileExists(searchPath, L"SkyrimLauncher.exe");
-}
-
-
-
-
-std::wstring SkyrimInfo::getRegPathStatic()
-{
- HKEY key;
- LONG errorcode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Skyrim",
- 0, KEY_QUERY_VALUE, &key);
-
- if (errorcode != ERROR_SUCCESS) {
- return std::wstring();
- }
-
- WCHAR temp[MAX_PATH];
- DWORD bufferSize = MAX_PATH;
-
- if (::RegQueryValueExW(key, L"Installed Path", nullptr, nullptr, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
- return std::wstring(temp);
- } else {
- return std::wstring();
- }
-}
-
-std::vector SkyrimInfo::getIniFileNames() const
-{
- return boost::assign::list_of(L"skyrim.ini")(L"skyrimprefs.ini");
-}
-
-} // namespace MOShared
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h
deleted file mode 100644
index a13b834e..00000000
--- a/src/shared/skyriminfo.h
+++ /dev/null
@@ -1,58 +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 SKYRIMINFO_H
-#define SKYRIMINFO_H
-
-
-#include "gameinfo.h"
-
-namespace MOShared {
-
-
-class SkyrimInfo : public GameInfo
-{
-
- friend class GameInfo;
-
-public:
-
- virtual ~SkyrimInfo() {}
-
- static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() const { return getRegPathStatic(); }
-
- // file name of this games ini (no path)
- virtual std::vector getIniFileNames() const;
-
-private:
-
- SkyrimInfo(const std::wstring &gameDirectory);
-
- static bool identifyGame(const std::wstring &searchPath);
-
-private:
-
- std::wstring m_AppData;
-
-};
-
-} // namespace MOShared
-
-#endif // SKYRIMINFO_H
diff --git a/src/spawn.cpp b/src/spawn.cpp
index 0ff64af0..ac8ccf30 100644
--- a/src/spawn.cpp
+++ b/src/spawn.cpp
@@ -22,7 +22,6 @@ along with Mod Organizer. If not, see .
#include "report.h"
#include "utility.h"
#include
-#include
#include
#include
#include
--
cgit v1.3.1
From bfbb19099839019c785dc81c83b07dadbd394168 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Fri, 27 May 2016 14:04:00 +0200
Subject: moved button to switch instance (and to portable mode) to the main
window
---
src/instancemanager.cpp | 100 +++++++++++++++++++++++-----------------------
src/instancemanager.h | 15 +++----
src/main.cpp | 4 +-
src/mainwindow.cpp | 12 ++++++
src/mainwindow.h | 3 ++
src/mainwindow.ui | 13 ++++++
src/nxmaccessmanager.cpp | 2 -
src/resources.qrc | 3 +-
src/resources/mo_icon.png | Bin 0 -> 1011 bytes
src/resources/package.png | Bin 0 -> 1067 bytes
src/settingsdialog.cpp | 12 ------
src/settingsdialog.h | 23 ++++-------
src/settingsdialog.ui | 52 ++++++------------------
13 files changed, 109 insertions(+), 130 deletions(-)
create mode 100644 src/resources/mo_icon.png
create mode 100644 src/resources/package.png
(limited to 'src/main.cpp')
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index c74f3c1a..f7b953ad 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -27,6 +27,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
static const char COMPANY_NAME[] = "Tannin";
@@ -40,6 +41,11 @@ InstanceManager::InstanceManager()
{
}
+InstanceManager &InstanceManager::instance()
+{
+ static InstanceManager s_Instance;
+ return s_Instance;
+}
QString InstanceManager::currentInstance() const
{
@@ -49,6 +55,7 @@ QString InstanceManager::currentInstance() const
void InstanceManager::clearCurrentInstance()
{
setCurrentInstance("");
+ m_Reset = true;
}
void InstanceManager::setCurrentInstance(const QString &name)
@@ -81,26 +88,51 @@ QString InstanceManager::queryInstanceName() const
QString InstanceManager::chooseInstance(const QStringList &instanceList) const
{
- SelectionDialog selection(QObject::tr("Choose Instance"), nullptr);
+ enum class Special : uint8_t {
+ NewInstance,
+ Portable
+ };
+
+ SelectionDialog selection(
+ QString("%1
%2")
+ .arg(QObject::tr("Choose Instance"))
+ .arg(QObject::tr(
+ "Each Instance is a full set of MO data files (mods, "
+ "downloads, profiles, configuration, ...). Use multiple "
+ "instances for different games. If your MO folder is "
+ "writable, you can also store a single instance locally (called "
+ "a portable install).")),
+ nullptr);
selection.disableCancel();
for (const QString &instance : instanceList) {
selection.addChoice(instance, "", instance);
}
- selection.addChoice(QObject::tr("New"),
+ selection.addChoice(QIcon(":/MO/gui/add"), QObject::tr("New"),
QObject::tr("Create a new instance."),
- "");
+ static_cast(Special::NewInstance));
+
+ if (QFileInfo(qApp->applicationDirPath()).isWritable()) {
+ selection.addChoice(QIcon(":/MO/gui/package"), QObject::tr("Portable"),
+ QObject::tr("Use MO folder for data."),
+ static_cast(Special::Portable));
+ }
+
if (selection.exec() == QDialog::Rejected) {
qDebug("rejected");
throw MOBase::MyException(QObject::tr("Canceled"));
}
- QString choice = selection.getChoiceData().toString();
+ QVariant choice = selection.getChoiceData();
- if (choice.isEmpty()) {
- return queryInstanceName();
+ if (choice.type() == QVariant::String) {
+ return choice.toString();
} else {
- return choice;
+ switch (choice.value()) {
+ case Special::NewInstance: return queryInstanceName();
+ case Special::Portable: return QString();
+ default: throw std::runtime_error("invalid selection");
+ }
}
}
@@ -125,27 +157,6 @@ bool InstanceManager::portableInstall() const
}
-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()) {
@@ -166,31 +177,22 @@ void InstanceManager::createDataPath(const QString &dataPath) const
QString InstanceManager::determineDataPath()
{
QString instanceId = currentInstance();
+ if (instanceId.isEmpty() && portableInstall() && !m_Reset) {
+ // startup, apparently using portable mode before
+ return qApp->applicationDirPath();
+ }
+
QString dataPath = QDir::fromNativeSeparators(
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
+ "/" + instanceId);
- if ((instanceId.isEmpty() || !QFileInfo::exists(dataPath)) && !portableInstall()) {
- // no portable install and no selected instance
-
- QStringList instanceList = instances();
-
- if (instanceList.size() == 0) {
- if (QFileInfo(qApp->applicationDirPath()).isWritable()) {
- switch (queryInstallMode()) {
- case InstallationMode::PORTABLE: {
- instanceId = QString();
- } break;
- case InstallationMode::REGULAR: {
- instanceId = queryInstanceName();
- } break;
- }
- } else {
- instanceId = queryInstanceName();
- }
- } else {
- // don't offer portable instance if we can't set one up.
- instanceId = chooseInstance(instanceList);
+
+ if (instanceId.isEmpty() || !QFileInfo::exists(dataPath)) {
+ instanceId = chooseInstance(instances());
+ if (!instanceId.isEmpty()) {
+ dataPath = QDir::fromNativeSeparators(
+ QStandardPaths::writableLocation(QStandardPaths::DataLocation)
+ + "/" + instanceId);
}
}
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 2e17d1c0..a0a5df09 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -27,25 +27,21 @@ along with Mod Organizer. If not, see .
class InstanceManager {
- enum class InstallationMode {
- PORTABLE,
- REGULAR
- };
-
public:
- InstanceManager();
+ static InstanceManager &instance();
QString determineDataPath();
- QStringList instances() const;
void clearCurrentInstance();
private:
+ InstanceManager();
+
QString currentInstance() const;
QString instancePath() const;
- bool portableInstall() const;
+ QStringList instances() const;
void setCurrentInstance(const QString &name);
@@ -53,10 +49,11 @@ private:
QString chooseInstance(const QStringList &instanceList) const;
void createDataPath(const QString &dataPath) const;
- InstallationMode queryInstallMode() const;
+ bool portableInstall() const;
private:
QSettings m_AppSettings;
+ bool m_Reset {false};
};
diff --git a/src/main.cpp b/src/main.cpp
index 6940e288..e289453c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -630,13 +630,12 @@ int main(int argc, char *argv[])
QString dataPath;
try {
- dataPath = InstanceManager().determineDataPath();
+ dataPath = InstanceManager::instance().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");
@@ -647,7 +646,6 @@ int main(int argc, char *argv[])
}
int result = runApplication(application, instance, splash);
-
if (result != INT_MAX) {
return result;
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index dcff139a..66c2b557 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -37,6 +37,7 @@ along with Mod Organizer. If not, see .
#include "savegameinfo.h"
#include "spawn.h"
#include "versioninfo.h"
+#include "instancemanager.h"
#include "report.h"
#include "modlist.h"
@@ -3883,6 +3884,17 @@ void MainWindow::on_actionProblems_triggered()
}
}
+void MainWindow::on_actionChange_Game_triggered()
+{
+ if (QMessageBox::question(this, tr("Are you sure?"),
+ tr("This will restart MO, continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel)
+ == QMessageBox::Yes) {
+ InstanceManager::instance().clearCurrentInstance();
+ qApp->exit(INT_MAX);
+ }
+}
+
void MainWindow::setCategoryListVisible(bool visible)
{
if (visible) {
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 43b2bede..3364bb37 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -183,6 +183,9 @@ protected:
virtual void dragEnterEvent(QDragEnterEvent *event);
virtual void dropEvent(QDropEvent *event);
+private slots:
+ void on_actionChange_Game_triggered();
+
private slots:
void on_clickBlankButton_clicked();
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index f504994a..e30a165d 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -1197,6 +1197,7 @@ p, li { white-space: pre-wrap; }
false
+
@@ -1383,6 +1384,18 @@ Right now this has very limited functionality
Ctrl+C
+
+
+
+ :/MO/gui/app_icon:/MO/gui/app_icon
+
+
+ Change Game
+
+
+ Open the game selection dialog
+
+
diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp
index 3f90647b..17c50e35 100644
--- a/src/nxmaccessmanager.cpp
+++ b/src/nxmaccessmanager.cpp
@@ -215,7 +215,6 @@ void NXMAccessManager::login(const QString &username, const QString &password)
emit loginSuccessful(false);
return;
}
-
m_Username = username;
m_Password = password;
pageLogin();
@@ -237,7 +236,6 @@ QString NXMAccessManager::userAgent(const QString &subModule) const
void NXMAccessManager::pageLogin()
{
qDebug("logging %s in on Nexus", qPrintable(m_Username));
-
QString requestString = (Nexus_Management_URL + "/Sessions/?Login&uri=%1")
.arg(QString(QUrl::toPercentEncoding(Nexus_Management_URL)));
diff --git a/src/resources.qrc b/src/resources.qrc
index 8434b367..d357801c 100644
--- a/src/resources.qrc
+++ b/src/resources.qrc
@@ -26,7 +26,6 @@
resources/software-update-available.png
resources/emblem-important.png
resources/check.png
- mo_icon.ico
resources/dialog-warning.png
resources/symbol-backup.png
resources/applications-accessories.png
@@ -68,6 +67,8 @@
resources/status_active.png
resources/status_awaiting.png
resources/status_inactive.png
+ resources/mo_icon.png
+ resources/package.png
resources/contents/jigsaw-piece.png
diff --git a/src/resources/mo_icon.png b/src/resources/mo_icon.png
new file mode 100644
index 00000000..c926d722
Binary files /dev/null and b/src/resources/mo_icon.png differ
diff --git a/src/resources/package.png b/src/resources/package.png
new file mode 100644
index 00000000..4b55b504
Binary files /dev/null and b/src/resources/package.png differ
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index c66cc243..0d86018c 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -217,18 +217,6 @@ 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);
- }
-}
-
void SettingsDialog::on_clearCacheButton_clicked()
{
QDir(Settings::instance().getCacheDirectory()).removeRecursively();
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
index 1ae21015..658fbce4 100644
--- a/src/settingsdialog.h
+++ b/src/settingsdialog.h
@@ -52,21 +52,6 @@ signals:
void resetDialogs();
-private slots:
- void on_clearCacheButton_clicked();
-
-private slots:
- void on_browseBaseDirBtn_clicked();
-
-private slots:
- void on_browseOverwriteDirBtn_clicked();
-
-private slots:
- void on_browseProfilesDirBtn_clicked();
-
-private slots:
- void on_changeInstanceButton_clicked();
-
private:
void storeSettings(QListWidgetItem *pluginItem);
@@ -92,6 +77,14 @@ private slots:
void on_associateButton_clicked();
+ void on_clearCacheButton_clicked();
+
+ void on_browseBaseDirBtn_clicked();
+
+ void on_browseOverwriteDirBtn_clicked();
+
+ void on_browseProfilesDirBtn_clicked();
+
private:
Ui::SettingsDialog *ui;
};
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 9ebed3b8..1f751da8 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -124,19 +124,6 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
@@ -182,6 +169,19 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
-
@@ -198,32 +198,6 @@ If you use pre-releases, never contact me directly by e-mail or via private mess
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Restart MO and choose a different set of data paths.
-
-
- This will restart MO and give you opportunity to switch to a different set of data paths.
-
-
- Change Instance
-
-
-
--
cgit v1.3.1
From fcebf21c446500af79bf58486db503257bb4bc30 Mon Sep 17 00:00:00 2001
From: Tannin
Date: Sun, 5 Jun 2016 14:16:55 +0200
Subject: fixed startup errors
---
src/instancemanager.cpp | 2 +-
src/main.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index f7b953ad..a9182d52 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -196,7 +196,7 @@ QString InstanceManager::determineDataPath()
}
}
- if (instanceId.isEmpty() || !QFileInfo::exists(dataPath)) {
+ if (instanceId.isEmpty()) {
return qApp->applicationDirPath();
} else {
setCurrentInstance(instanceId);
diff --git a/src/main.cpp b/src/main.cpp
index e289453c..6b585b5c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -533,13 +533,13 @@ int runApplication(MOApplication &application, SingleInstance &instance,
// 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;
}
}
- return 0;
}
NexusInterface::instance()->getAccessManager()->startLoginCheck();
--
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/main.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 695593968b0d8b912c0546aafe4ba97c031a590c Mon Sep 17 00:00:00 2001
From: lepresidente
Date: Sun, 4 Dec 2016 18:15:59 +0200
Subject: updated email for dump reports.
---
src/main.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 16b6b80f..d14641a4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -149,7 +149,7 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
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 sherb@gmx.net, "
+ "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"
--
cgit v1.3.1
From 3974ddced4e02866c6548066d0c546f3cf6d77db Mon Sep 17 00:00:00 2001
From: Al12rs
Date: Fri, 10 Nov 2017 21:00:24 +0100
Subject: Fix for MO finding the wrong game to manage. Commented out code that
tried to deduce game and found wrong one. Now, if not already set in INI,
file MO will ask the user which one to manage.
---
src/main.cpp | 4 ++++
1 file changed, 4 insertions(+)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index d14641a4..526563a2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -318,6 +318,9 @@ MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &sett
}
}
+ //The following code would try to determine the right game to mange but it would usually find the wrong one
+ //so it was commented out.
+ /*
//OK, we are in a new setup or existing info is useless.
//See if MO has been installed inside a game directory
for (IPluginGame * const game : plugins.plugins()) {
@@ -341,6 +344,7 @@ MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &sett
//OK, chop off the last directory and try again
} while (gameDir.cdUp());
}
+ */
//Then try a selection dialogue.
if (!gamePath.isEmpty() || !gameName.isEmpty()) {
--
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/main.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 b75e3c12318267be1589cee5e13a9fc89b0097b1 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Sat, 9 Dec 2017 21:38:47 +0200
Subject: Collect crash dumps also for vectored exceptions
---
src/main.cpp | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 71fbc943..40224170 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -128,6 +128,12 @@ bool isNxmLink(const QString &link)
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
+ if ((exceptionPtrs->ExceptionRecord->ExceptionCode < 0x80000000) // non-critical
+ || (exceptionPtrs->ExceptionRecord->ExceptionCode == 0xe06d7363)) { // cpp exception
+ // don't report non-critical exceptions
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
const std::wstring& dumpPath = OrganizerCore::crashDumpsPath();
int dumpRes =
CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str());
@@ -522,7 +528,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
int main(int argc, char *argv[])
{
- SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
+ AddVectoredExceptionHandler(0, MyUnhandledExceptionFilter);
MOApplication application(argc, argv);
QStringList arguments = application.arguments();
--
cgit v1.3.1
From d43f35f56bc2d9164b6fe9aa5591eef287bebe07 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Sun, 10 Dec 2017 23:33:01 +0200
Subject: Run shortcuts using moshortcut:// to avoid command line problems
---
src/main.cpp | 21 ++++++++++-
src/mainwindow.cpp | 7 ++--
src/organizercore.cpp | 96 +++++++++++++++++++++++++++++----------------------
src/organizercore.h | 10 +++++-
4 files changed, 87 insertions(+), 47 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 40224170..9b2afecc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -126,6 +126,16 @@ bool isNxmLink(const QString &link)
return link.startsWith("nxm://", Qt::CaseInsensitive);
}
+bool isMoShortcut(const QString &link)
+{
+ return link.startsWith("moshortcut://", Qt::CaseInsensitive);
+}
+
+QString moShortcutName(const QString &link)
+{
+ return link.mid(strlen("moshortcut://"));
+}
+
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
if ((exceptionPtrs->ExceptionRecord->ExceptionCode < 0x80000000) // non-critical
@@ -467,7 +477,16 @@ int runApplication(MOApplication &application, SingleInstance &instance,
// if we have a command line parameter, it is either a nxm link or
// a binary to start
if (arguments.size() > 1) {
- if (isNxmLink(arguments.at(1))) {
+ if (isMoShortcut(arguments.at(1))) {
+ try {
+ organizer.runShortcut(moShortcutName(arguments.at(1)));
+ return 0;
+ } catch (const std::exception &e) {
+ reportError(
+ QObject::tr("failed to start shortcut: %1").arg(e.what()));
+ return 1;
+ }
+ } else if (isNxmLink(arguments.at(1))) {
qDebug("starting download from command line: %s",
qPrintable(arguments.at(1)));
organizer.externalMessage(arguments.at(1));
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 1db895fc..632b64e9 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -3199,11 +3199,10 @@ void MainWindow::addWindowsLink(const ShortcutType mapping)
QString executable = QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath());
std::wstring targetFile = ToWString(exeInfo.absoluteFilePath());
- std::wstring parameter = ToWString(QString("\"%1\" %2").arg(executable)
- .arg(selectedExecutable.m_Arguments));
- std::wstring description = ToWString(selectedExecutable.m_BinaryInfo.fileName());
+ std::wstring parameter = ToWString(QString("\"moshortcut://%1\"").arg(selectedExecutable.m_Title));
+ std::wstring description = ToWString(QString("Run %1 with ModOrganizer").arg(selectedExecutable.m_Title));
std::wstring iconFile = ToWString(executable);
- std::wstring currentDirectory = ToWString(QDir::toNativeSeparators(exeInfo.absolutePath()));
+ std::wstring currentDirectory = ToWString(QDir::toNativeSeparators(qApp->applicationDirPath()));
if (CreateShortcut(targetFile.c_str()
, parameter.c_str()
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 30f96caf..116552df 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -1068,19 +1068,9 @@ QStringList OrganizerCore::modsSortedByProfilePriority() const
void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, const QString &steamAppID, const QString &customOverwrite)
{
- ILockedWaitingForProcess* uilock = nullptr;
- if (m_UserInterface != nullptr) {
- uilock = m_UserInterface->lock();
- }
- ON_BLOCK_EXIT([&] () {
- if (m_UserInterface != nullptr) { m_UserInterface->unlock(); }
- });
-
- HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->name(), currentDirectory, steamAppID, customOverwrite);
+ DWORD processExitCode = 0;
+ HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->name(), currentDirectory, steamAppID, customOverwrite, &processExitCode);
if (processHandle != INVALID_HANDLE_VALUE) {
- DWORD processExitCode;
- (void)waitForProcessCompletion(processHandle, &processExitCode, uilock);
-
refreshDirectoryStructure();
// need to remove our stored load order because it may be outdated if a foreign tool changed the
// file time. After removing that file, refreshESPList will use the file time as the order
@@ -1092,7 +1082,6 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument
refreshESPList();
savePluginList();
- cycleDiagnostics();
//These callbacks should not fiddle with directoy structure and ESPs.
m_FinishedRun(binary.absoluteFilePath(), processExitCode);
@@ -1104,7 +1093,45 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary,
const QString &profileName,
const QDir ¤tDirectory,
const QString &steamAppID,
- const QString &customOverwrite)
+ const QString &customOverwrite,
+ LPDWORD exitCode)
+{
+ HANDLE processHandle = spawnBinaryProcess(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite);
+ if (processHandle != INVALID_HANDLE_VALUE) {
+ std::unique_ptr dlg;
+ ILockedWaitingForProcess* uilock = nullptr;
+
+ if (m_UserInterface != nullptr) {
+ uilock = m_UserInterface->lock();
+ }
+ else {
+ // i.e. when running command line shortcuts there is no m_UserInterface
+ dlg.reset(new LockedDialog);
+ dlg->show();
+ dlg->setEnabled(true);
+ uilock = dlg.get();
+ }
+
+ ON_BLOCK_EXIT([&]() {
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->unlock();
+ } });
+
+ DWORD ignoreExitCode;
+ waitForProcessCompletion(processHandle, exitCode ? exitCode : &ignoreExitCode, uilock);
+ cycleDiagnostics();
+ }
+
+ return processHandle;
+}
+
+
+HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary,
+ const QString &arguments,
+ const QString &profileName,
+ const QDir ¤tDirectory,
+ const QString &steamAppID,
+ const QString &customOverwrite)
{
prepareStart();
@@ -1199,6 +1226,19 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary,
}
}
+HANDLE OrganizerCore::runShortcut(const QString &title)
+{
+ Executable& exe = m_ExecutablesList.find(title);
+
+ return spawnBinaryDirect(
+ exe.m_BinaryInfo, exe.m_Arguments,
+ m_CurrentProfile->name(),
+ exe.m_WorkingDirectory.length() != 0
+ ? exe.m_WorkingDirectory
+ : exe.m_BinaryInfo.absolutePath(),
+ exe.m_SteamAppID, "");
+}
+
HANDLE OrganizerCore::startApplication(const QString &executable,
const QStringList &args,
const QString &cwd,
@@ -1260,33 +1300,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable,
}
}
- HANDLE processHandle = spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite);
- if (processHandle != INVALID_HANDLE_VALUE) {
- std::unique_ptr dlg;
- ILockedWaitingForProcess* uilock = nullptr;
-
- if (m_UserInterface != nullptr) {
- uilock = m_UserInterface->lock();
- }
- else {
- // i.e. when running command line shortcuts there is no m_UserInterface
- dlg.reset(new LockedDialog);
- dlg->show();
- dlg->setEnabled(true);
- uilock = dlg.get();
- }
-
- ON_BLOCK_EXIT([&]() {
- if (m_UserInterface != nullptr) {
- m_UserInterface->unlock();
- } });
-
- DWORD processExitCode;
- waitForProcessCompletion(processHandle, &processExitCode, uilock);
- cycleDiagnostics();
- }
-
- return processHandle;
+ return spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite);
}
bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode)
diff --git a/src/organizercore.h b/src/organizercore.h
index 0927c88e..901780a1 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -145,7 +145,14 @@ public:
const QString &profileName,
const QDir ¤tDirectory,
const QString &steamAppID,
- const QString &customOverwrite);
+ const QString &customOverwrite,
+ LPDWORD exitCode = nullptr);
+
+ HANDLE spawnBinaryProcess(const QFileInfo &binary, const QString &arguments,
+ const QString &profileName,
+ const QDir ¤tDirectory,
+ const QString &steamAppID,
+ const QString &customOverwrite);
void loginSuccessfulUpdate(bool necessary);
void loginFailedUpdate(const QString &message);
@@ -192,6 +199,7 @@ public:
DownloadManager *downloadManager();
PluginList *pluginList();
ModList *modList();
+ HANDLE runShortcut(const QString &title);
HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile);
bool waitForApplication(HANDLE processHandle, LPDWORD exitCode = nullptr);
bool onModInstalled(const std::function &func);
--
cgit v1.3.1
From ad702537bd6dc4eff40dd6b6d51536b2758dca6c Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Mon, 11 Dec 2017 00:11:17 +0200
Subject: Use single instance also for MO shortcuts
---
src/main.cpp | 27 +++++++--------------------
src/organizercore.cpp | 5 ++++-
src/organizercore.h | 4 ++++
3 files changed, 15 insertions(+), 21 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 9b2afecc..dbf41afb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -121,21 +121,6 @@ bool bootstrap()
}
-bool isNxmLink(const QString &link)
-{
- return link.startsWith("nxm://", Qt::CaseInsensitive);
-}
-
-bool isMoShortcut(const QString &link)
-{
- return link.startsWith("moshortcut://", Qt::CaseInsensitive);
-}
-
-QString moShortcutName(const QString &link)
-{
- return link.mid(strlen("moshortcut://"));
-}
-
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
if ((exceptionPtrs->ExceptionRecord->ExceptionCode < 0x80000000) // non-critical
@@ -477,16 +462,16 @@ int runApplication(MOApplication &application, SingleInstance &instance,
// if we have a command line parameter, it is either a nxm link or
// a binary to start
if (arguments.size() > 1) {
- if (isMoShortcut(arguments.at(1))) {
+ if (OrganizerCore::isMoShortcut(arguments.at(1))) {
try {
- organizer.runShortcut(moShortcutName(arguments.at(1)));
+ organizer.runShortcut(OrganizerCore::moShortcutName(arguments.at(1)));
return 0;
} catch (const std::exception &e) {
reportError(
QObject::tr("failed to start shortcut: %1").arg(e.what()));
return 1;
}
- } else if (isNxmLink(arguments.at(1))) {
+ } else if (OrganizerCore::isNxmLink(arguments.at(1))) {
qDebug("starting download from command line: %s",
qPrintable(arguments.at(1)));
organizer.externalMessage(arguments.at(1));
@@ -579,8 +564,10 @@ int main(int argc, char *argv[])
SingleInstance instance(forcePrimary);
if (!instance.primaryInstance()) {
- if ((arguments.size() == 2) && isNxmLink(arguments.at(1))) {
- qDebug("not primary instance, sending download message");
+ if ((arguments.size() == 2)
+ && (OrganizerCore::isMoShortcut(arguments.at(1)) || OrganizerCore::isNxmLink(arguments.at(1))))
+ {
+ qDebug("not primary instance, sending shortcut/download message");
instance.sendMessage(arguments.at(1));
return 0;
} else if (arguments.size() == 1) {
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 116552df..bc0578b3 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -578,7 +578,10 @@ void OrganizerCore::downloadRequestedNXM(const QString &url)
void OrganizerCore::externalMessage(const QString &message)
{
- if (message.left(6).toLower() == "nxm://") {
+ if (isMoShortcut(message)) {
+ runShortcut(moShortcutName(message));
+ }
+ else if (isNxmLink(message)) {
MessageDialog::showMessage(tr("Download started"), qApp->activeWindow());
downloadRequestedNXM(message);
}
diff --git a/src/organizercore.h b/src/organizercore.h
index 901780a1..f8806289 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -85,6 +85,10 @@ private:
typedef boost::signals2::signal SignalModInstalled;
public:
+ static bool isNxmLink(const QString &link) { return link.startsWith("nxm://", Qt::CaseInsensitive); }
+ static bool isMoShortcut(const QString &link) { return link.startsWith("moshortcut://", Qt::CaseInsensitive); }
+ static QString moShortcutName(const QString &link) { return link.mid(strlen("moshortcut://")); }
+
OrganizerCore(const QSettings &initSettings);
--
cgit v1.3.1
From ebb30e0c3731ee4acc86de63c4b32a6be9e4de4f Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Mon, 11 Dec 2017 20:13:35 +0200
Subject: Revert "Collect crash dumps also for vectored exceptions"
This reverts commit b75e3c12318267be1589cee5e13a9fc89b0097b1.
---
src/main.cpp | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index dbf41afb..7f1f199e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -123,12 +123,6 @@ bool bootstrap()
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
- if ((exceptionPtrs->ExceptionRecord->ExceptionCode < 0x80000000) // non-critical
- || (exceptionPtrs->ExceptionRecord->ExceptionCode == 0xe06d7363)) { // cpp exception
- // don't report non-critical exceptions
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
const std::wstring& dumpPath = OrganizerCore::crashDumpsPath();
int dumpRes =
CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str());
@@ -532,7 +526,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
int main(int argc, char *argv[])
{
- AddVectoredExceptionHandler(0, MyUnhandledExceptionFilter);
+ SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
MOApplication application(argc, argv);
QStringList arguments = application.arguments();
--
cgit v1.3.1
From 2c69f9c407ec803c3c99713fe591717ebcee191b Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Mon, 11 Dec 2017 20:23:42 +0200
Subject: call previous unhandled exception filter
---
src/main.cpp | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 7f1f199e..eed4dfd3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -120,20 +120,22 @@ bool bootstrap()
return true;
}
+LPTOP_LEVEL_EXCEPTION_FILTER prevUnhandledExceptionFilter = nullptr;
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
const std::wstring& dumpPath = OrganizerCore::crashDumpsPath();
int dumpRes =
CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str());
- if (!dumpRes) {
+ if (!dumpRes)
qCritical("ModOrganizer has crashed, crash dump created.");
- return EXCEPTION_EXECUTE_HANDLER;
- }
- else {
+ else
qCritical("ModOrganizer has crashed, CreateMiniDump failed (%d, error %lu).", dumpRes, GetLastError());
+
+ if (prevUnhandledExceptionFilter)
+ return prevUnhandledExceptionFilter(exceptionPtrs);
+ else
return EXCEPTION_CONTINUE_SEARCH;
- }
}
static bool HaveWriteAccess(const std::wstring &path)
@@ -526,7 +528,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
int main(int argc, char *argv[])
{
- SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
+ prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
MOApplication application(argc, argv);
QStringList arguments = application.arguments();
--
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/main.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 4d54b962aaa13e6f78f2c89dcc9f03f9fadac35c Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Wed, 13 Dec 2017 09:33:20 +0200
Subject: Allow silent closing during instance selection
---
src/main.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index b4faf570..90c15ccd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -578,8 +578,8 @@ int main(int argc, char *argv[])
try {
dataPath = InstanceManager::instance().determineDataPath();
} catch (const std::exception &e) {
- QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"),
- e.what());
+ if (strcmp(e.what(),"Canceled"))
+ QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"), e.what());
return 1;
}
application.setProperty("dataPath", dataPath);
--
cgit v1.3.1
From 4656ba9447d9bd0ebe5540a54892ec41abda047b Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Sun, 17 Dec 2017 22:31:46 +0200
Subject: Increase mo_interface log to help diagnose problems
---
src/main.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 90c15ccd..17ef5eba 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -587,7 +587,7 @@ int main(int argc, char *argv[])
// 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");
+ LogBuffer::init(1000, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
QString splash = dataPath + "/splash.png";
if (!QFile::exists(dataPath + "/splash.png")) {
--
cgit v1.3.1
From 7dad8bcb282ac385267087961b29af608f81593d Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Mon, 18 Dec 2017 02:09:21 +0200
Subject: avoid splash screen when running a shortcut
---
src/main.cpp | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 17ef5eba..4cf47a3c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -367,8 +367,6 @@ int runApplication(MOApplication &application, SingleInstance &instance,
const QString &splashPath)
{
qDebug("start main application");
- QPixmap pixmap(splashPath);
- QSplashScreen splash(pixmap);
QString dataPath = application.property("dataPath").toString();
qDebug("data path: %s", qPrintable(dataPath));
@@ -382,13 +380,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
try {
qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
- splash.show();
- } catch (const std::exception &e) {
- reportError(e.what());
- return 1;
- }
- try {
QSettings settings(dataPath + "/"
+ QString::fromStdWString(AppConfig::iniFileName()),
QSettings::IniFormat);
@@ -488,6 +480,10 @@ int runApplication(MOApplication &application, SingleInstance &instance,
}
}
+ QPixmap pixmap(splashPath);
+ QSplashScreen splash(pixmap);
+ splash.show();
+
NexusInterface::instance()->getAccessManager()->startLoginCheck();
qDebug("initializing tutorials");
--
cgit v1.3.1
From cb1c9f5e83e98039d38f548c80d4b95442163cf2 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Tue, 19 Dec 2017 00:44:18 +0200
Subject: Tie moshortcuts to a specific instance
---
src/CMakeLists.txt | 2 ++
src/executableslist.cpp | 2 +-
src/instancemanager.cpp | 17 ++++++++++++++---
src/instancemanager.h | 8 ++++++--
src/main.cpp | 16 +++++++++++-----
src/mainwindow.cpp | 3 ++-
src/moshortcut.cpp | 39 +++++++++++++++++++++++++++++++++++++++
src/moshortcut.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++
src/organizercore.cpp | 15 +++++++++++----
src/organizercore.h | 6 ++----
10 files changed, 134 insertions(+), 20 deletions(-)
create mode 100644 src/moshortcut.cpp
create mode 100644 src/moshortcut.h
(limited to 'src/main.cpp')
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 914bdd12..0c70fe57 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -88,6 +88,7 @@ SET(organizer_SRCS
instancemanager.cpp
usvfsconnector.cpp
eventfilter.cpp
+ moshortcut.cpp
shared/windows_error.cpp
shared/error_report.cpp
@@ -179,6 +180,7 @@ SET(organizer_HDRS
usvfsconnector.h
eventfilter.h
descriptionpage.h
+ moshortcut.h
shared/windows_error.h
shared/error_report.h
diff --git a/src/executableslist.cpp b/src/executableslist.cpp
index b1890ac9..21cb6ed4 100644
--- a/src/executableslist.cpp
+++ b/src/executableslist.cpp
@@ -86,7 +86,7 @@ Executable &ExecutablesList::find(const QString &title)
return exe;
}
}
- throw std::runtime_error(QString("invalid name %1").arg(title).toLocal8Bit().constData());
+ throw std::runtime_error(QString("invalid executable name %1").arg(title).toLocal8Bit().constData());
}
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index b1b85cc6..34e23d7b 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -47,9 +47,19 @@ InstanceManager &InstanceManager::instance()
return s_Instance;
}
+void InstanceManager::overrideInstance(const QString& instanceName)
+{
+ m_overrideInstanceName = instanceName;
+ m_overrideInstance = true;
+}
+
+
QString InstanceManager::currentInstance() const
{
- return m_AppSettings.value(INSTANCE_KEY, "").toString();
+ if (m_overrideInstance)
+ return m_overrideInstanceName;
+ else
+ return m_AppSettings.value(INSTANCE_KEY, "").toString();
}
void InstanceManager::clearCurrentInstance()
@@ -177,7 +187,8 @@ void InstanceManager::createDataPath(const QString &dataPath) const
QString InstanceManager::determineDataPath()
{
QString instanceId = currentInstance();
- if (instanceId.isEmpty() && portableInstall() && !m_Reset) {
+ if (instanceId.isEmpty() && !m_Reset && (m_overrideInstance || portableInstall()))
+ {
// startup, apparently using portable mode before
return qApp->applicationDirPath();
}
@@ -187,7 +198,7 @@ QString InstanceManager::determineDataPath()
+ "/" + instanceId);
- if (instanceId.isEmpty() || !QFileInfo::exists(dataPath)) {
+ if (!m_overrideInstance && (instanceId.isEmpty() || !QFileInfo::exists(dataPath))) {
instanceId = chooseInstance(instances());
setCurrentInstance(instanceId);
if (!instanceId.isEmpty()) {
diff --git a/src/instancemanager.h b/src/instancemanager.h
index a0a5df09..2782c71d 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -34,11 +34,14 @@ public:
QString determineDataPath();
void clearCurrentInstance();
+ void overrideInstance(const QString& instanceName);
+
+ QString currentInstance() const;
+
private:
InstanceManager();
- QString currentInstance() const;
QString instancePath() const;
QStringList instances() const;
@@ -55,5 +58,6 @@ private:
QSettings m_AppSettings;
bool m_Reset {false};
-
+ bool m_overrideInstance{false};
+ QString m_overrideInstanceName;
};
diff --git a/src/main.cpp b/src/main.cpp
index 4cf47a3c..3d315f1d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -45,6 +45,7 @@ along with Mod Organizer. If not, see .
#include "tutorialmanager.h"
#include "nxmaccessmanager.h"
#include "instancemanager.h"
+#include "moshortcut.h"
#include
#include
@@ -450,9 +451,9 @@ int runApplication(MOApplication &application, SingleInstance &instance,
// if we have a command line parameter, it is either a nxm link or
// a binary to start
if (arguments.size() > 1) {
- if (OrganizerCore::isMoShortcut(arguments.at(1))) {
+ if (MOShortcut shortcut{ arguments.at(1) }) {
try {
- organizer.runShortcut(OrganizerCore::moShortcutName(arguments.at(1)));
+ organizer.runShortcut(shortcut);
return 0;
} catch (const std::exception &e) {
reportError(
@@ -552,10 +553,12 @@ int main(int argc, char *argv[])
forcePrimary = true;
}
+ MOShortcut moshortcut{ arguments.size() > 1 ? arguments.at(1) : "" };
+
SingleInstance instance(forcePrimary);
if (!instance.primaryInstance()) {
- if ((arguments.size() == 2)
- && (OrganizerCore::isMoShortcut(arguments.at(1)) || OrganizerCore::isNxmLink(arguments.at(1))))
+ if (moshortcut ||
+ arguments.size() > 1 && OrganizerCore::isNxmLink(arguments.at(1)))
{
qDebug("not primary instance, sending shortcut/download message");
instance.sendMessage(arguments.at(1));
@@ -572,7 +575,10 @@ int main(int argc, char *argv[])
QString dataPath;
try {
- dataPath = InstanceManager::instance().determineDataPath();
+ InstanceManager& instanceManager = InstanceManager::instance();
+ if (moshortcut && moshortcut.hasInstance())
+ instanceManager.overrideInstance(moshortcut.instance());
+ dataPath = instanceManager.determineDataPath();
} catch (const std::exception &e) {
if (strcmp(e.what(),"Canceled"))
QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"), e.what());
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 6f156269..1c5e321d 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -3331,7 +3331,8 @@ void MainWindow::addWindowsLink(const ShortcutType mapping)
QString executable = QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath());
std::wstring targetFile = ToWString(exeInfo.absoluteFilePath());
- std::wstring parameter = ToWString(QString("\"moshortcut://%1\"").arg(selectedExecutable.m_Title));
+ std::wstring parameter = ToWString(
+ QString("\"moshortcut://%1:%2\"").arg(InstanceManager::instance().currentInstance(),selectedExecutable.m_Title));
std::wstring description = ToWString(QString("Run %1 with ModOrganizer").arg(selectedExecutable.m_Title));
std::wstring iconFile = ToWString(executable);
std::wstring currentDirectory = ToWString(QDir::toNativeSeparators(qApp->applicationDirPath()));
diff --git a/src/moshortcut.cpp b/src/moshortcut.cpp
new file mode 100644
index 00000000..c8c2ef6f
--- /dev/null
+++ b/src/moshortcut.cpp
@@ -0,0 +1,39 @@
+/*
+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 "moshortcut.h"
+
+
+MOShortcut::MOShortcut(const QString& link)
+ : m_valid(link.startsWith("moshortcut://"))
+ , m_hasInstance(false)
+{
+ if (m_valid) {
+ int start = (int)strlen("moshortcut://");
+ int sep = link.indexOf(':', start);
+ if (sep >= 0) {
+ m_hasInstance = true;
+ m_instance = link.mid(start, sep - start);
+ m_executable = link.mid(sep + 1);
+ }
+ else
+ m_executable = link.mid(start);
+ }
+}
diff --git a/src/moshortcut.h b/src/moshortcut.h
new file mode 100644
index 00000000..7b7574b9
--- /dev/null
+++ b/src/moshortcut.h
@@ -0,0 +1,46 @@
+/*
+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
+
+
+class MOShortcut {
+
+public:
+ MOShortcut(const QString& link);
+
+ /// true iff intialized using a valid moshortcut link
+ operator bool() const { return m_valid; }
+
+ bool hasInstance() const { return m_hasInstance; }
+
+ const QString& instance() const { return m_instance; }
+
+ const QString& executable() const { return m_executable; }
+
+private:
+ QString m_instance;
+ QString m_executable;
+ bool m_valid;
+ bool m_hasInstance;
+};
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 3be9559a..7668485c 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -32,6 +32,7 @@
#include
#include
#include "lockeddialog.h"
+#include "instancemanager.h"
#include
#include
@@ -578,8 +579,8 @@ void OrganizerCore::downloadRequestedNXM(const QString &url)
void OrganizerCore::externalMessage(const QString &message)
{
- if (isMoShortcut(message)) {
- runShortcut(moShortcutName(message));
+ if (MOShortcut moshortcut{ message }) {
+ runShortcut(moshortcut);
}
else if (isNxmLink(message)) {
MessageDialog::showMessage(tr("Download started"), qApp->activeWindow());
@@ -1228,9 +1229,15 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary,
}
}
-HANDLE OrganizerCore::runShortcut(const QString &title)
+HANDLE OrganizerCore::runShortcut(const MOShortcut& shortcut)
{
- Executable& exe = m_ExecutablesList.find(title);
+ if (shortcut.hasInstance() && shortcut.instance() != InstanceManager::instance().currentInstance())
+ throw std::runtime_error(
+ QString("Refusing to run executable from different instance %1:%2")
+ .arg(shortcut.instance(),shortcut.executable())
+ .toLocal8Bit().constData());
+
+ Executable& exe = m_ExecutablesList.find(shortcut.executable());
return spawnBinaryDirect(
exe.m_BinaryInfo, exe.m_Arguments,
diff --git a/src/organizercore.h b/src/organizercore.h
index decb3d01..f98e9d0a 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -13,6 +13,7 @@
#include "downloadmanager.h"
#include "executableslist.h"
#include "usvfsconnector.h"
+#include "moshortcut.h"
#include
#include
#include
@@ -86,9 +87,6 @@ private:
public:
static bool isNxmLink(const QString &link) { return link.startsWith("nxm://", Qt::CaseInsensitive); }
- static bool isMoShortcut(const QString &link) { return link.startsWith("moshortcut://", Qt::CaseInsensitive); }
- static QString moShortcutName(const QString &link) { return link.mid(strlen("moshortcut://")); }
-
OrganizerCore(const QSettings &initSettings);
@@ -203,7 +201,7 @@ public:
DownloadManager *downloadManager();
PluginList *pluginList();
ModList *modList();
- HANDLE runShortcut(const QString &title);
+ HANDLE runShortcut(const MOShortcut& shortcut);
HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile);
bool waitForApplication(HANDLE processHandle, LPDWORD exitCode = nullptr);
HANDLE findAndOpenAUSVFSProcess();
--
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/main.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 57e65abf75f62bf07880e0a2f888eaf5f14f0871 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Wed, 27 Dec 2017 01:31:43 +0200
Subject: Clean up proxy spawning a process (cleaner args forwarding and
QProcess had some problems even without arguments)
---
src/main.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 62 insertions(+), 11 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 99ff641a..5418abc2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -78,6 +78,7 @@ along with Mod Organizer. If not, see .
#include
#include
+#include
#include
@@ -139,6 +140,60 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
return EXCEPTION_CONTINUE_SEARCH;
}
+// Parses the first parseArgCount arguments of the current process command line and returns
+// them in parsedArgs, the rest of the command line is returned untouched.
+LPCWSTR UntouchedCommandLineArguments(int parseArgCount, std::vector& parsedArgs)
+{
+ LPCWSTR cmd = GetCommandLineW();
+ LPCWSTR arg = nullptr; // to skip executable name
+ for (; parseArgCount >= 0 && *cmd; ++cmd)
+ {
+ if (*cmd == '"') {
+ int escaped = 0;
+ for (++cmd; *cmd && (*cmd != '"' || escaped % 2 != 0); ++cmd)
+ escaped = *cmd == '\\' ? escaped + 1 : 0;
+ }
+ if (*cmd == ' ') {
+ if (arg)
+ if (cmd-1 > arg && *arg == '"' && *(cmd-1) == '"')
+ parsedArgs.push_back(std::wstring(arg+1, cmd-1));
+ else
+ parsedArgs.push_back(std::wstring(arg, cmd));
+ arg = cmd + 1;
+ --parseArgCount;
+ }
+ }
+ return cmd;
+}
+
+static int SpawnWaitProcess(LPCWSTR workingDirectory, LPCWSTR commandLine) {
+ PROCESS_INFORMATION pi{ 0 };
+ STARTUPINFO si{ 0 };
+ si.cb = sizeof(si);
+ std::wstring commandLineCopy = commandLine;
+
+ if (!CreateProcessW(NULL, &commandLineCopy[0], NULL, NULL, FALSE, 0, NULL, workingDirectory, &si, &pi)) {
+ // A bit of a problem where to log the error message here, at least this way you can get the message
+ // using a either DebugView or a live debugger:
+ std::wostringstream ost;
+ ost << L"CreateProcess failed: " << commandLine << ", " << GetLastError();
+ OutputDebugStringW(ost.str().c_str());
+ return -1;
+ }
+
+ WaitForSingleObject(pi.hProcess, INFINITE);
+
+ DWORD exitCode = (DWORD)-1;
+ ::GetExitCodeProcess(pi.hProcess, &exitCode);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ return static_cast(exitCode);
+}
+
+static DWORD WaitForProcess() {
+
+}
+
static bool HaveWriteAccess(const std::wstring &path)
{
bool writable = false;
@@ -532,20 +587,16 @@ int runApplication(MOApplication &application, SingleInstance &instance,
int main(int argc, char *argv[])
{
+ if (argc >= 4) {
+ std::vector arg;
+ auto args = UntouchedCommandLineArguments(2, arg);
+ if (arg[0] == L"launch")
+ return SpawnWaitProcess(arg[1].c_str(), args);
+ }
+
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)
--
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/main.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 58ec83f8c86784b7ea1bfcc67d575c91606beca8 Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Thu, 4 Jan 2018 20:53:24 +0200
Subject: Log the MO version for diagnostic purposes
---
src/main.cpp | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 4c5ac75c..3e02a4a7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -419,10 +419,28 @@ void setupPath()
::SetEnvironmentVariableW(L"PATH", newPath.c_str());
}
+static QString getVersionDisplayString()
+{
+ VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath()));
+ return VersionInfo(version.dwFileVersionMS >> 16,
+ version.dwFileVersionMS & 0xFFFF,
+ version.dwFileVersionLS >> 16,
+ version.dwFileVersionLS & 0xFFFF).displayString();
+}
+
int runApplication(MOApplication &application, SingleInstance &instance,
const QString &splashPath)
{
- qDebug("start main application");
+
+ qDebug("Starting Mod Organizer version %s revision %s", qPrintable(getVersionDisplayString()),
+#if defined(HGID)
+ HGID
+#elif defined(GITID)
+ GITID
+#else
+ "unknown"
+#endif
+ );
QString dataPath = application.property("dataPath").toString();
qDebug("data path: %s", qPrintable(dataPath));
--
cgit v1.3.1
From 71995f03434be1a7f8b9877089af1bda24e8720b Mon Sep 17 00:00:00 2001
From: Eran Mizrahi
Date: Sat, 6 Jan 2018 03:51:34 +0200
Subject: preload openssl dlls (probably unnecessary but can help
troubleshooting openssl issues)
---
src/main.cpp | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 3e02a4a7..c64e2d8d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -419,6 +419,29 @@ void setupPath()
::SetEnvironmentVariableW(L"PATH", newPath.c_str());
}
+static void preloadSsl()
+{
+ QString appPath = QDir::toNativeSeparators(QCoreApplication::applicationDirPath());
+ if (GetModuleHandleA("libeay32.dll"))
+ qWarning("libeay32.dll already loaded?!");
+ else {
+ QString libeay32 = appPath + "\\libeay32.dll";
+ if (!QFile::exists(libeay32))
+ qWarning("libeay32.dll not found: %s", qPrintable(libeay32));
+ else if (!LoadLibraryW(libeay32.toStdWString().c_str()))
+ qWarning("failed to load: %s, %d", qPrintable(libeay32), GetLastError());
+ }
+ if (GetModuleHandleA("ssleay32.dll"))
+ qWarning("ssleay32.dll already loaded?!");
+ else {
+ QString ssleay32 = appPath + "\\ssleay32.dll";
+ if (!QFile::exists(ssleay32))
+ qWarning("ssleay32.dll not found: %s", qPrintable(ssleay32));
+ else if (!LoadLibraryW(ssleay32.toStdWString().c_str()))
+ qWarning("failed to load: %s, %d", qPrintable(ssleay32), GetLastError());
+ }
+}
+
static QString getVersionDisplayString()
{
VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath()));
@@ -442,6 +465,13 @@ int runApplication(MOApplication &application, SingleInstance &instance,
#endif
);
+#if !defined(QT_NO_SSL)
+ preloadSsl();
+ qDebug("ssl support: %d", QSslSocket::supportsSsl());
+#else
+ qDebug("non-ssl build");
+#endif
+
QString dataPath = application.property("dataPath").toString();
qDebug("data path: %s", qPrintable(dataPath));
@@ -618,12 +648,6 @@ int main(int argc, char *argv[])
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");
--
cgit v1.3.1
From 9ddbf25809e42f2b34d1757c11e3abdf6d7577c4 Mon Sep 17 00:00:00 2001
From: Al12rs
Date: Mon, 12 Feb 2018 17:19:07 +0100
Subject: Added support for High DPI Scaling for higher resolution monitors.
---
src/main.cpp | 3 +++
1 file changed, 3 insertions(+)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index c64e2d8d..935b7404 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -636,6 +636,9 @@ int runApplication(MOApplication &application, SingleInstance &instance,
int main(int argc, char *argv[])
{
+ //Should allow for better scaling of ui with higher resolution displays
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
if (argc >= 4) {
std::vector arg;
auto args = UntouchedCommandLineArguments(2, arg);
--
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/main.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