diff options
| author | Al <gabriel.cortesi@outlook.com> | 2018-07-17 02:08:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-07-17 02:08:17 +0200 |
| commit | 103e3f3098539a8d3b75abc9bfb33344b2576ef9 (patch) | |
| tree | 2d46b1c7f014021a6b3db1490a01fe827367c0e1 | |
| parent | 872c33fe5592eb84a2f6c01a2e47b72602b6139e (diff) | |
| parent | 6552054e58d8c108c59b38335870529da78a27f1 (diff) | |
Merge pull request #438 from LostDragonist/Develop
Added support for selecting multiple mod for multiple modlist options.
Added check for Windows Event Service before spawning new hooked processes.
| -rw-r--r-- | src/downloadmanager.cpp | 2 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 99 | ||||
| -rw-r--r-- | src/modinfo.cpp | 6 | ||||
| -rw-r--r-- | src/organizercore.cpp | 109 |
4 files changed, 184 insertions, 32 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 0c83bf92..385d2246 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -1661,7 +1661,7 @@ void DownloadManager::nxmRequestFailed(QString gameName, int modID, int fileID, void DownloadManager::downloadFinished(int index)
{
DownloadInfo *info;
- if (index)
+ if (index >= 0)
info = m_ActiveDownloads[index];
else
info = findDownload(this->sender(), &index);
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 436d4d26..f70e66a6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2619,20 +2619,44 @@ void MainWindow::displayModInformation(int row, int tab) void MainWindow::ignoreMissingData_clicked()
{
- ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
- QDir(info->absolutePath()).mkdir("textures");
- info->testValid();
- connect(this, SIGNAL(modListDataChanged(QModelIndex,QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+ QItemSelectionModel *selection = ui->modList->selectionModel();
+ if (selection->hasSelection() && selection->selectedRows().count() > 1) {
+ for (QModelIndex idx : selection->selectedRows()) {
+ int row_idx = idx.data(Qt::UserRole + 1).toInt();
+ ModInfo::Ptr info = ModInfo::getByIndex(row_idx);
+ QDir(info->absolutePath()).mkdir("textures");
+ info->testValid();
+ connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex)));
+
+ emit modListDataChanged(m_OrganizerCore.modList()->index(row_idx, 0), m_OrganizerCore.modList()->index(row_idx, m_OrganizerCore.modList()->columnCount() - 1));
+ }
+ } else {
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ QDir(info->absolutePath()).mkdir("textures");
+ info->testValid();
+ connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex)));
- emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
+ emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
+ }
}
void MainWindow::markConverted_clicked()
{
- ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
- info->markConverted(true);
- connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex)));
- emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
+ QItemSelectionModel *selection = ui->modList->selectionModel();
+ if (selection->hasSelection() && selection->selectedRows().count() > 1) {
+ for (QModelIndex idx : selection->selectedRows()) {
+ int row_idx = idx.data(Qt::UserRole + 1).toInt();
+ ModInfo::Ptr info = ModInfo::getByIndex(row_idx);
+ info->markConverted(true);
+ connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex)));
+ emit modListDataChanged(m_OrganizerCore.modList()->index(row_idx, 0), m_OrganizerCore.modList()->index(row_idx, m_OrganizerCore.modList()->columnCount() - 1));
+ }
+ } else {
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ info->markConverted(true);
+ connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex)));
+ emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
+ }
}
@@ -2659,9 +2683,17 @@ void MainWindow::visitWebPage_clicked() void MainWindow::openExplorer_clicked()
{
- ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
-
- ::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+ QItemSelectionModel *selection = ui->modList->selectionModel();
+ if (selection->hasSelection() && selection->selectedRows().count() > 1) {
+ for (QModelIndex idx : selection->selectedRows()) {
+ ModInfo::Ptr info = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt());
+ ::ShellExecuteW(nullptr, L"explore", ToWString(info->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+ }
+ }
+ else {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
+ ::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+ }
}
void MainWindow::openExplorer_activated()
@@ -3076,14 +3108,32 @@ void MainWindow::changeVersioningScheme() { }
void MainWindow::ignoreUpdate() {
- ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
- info->ignoreUpdate(true);
+ QItemSelectionModel *selection = ui->modList->selectionModel();
+ if (selection->hasSelection() && selection->selectedRows().count() > 1) {
+ for (QModelIndex idx : selection->selectedRows()) {
+ ModInfo::Ptr info = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt());
+ info->ignoreUpdate(true);
+ }
+ }
+ else {
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ info->ignoreUpdate(true);
+ }
}
void MainWindow::unignoreUpdate()
{
- ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
- info->ignoreUpdate(false);
+ QItemSelectionModel *selection = ui->modList->selectionModel();
+ if (selection->hasSelection() && selection->selectedRows().count() > 1) {
+ for (QModelIndex idx : selection->selectedRows()) {
+ ModInfo::Ptr info = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt());
+ info->ignoreUpdate(false);
+ }
+ }
+ else {
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ info->ignoreUpdate(false);
+ }
}
void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu,
@@ -4204,12 +4254,16 @@ void MainWindow::on_actionUpdate_triggered() void MainWindow::on_actionEndorseMO_triggered()
{
+ // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now
+ IPluginGame * game = m_OrganizerCore.getGame("skyrimse");
+ if (!game) return;
+
if (QMessageBox::question(this, tr("Endorse Mod Organizer"),
tr("Do you want to endorse Mod Organizer on %1 now?").arg(
- NexusInterface::instance(&m_PluginContainer)->getGameURL(m_OrganizerCore.managedGame()->gameShortName())),
+ NexusInterface::instance(&m_PluginContainer)->getGameURL(game->gameShortName())),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
NexusInterface::instance(&m_PluginContainer)->requestToggleEndorsement(
- m_OrganizerCore.managedGame()->gameShortName(), m_OrganizerCore.managedGame()->nexusModOrganizerID(), true, this, QVariant(), QString());
+ game->gameShortName(), game->nexusModOrganizerID(), true, this, QVariant(), QString());
}
}
@@ -4274,8 +4328,11 @@ void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant us QVariantList resultList = resultData.toList();
for (auto iter = resultList.begin(); iter != resultList.end(); ++iter) {
QVariantMap result = iter->toMap();
- if (result["id"].toInt() == m_OrganizerCore.managedGame()->nexusModOrganizerID()
- && result["game_id"].toInt() == m_OrganizerCore.managedGame()->nexusGameID()) {
+ // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now
+ IPluginGame * game = m_OrganizerCore.getGame("skyrimse");
+ if (game
+ && result["id"].toInt() == game->nexusModOrganizerID()
+ && result["game_id"].toInt() == game->nexusGameID()) {
if (!result["voted_by_user"].toBool()) {
ui->actionEndorseMO->setVisible(true);
}
@@ -4326,7 +4383,7 @@ void MainWindow::nxmEndorsementToggled(QString, int, QVariant, QVariant resultDa {
if (resultData.toBool()) {
ui->actionEndorseMO->setVisible(false);
- QMessageBox::question(this, tr("Thank you!"), tr("Thank you for your endorsement!"));
+ QMessageBox::information(this, tr("Thank you!"), tr("Thank you for your endorsement!"));
}
if (!disconnect(sender(), SIGNAL(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)),
diff --git a/src/modinfo.cpp b/src/modinfo.cpp index bd4c1254..1f2520c9 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -286,9 +286,9 @@ int ModInfo::checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiv int result = 0; std::vector<int> modIDs; - //I ought to store this, it's used elsewhere - IPluginGame const *game = qApp->property("managed_game").value<IPluginGame *>(); - if (game->nexusModOrganizerID()) { + // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now + IPluginGame const *game = pluginContainer->managedGame("Skyrim Special Edition"); + if (game && game->nexusModOrganizerID()) { modIDs.push_back(game->nexusModOrganizerID()); checkChunkForUpdate(pluginContainer, modIDs, receiver, game->gameShortName()); modIDs.clear(); diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 35486f98..142faabe 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -186,6 +186,86 @@ QStringList toStringList(InputIterator current, InputIterator end) return result;
}
+bool checkService()
+{
+ SC_HANDLE serviceManagerHandle = NULL;
+ SC_HANDLE serviceHandle = NULL;
+ LPSERVICE_STATUS_PROCESS serviceStatus = NULL;
+ LPQUERY_SERVICE_CONFIG serviceConfig = NULL;
+ bool serviceRunning = true;
+
+ DWORD bytesNeeded;
+
+ try {
+ serviceManagerHandle = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
+ if (!serviceManagerHandle) {
+ qWarning("failed to open service manager (query status) (error %d)", GetLastError());
+ throw 1;
+ }
+
+ serviceHandle = OpenService(serviceManagerHandle, L"EventLog", SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
+ if (!serviceHandle) {
+ qWarning("failed to open EventLog service (query status) (error %d)", GetLastError());
+ throw 2;
+ }
+
+ if (QueryServiceConfig(serviceHandle, NULL, 0, &bytesNeeded)
+ || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
+ qWarning("failed to get size of service config (error %d)", GetLastError());
+ throw 3;
+ }
+
+ DWORD serviceConfigSize = bytesNeeded;
+ serviceConfig = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, serviceConfigSize);
+ if (!QueryServiceConfig(serviceHandle, serviceConfig, serviceConfigSize, &bytesNeeded)) {
+ qWarning("failed to query service config (error %d)", GetLastError());
+ throw 4;
+ }
+
+ if (serviceConfig->dwStartType == SERVICE_DISABLED) {
+ qCritical("Windows Event Log service is disabled!");
+ serviceRunning = false;
+ }
+
+ if (QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, NULL, 0, &bytesNeeded)
+ || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
+ qWarning("failed to get size of service status (error %d)", GetLastError());
+ throw 5;
+ }
+
+ DWORD serviceStatusSize = bytesNeeded;
+ serviceStatus = (LPSERVICE_STATUS_PROCESS)LocalAlloc(LMEM_FIXED, serviceStatusSize);
+ if (!QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, (LPBYTE)serviceStatus, serviceStatusSize, &bytesNeeded)) {
+ qWarning("failed to query service status (error %d)", GetLastError());
+ throw 6;
+ }
+
+ if (serviceStatus->dwCurrentState != SERVICE_RUNNING) {
+ qCritical("Windows Event Log service is not running");
+ serviceRunning = false;
+ }
+ }
+ catch (int e) {
+ UNUSED_VAR(e);
+ serviceRunning = false;
+ }
+
+ if (serviceStatus) {
+ LocalFree(serviceStatus);
+ }
+ if (serviceConfig) {
+ LocalFree(serviceConfig);
+ }
+ if (serviceHandle) {
+ CloseServiceHandle(serviceHandle);
+ }
+ if (serviceManagerHandle) {
+ CloseServiceHandle(serviceManagerHandle);
+ }
+
+ return serviceRunning;
+}
+
OrganizerCore::OrganizerCore(const QSettings &initSettings)
: m_UserInterface(nullptr)
, m_PluginContainer(nullptr)
@@ -1190,6 +1270,11 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary, ToWString(m_Settings.getSteamAppID()).c_str());
}
+ QWidget *window = qApp->activeWindow();
+ if ((window != nullptr) && (!window->isVisible())) {
+ window = nullptr;
+ }
+
// This could possibly be extracted somewhere else but it's probably for when
// we have more than one provider of game registration.
if ((QFileInfo(
@@ -1200,16 +1285,12 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary, .exists())
&& (m_Settings.getLoadMechanism() == LoadMechanism::LOAD_MODORGANIZER)) {
if (!testForSteam()) {
- QWidget *window = qApp->activeWindow();
- if ((window != nullptr) && (!window->isVisible())) {
- window = nullptr;
- }
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?"),
QDialogButtonBox::Yes | QDialogButtonBox::No) == QDialogButtonBox::Yes) {
- startSteam(qApp->activeWindow());
+ startSteam(window);
}
}
}
@@ -1229,10 +1310,24 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary, try {
m_USVFS.updateMapping(fileMapping(profileName, customOverwrite));
} catch (const std::exception &e) {
- QMessageBox::warning(qApp->activeWindow(), tr("Error"), e.what());
+ QMessageBox::warning(window, tr("Error"), e.what());
return INVALID_HANDLE_VALUE;
}
+ // Check if the Windows Event Logging service is running. For some reason, this seems to be
+ // critical to the successful running of usvfs.
+ if (!checkService()) {
+ if (QuestionBoxMemory::query(window, QString("eventLogService"), binary.fileName(),
+ tr("Windows Event Log Error"),
+ tr("The Windows Event Log service is disabled and/or not running. This prevents"
+ " USVFS from running properly. Your mods may not be working in the executable"
+ " that you are launching. Note that you may have to restart MO and/or your PC"
+ " after the service is fixed.\n\nContinue launching %1?").arg(binary.fileName()),
+ QDialogButtonBox::Yes | QDialogButtonBox::No) == QDialogButtonBox::No) {
+ return INVALID_HANDLE_VALUE;
+ }
+ }
+
QString modsPath = settings().getModDirectory();
// Check if this a request with either an executable or a working directory under our mods folder
@@ -2204,4 +2299,4 @@ std::vector<Mapping> OrganizerCore::fileMapping( result.insert(result.end(), subRes.begin(), subRes.end());
}
return result;
-}
+}
\ No newline at end of file |
