summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTanninOne <seppleviathan@gmx.de>2016-06-30 19:03:45 +0200
committerGitHub <noreply@github.com>2016-06-30 19:03:45 +0200
commit4a582e524dd012ed9d5fdb4f9c97aab22c8dac85 (patch)
tree8636fd48efe160d7325906cfb88b90374e0522a0 /src
parent89221af929f86d7038cb9578433d46c5f144dc33 (diff)
parent42407866e9f04cac3c1bad0e1002e23c6f0d5064 (diff)
Merge pull request #837 from ThosRTanner/issue/309
Changes for TanninOne/modorganizer#309 (3 of 3)
Diffstat (limited to 'src')
-rw-r--r--src/dlls.manifest.debug.qt56
-rw-r--r--src/dlls.manifest.qt58
-rw-r--r--src/iuserinterface.h1
-rw-r--r--src/lockeddialog.cpp5
-rw-r--r--src/lockeddialog.h11
-rw-r--r--src/mainwindow.cpp25
-rw-r--r--src/mainwindow.h2
-rw-r--r--src/organizercore.cpp117
-rw-r--r--src/organizercore.h11
-rw-r--r--src/pluginlist.cpp1
-rw-r--r--src/settings.cpp36
-rw-r--r--src/settings.h24
12 files changed, 157 insertions, 90 deletions
diff --git a/src/dlls.manifest.debug.qt5 b/src/dlls.manifest.debug.qt5
index 59497baa..a2f75206 100644
--- a/src/dlls.manifest.debug.qt5
+++ b/src/dlls.manifest.debug.qt5
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="dlls" version="1.0.0.0" processorArchitecture="x86"/>
- <file name="icuin53.dll"/>
- <file name="icuuc53.dll"/>
- <file name="icudt53.dll"/>
+ <file name="icuin54.dll"/>
+ <file name="icuuc54.dll"/>
+ <file name="icudt54.dll"/>
<file name="Qt5Cored.dll"/>
<file name="Qt5Declaratived.dll"/>
<file name="Qt5Guid.dll"/>
diff --git a/src/dlls.manifest.qt5 b/src/dlls.manifest.qt5
index 76206f21..5c64e4f9 100644
--- a/src/dlls.manifest.qt5
+++ b/src/dlls.manifest.qt5
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="dlls" version="1.0.0.0" processorArchitecture="x86"/>
- <file name="icuin53.dll"/>
- <file name="icuuc53.dll"/>
- <file name="icudt53.dll"/>
+ <file name="icuin54.dll"/>
+ <file name="icuuc54.dll"/>
+ <file name="icudt54.dll"/>
<file name="Qt5Core.dll"/>
<file name="Qt5Declarative.dll"/>
<file name="Qt5Gui.dll"/>
@@ -26,4 +26,4 @@
<file name="Qt5WinExtras.dll"/>
<file name="Qt5Xml.dll"/>
<file name="Qt5XmlPatterns.dll"/>
-</assembly> \ No newline at end of file
+</assembly>
diff --git a/src/iuserinterface.h b/src/iuserinterface.h
index e03bcde2..540839c6 100644
--- a/src/iuserinterface.h
+++ b/src/iuserinterface.h
@@ -34,6 +34,7 @@ public:
virtual void lock() = 0;
virtual void unlock() = 0;
virtual bool unlockClicked() = 0;
+ virtual void setProcessName(QString const &) = 0;
};
diff --git a/src/lockeddialog.cpp b/src/lockeddialog.cpp
index 907e3c0a..519abd5b 100644
--- a/src/lockeddialog.cpp
+++ b/src/lockeddialog.cpp
@@ -19,8 +19,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "lockeddialog.h"
#include "ui_lockeddialog.h"
-#include <QResizeEvent>
+#include <QPoint>
+#include <QResizeEvent>
+#include <QWidget>
+#include <Qt> // for Qt::FramelessWindowHint, etc
LockedDialog::LockedDialog(QWidget *parent, const QString &text, bool unlockButton)
: QDialog(parent)
diff --git a/src/lockeddialog.h b/src/lockeddialog.h
index 60af425d..29ac459b 100644
--- a/src/lockeddialog.h
+++ b/src/lockeddialog.h
@@ -20,7 +20,12 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#ifndef LOCKEDDIALOG_H
#define LOCKEDDIALOG_H
-#include <QDialog>
+#include <QDialog> // for QDialog
+#include <QObject> // for Q_OBJECT, slots
+#include <QString> // for QString
+
+class QResizeEvent;
+class QWidget;
namespace Ui {
class LockedDialog;
@@ -49,6 +54,10 @@ public:
**/
bool unlockClicked() const { return m_UnlockClicked; }
+ /**
+ * @brief set the name of the process being run
+ * @param name of process
+ */
void setProcessName(const QString &name);
protected:
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 096ce94b..72ee8d6a 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -34,6 +34,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "organizercore.h"
#include "pluginlistsortproxy.h"
#include "previewgenerator.h"
+#include "serverinfo.h"
#include "savegameinfo.h"
#include "spawn.h"
#include "versioninfo.h"
@@ -1608,18 +1609,31 @@ void MainWindow::storeSettings(QSettings &settings)
void MainWindow::lock()
{
+ if (m_LockDialog != nullptr) {
+ ++m_LockCount;
+ return;
+ }
m_LockDialog = new LockedDialog(qApp->activeWindow());
m_LockDialog->show();
setEnabled(false);
+ m_LockDialog->setEnabled(true); //What's the point otherwise?
+ ++m_LockCount;
}
void MainWindow::unlock()
{
- if (m_LockDialog != nullptr) {
+ //If you come through here with a null lock pointer, it's a bug!
+ if (m_LockDialog == nullptr) {
+ qDebug("Unlocking main window when already unlocked");
+ return;
+ }
+ --m_LockCount;
+ if (m_LockCount == 0) {
m_LockDialog->hide();
m_LockDialog->deleteLater();
+ m_LockDialog = nullptr;
+ setEnabled(true);
}
- setEnabled(true);
}
bool MainWindow::unlockClicked()
@@ -1631,6 +1645,13 @@ bool MainWindow::unlockClicked()
}
}
+void MainWindow::setProcessName(QString const &name)
+{
+ if (m_LockDialog != nullptr) {
+ m_LockDialog->setProcessName(name);
+ }
+}
+
void MainWindow::on_btnRefreshData_clicked()
{
m_OrganizerCore.refreshDirectoryStructure();
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 177048b4..8e63a14f 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -118,6 +118,7 @@ public:
virtual void lock() override;
virtual void unlock() override;
virtual bool unlockClicked() override;
+ virtual void setProcessName(QString const &name) override;
bool addProfile();
void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives);
@@ -350,6 +351,7 @@ private:
bool m_DidUpdateMasterList;
LockedDialog *m_LockDialog { nullptr };
+ uint64_t m_LockCount { 0 };
MOBase::DelayedFileWriter m_ArchiveListWriter;
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index cee367b0..196ef6bf 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -1,13 +1,19 @@
#include "organizercore.h"
+#include "delayedfilewriter.h"
+#include "guessedvalue.h"
#include "imodinterface.h"
+#include "imoinfo.h"
#include "iplugingame.h"
#include "iuserinterface.h"
#include "loadmechanism.h"
#include "messagedialog.h"
#include "modlistsortproxy.h"
+#include "modrepositoryfileinfo.h"
+#include "nexusinterface.h"
#include "plugincontainer.h"
#include "pluginlistsortproxy.h"
+#include "profile.h"
#include "logbuffer.h"
#include "credentialsdialog.h"
#include "filedialogmemory.h"
@@ -26,21 +32,32 @@
#include <questionboxmemory.h>
#include <QApplication>
+#include <QCoreApplication>
+#include <QDialog>
#include <QDialogButtonBox>
#include <QMessageBox>
#include <QNetworkInterface>
#include <QProcess>
#include <QTimer>
+#include <QUrl>
#include <QWidget>
#include <QtDebug>
+#include <QtGlobal> // for qPrintable, etc
#include <Psapi.h>
+#include <tchar.h> // for _tcsicmp
+
+#include <limits.h>
+#include <stddef.h>
+#include <string.h> // for memset, wcsrchr
#include <exception>
#include <functional>
#include <memory>
#include <set>
+#include <string> //for wstring
+#include <tuple>
#include <utility>
@@ -892,66 +909,22 @@ QStringList OrganizerCore::modsSortedByProfilePriority() const
void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir &currentDirectory, bool closeAfterStart, const QString &steamAppID)
{
- LockedDialog *dialog = new LockedDialog(qApp->activeWindow());
- dialog->show();
- ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); });
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->lock();
+ }
+ ON_BLOCK_EXIT([&] () {
+ if (m_UserInterface != nullptr) { m_UserInterface->unlock(); }
+ });
HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->name(), currentDirectory, steamAppID);
if (processHandle != INVALID_HANDLE_VALUE) {
if (closeAfterStart && (m_UserInterface != nullptr)) {
m_UserInterface->closeWindow();
} else {
- if (m_UserInterface != nullptr) {
- m_UserInterface->setWindowEnabled(false);
- }
- // re-enable the locked dialog because what'd be the point otherwise?
- dialog->setEnabled(true);
-
- QCoreApplication::processEvents();
DWORD processExitCode;
- DWORD retLen;
- JOBOBJECT_BASIC_PROCESS_ID_LIST info;
-
- {
- DWORD currentProcess = 0UL;
- bool isJobHandle = true;
+ (void)waitForProcessCompletion(processHandle, &processExitCode);
- DWORD res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
- while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0) && !dialog->unlockClicked()) {
- if (isJobHandle) {
- if (::QueryInformationJobObject(processHandle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
- if (info.NumberOfProcessIdsInList == 0) {
- break;
- } else {
- if (info.ProcessIdList[0] != currentProcess) {
- currentProcess = info.ProcessIdList[0];
- dialog->setProcessName(ToQString(getProcessName(currentProcess)));
- }
- }
- } else {
- // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
- // is more than one that's good enough. ERROR_MORE_DATA simply signals there are at least two processes running.
- // any other error probably means the handle is a regular process handle, probably caused by running MO in a job without
- // the right to break out.
- if (::GetLastError() != ERROR_MORE_DATA) {
- isJobHandle = false;
- }
- }
- }
-
- // keep processing events so the app doesn't appear dead
- QCoreApplication::processEvents();
-
- res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
- }
- ::GetExitCodeProcess(processHandle, &processExitCode);
- }
- ::CloseHandle(processHandle);
-
- if (m_UserInterface != nullptr) {
- m_UserInterface->setWindowEnabled(true);
- }
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
@@ -965,6 +938,7 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument
savePluginList();
}
+ //These callbacks should not fiddle with directoy structure and ESPs.
m_FinishedRun(binary.absoluteFilePath(), processExitCode);
}
}
@@ -996,7 +970,7 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString &
if ((window != nullptr) && (!window->isVisible())) {
window = nullptr;
}
- if (QuestionBoxMemory::query(window, "steamQuery",
+ if (QuestionBoxMemory::query(window, "steamQuery", binary.fileName(),
tr("Start Steam?"),
tr("Steam is required to be running already to correctly start the game. "
"Should MO try to start steam now?"),
@@ -1081,22 +1055,30 @@ bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode)
{
if (m_UserInterface != nullptr) {
m_UserInterface->lock();
- ON_BLOCK_EXIT([&] () { m_UserInterface->unlock(); });
}
- DWORD retLen;
- JOBOBJECT_BASIC_PROCESS_ID_LIST info;
+ ON_BLOCK_EXIT([&] () {
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->unlock();
+ } });
+ return waitForProcessCompletion(handle, exitCode);
+}
+bool OrganizerCore::waitForProcessCompletion(HANDLE handle, LPDWORD exitCode)
+{
bool isJobHandle = true;
ULONG lastProcessID = ULONG_MAX;
HANDLE processHandle = handle;
- DWORD res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE);
- while ((res != WAIT_FAILED)
- && (res != WAIT_OBJECT_0)
- && ((m_UserInterface == nullptr) || !m_UserInterface->unlockClicked())) {
+ DWORD res;
+ //Wait for a an event on the handle, a key press, mouse click or timeout
+ while (res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE),
+ (res != WAIT_FAILED && res != WAIT_OBJECT_0
+ && (m_UserInterface == nullptr || !m_UserInterface->unlockClicked()))) {
if (isJobHandle) {
+ DWORD retLen;
+ JOBOBJECT_BASIC_PROCESS_ID_LIST info;
if (::QueryInformationJobObject(handle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
if (info.NumberOfProcessIdsInList == 0) {
// fake signaled state
@@ -1106,6 +1088,9 @@ bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode)
// this is indeed a job handle. Figure out one of the process handles as well.
if (lastProcessID != info.ProcessIdList[0]) {
lastProcessID = info.ProcessIdList[0];
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->setProcessName(ToQString(getProcessName(lastProcessID)));
+ }
if (processHandle != handle) {
::CloseHandle(processHandle);
}
@@ -1125,14 +1110,22 @@ bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode)
// keep processing events so the app doesn't appear dead
QCoreApplication::processEvents();
-
- res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE);
}
if (exitCode != nullptr) {
- ::GetExitCodeProcess(processHandle, exitCode);
+ //This is actually wrong if the process we started finished before we
+ //got the event and so we end up with a job handle.
+ if (! ::GetExitCodeProcess(processHandle, exitCode))
+ {
+ DWORD error = ::GetLastError();
+ qDebug() << "Failed to get process exit code: Error " << error;
+ }
}
+
::CloseHandle(processHandle);
+ if (handle != processHandle) {
+ ::CloseHandle(handle);
+ }
return res == WAIT_OBJECT_0;
}
diff --git a/src/organizercore.h b/src/organizercore.h
index b50b3e9f..28fc14ca 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -21,21 +21,28 @@
class ModListSortProxy;
class PluginListSortProxy;
class Profile;
-namespace MOBase { template <typename T> class GuessedValue; }
+namespace MOBase {
+ template <typename T> class GuessedValue;
+ class IModInterface;
+}
namespace MOShared { class DirectoryEntry; }
#include <QDir>
+#include <QFileInfo>
#include <QList>
#include <QObject>
#include <QSettings>
#include <QString>
#include <QStringList>
#include <QThread>
+#include <QVariant>
class QNetworkReply;
class QUrl;
class QWidget;
+#include <Windows.h> //for HANDLE, LPDWORD
+
#include <functional>
#include <vector>
@@ -228,6 +235,8 @@ private:
const MOShared::DirectoryEntry *directoryEntry);
*/
+ bool waitForProcessCompletion(HANDLE handle, LPDWORD exitCode);
+
private slots:
void directory_refreshed();
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index bf5a09dc..96757ec6 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -33,6 +33,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QMessageBox>
#include <QMimeData>
#include <QCoreApplication>
+#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QTextCodec>
diff --git a/src/settings.cpp b/src/settings.cpp
index 7b812759..03e13826 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -19,22 +19,42 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "settings.h"
+#include "pluginsetting.h"
+#include "serverinfo.h"
#include "settingsdialog.h"
-#include "utility.h"
-#include "helper.h"
-#include <appconfig.h>
+#include "versioninfo.h"
+#include "appconfig.h"
#include <utility.h>
+#include <iplugin.h>
#include <iplugingame.h>
+#include <questionboxmemory.h>
#include <QCheckBox>
#include <QCoreApplication>
-#include <QDesktopServices>
+#include <QComboBox>
+#include <QDate>
+#include <QDialog>
+#include <QDir>
#include <QDirIterator>
+#include <QFileInfo>
#include <QLineEdit>
+#include <QListWidgetItem>
+#include <QLocale>
#include <QMessageBox>
#include <QRegExp>
+#include <QStringList>
+#include <QVariantMap>
+#include <Qt> // for Qt::UserRole, etc
+#include <QtDebug> // for qDebug, qWarning
+
+#include <Windows.h> // For ShellExecuteW, HINSTANCE, etc
+
+#include <algorithm> // for sort
#include <memory>
+#include <stdexcept> // for runtime_error
+#include <string>
+#include <utility> // for pair, make_pair
using namespace MOBase;
@@ -520,13 +540,7 @@ void Settings::addStyles(QComboBox *styleBox)
void Settings::resetDialogs()
{
- m_Settings.beginGroup("DialogChoices");
- QStringList keys = m_Settings.childKeys();
- foreach (QString key, keys) {
- m_Settings.remove(key);
- }
-
- m_Settings.endGroup();
+ QuestionBoxMemory::resetDialogs();
}
diff --git a/src/settings.h b/src/settings.h
index 1ee16e76..9f6adaa7 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -21,20 +21,34 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#define WORKAROUNDS_H
#include "loadmechanism.h"
-#include "serverinfo.h"
-#include <iplugin.h>
+#include <QList>
+#include <QMap>
+#include <QObject>
+#include <QSet>
#include <QSettings>
-#include <QListWidget>
-#include <QComboBox>
+#include <QString>
+#include <QVariant>
+#include <QtGlobal> //for uint
+
+#include <map>
+#include <vector>
+
+class QCheckBox;
+class QComboBox;
+class QLineEdit;
+class QListWidget;
+class QWidget;
+
+struct ServerInfo;
namespace MOBase {
+ class IPlugin;
class IPluginGame;
}
class SettingsDialog;
-class QCheckBox;
/**
* manages the settings for Mod Organizer. The settings are not cached