diff options
Diffstat (limited to 'src/organizercore.cpp')
| -rw-r--r-- | src/organizercore.cpp | 180 |
1 files changed, 140 insertions, 40 deletions
diff --git a/src/organizercore.cpp b/src/organizercore.cpp index fe032eba..5b322a0a 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -10,6 +10,7 @@ #include "report.h"
#include "spawn.h"
#include "safewritefile.h"
+#include "syncoverwritedialog.h"
#include <ipluginmodpage.h>
#include <directoryentry.h>
#include <scopeguard.h>
@@ -76,15 +77,25 @@ static std::wstring getProcessName(DWORD processId) }
}
-static bool testForSteam()
+bool OrganizerCore::testForSteam()
{
- DWORD processIDs[1024];
+ size_t currentSize = 1024;
+ std::unique_ptr<DWORD[]> processIDs;
DWORD bytesReturned;
- if (!::EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned)) {
- qWarning("failed to determine if steam is running");
- return true;
+ bool success = false;
+ while (!success) {
+ processIDs.reset(new DWORD[currentSize]);
+ if (!::EnumProcesses(processIDs.get(), currentSize * sizeof(DWORD), &bytesReturned)) {
+ qWarning("failed to determine if steam is running");
+ return true;
+ }
+ if (bytesReturned == (currentSize * sizeof(DWORD))) {
+ // maximum size used, list probably truncated
+ currentSize *= 2;
+ } else {
+ success = true;
+ }
}
-
TCHAR processName[MAX_PATH];
for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) {
memset(processName, '\0', sizeof(TCHAR) * MAX_PATH);
@@ -96,13 +107,15 @@ static bool testForSteam() DWORD ignore;
// first module in a process is always the binary
- if (::EnumProcessModules(process, &module, sizeof(HMODULE) * 1, &ignore)) {
+ if (EnumProcessModules(process, &module, sizeof(HMODULE) * 1, &ignore)) {
::GetModuleBaseName(process, module, processName, MAX_PATH);
if ((_tcsicmp(processName, TEXT("steam.exe")) == 0) ||
(_tcsicmp(processName, TEXT("steamservice.exe")) == 0)) {
return true;
}
}
+ } else {
+ qDebug("can't open process %lu: %lu", processIDs[i], ::GetLastError());
}
}
}
@@ -225,16 +238,16 @@ void OrganizerCore::storeSettings() int count = 0;
for (; current != end; ++current) {
const Executable &item = *current;
- if (item.m_Custom || item.m_Toolbar) {
- settings.setArrayIndex(count++);
+ settings.setArrayIndex(count++);
+ settings.setValue("title", item.m_Title);
+ settings.setValue("custom", item.m_Custom);
+ settings.setValue("toolbar", item.m_Toolbar);
+ if (item.m_Custom) {
settings.setValue("binary", item.m_BinaryInfo.absoluteFilePath());
- settings.setValue("title", item.m_Title);
settings.setValue("arguments", item.m_Arguments);
settings.setValue("workingDirectory", item.m_WorkingDirectory);
settings.setValue("closeOnStart", item.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE);
settings.setValue("steamAppID", item.m_SteamAppID);
- settings.setValue("custom", item.m_Custom);
- settings.setValue("toolbar", item.m_Toolbar);
}
}
settings.endArray();
@@ -501,7 +514,8 @@ MOBase::IModInterface *OrganizerCore::getMod(const QString &name) MOBase::IModInterface *OrganizerCore::createMod(GuessedValue<QString> &name)
{
- if (!m_InstallationManager.testOverwrite(name)) {
+ bool merge = false;
+ if (!m_InstallationManager.testOverwrite(name, &merge)) {
return nullptr;
}
@@ -509,13 +523,19 @@ MOBase::IModInterface *OrganizerCore::createMod(GuessedValue<QString> &name) QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(name);
- QSettings settingsFile(targetDirectory.mid(0).append("/meta.ini"), QSettings::IniFormat);
+ QSettings settingsFile(targetDirectory + "/meta.ini", QSettings::IniFormat);
+
+ if (!merge) {
+ settingsFile.setValue("modid", 0);
+ settingsFile.setValue("version", "");
+ settingsFile.setValue("newestVersion", "");
+ settingsFile.setValue("category", 0);
+ settingsFile.setValue("installationFile", "");
+
+ settingsFile.beginWriteArray("installedFiles", 0);
+ settingsFile.endArray();
+ }
- settingsFile.setValue("modid", 0);
- settingsFile.setValue("version", "");
- settingsFile.setValue("newestVersion", "");
- settingsFile.setValue("category", 0);
- settingsFile.setValue("installationFile", "");
return ModInfo::createFrom(QDir(targetDirectory), &m_DirectoryStructure).data();
}
@@ -560,7 +580,7 @@ QString OrganizerCore::pluginDataPath() const return pluginPath + "/data";
}
-MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName)
+MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName, const QString &initModName)
{
if (m_CurrentProfile == nullptr) {
return nullptr;
@@ -568,6 +588,9 @@ MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName) bool hasIniTweaks = false;
GuessedValue<QString> modName;
+ if (!initModName.isEmpty()) {
+ modName.update(initModName, GUESS_USER);
+ }
m_CurrentProfile->writeModlistNow();
m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
@@ -596,6 +619,63 @@ MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName) return nullptr;
}
+void OrganizerCore::installDownload(int index)
+{
+ try {
+ QString fileName = m_DownloadManager.getFilePath(index);
+ int modID = m_DownloadManager.getModID(index);
+ int fileID = m_DownloadManager.getFileInfo(index)->fileID;
+ GuessedValue<QString> modName;
+
+ // see if there already are mods with the specified mod id
+ if (modID != 0) {
+ std::vector<ModInfo::Ptr> modInfo = ModInfo::getByModID(modID);
+ for (auto iter = modInfo.begin(); iter != modInfo.end(); ++iter) {
+ std::vector<ModInfo::EFlag> flags = (*iter)->getFlags();
+ if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) == flags.end()) {
+ modName.update((*iter)->name(), GUESS_PRESET);
+ (*iter)->saveMeta();
+ }
+ }
+ }
+
+ m_CurrentProfile->writeModlistNow();
+
+ bool hasIniTweaks = false;
+ m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+ if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
+ MessageDialog::showMessage(tr("Installation successful"), qApp->activeWindow());
+ refreshModList();
+
+ int modIndex = ModInfo::getIndex(modName);
+ if (modIndex != UINT_MAX) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
+ modInfo->addInstalledFile(modID, fileID);
+
+ if (hasIniTweaks
+ && m_UserInterface != nullptr
+ && (QMessageBox::question(qApp->activeWindow(), tr("Configure Mod"),
+ tr("This mod contains ini tweaks. Do you want to configure them now?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) {
+ m_UserInterface->displayModInformation(modInfo, modIndex, ModInfoDialog::TAB_INIFILES);
+ }
+
+ m_ModInstalled(modName);
+ } else {
+ reportError(tr("mod \"%1\" not found").arg(modName));
+ }
+ m_DownloadManager.markInstalled(index);
+
+ emit modInstalled(modName);
+ } else if (m_InstallationManager.wasCancelled()) {
+ QMessageBox::information(qApp->activeWindow(), tr("Installation cancelled"),
+ tr("The mod was not installed completely."), QMessageBox::Ok);
+ }
+ } catch (const std::exception &e) {
+ reportError(e.what());
+ }
+}
+
void OrganizerCore::installDownload(int downloadIndex)
{
try {
@@ -901,19 +981,15 @@ HANDLE OrganizerCore::startApplication(const QString &executable, const QStringL // relative path, should be relative to game directory
binary = QFileInfo(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/" + executable);
}
-
- std::vector<Executable>::iterator current, end;
- m_ExecutablesList.getExecutables(current, end);
- for (; current != end; ++current) {
- if (current->m_BinaryInfo == binary) {
- steamAppID = current->m_SteamAppID;
- currentDirectory = current->m_WorkingDirectory;
- }
- }
-
if (cwd.length() == 0) {
currentDirectory = binary.absolutePath();
}
+ try {
+ const Executable &exe = m_ExecutablesList.findByBinary(binary);
+ steamAppID = exe.m_SteamAppID;
+ } catch (const std::runtime_error&) {
+ // nop
+ }
} else {
// only a file name, search executables list
try {
@@ -1044,12 +1120,29 @@ void OrganizerCore::refreshESPList() }
}
+QStringList OrganizerCore::defaultArchiveList()
+{
+ QStringList result;
+ wchar_t buffer[256];
+ std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName()));
+
+ if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().append(L"2").c_str(),
+ L"", buffer, 256, iniFileName.c_str()) != 0) {
+ result.append(ToQString(buffer).split(','));
+ }
+
+ for (int i = 0; i < m_DefaultArchives.count(); ++i) {
+ result[i] = result[i].trimmed();
+ }
+
+ return result;
+}
void OrganizerCore::refreshBSAList()
{
m_ArchivesInit = false;
- m_DefaultArchives.clear();
+ m_DefaultArchives = defaultArchiveList();
wchar_t buffer[256];
std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName()));
@@ -1063,15 +1156,6 @@ void OrganizerCore::refreshBSAList() }
}
- if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().append(L"2").c_str(),
- L"", buffer, 256, iniFileName.c_str()) != 0) {
- m_DefaultArchives.append(ToQString(buffer).split(','));
- }
-
- for (int i = 0; i < m_DefaultArchives.count(); ++i) {
- m_DefaultArchives[i] = m_DefaultArchives[i].trimmed();
- }
-
m_ActiveArchives.clear();
auto iter = enabledArchives();
@@ -1338,6 +1422,22 @@ void OrganizerCore::loginFailedUpdate(const QString &message) MessageDialog::showMessage(tr("login failed: %1. You need to log-in with Nexus to update MO.").arg(message), qApp->activeWindow());
}
+void OrganizerCore::syncOverwrite()
+{
+ unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool {
+ std::vector<ModInfo::EFlag> flags = mod->getFlags();
+ return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); });
+
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(overwriteIndex);
+ SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_DirectoryStructure, qApp->activeWindow());
+ if (syncDialog.exec() == QDialog::Accepted) {
+ syncDialog.apply(QDir::fromNativeSeparators(m_Settings.getModDirectory()));
+ modInfo->testValid();
+ refreshDirectoryStructure();
+ }
+
+}
+
std::vector<unsigned int> OrganizerCore::activeProblems() const
{
|
