From bd8267993d1ed0292200f3052e3c30d4fc9c84f7 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 4 Jan 2015 10:13:12 +0100 Subject: - fixes after merge --- src/directoryrefresher.cpp | 4 +- src/editexecutablesdialog.cpp | 4 +- src/iuserinterface.h | 8 +- src/main.cpp | 2 +- src/mainwindow.cpp | 264 ++++++------------------------------------ src/mainwindow.h | 17 +-- src/modinfo.h | 9 -- src/modlist.cpp | 5 - src/nxmaccessmanager.cpp | 4 +- src/organizercore.cpp | 173 +++++++++++++++++++++++---- src/organizercore.h | 13 ++- src/organizerproxy.cpp | 25 +--- src/plugincontainer.cpp | 2 - src/plugincontainer.h | 36 +++--- src/pluginlist.cpp | 2 +- src/settings.cpp | 15 ++- src/settings.h | 3 +- src/shared/appconfig.inc | 3 + src/shared/stackdata.cpp | 2 +- src/syncoverwritedialog.cpp | 6 +- 20 files changed, 248 insertions(+), 349 deletions(-) (limited to 'src') diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 24fda501..1a5c025d 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -65,12 +65,12 @@ void DirectoryRefresher::setMods(const std::vectorremoveFile(files[i]); } - static wchar_t *dirs[] = { L"fomod" }; + static const wchar_t *dirs[] = { L"fomod" }; for (int i = 0; i < sizeof(dirs) / sizeof(wchar_t*); ++i) { structure->removeDir(std::wstring(dirs[i])); } diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index e760e3e8..d83d14c8 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -275,8 +275,8 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath())); ui->argumentsEdit->setText(selectedExecutable.m_Arguments); ui->workingDirEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_WorkingDirectory)); - ui->closeCheckBox->setChecked(selectedExecutable.m_CloseMO == DEFAULT_CLOSE); - if (selectedExecutable.m_CloseMO == NEVER_CLOSE) { + ui->closeCheckBox->setChecked(selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE); + if (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::NEVER_CLOSE) { ui->closeCheckBox->setEnabled(false); ui->closeCheckBox->setToolTip(tr("MO must be kept running or this application will not work correctly.")); } else { diff --git a/src/iuserinterface.h b/src/iuserinterface.h index 76d4c75a..68cce2f7 100644 --- a/src/iuserinterface.h +++ b/src/iuserinterface.h @@ -11,9 +11,7 @@ class IUserInterface { public: - void storeSettings(QSettings &settings); - - virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "") = 0; + virtual void storeSettings(QSettings &settings) = 0; virtual bool waitForProcessOrJob(HANDLE processHandle, LPDWORD exitCode = NULL) = 0; @@ -24,10 +22,6 @@ public: virtual void disconnectPlugins() = 0; - virtual bool close() = 0; - - virtual void setEnabled(bool enabled) = 0; - virtual void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab) = 0; virtual void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives) = 0; diff --git a/src/main.cpp b/src/main.cpp index 5a57cf47..4aab45b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -530,7 +530,7 @@ int main(int argc, char *argv[]) arguments.removeFirst(); // remove binary name // pass the remaining parameters to the binary try { - mainWindow.startApplication(exeName, arguments, QString(), selectedProfileName); + organizer.startApplication(exeName, arguments, QString(), selectedProfileName); } catch (const std::exception &e) { reportError(QObject::tr("failed to start application: %1").arg(e.what())); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5d9b12a9..a2df0c24 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -285,7 +285,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize connect(&m_OrganizerCore, &OrganizerCore::modInstalled, this, &MainWindow::modInstalled); - connect(&m_IntegratedBrowser, SIGNAL(requestDownload(QUrl,QNetworkReply*)), this, SLOT(requestDownload(QUrl,QNetworkReply*))); + connect(&m_IntegratedBrowser, SIGNAL(requestDownload(QUrl,QNetworkReply*)), &m_OrganizerCore, SLOT(requestDownload(QUrl,QNetworkReply*))); connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString))); @@ -318,6 +318,14 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize installTranslator(QFileInfo(fileName).baseName()); } + for (IPluginTool *toolPlugin : m_PluginContainer.plugins()) { + registerPluginTool(toolPlugin); + } + + for (IPluginModPage *modPagePlugin : m_PluginContainer.plugins()) { + registerModPage(modPagePlugin); + } + refreshExecutablesList(); updateToolBar(); } @@ -325,8 +333,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize MainWindow::~MainWindow() { - m_AboutToRun.disconnect_all_slots(); - m_ModInstalled.disconnect_all_slots(); m_PluginContainer.setUserInterface(nullptr, nullptr); m_OrganizerCore.setUserInterface(nullptr, nullptr); m_IntegratedBrowser.close(); @@ -919,7 +925,6 @@ void MainWindow::toolPluginInvoke() } } - void MainWindow::modPagePluginInvoke() { QAction *triggeredAction = qobject_cast(sender()); @@ -932,7 +937,6 @@ void MainWindow::modPagePluginInvoke() } } - void MainWindow::registerPluginTool(IPluginTool *tool) { QAction *action = new QAction(tool->icon(), tool->displayName(), ui->toolBar); @@ -944,7 +948,6 @@ void MainWindow::registerPluginTool(IPluginTool *tool) toolBtn->menu()->addAction(action); } - void MainWindow::registerModPage(IPluginModPage *modPage) { // turn the browser action into a drop-down menu if necessary @@ -1009,10 +1012,8 @@ void MainWindow::activateSelectedProfile() m_ModListSortProxy->setProfile(m_OrganizerCore.currentProfile()); - connect(m_OrganizerCore.currentProfile(), SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint))); - refreshSaveList(); - refreshModList(); + m_OrganizerCore.refreshModList(); } void MainWindow::on_profileBox_currentIndexChanged(int index) @@ -1415,7 +1416,7 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString subItem->setExpanded(true); } - m_OrganizerCore.checkBSAList(); + checkBSAList(defaultArchives); } @@ -1597,7 +1598,7 @@ void MainWindow::installMod() if (fileName.length() == 0) { return; } else { - m_OrganizerCore.installMod(fileName); + m_OrganizerCore.installMod(fileName, QString()); } } catch (const std::exception &e) { reportError(e.what()); @@ -1694,7 +1695,7 @@ bool MainWindow::modifyExecutablesDialog() { bool result = false; try { - EditExecutablesDialog dialog(m_OrganizerCore.executablesList()); + EditExecutablesDialog dialog(*m_OrganizerCore.executablesList()); if (dialog.exec() == QDialog::Accepted) { m_OrganizerCore.setExecutablesDialog(dialog.getExecutablesList()); result = true; @@ -1866,7 +1867,7 @@ void MainWindow::modorder_changed() } m_OrganizerCore.refreshBSAList(); m_OrganizerCore.currentProfile()->writeModlist(); - m_OrganizerCore.saveArchiveList(); + saveArchiveList(); m_OrganizerCore.directoryStructure()->getFileRegister()->sortOrigins(); { // refresh selection @@ -1883,11 +1884,10 @@ void MainWindow::modorder_changed() } } -void MainWindow::modInstalled() +void MainWindow::modInstalled(const QString &modName) { QModelIndexList posList = - m_OrganizerCore.modList().match(m_OrganizerCore.modList().index(0, 0), - Qt::DisplayRole, static_cast(modName)); + m_OrganizerCore.modList()->match(m_OrganizerCore.modList()->index(0, 0), Qt::DisplayRole, modName); if (posList.count() == 1) { ui->modList->scrollTo(posList.at(0)); } @@ -2151,7 +2151,7 @@ void MainWindow::restoreBackup_clicked() if (!modDir.rename(modInfo->absolutePath(), destinationPath)) { reportError(tr("failed to rename \"%1\" to \"%2\"").arg(modInfo->absolutePath()).arg(destinationPath)); } - refreshModList(); + m_OrganizerCore.refreshModList(); } } } @@ -2262,7 +2262,7 @@ void MainWindow::resumeDownload(int downloadIndex) QString username, password; if (m_OrganizerCore.settings().getNexusLogin(username, password)) { //m_PostLoginTasks.push_back(boost::bind(&MainWindow::resumeDownload, _1, downloadIndex)); - m_OrganizerCore.doAfterLogin(std::bind(&MainWindow::resumeDownload, this, downloadIndex)); + m_OrganizerCore.doAfterLogin([this, downloadIndex] () { this->resumeDownload(downloadIndex); }); NexusInterface::instance()->getAccessManager()->login(username, password); } else { MessageDialog::showMessage(tr("You need to be logged in with Nexus to resume a download"), this); @@ -2278,7 +2278,8 @@ void MainWindow::endorseMod(ModInfo::Ptr mod) } else { QString username, password; if (m_OrganizerCore.settings().getNexusLogin(username, password)) { - m_PostLoginTasks.push_back(boost::bind(&MainWindow::endorseMod, _1, mod)); + //m_PostLoginTasks.push_back(boost::bind(&MainWindow::endorseMod, _1, mod)); + m_OrganizerCore.doAfterLogin([&] () { this->endorseMod(mod); }); NexusInterface::instance()->getAccessManager()->login(username, password); } else { MessageDialog::showMessage(tr("You need to be logged in with Nexus to endorse"), this); @@ -2305,7 +2306,8 @@ void MainWindow::unendorse_clicked() ModInfo::getByIndex(m_ContextRow)->endorse(false); } else { if (m_OrganizerCore.settings().getNexusLogin(username, password)) { - m_PostLoginTasks.push_back(boost::mem_fn(&MainWindow::unendorse_clicked)); + //m_PostLoginTasks.push_back(boost::mem_fn(&MainWindow::unendorse_clicked)); + m_OrganizerCore.doAfterLogin([this] () { this->unendorse_clicked(); }); NexusInterface::instance()->getAccessManager()->login(username, password); } else { MessageDialog::showMessage(tr("You need to be logged in with Nexus to endorse"), this); @@ -2320,7 +2322,7 @@ void MainWindow::loginFailed(const QString &message) void MainWindow::windowTutorialFinished(const QString &windowName) { - m_OrganizerCore.settings().directInterface().setValue(QString("CompletedWindowTutorials/") + windowName, this); + m_OrganizerCore.settings().directInterface().setValue(QString("CompletedWindowTutorials/") + windowName, true); } void MainWindow::overwriteClosed(int) @@ -2489,17 +2491,7 @@ void MainWindow::information_clicked() } } -void MainWindow::syncOverwrite() -{ - ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); - SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_OrganizerCore.directoryStructure(), this); - if (syncDialog.exec() == QDialog::Accepted) { - syncDialog.apply(QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory())); - modInfo->testValid(); - refreshDirectoryStructure(); - } -} void MainWindow::createModFromOverwrite() { @@ -2527,11 +2519,15 @@ void MainWindow::createModFromOverwrite() return; } - ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(m_ContextRow); + unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool { + std::vector flags = mod->getFlags(); + return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); }); + + ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(overwriteIndex); shellMove(QStringList(QDir::toNativeSeparators(overwriteInfo->absolutePath()) + "\\*"), QStringList(QDir::toNativeSeparators(newMod->absolutePath())), this); - refreshModList(); + m_OrganizerCore.refreshModList(); } void MainWindow::cancelModListEditor() @@ -2743,7 +2739,7 @@ void MainWindow::savePrimaryCategory() bool MainWindow::saveArchiveList() { - if (m_ArchivesInit) { + if (m_OrganizerCore.isArchivesInit()) { SafeWriteFile archiveFile(m_OrganizerCore.currentProfile()->getArchivesFileName()); for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i); @@ -2777,7 +2773,7 @@ void MainWindow::checkModsForUpdates() } else { QString username, password; if (m_OrganizerCore.settings().getNexusLogin(username, password)) { - m_OrganizerCore.doAfterLogin(boost::mem_fn(&MainWindow::checkModsForUpdates)); + m_OrganizerCore.doAfterLogin([this] () { this->checkModsForUpdates(); }); NexusInterface::instance()->getAccessManager()->login(username, password); } else { // otherwise there will be no endorsement info m_ModsToUpdate = ModInfo::checkAllForUpdate(this); @@ -2974,7 +2970,7 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) std::vector flags = info->getFlags(); if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) { if (QDir(info->absolutePath()).count() > 2) { - menu->addAction(tr("Sync to Mods..."), this, SLOT(syncOverwrite())); + menu->addAction(tr("Sync to Mods..."), &m_OrganizerCore, SLOT(syncOverwrite())); menu->addAction(tr("Create Mod..."), this, SLOT(createModFromOverwrite())); } } else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end()) { @@ -3403,67 +3399,6 @@ void MainWindow::languageChange(const QString &newLanguage) ui->listOptionsBtn->setMenu(modListContextMenu()); } - -void MainWindow::installDownload(int index) -{ - try { - QString fileName = m_OrganizerCore.downloadManager()->getFilePath(index); - int modID = m_OrganizerCore.downloadManager()->getModID(index); - int fileID = m_OrganizerCore.downloadManager()->getFileInfo(index)->fileID; - GuessedValue modName; - - // see if there already are mods with the specified mod id - if (modID != 0) { - std::vector modInfo = ModInfo::getByModID(modID); - for (auto iter = modInfo.begin(); iter != modInfo.end(); ++iter) { - std::vector flags = (*iter)->getFlags(); - if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) == flags.end()) { - modName.update((*iter)->name(), GUESS_PRESET); - (*iter)->saveMeta(); - } - } - } - - m_OrganizerCore.currentProfile()->writeModlistNow(); - - bool hasIniTweaks = false; - m_OrganizerCore.installationManager()->setModsDirectory(m_OrganizerCore.settings().getModDirectory()); - if (m_OrganizerCore.installationManager()->install(fileName, modName, hasIniTweaks)) { - MessageDialog::showMessage(tr("Installation successful"), this); - refreshModList(); - - QModelIndexList posList = m_OrganizerCore.modList()->match(m_OrganizerCore.modList()->index(0, 0), Qt::DisplayRole, static_cast(modName)); - if (posList.count() == 1) { - ui->modList->scrollTo(posList.at(0)); - } - int modIndex = ModInfo::getIndex(modName); - if (modIndex != UINT_MAX) { - ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex); - modInfo->addInstalledFile(modID, fileID); - - if (hasIniTweaks && - (QMessageBox::question(this, tr("Configure Mod"), - tr("This mod contains ini tweaks. Do you want to configure them now?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) { - displayModInformation(modInfo, modIndex, ModInfoDialog::TAB_INIFILES); - } - - m_ModInstalled(modName); - } else { - reportError(tr("mod \"%1\" not found").arg(modName)); - } - m_OrganizerCore.downloadManager()->markInstalled(index); - - emit modInstalled(); - } else if (m_OrganizerCore.installationManager()->wasCancelled()) { - QMessageBox::information(this, tr("Installation cancelled"), tr("The mod was not installed completely."), QMessageBox::Ok); - } - } catch (const std::exception &e) { - reportError(e.what()); - } -} - - void MainWindow::writeDataToFile(QFile &file, const QString &directory, const DirectoryEntry &directoryEntry) { { // list files @@ -3711,7 +3646,7 @@ void MainWindow::openDataFile() QString arguments; switch (getBinaryExecuteInfo(targetInfo, binaryInfo, arguments)) { case 1: { - spawnBinaryDirect(binaryInfo, arguments, m_OrganizerCore.currentProfile()->getName(), targetInfo.absolutePath(), ""); + m_OrganizerCore.spawnBinaryDirect(binaryInfo, arguments, m_OrganizerCore.currentProfile()->getName(), targetInfo.absolutePath(), ""); } break; case 2: { ::ShellExecuteW(NULL, L"open", ToWString(targetInfo.absoluteFilePath()).c_str(), NULL, NULL, SW_SHOWNORMAL); @@ -3839,7 +3774,7 @@ void MainWindow::updateDownloadListDelegate() ui->downloadView->sortByColumn(1, Qt::AscendingOrder); ui->downloadView->header()->resizeSections(QHeaderView::Fixed); - connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), this, SLOT(installDownload(int))); + connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool))); connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int))); @@ -4354,135 +4289,12 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU } } - -HANDLE MainWindow::startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile) -{ - QFileInfo binary; - QString arguments = args.join(" "); - QString currentDirectory = cwd; - QString profileName = profile; - if (profile.length() == 0) { - if (m_OrganizerCore.currentProfile() != NULL) { - profileName = m_OrganizerCore.currentProfile()->getName(); - } else { - throw MyException(tr("No profile set")); - } - } - QString steamAppID; - if (executable.contains('\\') || executable.contains('/')) { - // file path - - binary = QFileInfo(executable); - if (binary.isRelative()) { - // relative path, should be relative to game directory - binary = QFileInfo(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/" + executable); - } - - std::vector::iterator current, end; - m_OrganizerCore.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 { - const Executable &exe = m_OrganizerCore.executablesList()->find(executable); - steamAppID = exe.m_SteamAppID; - if (arguments == "") { - arguments = exe.m_Arguments; - } - binary = exe.m_BinaryInfo; - if (cwd.length() == 0) { - currentDirectory = exe.m_WorkingDirectory; - } - } catch (const std::runtime_error&) { - qWarning("\"%s\" not set up as executable", executable.toUtf8().constData()); - binary = QFileInfo(executable); - } - } - - return spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID); -} - - -bool MainWindow::waitForProcessOrJob(HANDLE handle, LPDWORD exitCode) -{ - LockedDialog *dialog = new LockedDialog(this); - dialog->show(); - setEnabled(false); - ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); this->setEnabled(true); }); - - DWORD retLen; - JOBOBJECT_BASIC_PROCESS_ID_LIST info; - - 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) && !dialog->unlockClicked()) { - if (isJobHandle) { - if (::QueryInformationJobObject(handle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) { - if (info.NumberOfProcessIdsInList == 0) { - // fake signaled state - res = WAIT_OBJECT_0; - break; - } else { - // 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 (processHandle != handle) { - ::CloseHandle(processHandle); - } - processHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, lastProcessID); - } - } - } 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, &handle, false, 500, QS_KEY | QS_MOUSE); - } - - if (exitCode != NULL) { - ::GetExitCodeProcess(processHandle, exitCode); - } - ::CloseHandle(processHandle); - - return res == WAIT_OBJECT_0; -} - - bool MainWindow::waitForProcessOrJob(HANDLE handle, LPDWORD exitCode) { LockedDialog *dialog = new LockedDialog(this); dialog->show(); setEnabled(false); - ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); this->setEnabled(true); }); + ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); setEnabled(true); }); DWORD retLen; JOBOBJECT_BASIC_PROCESS_ID_LIST info; @@ -4545,8 +4357,8 @@ void MainWindow::on_bossButton_clicked() bool success = false; try { - this->setEnabled(false); - ON_BLOCK_EXIT([&] () { this->setEnabled(true); }); + setEnabled(false); + ON_BLOCK_EXIT([&] () { setEnabled(true); }); QProgressDialog dialog(this); dialog.setLabelText(tr("Please wait while LOOT is running")); dialog.setMaximum(0); @@ -4792,7 +4604,7 @@ void MainWindow::on_restoreModsButton_clicked() QMessageBox::critical(this, tr("Restore failed"), tr("Failed to restore the backup. Errorcode: %1").arg(windowsErrorString(::GetLastError()))); } - refreshModList(false); + m_OrganizerCore.refreshModList(false); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 8adaeb1f..199047b1 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -109,8 +109,6 @@ public: std::string readFromPipe(HANDLE stdOutRead); void processLOOTOut(const std::string &lootOut, std::string &reportURL, std::string &errorMessages, QProgressDialog &dialog); - HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = ""); - bool waitForProcessOrJob(HANDLE processHandle, LPDWORD exitCode = NULL); void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo); @@ -122,9 +120,6 @@ public: virtual void disconnectPlugins(); void unloadPlugins(); - virtual bool close(); - virtual void setEnabled(bool enabled); - void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab); public slots: @@ -163,8 +158,6 @@ protected: private: - void refreshModList(bool saveChanges = true); - void actionToToolButton(QAction *&sourceAction); void updateToolBar(); @@ -174,10 +167,7 @@ private: void startSteam(); - HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID); - void updateTo(QTreeWidgetItem *subTree, const std::wstring &directorySoFar, const MOShared::DirectoryEntry &directoryEntry, bool conflictsOnly); - void refreshDirectoryStructure(); bool refreshProfiles(bool selectProfile = true); void refreshExecutablesList(); void installMod(); @@ -365,15 +355,12 @@ private slots: void linkMenu(); void languageChange(const QString &newLanguage); - void modStatusChanged(unsigned int index); void saveSelectionChanged(QListWidgetItem *newItem); void windowTutorialFinished(const QString &windowName); BSA::EErrorCode extractBSA(BSA::Archive &archive, BSA::Folder::Ptr folder, const QString &destination, QProgressDialog &extractProgress); - void syncOverwrite(); - void createModFromOverwrite(); void procError(QProcess::ProcessError error); @@ -387,7 +374,6 @@ private slots: void linkClicked(const QString &url); - void installDownload(int index); void updateAvailable(); void motdReceived(const QString &motd); @@ -404,7 +390,7 @@ private slots: void modDetailsUpdated(bool success); void modlistChanged(int row); - void modInstalled(); + void modInstalled(const QString &modName); void nxmUpdatesAvailable(const std::vector &modIDs, QVariant userData, QVariant resultData, int requestID); void nxmEndorsementToggled(int, QVariant, QVariant resultData, int); @@ -481,7 +467,6 @@ private slots: void about(); void delayedRemove(); - void requestDownload(const QUrl &url, QNetworkReply *reply); void modlistSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous); void modListSortIndicatorChanged(int column, Qt::SortOrder order); diff --git a/src/modinfo.h b/src/modinfo.h index d532202b..048196f7 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -418,11 +418,6 @@ public: */ virtual std::vector getContents() const { return std::vector(); } - /** - * @return a list of content types contained in a mod - */ - virtual std::vector getContents() const { return std::vector(); } - /** * @brief test if the specified flag is set for this mod * @param flag the flag to test @@ -1075,10 +1070,6 @@ public: static const char INT_IDENTIFIER[]; -public: - - static const char INT_IDENTIFIER[]; - public: virtual bool updateAvailable() const { return false; } diff --git a/src/modlist.cpp b/src/modlist.cpp index bfe8a70e..7b922c7c 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -657,11 +657,6 @@ void ModList::disconnectSlots() { m_ModStateChanged.disconnect_all_slots(); } -void ModList::disconnectSlots() { - m_ModMoved.disconnect_all_slots(); - m_ModStateChanged.disconnect_all_slots(); -} - IModList::ModStates ModList::state(unsigned int modIndex) const { IModList::ModStates result; diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 18b47707..9db9213c 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see . #include "utility.h" #include "selfupdater.h" #include "persistentcookiejar.h" +#include "settings.h" #include #include #include @@ -48,8 +49,7 @@ NXMAccessManager::NXMAccessManager(QObject *parent, const QString &moVersion) , m_MOVersion(moVersion) , m_LoginAttempted(false) { - setCookieJar(new PersistentCookieJar( - QDir::fromNativeSeparators(MOBase::ToQString(MOShared::GameInfo::instance().getCacheDir())) + "/nexus_cookies.dat", this)); + setCookieJar(new PersistentCookieJar(Settings::instance().getCacheDirectory())); } NXMAccessManager::~NXMAccessManager() diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 1e787670..0c414a15 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 #include #include @@ -76,7 +77,7 @@ static std::wstring getProcessName(DWORD processId) } } -bool MainWindow::testForSteam() +bool OrganizerCore::testForSteam() { size_t currentSize = 1024; std::unique_ptr processIDs; @@ -153,7 +154,7 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings) , m_UserInterface(nullptr) , m_PluginContainer(nullptr) , m_CurrentProfile(nullptr) - , m_Settings() + , m_Settings(initSettings) , m_Updater(NexusInterface::instance()) , m_AboutToRun() , m_FinishedRun() @@ -244,7 +245,7 @@ void OrganizerCore::storeSettings() settings.setValue("binary", item.m_BinaryInfo.absoluteFilePath()); settings.setValue("arguments", item.m_Arguments); settings.setValue("workingDirectory", item.m_WorkingDirectory); - settings.setValue("closeOnStart", item.m_CloseMO == DEFAULT_CLOSE); + settings.setValue("closeOnStart", item.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE); settings.setValue("steamAppID", item.m_SteamAppID); } } @@ -443,6 +444,7 @@ InstallationManager *OrganizerCore::installationManager() void OrganizerCore::setCurrentProfile(Profile *profile) { delete m_CurrentProfile; m_CurrentProfile = profile; + connect(m_CurrentProfile, SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint))); m_ModList.setProfile(profile); } @@ -601,6 +603,63 @@ MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName, const 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 modName; + + // see if there already are mods with the specified mod id + if (modID != 0) { + std::vector modInfo = ModInfo::getByModID(modID); + for (auto iter = modInfo.begin(); iter != modInfo.end(); ++iter) { + std::vector 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()); + } +} + QString OrganizerCore::resolvePath(const QString &fileName) const { if (m_DirectoryStructure == nullptr) { @@ -709,10 +768,11 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->getName(), currentDirectory, steamAppID); if (processHandle != INVALID_HANDLE_VALUE) { if (closeAfterStart && (m_UserInterface != nullptr)) { - m_UserInterface->close(); + qApp->closeAllWindows(); } else { - if (m_UserInterface != nullptr) { - m_UserInterface->setEnabled(false); + QWidget *mainWindow = qApp->activeWindow(); + if (mainWindow != nullptr) { + mainWindow->setEnabled(false); } // re-enable the locked dialog because what'd be the point otherwise? dialog->setEnabled(true); @@ -759,9 +819,10 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument } ::CloseHandle(processHandle); - if (m_UserInterface != nullptr) { - m_UserInterface->setEnabled(true); + if (mainWindow != nullptr) { + mainWindow->setEnabled(false); } + 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 @@ -829,9 +890,53 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString & HANDLE OrganizerCore::startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile) { - if (m_UserInterface != nullptr) { - return m_UserInterface->startApplication(executable, args, cwd, profile); + QFileInfo binary; + QString arguments = args.join(" "); + QString currentDirectory = cwd; + QString profileName = profile; + if (profile.length() == 0) { + if (m_CurrentProfile != NULL) { + profileName = m_CurrentProfile->getName(); + } else { + throw MyException(tr("No profile set")); + } + } + QString steamAppID; + if (executable.contains('\\') || executable.contains('/')) { + // file path + binary = QFileInfo(executable); + if (binary.isRelative()) { + // relative path, should be relative to game directory + binary = QFileInfo(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/" + executable); + } + 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 { + const Executable &exe = m_ExecutablesList.find(executable); + steamAppID = exe.m_SteamAppID; + if (arguments == "") { + arguments = exe.m_Arguments; + } + binary = exe.m_BinaryInfo; + if (cwd.length() == 0) { + currentDirectory = exe.m_WorkingDirectory; + } + } catch (const std::runtime_error&) { + qWarning("\"%s\" not set up as executable", executable.toUtf8().constData()); + binary = QFileInfo(executable); + } } + + return spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID); } bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode) const @@ -890,12 +995,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())); @@ -909,15 +1031,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(); @@ -927,7 +1040,7 @@ void OrganizerCore::refreshBSAList() } if (m_UserInterface != nullptr) { - m_UserInterface->updateBSAList(); + m_UserInterface->updateBSAList(m_DefaultArchives, m_ActiveArchives); } m_ArchivesInit = true; @@ -1185,11 +1298,27 @@ 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 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 OrganizerCore::activeProblems() const { std::vector problems; - if (enabledCount() > 255) { + if (m_PluginList.enabledCount() > 255) { problems.push_back(PROBLEM_TOOMANYPLUGINS); } return problems; diff --git a/src/organizercore.h b/src/organizercore.h index ad63dc51..1e03b20c 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -92,6 +92,8 @@ public: ModListSortProxy *createModListProxyModel(); PluginListSortProxy *createPluginListProxyModel(); + HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID); + bool isArchivesInit() const { return m_ArchivesInit; } bool saveCurrentLists(); @@ -107,7 +109,7 @@ public: void requestDownload(const QUrl &url, QNetworkReply *reply); - void doAfterLogin(std::function &function) { m_PostLoginTasks.append(function); } + void doAfterLogin(const std::function &function) { m_PostLoginTasks.append(function); } void spawnBinary(const QFileInfo &binary, const QString &arguments = "", const QDir ¤tDirectory = QDir(), bool closeAfterStart = true, const QString &steamAppID = ""); @@ -118,6 +120,8 @@ public: void loginFailed(const QString &message); void loginFailedUpdate(const QString &message); + void syncOverwrite(); + public: virtual MOBase::IGameInfo &gameInfo() const; virtual MOBase::IModRepositoryBridge *createNexusBridge() const; @@ -162,6 +166,7 @@ public slots: void profileRefresh(); void externalMessage(const QString &message); + void installDownload(int index); void refreshLists(); @@ -171,7 +176,7 @@ signals: * @brief emitted after a mod has been installed * @node this is currently only used for tutorials */ - void modInstalled(); + void modInstalled(const QString &modName); private: @@ -181,9 +186,11 @@ private: bool nexusLogin(); - HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID); void updateModActiveState(int index, bool active); + bool testForSteam(); + QStringList defaultArchiveList(); + private slots: void directory_refreshed(); diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 367ae001..2ce5b3ee 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -100,11 +100,6 @@ HANDLE OrganizerProxy::startApplication(const QString &executable, const QString return m_Proxied->startApplication(executable, args, cwd, profile); } -bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const -{ - return m_Proxied->waitForProcessOrJob(handle, exitCode); -} - bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const { return m_Proxied->waitForApplication(handle, exitCode); @@ -125,16 +120,14 @@ bool OrganizerProxy::onModInstalled(const std::function return m_Proxied->onModInstalled(func); } - void OrganizerProxy::refreshModList(bool saveChanges) { m_Proxied->refreshModList(saveChanges); } - IModInterface *OrganizerProxy::installMod(const QString &fileName) { - return m_Proxied->installMod(fileName); + return m_Proxied->installMod(fileName, QString()); } QString OrganizerProxy::resolvePath(const QString &fileName) const @@ -157,22 +150,6 @@ QStringList OrganizerProxy::getFileOrigins(const QString &fileName) const return m_Proxied->getFileOrigins(fileName); } -QStringList OrganizerProxy::getFileOrigins(const QString &fileName) const -{ - QStringList result; - const FileEntry::Ptr file = m_Proxied->m_DirectoryStructure->searchFile(ToWString(QFileInfo(fileName).fileName()), NULL); - - if (file.get() != NULL) { - result.append(ToQString(m_Proxied->m_DirectoryStructure->getOriginByID(file->getOrigin()).getName())); - foreach (int i, file->getAlternatives()) { - result.append(ToQString(m_Proxied->m_DirectoryStructure->getOriginByID(i).getName())); - } - } else { - qDebug("%s not found", qPrintable(fileName)); - } - return result; -} - QList OrganizerProxy::findFileInfos(const QString &path, const std::function &filter) const { return m_Proxied->findFileInfos(path, filter); diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index bd96828e..9e1da11b 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -90,7 +90,6 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) IPluginModPage *modPage = qobject_cast(plugin); if (verifyPlugin(modPage)) { bf::at_key(m_Plugins).push_back(modPage); - registerModPage(modPage); return true; } } @@ -106,7 +105,6 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) IPluginTool *tool = qobject_cast(plugin); if (verifyPlugin(tool)) { bf::at_key(m_Plugins).push_back(tool); - registerPluginTool(tool); return true; } } diff --git a/src/plugincontainer.h b/src/plugincontainer.h index 213b4154..3f4a98d7 100644 --- a/src/plugincontainer.h +++ b/src/plugincontainer.h @@ -15,6 +15,7 @@ #include #ifndef Q_MOC_RUN #include +#include #endif // Q_MOC_RUN #include @@ -25,6 +26,21 @@ class PluginContainer : public QObject, public MOBase::IPluginDiagnose Q_OBJECT Q_INTERFACES(MOBase::IPluginDiagnose) +private: + + typedef boost::fusion::map< + boost::fusion::pair>, + boost::fusion::pair>, + boost::fusion::pair>, + boost::fusion::pair>, + boost::fusion::pair>, + boost::fusion::pair>, + boost::fusion::pair>, + boost::fusion::pair> + > PluginMap; + + static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1; + public: PluginContainer(OrganizerCore *organizer); @@ -37,8 +53,9 @@ public: MOBase::IPluginGame *managedGame(const QString &name) const; template - std::vector plugins() const { - return boost::fusion::at_key(m_Plugins); + const std::vector &plugins() const { + typename boost::fusion::result_of::at_key::type temp = boost::fusion::at_key(m_Plugins); + return temp; } const PreviewGenerator &previewGenerator() const; @@ -66,21 +83,6 @@ private: bool registerPlugin(QObject *pluginObj, const QString &fileName); bool unregisterPlugin(QObject *pluginObj, const QString &fileName); -private: - - typedef boost::fusion::map< - boost::fusion::pair>, - boost::fusion::pair>, - boost::fusion::pair>, - boost::fusion::pair>, - boost::fusion::pair>, - boost::fusion::pair>, - boost::fusion::pair>, - boost::fusion::pair> - > PluginMap; - - static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1; - private: OrganizerCore *m_Organizer; diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index b2d02cd2..8642ef13 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1168,7 +1168,7 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event) } -PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME time, +PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME, const QString &originName, const QString &fullPath, bool hasIni) : m_Name(name), m_FullPath(fullPath), m_Enabled(enabled), m_ForceEnabled(enabled), diff --git a/src/settings.cpp b/src/settings.cpp index 274e5979..8571a83b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -60,8 +60,8 @@ static const unsigned char Key2[20] = { 0x99, 0xb8, 0x76, 0x42, 0x3e, 0xc1, 0x60 Settings *Settings::s_Instance = NULL; -Settings::Settings() - : m_Settings(ToQString(GameInfo::instance().getIniFilename()), QSettings::IniFormat) +Settings::Settings(const QSettings &settingsSource) + : m_Settings(settingsSource.fileName(), settingsSource.format()) { if (s_Instance != NULL) { throw std::runtime_error("second instance of \"Settings\" created"); @@ -181,7 +181,7 @@ QString Settings::getSteamAppID() const QString Settings::getDownloadDirectory() const { - return QDir::toNativeSeparators(m_Settings.value("Settings/download_directory", ToQString(GameInfo::instance().getDownloadDir())).toString()); + return getConfigurablePath("download_directory", ToQString(AppConfig::downloadPath())); } @@ -219,14 +219,19 @@ std::map Settings::getPreferredServers() return result; } +QString Settings::getConfigurablePath(const QString &key, const QString &def) const +{ + return m_Settings.value(QString("settings/") + key, qApp->property("dataPath").toString() + "/" + def).toString(); +} + QString Settings::getCacheDirectory() const { - return QDir::toNativeSeparators(m_Settings.value("Settings/cache_directory", ToQString(GameInfo::instance().getCacheDir())).toString()); + return getConfigurablePath("cache_directory", ToQString(AppConfig::cachePath())); } QString Settings::getModDirectory() const { - return QDir::toNativeSeparators(m_Settings.value("Settings/mod_directory", ToQString(GameInfo::instance().getModsDir())).toString()); + return getConfigurablePath("mod_directory", ToQString(AppConfig::modsPath())); } QString Settings::getNMMVersion() const diff --git a/src/settings.h b/src/settings.h index 5d398f49..cea4729a 100644 --- a/src/settings.h +++ b/src/settings.h @@ -43,7 +43,7 @@ public: /** * @brief constructor **/ - Settings(); + Settings(const QSettings &settingsSource); virtual ~Settings(); @@ -281,6 +281,7 @@ private: void addStyles(QComboBox *styleBox); void readPluginBlacklist(); void writePluginBlacklist(); + QString getConfigurablePath(const QString &key, const QString &def) const; private slots: diff --git a/src/shared/appconfig.inc b/src/shared/appconfig.inc index 7ce2724f..2ea4d627 100644 --- a/src/shared/appconfig.inc +++ b/src/shared/appconfig.inc @@ -1,7 +1,10 @@ APPPARAM(std::wstring, translationPrefix, L"organizer") APPPARAM(std::wstring, pluginPath, L"plugins") +APPPARAM(std::wstring, modsPath, L"mods") +APPPARAM(std::wstring, downloadPath, L"downloads") APPPARAM(std::wstring, overwritePath, L"overwrite") APPPARAM(std::wstring, stylesheetsPath, L"stylesheets") +APPPARAM(std::wstring, cachePath, L"webcache") APPPARAM(std::wstring, profileTweakIni, L"profile_tweaks.ini") APPPARAM(std::wstring, logFile, L"ModOrganizer.log") APPPARAM(std::wstring, proxyDLLTarget, L"steam_api.dll") diff --git a/src/shared/stackdata.cpp b/src/shared/stackdata.cpp index 7f6f6e52..39e69569 100644 --- a/src/shared/stackdata.cpp +++ b/src/shared/stackdata.cpp @@ -1,9 +1,9 @@ #include "stackdata.h" +#include "util.h" #include #include #include -#include #include diff --git a/src/syncoverwritedialog.cpp b/src/syncoverwritedialog.cpp index 380719d8..5f99bb83 100644 --- a/src/syncoverwritedialog.cpp +++ b/src/syncoverwritedialog.cpp @@ -129,7 +129,7 @@ void SyncOverwriteDialog::applyTo(QTreeWidgetItem *item, const QString &path, co QTreeWidgetItem *child = item->child(i); QString filePath; if (path.length() != 0) { - filePath = path.mid(0).append("/").append(child->text(0)); + filePath = path + "/" + child->text(0); } else { filePath = child->text(0); } @@ -141,8 +141,8 @@ void SyncOverwriteDialog::applyTo(QTreeWidgetItem *item, const QString &path, co int originID = comboBox->itemData(comboBox->currentIndex(), Qt::UserRole).toInt(); if (originID != -1) { FilesOrigin &origin = m_DirectoryStructure->getOriginByID(originID); - QString source = m_SourcePath.mid(0).append("/").append(filePath); - QString destination = modDirectory.mid(0).append("/").append(ToQString(origin.getName())).append("/").append(filePath); + QString source = m_SourcePath + "/" + filePath; + QString destination = modDirectory + "/" + ToQString(origin.getName()) + "/" + filePath; if (!QFile::remove(destination)) { reportError(tr("failed to remove %1").arg(destination)); } else if (!QFile::rename(source, destination)) { -- cgit v1.3.1