From 482f13a50b921e61d34d09f72a7fb4216efe742b Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 8 Sep 2014 20:37:23 +0200 Subject: - re-enabled building of loot_cli and started developing against the new api - extended set of default categories - more tolerand bbcode parser - added a few colors for the bbcode parser - more fixes to qt5 compatibility - started work on ability to unloading (and thus re-loading) of plugins - names of plugins are no longer localizable (because those names are also used to store settings) - added settings to disable individual diagnosis settings - path of dependencies is now configured in a .pri file instead of environment variablees - bugfix: if the modid-input is canceled, the id was saved as -1 and wasn't re-requested from the user - bugfix: moving files with the SHFileOperation-Api didn't update the vfs correctly (still not perfect but better) - bugfix: attempt to remove the deleter-file seems to have caused error messages for some users - bugfix: fixed a couple of cases that might have caused the tutorial to hang --- src/mainwindow.cpp | 77 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0d9fad5d..984d8cfd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -97,9 +97,6 @@ along with Mod Organizer. If not, see . #include #include #include -#include -#include -#include #include #include #include @@ -114,8 +111,13 @@ along with Mod Organizer. If not, see . #include #include #include +#ifndef Q_MOC_RUN #include #include +#include +#include +#include +#endif #include #ifdef TEST_MODELS @@ -313,8 +315,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_Updater, SIGNAL(updateAvailable()), this, SLOT(updateAvailable())); connect(&m_Updater, SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString))); -// connect(ExitProxy::instance(), SIGNAL(exit()), this, SLOT(close())); - connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool))); connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString))); connect(NexusInterface::instance(), SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString))); @@ -367,6 +367,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget MainWindow::~MainWindow() { + m_AboutToRun.disconnect_all_slots(); + m_ModInstalled.disconnect_all_slots(); m_RefresherThread.exit(); m_RefresherThread.wait(); m_IntegratedBrowser.close(); @@ -888,6 +890,8 @@ void MainWindow::closeEvent(QCloseEvent* event) storeSettings(); +// unloadPlugins(); + // profile has to be cleaned up before the modinfo-buffer is cleared delete m_CurrentProfile; m_CurrentProfile = NULL; @@ -895,6 +899,7 @@ void MainWindow::closeEvent(QCloseEvent* event) ModInfo::clear(); LogBuffer::cleanQuit(); m_ModList.setProfile(NULL); + NexusInterface::instance()->cleanup(); } @@ -1175,7 +1180,9 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) IPluginDiagnose *diagnose = qobject_cast(plugin); if (diagnose != NULL) { m_DiagnosisPlugins.push_back(diagnose); - diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); }); + m_DiagnosisConnections.push_back( + diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); }) + ); } } { // mod page plugin @@ -1204,6 +1211,7 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) IPluginPreview *preview = qobject_cast(plugin); if (verifyPlugin(preview)) { m_PreviewGenerator.registerPlugin(preview); + return true; } } { // proxy plugins @@ -1242,13 +1250,41 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) return false; } - -void MainWindow::loadPlugins() +void MainWindow::unloadPlugins() { + // disconnect all slots before unloading plugins so plugins don't have to take care of that + m_AboutToRun.disconnect_all_slots(); + m_ModInstalled.disconnect_all_slots(); + m_ModList.disconnectSlots(); + m_PluginList.disconnectSlots(); + m_DiagnosisPlugins.clear(); + foreach (const boost::signals2::connection &connection, m_DiagnosisConnections) { + connection.disconnect(); + } + m_DiagnosisConnections.clear(); + m_Settings.clearPlugins(); + if (ui->actionTool->menu() != NULL) { + ui->actionTool->menu()->clear(); + } + + foreach (QPluginLoader *loader, m_PluginLoaders) { + qDebug("unloading %s", qPrintable(loader->fileName())); + if (!loader->unload()) { + qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString())); + } + delete loader; + } + m_PluginLoaders.clear(); +} + +void MainWindow::loadPlugins() +{ + unloadPlugins(); + foreach (QObject *plugin, QPluginLoader::staticInstances()) { registerPlugin(plugin, ""); } @@ -1287,14 +1323,15 @@ void MainWindow::loadPlugins() loadCheck.flush(); QString pluginName = iter.filePath(); if (QLibrary::isLibrary(pluginName)) { - QPluginLoader pluginLoader(pluginName); - if (pluginLoader.instance() == NULL) { + QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this); + if (pluginLoader->instance() == NULL) { m_UnloadedPlugins.push_back(pluginName); qCritical("failed to load plugin %s: %s", - qPrintable(pluginName), qPrintable(pluginLoader.errorString())); + qPrintable(pluginName), qPrintable(pluginLoader->errorString())); } else { - if (registerPlugin(pluginLoader.instance(), pluginName)) { + if (registerPlugin(pluginLoader->instance(), pluginName)) { qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); + m_PluginLoaders.push_back(pluginLoader); } else { m_UnloadedPlugins.push_back(pluginName); qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); @@ -2214,6 +2251,8 @@ void MainWindow::storeSettings() void MainWindow::on_btnRefreshData_clicked() { if (!m_DirectoryUpdate) { + // save the mod list so changes don't get lost + m_CurrentProfile->writeModlistNow(true); refreshDirectoryStructure(); } else { qDebug("directory update"); @@ -4315,13 +4354,10 @@ void MainWindow::downloadRequested(QNetworkReply *reply, int modID, const QStrin void MainWindow::installTranslator(const QString &name) { -/* if (m_CurrentLanguage == "en_US") { - return; - }*/ QTranslator *translator = new QTranslator(this); QString fileName = name + "_" + m_CurrentLanguage; if (!translator->load(fileName, qApp->applicationDirPath() + "/translations")) { - if (m_CurrentLanguage != "en-US") { + if ((m_CurrentLanguage != "en-US") && (m_CurrentLanguage != "en_US")) { qWarning("localization file %s not found", qPrintable(fileName)); } // we don't actually expect localization files for english } @@ -4485,7 +4521,7 @@ int MainWindow::getBinaryExecuteInfo(const QFileInfo &targetInfo, if (::FindExecutableW(targetPathW.c_str(), NULL, buffer) > (HINSTANCE)32) { DWORD binaryType = 0UL; if (!::GetBinaryTypeW(targetPathW.c_str(), &binaryType)) { - qDebug("failed to determine binary type: %lu", ::GetLastError()); + qDebug("failed to determine binary type of \"%ls\": %lu", targetPathW.c_str(), ::GetLastError()); } else if (binaryType == SCS_32BIT_BINARY) { binaryPath = ToQString(buffer); } @@ -5088,9 +5124,6 @@ void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) void MainWindow::on_actionProblems_triggered() { -// QString problemDescription; -// checkForProblems(problemDescription); -// QMessageBox::information(this, tr("Problems"), problemDescription); ProblemsDialog problems(m_DiagnosisPlugins, this); if (problems.hasProblems()) { problems.exec(); @@ -5594,7 +5627,11 @@ 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); } -- cgit v1.3.1 From 7d271380868f96a7a2e1f36ee03b97ad9db7c52e Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 10 Sep 2014 20:43:33 +0200 Subject: when MO fails to overwrite its ini file it tries another method using qt functions --- src/mainwindow.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 984d8cfd..ae5c1e48 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2166,6 +2166,15 @@ void MainWindow::readSettings() } +bool renameFile(const QString &oldName, const QString &newName, bool overwrite = true) +{ + if (overwrite && QFile::exists(newName)) { + QFile::remove(newName); + } + return QFile::rename(oldName, newName); +} + + void MainWindow::storeSettings() { if (m_CurrentProfile == NULL) { @@ -2235,8 +2244,12 @@ void MainWindow::storeSettings() } if (result == QSettings::NoError) { if (!shellRename(iniFile + ".new", iniFile, true, this)) { - QMessageBox::critical(this, tr("Failed to write settings"), - tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(::GetLastError()))); + DWORD err = ::GetLastError(); + // make a second attempt using qt functions but if that fails print the error from the first attempt + if (!renameFile(iniFile + ".new", iniFile)) { + QMessageBox::critical(this, tr("Failed to write settings"), + tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(err))); + } } } else { QString reason = result == QSettings::AccessError ? tr("File is write protected") -- cgit v1.3.1 From 93bd29c13d3355b2544c2fd40dff1f4f985f9b57 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 24 Sep 2014 19:51:51 +0200 Subject: - several style fixes suggested by static analysis - will now support up to 4 levels of version numbers (major.minor.subminor.subsubminor --- src/browserdialog.cpp | 2 +- src/categories.cpp | 8 +++--- src/installationmanager.h | 2 +- src/main.cpp | 11 +++----- src/mainwindow.cpp | 55 +++++++++++++++++++--------------------- src/modinfo.cpp | 2 +- src/modlist.cpp | 8 ++++-- src/modlist.h | 2 +- src/modlistsortproxy.cpp | 2 +- src/nexusinterface.cpp | 5 +++- src/pluginlist.cpp | 50 ++++++++++++++++++------------------- src/profile.cpp | 4 ++- src/selfupdater.h | 3 ++- src/settings.cpp | 2 +- src/shared/directoryentry.cpp | 6 ++--- src/shared/directoryentry.h | 2 +- src/shared/fallout3info.cpp | 21 ++++++++-------- src/shared/fallout3info.h | 6 ++--- src/shared/falloutnvinfo.cpp | 58 +++++++++++++++++++------------------------ src/shared/falloutnvinfo.h | 6 ++--- src/shared/gameinfo.cpp | 40 ++++++++--------------------- src/shared/leaktrace.cpp | 2 +- src/shared/oblivioninfo.cpp | 21 ++++++++-------- src/shared/oblivioninfo.h | 6 ++--- src/shared/skyriminfo.cpp | 53 ++++++++++++++++++--------------------- src/shared/skyriminfo.h | 8 +++--- 26 files changed, 176 insertions(+), 209 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp index 521459d0..f93ffcae 100644 --- a/src/browserdialog.cpp +++ b/src/browserdialog.cpp @@ -22,10 +22,10 @@ along with Mod Organizer. If not, see . #include "messagedialog.h" #include "report.h" -#include "json.h" #include "persistentcookiejar.h" #include +#include "json.h" #include #include diff --git a/src/categories.cpp b/src/categories.cpp index 28b1f4a2..57e18a28 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -232,7 +232,7 @@ void CategoryFactory::loadDefaultCategories() int CategoryFactory::getParentID(unsigned int index) const { - if ((index < 0) || (index >= m_Categories.size())) { + if (index >= m_Categories.size()) { throw MyException(QObject::tr("invalid index %1").arg(index)); } @@ -267,7 +267,7 @@ bool CategoryFactory::isDecendantOf(int id, int parentID) const bool CategoryFactory::hasChildren(unsigned int index) const { - if ((index < 0) || (index >= m_Categories.size())) { + if (index >= m_Categories.size()) { throw MyException(QObject::tr("invalid index %1").arg(index)); } @@ -277,7 +277,7 @@ bool CategoryFactory::hasChildren(unsigned int index) const QString CategoryFactory::getCategoryName(unsigned int index) const { - if ((index < 0) || (index >= m_Categories.size())) { + if (index >= m_Categories.size()) { throw MyException(QObject::tr("invalid index %1").arg(index)); } @@ -287,7 +287,7 @@ QString CategoryFactory::getCategoryName(unsigned int index) const int CategoryFactory::getCategoryID(unsigned int index) const { - if ((index < 0) || (index >= m_Categories.size())) { + if (index >= m_Categories.size()) { throw MyException(QObject::tr("invalid index %1").arg(index)); } diff --git a/src/installationmanager.h b/src/installationmanager.h index d430c065..336c1ce3 100644 --- a/src/installationmanager.h +++ b/src/installationmanager.h @@ -55,7 +55,7 @@ public: **/ explicit InstallationManager(QWidget *parent); - ~InstallationManager(); + virtual ~InstallationManager(); /** * @brief update the directory where mods are to be installed diff --git a/src/main.cpp b/src/main.cpp index 3198208a..642bfa1a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -455,14 +455,9 @@ int main(int argc, char *argv[]) settings.setValue("gamePath", gamePath.toUtf8().constData()); } - int edition = 0; - if (settings.contains("game_edition")) { - edition = settings.value("game_edition").toInt(); - } else { + if (!settings.contains("game_edition")) { std::vector editions = GameInfo::instance().getSteamVariants(); - if (editions.size() < 2) { - edition = 0; - } else { + 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!)"), NULL); int index = 0; for (auto iter = editions.begin(); iter != editions.end(); ++iter) { @@ -475,7 +470,7 @@ int main(int argc, char *argv[]) } } } - +#pragma message("edition isn't used?") qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath))); ExecutablesList executablesList; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ae5c1e48..19be758e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1137,7 +1137,6 @@ void MainWindow::registerPluginTool(IPluginTool *tool) void MainWindow::registerModPage(IPluginModPage *modPage) { - QToolButton *browserBtn = NULL; // turn the browser action into a drop-down menu if necessary if (ui->actionNexus->menu() == NULL) { QAction *nexusAction = ui->actionNexus; @@ -1147,10 +1146,8 @@ void MainWindow::registerModPage(IPluginModPage *modPage) ui->toolBar->removeAction(nexusAction); actionToToolButton(ui->actionNexus); - browserBtn = qobject_cast(ui->toolBar->widgetForAction(ui->actionNexus)); + QToolButton *browserBtn = qobject_cast(ui->toolBar->widgetForAction(ui->actionNexus)); browserBtn->menu()->addAction(nexusAction); - } else { - browserBtn = qobject_cast(ui->toolBar->widgetForAction(ui->actionNexus)); } QAction *action = new QAction(modPage->icon(), modPage->displayName(), ui->toolBar); @@ -1434,30 +1431,32 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, DWORD retLen; JOBOBJECT_BASIC_PROCESS_ID_LIST info; - bool isJobHandle = true; + { + bool isJobHandle = true; - 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 { - // 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; + 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 { + // 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(); + // keep processing events so the app doesn't appear dead + QCoreApplication::processEvents(); - res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE); + res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE); + } } ::CloseHandle(processHandle); @@ -2191,11 +2190,7 @@ void MainWindow::storeSettings() QSettings::Status result = QSettings::NoError; { QSettings settings(iniFile + ".new", QSettings::IniFormat); - if (m_CurrentProfile != NULL) { - settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData()); - } else { - settings.remove("selected_profile"); - } + settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData()); settings.setValue("mod_list_state", ui->modList->header()->saveState()); settings.setValue("plugin_list_state", ui->espList->header()->saveState()); @@ -5560,11 +5555,11 @@ void MainWindow::on_bossButton_clicked() DWORD retLen; JOBOBJECT_BASIC_PROCESS_ID_LIST info; - bool isJobHandle = true; - ULONG lastProcessID; HANDLE processHandle = loot; if (loot != INVALID_HANDLE_VALUE) { + bool isJobHandle = true; + ULONG lastProcessID; DWORD res = ::MsgWaitForMultipleObjects(1, &loot, false, 1000, QS_KEY | QS_MOUSE); while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0)) { if (isJobHandle) { diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 796dab71..189e67b2 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -156,7 +156,7 @@ bool ModInfo::removeMod(unsigned int index) auto iter = s_ModsByModID.find(modInfo->getNexusID()); if (iter != s_ModsByModID.end()) { std::vector indices = iter->second; - std::remove(indices.begin(), indices.end(), index); + indices.erase(std::remove(indices.begin(), indices.end(), index), indices.end()); s_ModsByModID[modInfo->getNexusID()] = indices; } diff --git a/src/modlist.cpp b/src/modlist.cpp index eedf1ec6..fb8df15e 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -49,8 +49,12 @@ using namespace MOBase; ModList::ModList(QObject *parent) - : QAbstractItemModel(parent), m_Profile(NULL), m_Modified(false), - m_FontMetrics(QFont()), m_DropOnItems(false) + : QAbstractItemModel(parent) + , m_Profile(NULL) + , m_NexusInterface(NULL) + , m_Modified(false) + , m_FontMetrics(QFont()) + , m_DropOnItems(false) { m_ContentIcons[ModInfo::CONTENT_PLUGIN] = std::make_tuple(QIcon(":/MO/gui/content/plugin"), ":/MO/gui/content/plugin", tr("Game plugins (esp/esm)")); m_ContentIcons[ModInfo::CONTENT_INTERFACE] = std::make_tuple(QIcon(":/MO/gui/content/interface"), ":/MO/gui/content/interface", tr("Interface")); diff --git a/src/modlist.h b/src/modlist.h index 632689c6..cf52b2ec 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -267,7 +267,7 @@ private: struct TModInfo { TModInfo(unsigned int index, ModInfo::Ptr modInfo) - : modInfo(modInfo), nameOrder(index) {} + : modInfo(modInfo), nameOrder(index), priorityOrder(0), modIDOrder(0), categoryOrder(0) {} ModInfo::Ptr modInfo; unsigned int nameOrder; unsigned int priorityOrder; diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index da5d99d5..8907e712 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -298,7 +298,7 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const } break; case CategoryFactory::CATEGORY_SPECIAL_NOTENDORSED: { ModInfo::EEndorsedState state = info->endorsedState(); - if ((state == ModInfo::ENDORSED_FALSE) && (state != ModInfo::ENDORSED_NEVER)) return true; + if ((state == ModInfo::ENDORSED_FALSE) || (state == ModInfo::ENDORSED_NEVER)) return true; } break; case CategoryFactory::CATEGORY_SPECIAL_MANAGED: { if (!info->hasFlag(ModInfo::FLAG_FOREIGN)) return true; diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index 30221f4b..b4006097 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -20,7 +20,7 @@ along with Mod Organizer. If not, see . #include "nexusinterface.h" #include "nxmaccessmanager.h" #include "utility.h" -#include +#include "json.h" #include "selectiondialog.h" #include #include @@ -580,6 +580,7 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID , m_URL(url) , m_SubModule(subModule) , m_NexusGameID(nexusGameId) + , m_Endorse(false) {} NexusInterface::NXMRequestInfo::NXMRequestInfo(std::vector modIDList @@ -600,6 +601,7 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(std::vector modIDList , m_URL(url) , m_SubModule(subModule) , m_NexusGameID(nexusGameId) + , m_Endorse(false) {} NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID @@ -620,4 +622,5 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID , m_URL(url) , m_SubModule(subModule) , m_NexusGameID(nexusGameId) + , m_Endorse(false) {} diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index ff370fa4..973e3cfc 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -685,7 +685,7 @@ QString PluginList::origin(const QString &name) const { auto iter = m_ESPsByName.find(name.toLower()); if (iter == m_ESPsByName.end()) { - return false; + return QString(); } else { return m_ESPs[iter->second].m_OriginName; } @@ -836,7 +836,7 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const std::set_difference(m_ESPs[index].m_Masters.begin(), m_ESPs[index].m_Masters.end(), m_ESPs[index].m_MasterUnset.begin(), m_ESPs[index].m_MasterUnset.end(), std::inserter(enabledMasters, enabledMasters.end())); - if (enabledMasters.size() > 0) { + if (!enabledMasters.empty()) { text += "
" + tr("Enabled Masters") + ": " + SetJoin(enabledMasters, ", "); } if (m_ESPs[index].m_HasIni) { @@ -1102,34 +1102,34 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event) ((keyEvent->key() == Qt::Key_Up) || (keyEvent->key() == Qt::Key_Down))) { QItemSelectionModel *selectionModel = itemView->selectionModel(); const QSortFilterProxyModel *proxyModel = qobject_cast(selectionModel->model()); - int diff = -1; - if (((keyEvent->key() == Qt::Key_Up) && (proxyModel->sortOrder() == Qt::DescendingOrder)) || - ((keyEvent->key() == Qt::Key_Down) && (proxyModel->sortOrder() == Qt::AscendingOrder))) { - diff = 1; - } - QModelIndexList rows = selectionModel->selectedRows(); - // remove elements that aren't supposed to be movable - QMutableListIterator iter(rows); - while (iter.hasNext()) { - if ((iter.next().flags() & Qt::ItemIsDragEnabled) == 0) { - iter.remove(); + if (proxyModel != NULL) { + int diff = -1; + if (((keyEvent->key() == Qt::Key_Up) && (proxyModel->sortOrder() == Qt::DescendingOrder)) || + ((keyEvent->key() == Qt::Key_Down) && (proxyModel->sortOrder() == Qt::AscendingOrder))) { + diff = 1; } - } - if (keyEvent->key() == Qt::Key_Down) { - for (int i = 0; i < rows.size() / 2; ++i) { - rows.swap(i, rows.size() - i - 1); + QModelIndexList rows = selectionModel->selectedRows(); + // remove elements that aren't supposed to be movable + QMutableListIterator iter(rows); + while (iter.hasNext()) { + if ((iter.next().flags() & Qt::ItemIsDragEnabled) == 0) { + iter.remove(); + } } - } - foreach (QModelIndex idx, rows) { - if (proxyModel != NULL) { - idx = proxyModel->mapToSource(idx); + if (keyEvent->key() == Qt::Key_Down) { + for (int i = 0; i < rows.size() / 2; ++i) { + rows.swap(i, rows.size() - i - 1); + } } - int newPriority = m_ESPs[idx.row()].m_Priority + diff; - if ((newPriority >= 0) && (newPriority < rowCount())) { - setPluginPriority(idx.row(), newPriority); + foreach (QModelIndex idx, rows) { + idx = proxyModel->mapToSource(idx); + int newPriority = m_ESPs[idx.row()].m_Priority + diff; + if ((newPriority >= 0) && (newPriority < rowCount())) { + setPluginPriority(idx.row(), newPriority); + } } + refreshLoadOrder(); } - refreshLoadOrder(); return true; } else if (keyEvent->key() == Qt::Key_Space) { QItemSelectionModel *selectionModel = itemView->selectionModel(); diff --git a/src/profile.cpp b/src/profile.cpp index 77e4f813..958084d7 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -585,7 +585,9 @@ void Profile::mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const bool Profile::invalidationActive(bool *supported) const { if (GameInfo::instance().requiresBSAInvalidation()) { - *supported = true; + if (supported != NULL) { + *supported = true; + } wchar_t buffer[1024]; std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value diff --git a/src/selfupdater.h b/src/selfupdater.h index 9648f15a..75b0ff45 100644 --- a/src/selfupdater.h +++ b/src/selfupdater.h @@ -65,7 +65,8 @@ public: * @todo passing the nexus interface is unneccessary **/ SelfUpdater(NexusInterface *nexusInterface, QWidget *parent); - ~SelfUpdater(); + + virtual ~SelfUpdater(); /** * @brief start the update process diff --git a/src/settings.cpp b/src/settings.cpp index 04a5f279..0ca811a3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -25,7 +25,7 @@ along with Mod Organizer. If not, see . #include #include #include -#include +#include "json.h" #include #include diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 5d785822..24868a93 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -325,13 +325,13 @@ static bool ByOriginPriority(DirectoryEntry *entry, int LHS, int RHS) FileEntry::FileEntry() - : m_Index(UINT_MAX), m_Name(), m_Parent(NULL), m_LastAccessed(time(NULL)) + : m_Index(UINT_MAX), m_Name(), m_Origin(-1), m_Parent(NULL), m_LastAccessed(time(NULL)) { LEAK_TRACE; } FileEntry::FileEntry(Index index, const std::wstring &name, DirectoryEntry *parent) - : m_Index(index), m_Name(name), m_Parent(parent), m_Origin(-1), m_Archive(L""), m_LastAccessed(time(NULL)) + : m_Index(index), m_Name(name), m_Origin(-1), m_Parent(parent), m_Archive(L""), m_LastAccessed(time(NULL)) { LEAK_TRACE; } @@ -636,7 +636,7 @@ void DirectoryEntry::insertFile(const std::wstring &filePath, FilesOrigin &origi void DirectoryEntry::removeFile(FileEntry::Index index) { - if (m_Files.size() != 0) { + if (!m_Files.empty()) { auto iter = std::find_if(m_Files.begin(), m_Files.end(), [&index](const std::pair &iter) -> bool { return iter.second == index; } ); diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 096f373e..d588ab02 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -219,7 +219,7 @@ public: void clear(); bool isPopulated() const { return m_Populated; } - bool isEmpty() const { return (m_Files.size() == 0) && (m_SubDirectories.size() == 0); } + bool isEmpty() const { return m_Files.empty() && m_SubDirectories.empty(); } const DirectoryEntry *getParent() const { return m_Parent; } diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp index 9487d2de..22db91ac 100644 --- a/src/shared/fallout3info.cpp +++ b/src/shared/fallout3info.cpp @@ -54,15 +54,17 @@ std::wstring Fallout3Info::getRegPathStatic() 0, KEY_QUERY_VALUE, &key); if (errorcode != ERROR_SUCCESS) { - return L""; + return std::wstring(); } WCHAR temp[MAX_PATH]; DWORD bufferSize = MAX_PATH; - errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize); - - return std::wstring(temp); + if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) { + return std::wstring(temp); + } else { + return std::wstring(); + } } std::wstring Fallout3Info::getInvalidationBSA() @@ -233,15 +235,12 @@ void Fallout3Info::createProfile(const std::wstring &directory, bool useDefaults } } { // copy falloutprefs.ini-file - std::wstring target = directory.substr().append(L"\\falloutprefs.ini"); + std::wstring target = directory + L"\\falloutprefs.ini"; if (!FileExists(target)) { - std::wostringstream source; - source << getMyGamesDirectory() << L"\\Fallout3\\falloutprefs.ini"; - if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) { + std::wstring source = getMyGamesDirectory() + L"\\Fallout3\\falloutprefs.ini"; + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { if (::GetLastError() != ERROR_FILE_EXISTS) { - std::ostringstream stream; - stream << "failed to copy ini file: " << ToString(source.str(), false); - throw windows_error(stream.str()); + throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false)); } } } diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index 8e4c260d..d1356de1 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -38,7 +38,7 @@ public: virtual unsigned long getBSAVersion(); static std::wstring getRegPathStatic(); - virtual std::wstring getRegPath() { return Fallout3Info::getRegPathStatic(); } + virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"Fallout3.exe"; } virtual GameInfo::Type getType() { return TYPE_FALLOUT3; } @@ -75,9 +75,9 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); - virtual std::wstring getNexusInfoUrl() { return Fallout3Info::getNexusInfoUrlStatic(); } + virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); } static int getNexusModIDStatic(); - virtual int getNexusModID() { return Fallout3Info::getNexusModIDStatic(); } + virtual int getNexusModID() { return getNexusModIDStatic(); } virtual int getNexusGameID() { return 120; } virtual void createProfile(const std::wstring &directory, bool useDefaults); diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp index 9bba7fe4..0dde4db1 100644 --- a/src/shared/falloutnvinfo.cpp +++ b/src/shared/falloutnvinfo.cpp @@ -55,15 +55,17 @@ std::wstring FalloutNVInfo::getRegPathStatic() 0, KEY_QUERY_VALUE, &key); if (errorcode != ERROR_SUCCESS) { - return L""; + return std::wstring(); } WCHAR temp[MAX_PATH]; DWORD bufferSize = MAX_PATH; - errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize); - - return std::wstring(temp); + if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) { + return std::wstring(temp); + } else { + return std::wstring(); + } } std::wstring FalloutNVInfo::getInvalidationBSA() @@ -162,56 +164,46 @@ std::wstring FalloutNVInfo::getSteamAPPId(int) const void FalloutNVInfo::createProfile(const std::wstring &directory, bool useDefaults) { - std::wostringstream target; + std::wstring target = directory + L"\\plugins.txt"; // copy plugins.txt - target << directory << "\\plugins.txt"; - - if (!FileExists(target.str())) { - std::wostringstream source; - source << getLocalAppFolder() << "\\FalloutNV\\plugins.txt"; - if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) { - HANDLE file = ::CreateFileW(target.str().c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + if (!FileExists(target)) { + std::wstring source = getLocalAppFolder() + L"\\FalloutNV\\plugins.txt"; + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { + HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); ::CloseHandle(file); } } // copy ini-file - target.str(L""); target.clear(); - target << directory << L"\\fallout.ini"; + target = directory + L"\\fallout.ini"; - if (!FileExists(target.str())) { - std::wostringstream source; + if (!FileExists(target)) { + std::wstring source; if (useDefaults) { - source << getGameDirectory() << L"\\fallout_default.ini"; + source = getGameDirectory() + L"\\fallout_default.ini"; } else { - source << getMyGamesDirectory() << L"\\FalloutNV"; - if (FileExists(source.str(), L"fallout.ini")) { - source << L"\\fallout.ini"; + source = getMyGamesDirectory() + L"\\FalloutNV"; + if (FileExists(source, L"fallout.ini")) { + source += L"\\fallout.ini"; } else { - source.str(L""); - source << getGameDirectory() << L"\\fallout_default.ini"; + source = getGameDirectory() + L"\\fallout_default.ini"; } } - if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) { + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { if (::GetLastError() != ERROR_FILE_EXISTS) { - std::ostringstream stream; - stream << "failed to copy ini file: " << ToString(source.str(), false); - throw windows_error(stream.str()); + throw windows_error("failed to copy ini file: " + ToString(source, false)); } } } { // copy falloutprefs.ini-file - std::wstring target = directory.substr().append(L"\\falloutprefs.ini"); + std::wstring target = directory + L"\\falloutprefs.ini"; if (!FileExists(target)) { - std::wostringstream source; - source << getMyGamesDirectory() << L"\\FalloutNV\\falloutprefs.ini"; - if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) { + std::wstring source = getMyGamesDirectory() + L"\\FalloutNV\\falloutprefs.ini"; + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { if (::GetLastError() != ERROR_FILE_EXISTS) { - std::ostringstream stream; - stream << "failed to copy ini file: " << ToString(source.str(), false); - throw windows_error(stream.str()); + throw windows_error("failed to copy ini file: " + ToString(source, false)); } } } diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h index cfd373c7..50a0d00d 100644 --- a/src/shared/falloutnvinfo.h +++ b/src/shared/falloutnvinfo.h @@ -38,7 +38,7 @@ public: virtual unsigned long getBSAVersion(); static std::wstring getRegPathStatic(); - virtual std::wstring getRegPath() { return FalloutNVInfo::getRegPathStatic(); } + virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"FalloutNV.exe"; } virtual GameInfo::Type getType() { return TYPE_FALLOUTNV; } @@ -76,9 +76,9 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); - virtual std::wstring getNexusInfoUrl() { return FalloutNVInfo::getNexusInfoUrlStatic(); } + virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); } static int getNexusModIDStatic(); - virtual int getNexusModID() { return FalloutNVInfo::getNexusModIDStatic(); } + virtual int getNexusModID() { return getNexusModIDStatic(); } virtual int getNexusGameID() { return 130; } virtual void createProfile(const std::wstring &directory, bool useDefaults); diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp index 21e9a586..5439efff 100644 --- a/src/shared/gameinfo.cpp +++ b/src/shared/gameinfo.cpp @@ -57,7 +57,7 @@ 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); + memset(myDocuments, '\0', MAX_PATH * sizeof(wchar_t)); m_MyGamesDirectory.clear(); @@ -137,71 +137,53 @@ std::wstring GameInfo::getGameDirectory() const std::wstring GameInfo::getModsDir() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << L"\\mods"; - return temp.str(); + return m_OrganizerDirectory + L"\\mods"; } std::wstring GameInfo::getProfilesDir() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << L"\\profiles"; - return temp.str(); + return m_OrganizerDirectory + L"\\profiles"; } std::wstring GameInfo::getIniFilename() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << L"\\ModOrganizer.ini"; - return temp.str(); + return m_OrganizerDirectory + L"\\ModOrganizer.ini"; } std::wstring GameInfo::getDownloadDir() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << L"\\downloads"; - return temp.str(); + return m_OrganizerDirectory + L"\\downloads"; } std::wstring GameInfo::getCacheDir() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << L"\\webcache"; - return temp.str(); + return m_OrganizerDirectory + L"\\webcache"; } std::wstring GameInfo::getOverwriteDir() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << "\\overwrite"; - return temp.str(); + return m_OrganizerDirectory + L"\\overwrite"; } std::wstring GameInfo::getLogDir() const { - std::wostringstream temp; - temp << m_OrganizerDataDirectory << "\\logs"; - return temp.str(); + return m_OrganizerDirectory + L"\\logs"; } std::wstring GameInfo::getLootDir() const { - std::wostringstream temp; - temp << m_OrganizerDirectory << "\\loot"; - return temp.str(); + return m_OrganizerDirectory + L"\\loot"; } std::wstring GameInfo::getTutorialDir() const { - std::wostringstream temp; - temp << m_OrganizerDirectory << "\\tutorials"; - return temp.str(); + return m_OrganizerDirectory + L"\\tutorials"; } @@ -219,7 +201,7 @@ std::vector GameInfo::getSteamVariants() const std::wstring GameInfo::getLocalAppFolder() const { wchar_t localAppFolder[MAX_PATH]; - memset(localAppFolder, '\0', MAX_PATH); + memset(localAppFolder, '\0', MAX_PATH * sizeof(wchar_t)); if (::SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, localAppFolder) == S_OK) { return localAppFolder; diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp index 68e57609..729eb42e 100644 --- a/src/shared/leaktrace.cpp +++ b/src/shared/leaktrace.cpp @@ -36,7 +36,7 @@ class StackData { public: StackData() - : m_FunctionName("Dummy"), m_CodeLine(0) + : m_Count(0), m_Hash(0UL), m_FunctionName("Dummy"), m_CodeLine(0) {} StackData(const char *functionName, int line) { m_Count = ::CaptureStackBackTrace(FRAMES_TO_SKIP, FRAMES_TO_CAPTURE, m_Stack, &m_Hash); diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp index f317812f..790fcdb0 100644 --- a/src/shared/oblivioninfo.cpp +++ b/src/shared/oblivioninfo.cpp @@ -55,15 +55,17 @@ std::wstring OblivionInfo::getRegPathStatic() 0, KEY_QUERY_VALUE, &key); if (errorcode != ERROR_SUCCESS) { - return L""; + return std::wstring(); } WCHAR temp[MAX_PATH]; DWORD bufferSize = MAX_PATH; - errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize); - - return std::wstring(temp); + if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) { + return std::wstring(temp); + } else { + return std::wstring(); + } } std::wstring OblivionInfo::getInvalidationBSA() @@ -188,16 +190,13 @@ void OblivionInfo::createProfile(const std::wstring &directory, bool useDefaults } { // copy oblivionprefs.ini-file - std::wstring target = directory.substr().append(L"\\oblivionprefs.ini"); + std::wstring target = directory + L"\\oblivionprefs.ini"; if (!FileExists(target)) { - std::wostringstream source; - source << getMyGamesDirectory() << L"\\Oblivion\\oblivionprefs.ini"; - if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) { + std::wstring source = getMyGamesDirectory() + L"\\Oblivion\\oblivionprefs.ini"; + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { if ((::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL) == INVALID_HANDLE_VALUE) && (::GetLastError() != ERROR_FILE_EXISTS)) { - std::ostringstream stream; - stream << "failed to create ini file: " << ToString(target.c_str(), false); - throw windows_error(stream.str()); + throw windows_error(std::string("failed to create ini file: ") + ToString(target, false)); } } } diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h index 02fd90b4..e64ae37b 100644 --- a/src/shared/oblivioninfo.h +++ b/src/shared/oblivioninfo.h @@ -36,7 +36,7 @@ public: virtual unsigned long getBSAVersion(); static std::wstring getRegPathStatic(); - virtual std::wstring getRegPath() { return OblivionInfo::getRegPathStatic(); } + virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"Oblivion.exe"; } virtual GameInfo::Type getType() { return TYPE_OBLIVION; } @@ -72,9 +72,9 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); - virtual std::wstring getNexusInfoUrl() { return OblivionInfo::getNexusInfoUrlStatic(); } + virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); } static int getNexusModIDStatic(); - virtual int getNexusModID() { return OblivionInfo::getNexusModIDStatic(); } + virtual int getNexusModID() { return getNexusModIDStatic(); } virtual int getNexusGameID() { return 101; } virtual void createProfile(const std::wstring &directory, bool useDefaults); diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index c985fe9f..319e58d5 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -63,15 +63,17 @@ std::wstring SkyrimInfo::getRegPathStatic() 0, KEY_QUERY_VALUE, &key); if (errorcode != ERROR_SUCCESS) { - return L""; + return std::wstring(); } WCHAR temp[MAX_PATH]; DWORD bufferSize = MAX_PATH; - errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize); - - return std::wstring(temp); + if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) { + return std::wstring(temp); + } else { + return std::wstring(); + } } @@ -222,7 +224,7 @@ int SkyrimInfo::getNexusModIDStatic() void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults) { { // copy plugins.txt - std::wstring target = directory.substr().append(L"\\plugins.txt"); + std::wstring target = directory + L"\\plugins.txt"; if (!FileExists(target)) { std::wostringstream source; source << getLocalAppFolder() << "\\Skyrim\\plugins.txt"; @@ -231,11 +233,10 @@ void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults) ::CloseHandle(file); } } - target = directory.substr().append(L"\\loadorder.txt"); + target = directory + L"\\loadorder.txt"; if (!FileExists(target)) { - std::wostringstream source; - source << getLocalAppFolder() << "\\Skyrim\\loadorder.txt"; - if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) { + std::wstring source = getLocalAppFolder() + L"\\Skyrim\\loadorder.txt"; + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); ::CloseHandle(file); } @@ -243,42 +244,36 @@ void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults) } { // copy skyrim.ini-file - std::wstring target = directory.substr().append(L"\\skyrim.ini"); + std::wstring target = directory + L"\\skyrim.ini"; if (!FileExists(target)) { - std::wostringstream source; + std::wstring source; if (useDefaults) { - source << getGameDirectory() << L"\\skyrim_default.ini"; + source = getGameDirectory() + L"\\skyrim_default.ini"; } else { - source << getMyGamesDirectory() << L"\\Skyrim"; - if (FileExists(source.str(), L"skyrim.ini")) { - source << L"\\skyrim.ini"; + source = getMyGamesDirectory() + L"\\Skyrim"; + if (FileExists(source, L"skyrim.ini")) { + source += L"\\skyrim.ini"; } else { - source.str(L""); - source << getGameDirectory() << L"\\skyrim_default.ini"; + source = getGameDirectory() + L"\\skyrim_default.ini"; } } - if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) { + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { if (::GetLastError() != ERROR_FILE_EXISTS) { - std::ostringstream stream; - stream << "failed to copy ini file: " << ToString(source.str(), false); - throw windows_error(stream.str()); + throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false)); } } } } { // copy skyrimprefs.ini-file - std::wstring target = directory.substr().append(L"\\skyrimprefs.ini"); + std::wstring target = directory + L"\\skyrimprefs.ini"; if (!FileExists(target)) { - std::wostringstream source; - source << getMyGamesDirectory() << L"\\Skyrim\\skyrimprefs.ini"; - if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) { - log("failed to copy ini file %ls", source.str().c_str()); + std::wstring source = getMyGamesDirectory() + L"\\Skyrim\\skyrimprefs.ini"; + if (!::CopyFileW(source.c_str(), target.c_str(), true)) { + log("failed to copy ini file %ls", source.c_str()); // create empty if (::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) == INVALID_HANDLE_VALUE) { - std::ostringstream stream; - stream << "failed to copy ini file: " << ToString(source.str(), false); - throw windows_error(stream.str()); + throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false)); } } } diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index 132f2aee..a7aff8dc 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -38,7 +38,7 @@ public: virtual unsigned long getBSAVersion(); static std::wstring getRegPathStatic(); - virtual std::wstring getRegPath() { return SkyrimInfo::getRegPathStatic(); } + virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"TESV.exe"; } virtual GameInfo::Type getType() { return TYPE_SKYRIM; } @@ -81,11 +81,11 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); - virtual std::wstring getNexusInfoUrl() { return SkyrimInfo::getNexusInfoUrlStatic(); } + virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); } static int getNexusModIDStatic(); - virtual int getNexusModID() { return SkyrimInfo::getNexusModIDStatic(); } + virtual int getNexusModID() { return getNexusModIDStatic(); } static int getNexusGameIDStatic() { return 110; } - virtual int getNexusGameID() { return SkyrimInfo::getNexusGameIDStatic(); } + virtual int getNexusGameID() { return getNexusGameIDStatic(); } virtual void createProfile(const std::wstring &directory, bool useDefaults); virtual void repairProfile(const std::wstring &directory); -- cgit v1.3.1 From db0e278817cf5a36e15f1945c52e73726598e8d9 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 29 Sep 2014 20:35:35 +0200 Subject: - moved the hook-recursion-protection to tls - some code cleanup and consolidation - hook.dll will now report all of its own exceptions - some more logging during startup - changed the way urls are encoded for download requests - now displaying (one of the) process name(s) while waiting for a program to end - bugfix: spawned processes were forced to leave the job --- src/downloadmanager.cpp | 50 ++++++++++++++++--------------------------- src/mainwindow.cpp | 15 +++++++++++++ src/profile.cpp | 7 +++--- src/shared/directoryentry.cpp | 10 ++++----- src/spawn.cpp | 2 +- 5 files changed, 42 insertions(+), 42 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index bc31adf4..b3b18a38 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -331,7 +331,8 @@ bool DownloadManager::addDownload(const QStringList &URLs, fileName = "unknown"; } - QNetworkRequest request(URLs.first()); + QUrl preferredUrl = QUrl::fromEncoded(URLs.first().toLocal8Bit()); + QNetworkRequest request(preferredUrl); return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, fileInfo); } @@ -1198,47 +1199,34 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test), QString())); } - -// sort function to sort by best download server -bool DownloadManager::ServerByPreference(const std::map &preferredServers, const QVariant &LHS, const QVariant &RHS) +int evaluateFileInfoMap(const QVariantMap &map, const std::map &preferredServers) { - int LHSVal = 0; - int RHSVal = 0; + int result = 0; - QVariantMap LHSMap = LHS.toMap(); - QVariantMap RHSMap = RHS.toMap(); - - int LHSUsers = LHSMap["ConnectedUsers"].toInt(); - int RHSUsers = RHSMap["ConnectedUsers"].toInt(); + int users = map["ConnectedUsers"].toInt(); // 0 users is probably a sign that the server is offline. Since there is currently no // mechanism to try a different server, we avoid those without users - if (LHSUsers == 0) { - LHSVal -= 500; - } else { - LHSVal -= LHSUsers; - } - if (RHSUsers == 0) { - RHSVal -= 500; + if (users == 0) { + result -= 500; } else { - RHSVal -= RHSUsers; + result -= users; } - // user preference. This is a bit silly because the more servers on the preferred list the higher the boost - auto LHSPreference = preferredServers.find(LHSMap["Name"].toString()); - auto RHSPreference = preferredServers.find(RHSMap["Name"].toString()); + auto preference = preferredServers.find(map["Name"].toString()); - if (LHSPreference != preferredServers.end()) { - LHSVal += 100 + LHSPreference->second * 20; - } - if (RHSPreference != preferredServers.end()) { - RHSVal += 100 + RHSPreference->second * 20; + if (preference != preferredServers.end()) { + result += 100 + preference->second * 20; } - // premium isn't valued high because premium servers already get a massive boost for having few users online - if (LHSMap["IsPremium"].toBool()) LHSVal += 5; - if (RHSMap["IsPremium"].toBool()) RHSVal += 5; + if (map["IsPremium"].toBool()) result += 5; + + return result; +} - return RHSVal < LHSVal; +// sort function to sort by best download server +bool DownloadManager::ServerByPreference(const std::map &preferredServers, const QVariant &LHS, const QVariant &RHS) +{ + return evaluateFileInfoMap(LHS.toMap(), preferredServers) > evaluateFileInfoMap(RHS.toMap(), preferredServers); } int DownloadManager::startDownloadURLs(const QStringList &urls) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 19be758e..17743312 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1410,6 +1410,15 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg } } +std::wstring getProcessName(DWORD processId) +{ + HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, processId); + + DWORD value = MAX_PATH; + wchar_t buffer[MAX_PATH]; + ::QueryFullProcessImageNameW(process, 0, buffer, &value); + return buffer; +} void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID) { @@ -1432,6 +1441,7 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, JOBOBJECT_BASIC_PROCESS_ID_LIST info; { + DWORD currentProcess = 0UL; bool isJobHandle = true; DWORD res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE); @@ -1439,6 +1449,11 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, if (isJobHandle) { if (::QueryInformationJobObject(processHandle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) { if (info.NumberOfProcessIdsInList == 0) { + } else { + if (info.ProcessIdList[0] != currentProcess) { + currentProcess = info.ProcessIdList[0]; + dialog->setProcessName(ToQString(getProcessName(currentProcess))); + } break; } } else { diff --git a/src/profile.cpp b/src/profile.cpp index 958084d7..6e9d8f0f 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -217,7 +217,7 @@ void Profile::createTweakedIniFile() } if (localSavesEnabled()) { - if (!::WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"1", ToWString(tweakedIni).c_str())) { + if (!::WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"0", ToWString(tweakedIni).c_str())) { error = true; } @@ -238,7 +238,7 @@ void Profile::createTweakedIniFile() void Profile::refreshModStatus() { QFile file(getModlistFileName()); - if (!file.exists()) { + if (!file.open(QIODevice::ReadOnly)) { throw MyException(tr("\"%1\" is missing or inaccessible").arg(getModlistFileName())); } @@ -249,10 +249,9 @@ void Profile::refreshModStatus() std::set namesRead; // load mods from file and update enabled state and priority for them - file.open(QIODevice::ReadOnly); int index = 0; while (!file.atEnd()) { - QByteArray line = file.readLine(); + QByteArray line = file.readLine().trimmed(); bool enabled = true; QString modName; if (line.length() == 0) { diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 24868a93..0adf0812 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -72,8 +72,7 @@ public: } bool exists(const std::wstring &name) { - std::map::iterator iter = m_OriginsNameMap.find(name); - return iter != m_OriginsNameMap.end(); + return m_OriginsNameMap.find(name) != m_OriginsNameMap.end(); } FilesOrigin &getByID(Index ID) { @@ -369,16 +368,14 @@ std::wstring FileEntry::getFullPath() const bool ignore = false; result = m_Parent->getOriginByID(getOrigin(ignore)).getPath(); //base directory for origin recurseParents(result, m_Parent); // all intermediate directories - result.append(L"\\").append(m_Name); // the actual filename - return result; + return result + L"\\" + m_Name; } std::wstring FileEntry::getRelativePath() const { std::wstring result; recurseParents(result, m_Parent); // all intermediate directories - result.append(L"\\").append(m_Name); // the actual filename - return result; + return result + L"\\" + m_Name; } @@ -446,6 +443,7 @@ void DirectoryEntry::addFromOrigin(const std::wstring &originName, const std::ws boost::scoped_array buffer(new wchar_t[MAXPATH_UNICODE + 1]); memset(buffer.get(), L'\0', MAXPATH_UNICODE + 1); int offset = _snwprintf(buffer.get(), MAXPATH_UNICODE, L"%ls", directory.c_str()); + buffer.get()[offset] = L'\0'; addFiles(origin, buffer.get(), offset); } m_Populated = true; diff --git a/src/spawn.cpp b/src/spawn.cpp index ddcf573e..cd7e202e 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -120,7 +120,7 @@ HANDLE startBinary(const QFileInfo &binary, JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo; ::QueryInformationJobObject(NULL, JobObjectExtendedLimitInformation, &jobInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION), NULL); - jobInfo.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_BREAKAWAY_OK; + jobInfo.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK; HANDLE jobObject = ::CreateJobObject(NULL, NULL); -- cgit v1.3.1 From df0bd3331a4b2174f99117c5a6f21ff6bddca1ba Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 5 Nov 2014 23:48:06 +0100 Subject: - archive library can now query for password during extraction (seems to be necessary for rars) - process blacklist is now taken from a file if there is one, not hardcoded - removed workaround for the papyrus compiler - updated loot client to work with the actual api - loot client now links with loot32.dll at runtime - loot client now produces its output in a (json-)file which includes all plugin messages and dirty flags - fomod installer now tries to parse the xml with several encodings - fomod installer will now display a diagnostics warning if the jpg imageformat isn't supported - base preview plugin now tries to be a bit smarter about resizing images to fit the screen - bugfix: fomod installer no longer tries to open an image even after detecting its invalid - bugfix: potential null-pointer dereferentiation in getprivateprofile... hooks - bugfix: potential null-pointer dereferentiation in download manager - bugfix: internal origin name showed up in one more place - bugfix: ToString function produced strings that were one (zero-termination-)character too long --- src/aboutdialog.cpp | 1 - src/dlls.manifest.debug.qt5 | 3 +++ src/downloadmanager.cpp | 2 +- src/main.cpp | 2 +- src/mainwindow.cpp | 48 ++++++++++++++++++++++++++++++++------------- src/mainwindow.h | 2 +- src/organizer.pro | 2 +- src/pluginlist.cpp | 12 +++++++++++- src/settings.cpp | 2 +- src/shared/util.cpp | 9 ++++++--- 10 files changed, 59 insertions(+), 24 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index b5bfeb04..90dcd073 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -41,7 +41,6 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent) addLicense("Boost Library", LICENSE_BOOST); addLicense("7-zip", LICENSE_LGPL3); addLicense("ZLib", LICENSE_ZLIB); - addLicense("NIF File Format Library", LICENSE_BSD3); 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); diff --git a/src/dlls.manifest.debug.qt5 b/src/dlls.manifest.debug.qt5 index 6cc0a83d..1bbdf691 100644 --- a/src/dlls.manifest.debug.qt5 +++ b/src/dlls.manifest.debug.qt5 @@ -8,7 +8,10 @@ + + + diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index bc31adf4..82701a05 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -606,7 +606,7 @@ void DownloadManager::pauseDownload(int index) DownloadInfo *info = m_ActiveDownloads.at(index); if (info->m_State == STATE_DOWNLOADING) { - if (info->m_Reply->isRunning()) { + if ((info->m_Reply != NULL) && (info->m_Reply->isRunning())) { setState(info, STATE_PAUSING); } else { setState(info, STATE_PAUSED); diff --git a/src/main.cpp b/src/main.cpp index 642bfa1a..b4139f09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -332,7 +332,7 @@ int main(int argc, char *argv[]) } } - application.addLibraryPath(application.applicationDirPath() + "/dlls"); + application.setLibraryPaths(QStringList() << (application.applicationDirPath() + "/dlls")); SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 19be758e..d9db84ae 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -103,6 +103,10 @@ along with Mod Organizer. If not, see . #include #include #include +#include +#include +#include +#include #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include #else @@ -1268,14 +1272,14 @@ void MainWindow::unloadPlugins() ui->actionTool->menu()->clear(); } - foreach (QPluginLoader *loader, m_PluginLoaders) { - qDebug("unloading %s", qPrintable(loader->fileName())); + while (!m_PluginLoaders.empty()) { + QPluginLoader *loader = m_PluginLoaders.back(); + m_PluginLoaders.pop_back(); if (!loader->unload()) { qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString())); } delete loader; } - m_PluginLoaders.clear(); } void MainWindow::loadPlugins() @@ -1322,7 +1326,7 @@ void MainWindow::loadPlugins() if (QLibrary::isLibrary(pluginName)) { QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this); if (pluginLoader->instance() == NULL) { - m_UnloadedPlugins.push_back(pluginName); + m_FailedPlugins.push_back(pluginName); qCritical("failed to load plugin %s: %s", qPrintable(pluginName), qPrintable(pluginLoader->errorString())); } else { @@ -1330,7 +1334,7 @@ void MainWindow::loadPlugins() qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); m_PluginLoaders.push_back(pluginLoader); } else { - m_UnloadedPlugins.push_back(pluginName); + m_FailedPlugins.push_back(pluginName); qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); } } @@ -2285,7 +2289,7 @@ void MainWindow::on_tabWidget_currentChanged(int index) std::vector MainWindow::activeProblems() const { std::vector problems; - if (m_UnloadedPlugins.size() != 0) { + if (m_FailedPlugins.size() != 0) { problems.push_back(PROBLEM_PLUGINSNOTLOADED); } if (m_PluginList.enabledCount() > 255) { @@ -2314,7 +2318,7 @@ QString MainWindow::fullDescription(unsigned int key) const switch (key) { case PROBLEM_PLUGINSNOTLOADED: { QString result = tr("The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:") + "
    "; - foreach (const QString &plugin, m_UnloadedPlugins) { + foreach (const QString &plugin, m_FailedPlugins) { result += "
  • " + plugin + "
  • "; } result += "
      "; @@ -5375,13 +5379,10 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU foreach (const std::string &line, lines) { if (line.length() > 0) { - size_t progidx = line.find("[progress]"); - size_t reportidx = line.find("[Report]"); - size_t erroridx = line.find("[error]"); + size_t progidx = line.find("[progress]"); + size_t erroridx = line.find("[error]"); if (progidx != std::string::npos) { dialog.setLabelText(line.substr(progidx + 11).c_str()); - } else if (reportidx != std::string::npos) { - reportURL = line.substr(reportidx + 9); } else if (erroridx != std::string::npos) { qWarning("%s", line.c_str()); errorMessages.append(boost::algorithm::trim_copy(line.substr(erroridx + 8)) + "\n"); @@ -5525,12 +5526,15 @@ void MainWindow::on_bossButton_clicked() dialog.setMaximum(0); dialog.show(); + QString outPath = QDir::temp().absoluteFilePath("lootreport.json"); + QStringList parameters; parameters << "--unattended" << "--stdout" << "--noreport" << "--game" << ToQString(GameInfo::instance().getGameShortName()) - << "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory())); + << "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory())) + << "--out" << outPath; if (m_DidUpdateMasterList) { parameters << "--skipUpdateMasterlist"; @@ -5540,7 +5544,7 @@ void MainWindow::on_bossButton_clicked() HANDLE stdOutWrite = INVALID_HANDLE_VALUE; HANDLE stdOutRead = INVALID_HANDLE_VALUE; createStdoutPipe(&stdOutRead, &stdOutWrite); - HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/LOOT.exe"), + HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"), parameters.join(" "), m_CurrentProfile->getName(), m_Settings.logLevel(), @@ -5615,6 +5619,22 @@ void MainWindow::on_bossButton_clicked() return; } else { success = true; + QFile outFile(outPath); + outFile.open(QIODevice::ReadOnly); + QJsonDocument doc = QJsonDocument::fromJson(outFile.readAll()); + QJsonArray array = doc.array(); + for (auto iter = array.begin(); iter != array.end(); ++iter) { + QJsonObject pluginObj = (*iter).toObject(); + QJsonArray pluginMessages = pluginObj["messages"].toArray(); + for (auto msgIter = pluginMessages.begin(); msgIter != pluginMessages.end(); ++msgIter) { + QJsonObject msg = (*msgIter).toObject(); + m_PluginList.addInformation(pluginObj["name"].toString(), + QString("%1: %2").arg(msg["type"].toString(), msg["message"].toString())); + } + if (pluginObj["dirty"].toString() == "yes") + m_PluginList.addInformation(pluginObj["name"].toString(), "dirty"); + } + } } else { reportError(tr("failed to start loot")); diff --git a/src/mainwindow.h b/src/mainwindow.h index 8bd663ac..ea79fc37 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -381,7 +381,7 @@ private: std::vector m_DiagnosisPlugins; std::vector m_DiagnosisConnections; std::vector m_ModPages; - std::vector m_UnloadedPlugins; + std::vector m_FailedPlugins; std::vector m_PluginLoaders; QFile m_PluginsCheck; diff --git a/src/organizer.pro b/src/organizer.pro index b24586e6..fd1e6aad 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -341,7 +341,7 @@ SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g DSTDIR ~= s,/,$$QMAKE_DIR_SEP,g QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n) -QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.pdb) $$quote($$DSTDIR) $$escape_expand(\\n) +QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n) QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\stylesheets) $$quote($$DSTDIR)\\stylesheets $$escape_expand(\\n) QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\tutorials) $$quote($$DSTDIR)\\tutorials $$escape_expand(\\n) QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\*.qm) $$quote($$DSTDIR)\\translations $$escape_expand(\\n) diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 973e3cfc..b2d02cd2 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see . #include "settings.h" #include "safewritefile.h" #include "scopeguard.h" +#include "modinfo.h" #include #include #include @@ -158,7 +159,14 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD QString iniPath = QFileInfo(filename).baseName() + ".ini"; bool hasIni = baseDirectory.findFile(ToWString(iniPath)).get() != NULL; - m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath()), hasIni)); + QString originName = ToQString(origin.getName()); + unsigned int modIndex = ModInfo::getIndex(originName); + if (modIndex != UINT_MAX) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex); + originName = modInfo->name(); + } + + m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), originName, ToQString(current->getFullPath()), hasIni)); } catch (const std::exception &e) { reportError(tr("failed to update esp info for file %1 (source id: %2), error: %3").arg(filename).arg(current->getOrigin(archive)).arg(e.what())); } @@ -290,6 +298,8 @@ void PluginList::addInformation(const QString &name, const QString &message) if (iter != m_ESPsByName.end()) { m_AdditionalInfo[name.toLower()].m_Messages.append(message); + } else { + qWarning("failed to associate message for \"%s\"", qPrintable(name)); } } diff --git a/src/settings.cpp b/src/settings.cpp index 0ca811a3..274e5979 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -231,7 +231,7 @@ QString Settings::getModDirectory() const QString Settings::getNMMVersion() const { - static const QString MIN_NMM_VERSION = "0.47.0"; + static const QString MIN_NMM_VERSION = "0.52.3"; QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString(); if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) { result = MIN_NMM_VERSION; diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 4bc5a8a4..d4a77929 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -71,7 +71,9 @@ std::string ToString(const std::wstring &source, bool utf8) if (sizeRequired == 0) { throw windows_error("failed to convert string to multibyte"); } - result.resize(sizeRequired, '\0'); + // the size returned by WideCharToMultiByte contains zero termination IF -1 is specified for the length. + // we don't want that \0 in the string because then the length field would be wrong. Because madness + result.resize(sizeRequired - 1, '\0'); ::WideCharToMultiByte(codepage, 0, &source[0], (int)source.size(), &result[0], sizeRequired, NULL, NULL); return result; } @@ -117,14 +119,15 @@ std::wstring ToLower(const std::wstring &text) VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) { - DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), NULL); + DWORD handle; + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); if (size == 0) { throw windows_error("failed to determine file version info size"); } void *buffer = new char[size]; try { - if (!::GetFileVersionInfoW(fileName.c_str(), 0UL, size, buffer)) { + if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer)) { throw windows_error("failed to determine file version info"); } -- cgit v1.3.1 From 7c1273b246117740dd17fb70ad712346421224d7 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 11 Nov 2014 21:41:22 +0100 Subject: some work on installer scripts --- src/mainwindow.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 17743312..90ddcf81 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -5435,11 +5435,22 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList 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_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(); } -- cgit v1.3.1 From 01265e9b0300cb4fe2dbed53050570ddee653da4 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 11 Nov 2014 21:46:16 +0100 Subject: - re-enabled use of img-tags in bbcode converter - addded a workaround for cases where, after a MO update, the stored modlist layout has no size for new columns - using a webview again for the nexus view of the modinfo dialog --- src/bbcode.cpp | 4 ++-- src/mainwindow.cpp | 11 +++++++++-- src/modinfodialog.cpp | 3 ++- src/modinfodialog.ui | 35 ++++++++++++++--------------------- src/modlistsortproxy.cpp | 30 ------------------------------ src/modlistsortproxy.h | 1 - 6 files changed, 27 insertions(+), 57 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/bbcode.cpp b/src/bbcode.cpp index 2e22859d..0f9170d4 100644 --- a/src/bbcode.cpp +++ b/src/bbcode.cpp @@ -177,9 +177,9 @@ private: m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"), "\\2"); m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), - "\\1"); + ""); m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), - "\\2"); + "\"\\1\""); m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"), "\\2"); m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"), diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ede14448..eb1e1b09 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -226,8 +226,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray()); // hack: force the resize-signal to be triggered because restoreState doesn't seem to do that - ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) + 1); - ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) - 1); + ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize + 1); + ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize - 1); } else { // hide these columns by default ui->modList->header()->setSectionHidden(ModList::COL_CONTENT, true); @@ -399,6 +399,13 @@ void MainWindow::resizeLists(bool modListCustom, bool pluginListCustom) #endif } + // ensure the columns aren't so small you can't see them any more + for (int i = 0; i < ui->modList->header()->count(); ++i) { + if (ui->modList->header()->sectionSize(i) < 10) { + ui->modList->header()->resizeSection(i, 10); + } + } + if (!pluginListCustom) { // resize plugin list to fit content #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 1cea9e1e..9133b166 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -84,7 +84,8 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo connect(&m_ThumbnailMapper, SIGNAL(mapped(const QString&)), this, SIGNAL(thumbnailClickedSignal(const QString&))); connect(this, SIGNAL(thumbnailClickedSignal(const QString&)), this, SLOT(thumbnailClicked(const QString&))); connect(m_ModInfo.data(), SIGNAL(modDetailsUpdated(bool)), this, SLOT(modDetailsUpdated(bool))); - connect(ui->descriptionView, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkClicked(QUrl))); + connect(ui->descriptionView, SIGNAL(linkClicked(QUrl)), this, SLOT(linkClicked(QUrl))); + ui->descriptionView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); if (directory->originExists(ToWString(modInfo->name()))) { m_Origin = &directory->getOriginByName(ToWString(modInfo->name())); diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui index d3862b58..a03edef7 100644 --- a/src/modinfodialog.ui +++ b/src/modinfodialog.ui @@ -232,8 +232,8 @@ 0 0 - 676 - 126 + 98 + 28 @@ -678,25 +678,11 @@ p, li { white-space: pre-wrap; } - - - - 0 - 200 - - - - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - - - Qt::TextBrowserInteraction - - - false + + + + about:blank + @@ -819,6 +805,13 @@ p, li { white-space: pre-wrap; } + + + QWebView + QWidget +
      QtWebKitWidgets/QWebView
      +
      +
      diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 8907e712..e132b71e 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -79,36 +79,6 @@ Qt::ItemFlags ModListSortProxy::flags(const QModelIndex &modelIndex) const return flags; } -void ModListSortProxy::displayColumnSelection(const QPoint &pos) -{ - QMenu menu; - - for (int i = 0; i <= ModList::COL_LASTCOLUMN; ++i) { - QCheckBox *checkBox = new QCheckBox(&menu); - checkBox->setText(ModList::getColumnName(i)); - checkBox->setChecked(m_EnabledColumns.test(i) ? Qt::Checked : Qt::Unchecked); - QWidgetAction *checkableAction = new QWidgetAction(&menu); - checkableAction->setDefaultWidget(checkBox); - menu.addAction(checkableAction); - } - menu.exec(pos); - int i = 0; - - emit layoutAboutToBeChanged(); - m_EnabledColumns.reset(); - foreach (const QAction *action, menu.actions()) { - const QWidgetAction *widgetAction = qobject_cast(action); - if (widgetAction != NULL) { - const QCheckBox *checkBox = qobject_cast(widgetAction->defaultWidget()); - if (checkBox != NULL) { - m_EnabledColumns.set(i, checkBox->checkState() == Qt::Checked); - } - } - ++i; - } - emit layoutChanged(); -} - void ModListSortProxy::enableAllVisible() { if (m_Profile == NULL) return; diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 71da79eb..05392c0b 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -95,7 +95,6 @@ public: public slots: - void displayColumnSelection(const QPoint &pos); void updateFilter(const QString &filter); signals: -- cgit v1.3.1 From 53896e66f113519253892903404264b4e49ab8a6 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 11 Nov 2014 23:48:22 +0100 Subject: - updated staging script to use qt5 and to fetch translations from transifex - removed call to function unavailable in Windows XP --- src/ModOrganizer.pro | 1 + src/mainwindow.cpp | 20 +- src/organizer_es.ts | 1247 ++++++++++++++------------- src/organizer_fr.ts | 2232 +++++++++++++++++++++++++----------------------- src/organizer_ru.ts | 1132 ++++++++++++------------ src/organizer_zh_CN.ts | 1692 ++++++++++++++++++------------------ src/organizer_zh_TW.ts | 2138 ++++++++++++++++++++++++---------------------- 7 files changed, 4336 insertions(+), 4126 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index 9b2d998b..a8f7f53e 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -15,6 +15,7 @@ SUBDIRS = bsatk \ loot_cli \ esptk +pythonRunner.depends = uibase plugins.depends = pythonRunner uibase hookdll.depends = shared organizer.depends = shared uibase plugins diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d6d4ebe3..024e2510 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -226,8 +226,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray()); // hack: force the resize-signal to be triggered because restoreState doesn't seem to do that - ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize + 1); - ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize - 1); + ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) + 1); + ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) - 1); } else { // hide these columns by default ui->modList->header()->setSectionHidden(ModList::COL_CONTENT, true); @@ -1425,10 +1425,18 @@ std::wstring getProcessName(DWORD processId) { HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, processId); - DWORD value = MAX_PATH; wchar_t buffer[MAX_PATH]; - ::QueryFullProcessImageNameW(process, 0, buffer, &value); - return buffer; + if (::GetProcessImageFileNameW(process, buffer, MAX_PATH) != 0) { + wchar_t *fileName = wcsrchr(buffer, L'\\'); + if (fileName == nullptr) { + fileName = buffer; + } else { + fileName += 1; + } + return fileName; + } else { + return std::wstring(L"unknown"); + } } void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID) @@ -1460,12 +1468,12 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, 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))); } - break; } } else { // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there diff --git a/src/organizer_es.ts b/src/organizer_es.ts index cf6f18a6..1803ca7f 100644 --- a/src/organizer_es.ts +++ b/src/organizer_es.ts @@ -1,6 +1,4 @@ - - - + AboutDialog @@ -62,7 +60,7 @@ <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -159,22 +157,22 @@ Si existe un componente que es requerido llamado "00 Core" . Las opcio Some Page - + Alguna Página Search - + Búsqueda new - + nuevo failed to start download - + Error al iniciar descarga @@ -225,20 +223,16 @@ Si existe un componente que es requerido llamado "00 Core" . Las opcio <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Puede coincidir con una o varias categorías de una ID interna de Nexus. Cada vez que se descarga un mod de la página de Nexus, Mod Organizador tratará de resolver la categoría definida en Nexus a una disponible en MO</span></p></body></html> + <!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 { espacio blanco: pre envoltura; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Se puede sincronizar una o varias categorías de nexo a un ID interno. Cada vez que se descarga un mod de la Página Nexus, Mod Organizer tratará de resolver la categoría definida en el Nexus a uno disponible en MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Para saber la categoria de una ID usada por nexo, visitar la lista de categorías de la página nexo y discernir sobre los enlaces de allí.</span></p></body></html> Parent ID - Parent ID + ID Paternal @@ -461,7 +455,7 @@ p, li { white-space: pre-wrap; } Un-Hide - Un-Hide + Hacer Visible @@ -577,7 +571,7 @@ p, li { white-space: pre-wrap; } Un-Hide - Un-Hide + Hacer Visible @@ -622,7 +616,7 @@ p, li { white-space: pre-wrap; } Remove All... - Quitar todos... + Eliminando todos... @@ -635,7 +629,7 @@ p, li { white-space: pre-wrap; } Memory allocation error (in refreshing directory). - + Error de asignación de memoria (en directorio refrescante). @@ -705,7 +699,7 @@ p, li { white-space: pre-wrap; } No known download urls. Sorry, this download can't be resumed. - + No se conocen descarga urls. Lo sentimos, esta descarga no se puede reanudar. @@ -750,12 +744,12 @@ p, li { white-space: pre-wrap; } Memory allocation error (in processing progress event). - + Error de asignación de memoria (en el procesamiento de eventos de progreso). Memory allocation error (in processing downloaded data). - + Error de asignación de memoria (en el procesamiento de datos descargados). @@ -830,13 +824,13 @@ p, li { white-space: pre-wrap; } Binary - Fichero + Binario Binary to run - Fiechero para ser ejecutado + Binario para funcionar @@ -846,18 +840,18 @@ p, li { white-space: pre-wrap; } Browse filesystem for the executable to run. - Examinar en busca del ejecutable. + Explorar sistema de archivos para hacer funcionar el ejecutable. ... - Examinar + ... Start in - Comienzo en + Comenzar en @@ -956,7 +950,7 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p Java (32-bit) required - Java (32-bit) requeredo + Java (32-bit) requerido @@ -1006,12 +1000,12 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p Find - Buscar + Encontrar: Find what: - Buscar: + Encuentra en: @@ -1028,7 +1022,7 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p &Find Next - &Encontrar + &Buscar siguiente @@ -1133,7 +1127,7 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html> <!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"> @@ -1177,87 +1171,87 @@ p, li { white-space: pre-wrap; } - + Extracting files Extrayendo ficheros - + failed to create backup fallo al crear copia de seguridad - + Mod Name Nombre del Mod - + Name Nombre - + Invalid name Nombre inválido - + The name you entered is invalid, please enter a different one. El nombre introducido no es válido, por favor introduzca uno diferente. - + File format "%1" not supported Formato de archivo no soportado para "%1" - + None of the available installer plugins were able to handle that archive Ninguno de los plugins del instalador disponible son capaces de manejar este archivo - + no error sin error - + 7z.dll not found 7z.dll no se encuentra - + 7z.dll isn't valid 7z.dll no es valido - + archive not found archivo no encontrado - + failed to open archive Error abriendo el fichero - + unsupported archive type formato de fichero no soportado - + internal library error error interno de libreria - + archive invalid archivo invalido - + unknown archive error Error de fichero desconocido @@ -1277,7 +1271,7 @@ p, li { white-space: pre-wrap; } MO is locked while the executable is running. - MO esta bloqueado mientras se ejecute el programa. + MO esta bloqueado mientras se ejecuta el programa. @@ -1317,27 +1311,27 @@ p, li { white-space: pre-wrap; } Click blank area to deselect - + Púlsar en el área en blanco para anular la selección If checked, only mods that match all selected categories are displayed. - + Si se selecciona, sólo mods que responden a todas las categorías seleccionadas son mostrados. And - + Y If checked, all mods that match at least one of the selected categories are displayed. - + Si se selecciona, se muestran todos los mods que coincidan con al menos una de las categorías seleccionadas. Or - + O @@ -1354,7 +1348,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1364,6 +1358,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Crear perfiles aquí. Cada perfil contiene su propia lista de mods activos y esps. De esta manera puedes cambiar rápidamente entre configuraciones para diferentes juegos.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Ten en cuenta que en estos momentos tu carga de esp no se mantiene separado para diferentes perfiles.</span></p></body></html> + + + Open list options... + Abrir Opciones de la lista... + Refresh list. This is usually not necessary unless you modified data outside the program. @@ -1373,13 +1372,13 @@ p, li { white-space: pre-wrap; } Restore Backup... - Restaurar copia de seguridad + Restaurar copia de seguridad... Create Backup - + Crear Copia de Seguridad @@ -1423,7 +1422,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1443,7 +1442,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html> <!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"> @@ -1466,7 +1465,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html> <!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"> @@ -1484,6 +1483,11 @@ p, li { white-space: pre-wrap; } Plugins Plugins + + + Sort + Ordenar + List of available esp/esm files @@ -1494,7 +1498,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html> <!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"> @@ -1502,30 +1506,20 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Esta lista contiene los ESP y ESMS contenidos en los mods activos. Requieren su propio orden de carga. Utilice arrastrar y soltar para modificar este orden de carga. Tenga en cuenta que MO sólo salvará el orden de carga de los mods que están activos/comprobados.<br />Hay una gran herramienta llamada &quot;BOSS&quot; para ordenar automáticamente los archivos.</span></p></body></html> - - - Sort - Ordenar - - - - Open list options... - - Archives - + Archivos <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>BSAs son paquetes de activos de juego (texturas, scripts, ...). Por defecto, el motor carga estos paquetes en una etapa distinta de archivos sueltos. MO puede gestionar esos archivos para alinear su orden de carga con la de archivos sueltos:</p><p>Si los archivos son <span style=" font-weight:600;">gestionados</span>, se especifica el orden de carga por la prioridad del mod correspondiente (panel izquierdo), lo mismo que los archivos sueltos. Puede activar manualmente cualquier BSA que no tiene un plugin correspondiente activo<br/></p><p>Si los archivos no son <span style=" font-weight:600;">gestionados</span> su orden de carga es especificado por la prioridad del plugin correspondiente (panel de la derecha, pestaña plugins). No podras, activar manualmente BSAs donde el plugin no está activo.</p><p>En cualquiera de los casos no se puede deshabilitar archivos si hay un plugin coincidente, el juego los cargará cueste lo que cueste.</p></body></html> <html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html> - + <html><head/><body><p>Dejar MO manejar archivos (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">leer más</span></a>)</p></body></html> @@ -1566,8 +1560,8 @@ BSA marcado aquí se cargan de tal manera que su orden de instalación se cumple - - + + Refresh Recargar @@ -1602,8 +1596,8 @@ BSA marcado aquí se cargan de tal manera que su orden de instalación se cumple <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1747,7 +1741,7 @@ p, li { white-space: pre-wrap; } - + Update Actualizacion @@ -1791,19 +1785,19 @@ Ahora esto tiene una funcionalidad muy limitada - + Endorse Mod Organizer Avalar Mod Organizer Copy Log to Clipboard - Copiar al Portapapeles + Copiar Log al Portapapeles Ctrl+C - Ctrl+M + Ctrl+C @@ -1920,6 +1914,25 @@ Ahora esto tiene una funcionalidad muy limitada Plugin "%1" failed Plugin "%1" fallido + + + Download? + Descarga? + + + + A download has been started but no installed page plugin recognizes it. +If you download anyway no information (i.e. version) will be associated with the download. +Continue? + Una descarga se ha iniciado, pero no hay página de plugin instalado reconocido. +Si lo descarga de todos modos ninguna información (ej. la versión) se asociará con la descarga. +Continuar? + + + + Browse Mod Page + Explorar Página de Mod + failed to init plugin %1: %2 @@ -1952,6 +1965,11 @@ Ahora esto tiene una funcionalidad muy limitada Please press OK once you're logged into steam. Por favor, pulsa OK una vez que hayas iniciado sesión en steam. + + + Executable "%1" not found + Ejecutable "%1" no encontrado + Start Steam? @@ -1963,924 +1981,889 @@ Ahora esto tiene una funcionalidad muy limitada Steam es requerido para iniciar correctamente el juego. ¿Debería MO tratar de iniciar ahora steam? - + Also in: <br> También en: <br> - + No conflict Sin conflictos - + <Edit...> <Editar...> - + + Failed to refresh list of esps: %1 + Fallo al actualizar la lista de esps: %1 + + + This bsa is enabled in the ini file so it may be required! Esta bsa está habilitada en el archivo ini, por lo que puede ser necesario - + Activating Network Proxy Activación de proxy de red - - - Installation successful - Instalacion completada - - - - - Configure Mod - Configurar Mod + + + Failed to write settings + Error al escribir la configuración - - - This mod contains ini tweaks. Do you want to configure them now? - Este mod contiene ajustes del ini. ¿Quieres configurarlos ahora? + + + An error occured trying to write back MO settings: %1 + Ha ocurrido un error tratando de escribir de nuevo la configuración de MO: %1 - - - mod "%1" not found - mod "%1" no encontrado + + File is write protected + El archivo está protegido contra escritura - - - Installation cancelled - Instalación cancelada + + Invalid file format (probably a bug) + Formato de archivo no válido (probablemente sea un bug) - - - The mod was not installed completely. - El mod no fue instalado completamente. + + Unknown error %1 + Error desconocido %1 - + Some plugins could not be loaded Algún plugins no se pudo cargar - + Too many esps and esms enabled Demasiados esps y esms habilitado - - + + Description missing Falta la descripción - + The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: Los siguientes plugins no se pudieron cargar. La razón puede ser dependencias faltantes (es decir python) o una versión obsoleta: - + The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> El juego no permite cargar más de 255 plugins activos (incluidos los oficiales). Tienes que desactivar algunos plugins no utilizados o fusionar algunos plugins en uno solo. Aquí podras encontrar una guía: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + Choose Mod Seleccione Mod - + Mod Archive Archivo Mod - + + + Installation successful + Instalacion completada + + + + + Configure Mod + Configurar Mod + + + + + This mod contains ini tweaks. Do you want to configure them now? + Este mod contiene ajustes del ini. ¿Quieres configurarlos ahora? + + + + + mod "%1" not found + mod "%1" no encontrado + + + + + Installation cancelled + Instalación cancelada + + + + + The mod was not installed completely. + El mod no fue instalado completamente. + + + Start Tutorial? Iniciar tutorial? - + You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue? Estás a punto de iniciar un tutorial. Por razones técnicas, no es posible terminar el tutorial antes de tiempo. ¿Desea continuar? - - + + Download started Descarga iniciada - + failed to update mod list: %1 Fallo al actualizar la lista de Mods: %1 - + failed to spawn notepad.exe: %1 Fallo al cargar el Bloc de notas: %1 - + failed to open %1 Fallo al abrir %1 - + failed to change origin name: %1 fallo al cambiar el nombre original del fichero %1 - - Executable "%1" not found - Ejecutable "%1" no encontrado - - - - Failed to refresh list of esps: %1 - Fallo al actualizar la lista de esps: %1 + + failed to move "%1" from mod "%2" to "%3": %4 + Error al mover "%1" desde mod "%2" to "%3": %4 - - failed to move "%1" from mod "%2" to "%3": %4 - + + <Contains %1> + <Contiene %1> - + <Checked> <Marcado> - + <Unchecked> <Desmarcado> - + <Update> <Actualizacion> - + + <Managed by MO> + <Gestionado por MO> + + + + <Managed outside MO> + <Gestionado fuera MO> + + + <No category> <No categoría> - + <Conflicted> <En conflicto> - + <Not Endorsed> <No Avalado> - + failed to rename mod: %1 fallo al renombrar el mod: %1 - + Overwrite? - ¿Sobrescribir? + Sobrescribir? - + This will replace the existing mod "%1". Continue? Esto reemplazará el vigente mod "%1". ¿Desea continuar? - + failed to remove mod "%1" Fallo eliminando mod "%1" - - - + + + failed to rename "%1" to "%2" Fallo al renombrar "%1" a "%2" - + Multiple esps activated, please check that they don't conflict. Múltiples esps activados, por favor verifique que no entren en conflicto. - - - - + + + + Confirm Confirmar - + Remove the following mods?<br><ul>%1</ul> ¿Quitar el siguiente mods?<br><ul>%1</ul> - + failed to remove mod: %1 fallo al eliminar mod: %1 - - + + Failed Fallo - + Installation file no longer exists El archivo de instalación ya no existe - + Mods installed with old versions of MO can't be reinstalled in this way. Mods instalados con las viejas versiones de MO no pueden ser instalados de nuevo de este modo. - - - You need to be logged in with Nexus to endorse - Necesita estar conectado con Nexus para avalar - - - - Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. - - - - - - - - Delete %n save(s) - - - - - - - - Extract BSA - Extraer BSA + + You need to be logged in with Nexus to resume a download + Tienes que estar conectado con Nexus para reanudar una descarga - - - failed to read %1: %2 - fallo al leer %1: %2 + + + You need to be logged in with Nexus to endorse + Necesita estar conectado con Nexus para avalar - - This archive contains invalid hashes. Some files may be broken. - Este archivo contiene hashes no válidos. Algunos archivos pueden estar rotos. + + Failed to display overwrite dialog: %1 + No se pudo mostrar diálogo de sobreescritura: %1 - + Nexus ID for this Mod is unknown Se desconoce la ID en Nexus para este Mod - - Download? - Descargas - - - - A download has been started but no installed page plugin recognizes it. -If you download anyway no information (i.e. version) will be associated with the download. -Continue? - - - - - Browse Mod Page - - - - - - Failed to write settings - - - - - - An error occured trying to write back MO settings: %1 - - - - - File is write protected - - - - - Invalid file format (probably a bug) - - - - - Unknown error %1 - - - - - <Managed by MO> - - - - - <Managed outside MO> - - - - - You need to be logged in with Nexus to resume a download - Necesita estar conectado con Nexus para avalar - - - - Failed to display overwrite dialog: %1 - - - - - + + Create Mod... Crear Mod... - + This will move all files from overwrite into a new, regular mod. Please enter a name: Esto moverá todos los archivos de sobrescritura en un nuevo mod, regular. Por favor, introduzca un nombre: - + A mod with this name already exists Ya existe un mod con este nombre - + Continue? ¿Continuar? - + The versioning scheme decides which version is considered newer than another. This function will guess the versioning scheme under the assumption that the installed version is outdated. El esquema de versiones decide qué versión es considerada más nueva una que otra. Esta función adivinará el esquema de versiones bajo el supuesto de que la versión instalada es obsoleta. - - + + Sorry Lo siento - + I don't know a versioning scheme where %1 is newer than %2. Se desconoce un esquema de versiones donde %1 es más reciente que %2. - + Really enable all visible mods? ¿Permitir realmente todos los mods visibles? - + Really disable all visible mods? ¿Realmente desactivar todos los mods visibles? - + Choose what to export Elija un archivo a exportar - + Everything Todo - + All installed mods are included in the list Todos los mods instalados están incluidos en la lista - + Active Mods Mods Activos - + Only active (checked) mods from your current profile are included Mods sólo activos (Marcados) es incluido de su perfil actual - + Visible Visible - + All mods visible in the mod list are included Todo mods visible en la lista de mod son incluidos - + export failed: %1 Falló al exportar: %1 - + Install Mod... Instalar Mod... - + Enable all visible Activar todos los visibles - + Disable all visible Desactivar todo lo visible - + Check all for update Comprobar todo para actualizar - + Export to csv... Exportar a CSV... - + All Mods - + Todo los Mods - + Sync to Mods... Sincronizar con Mods... - + Restore Backup Restaurar copia de seguridad - + Remove Backup... Eliminar copia de seguridad... - + Add/Remove Categories Añadir/Quitar Categorías - + Replace Categories Remplazar Categorías - + Primary Category Categoría Primaria - + Change versioning scheme Cambiar esquema de versiones - + Un-ignore update No ignorar actualización - + Ignore update No Ignorar actualización - + Rename Mod... Renombrar Mod... - + Remove Mod... Quitar Mod... - + Reinstall Mod Reinstalar Mod - + Un-Endorse No Avalado - - + + Endorse Avalado - + Won't endorse - No avalar + No avalado - + Endorsement state unknown Estado de avalado desconocido - + Ignore missing data Ignorar data desaparecido - + Visit on Nexus Visite Nexus - + Open in explorer Abrir en explorador - + Information... Informacion... - - + + Exception: Excepción: - - + + Unknown exception Excepción desconocida - + <All> <Todo> - + <Multiple> <Multiple> - - - Please wait while LOOT is running - + + + Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. + Seguro que desea eliminar el siguiente %n salvado(s)?<br><ul>%1</ul><br>Los salvados Eliminados serán enviados a la papelera de reciclaje.Seguro que desea eliminar el siguiente %n salvado(s)?<br><ul>%1</ul><br>Los salvados Eliminados serán enviados a la papelera de reciclaje. - Really delete "%1"? - Realmente desea borrar "%1"? + + Please wait while LOOT is running + Por favor espera mientras se está ejecutando LOOT - + Fix Mods... - Fix Mods... + Arreglar Mods... - - Delete - Eliminar + + + Delete %n save(s) + Eliminar %n guardado(s)Eliminar %n guardo(s) - + failed to remove %1 Fallo eliminando %1 - - + + failed to create %1 Fallo al crear %1 - + Can't change download directory while downloads are in progress! No se puede cambiar el directorio de descarga, mientras que las descargas están en curso - + Download failed Descarga fallida - + failed to write to file %1 Fallo de escritura en el fichero %1 - + %1 written %1 escrito - + Select binary Selecciona el binario - + Binary Binario - + Enter Name Introducir Nombre - + Please enter a name for the executable Por favor, introduce un nombre para el ejecutable - + Not an executable No es un ejecutable - + This is not a recognized executable. Esto no es un ejecutable reconocido. - - + + Replace file? ¿Reemplazar archivo? - + There already is a hidden version of this file. Replace it? Ya existe una versión oculta de este archivo. Reemplazarlo? - - + + File operation failed La operación del archivo falló - - + + Failed to remove "%1". Maybe you lack the required file permissions? Fallo al eliminar "%1". ¿Tal vez no tengas los permisos necesarios? - + There already is a visible version of this file. Replace it? Ya existe una versión visible de este archivo. ¿Reemplazarlo? - + file not found: %1 archivo no encontrado: %1 - + failed to generate preview for %1 fallo al generar vista anticipada para %1 - + Sorry, can't preview anything. This function currently does not support extracting from bsas. Lo sentimos, no se puede obtener una vista previa de nada. Esta función no admite la extracción de bsas. - + Update available Actualización disponible - + Open/Execute Abrir/Ejecutar - + Add as Executable Añadir un ejecutable - + Preview Previsualizar - + Un-Hide Desocultar - + Hide Ocultar - + Write To File... Escribir al fichero... - + Do you want to endorse Mod Organizer on %1 now? ¿Quieres avalar Mod Organizer en %1 ahora? - + Thank you! - + Gracias! - + Thank you for your endorsement! - + Gracias por su respaldo! - + Request to Nexus failed: %1 Solicitud de Nexus ha fallado: %1 - - + + login successful login correcto - + login failed: %1. Trying to download anyway login fallado: %1. Intentando descarga de todos modos - + login failed: %1 Falló el inicio de sesión: %1 - + login failed: %1. You need to log-in with Nexus to update MO. login fallido: %1. Necesitas hacer login con Nexus para actualizar MO. - + + + failed to read %1: %2 + fallo al leer %1: %2 + + + Error Error - + failed to extract %1 (errorcode %2) fallo al extraer %1 (Código de error %2) - + + Extract BSA + Extraer BSA + + + + This archive contains invalid hashes. Some files may be broken. + Este archivo contiene hashes no válidos. Algunos archivos pueden estar rotos. + + + Extract... Extraer... - + Edit Categories... Editar Categorías... - + Deselect filter - + Deselecciona filtro - + Remove Eliminar - + Enable all Activar todo - + Disable all Desactivar todos - + Unlock load order Desbloquear el orden de carga - + Lock load order Orden de carga bloqueado - + depends on missing "%1" - + depende de que falta "%1" - + incompatible with "%1" - + incompatible con "%1" - + No profile set - + No conjunto de perfil - LOOT working - BOSS trabajando - - - + loot failed. Exit code was: %1 - + loot falló. Código de salida fue: %1 - + failed to start loot - + Error al iniciar loot - + failed to run loot: %1 - fallo al ejecutar boss: %1 + Error al ejecutar loot: %1 - + Errors occured - + Se han producido errores - + Backup of load order created - + Copia de seguridad de orden de carga creado - + Choose backup to restore - + Elije copia de seguridad para restaurar - + No Backups - + No hay copias de seguridad - + There are no backups to restore - + No hay copias de seguridad para restaurar - - + + Restore failed - + Error en la restauración - - + + Failed to restore the backup. Errorcode: %1 - + Error al restaurar la copia de seguridad. Código de error: %1 - + Backup of modlist created - + Copia de seguridad de la lista de mod creado @@ -2895,8 +2878,63 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers ModInfo - - + + Plugins + Plugins + + + + Textures + Texturas + + + + Meshes + Meshes + + + + UI Changes + UI Cambios + + + + Music + Music + + + + Sound Effects + Efectos de Sonido + + + + Scripts + Scripts + + + + SKSE Plugins + SKSE Plugins + + + + SkyProc Tools + SkyProc Tools + + + + Strings + Strings + + + + invalid content type %1 + tipo de contenido inválido %1 + + + + invalid index %1 indice invalido %1 @@ -2904,7 +2942,7 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers ModInfoBackup - + This is the backup of a mod Esta es la copia de seguridad de un mod @@ -2945,7 +2983,7 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers Ini Files - + Archivos Ini @@ -2960,17 +2998,17 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers Ini Tweaks - + Ini Tweaks This is a list of ini tweaks (ini modifications that can be toggled). - + Esta es una lista de ajustes ini (modificaciones INI que pueden activarse). This is a list of ini tweaks. Ini Tweaks are (usually small) fragments of ini files that are applied over existing settings in skyrim.ini/skyrimprefs.ini. Each tweak can be toggled individually. You should check the description of the mod wether the tweaks are really optional. - + Esta es una lista de ajustes ini. los ajustes Ini son (generalmente pequeños) fragmentos de archivos ini que se aplican sobre los valores existentes en el skyrim.ini/skyrimprefs.ini. Cada truco se puede activar de forma individual. Debes comprobar la descripción del mod los ajustes son opcionales. @@ -3120,7 +3158,7 @@ La mayoría de los mods no tienen esps opcionales, por lo que es muy probable qu <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html> <!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"> @@ -3133,7 +3171,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html> <!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"> @@ -3149,12 +3187,12 @@ p, li { white-space: pre-wrap; } Refresh - Recargar + Refrescar Refresh all information from Nexus. - Recargar toda la información de Nexus. + Refrescar toda la información de Nexus. @@ -3166,7 +3204,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> <!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"> @@ -3187,7 +3225,7 @@ p, li { white-space: pre-wrap; } Filetree - Contenido + Árbol de archivo @@ -3199,14 +3237,14 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html> <!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; } +p, li { espacio blanco: pre envoltura; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Esta es una vista de directorio modificable del directorio mod. Puedes moverte por archivos mediante arrastrar y soltar; y cambiar su nombre con (doble clic).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Los cambios pasan inmediatamente sobre el disco, también hacen</span><span style=" font-size:8pt; font-weight:600;"> ser cuidadoso</span><span style=" font-size:8pt;">.</span></p></body></html> @@ -3225,227 +3263,227 @@ p, li { white-space: pre-wrap; } Cerrar - + &Delete - &Delete + &Borrar - + &Rename - &Rename + &Renombrar - + &Hide &Ocultar - + &Unhide &Mostrar - + &Open &Abrir - + &New Folder &Nueva Carpeta - - + + Save changes? - ¿Guardar cambios? + Guardar cambios? - - + + Save changes to "%1"? - ¿Guardar cambios a %1? + Guardar cambios a %1? - + File Exists - Existe el fichero + Archivo Existe - + A file with that name exists, please enter a new one Un fichero con ese nombre ya existe, por favor selecciona otro nombre - + failed to move file Error al mover el fichero - + failed to create directory "optional" Error al crear el directorio "optional" - - + + Info requested, please wait Informacion solicitada, por favor espere - + Main Principal - + Update Actualizacion - + Optional Opcional - + Old Antiguo - + Misc Misc - + Unknown Desconocido - + Current Version: %1 Version actual: %1 - + No update available Sin actualizacion - + (description incomplete, please visit nexus) (descripción incompleta, por favor visite nexus) - + <a href="%1">Visit on Nexus</a> <a href="%1">Visite en Nexus</a> - + Failed to delete %1 Error borrando %1 - - + + Confirm Confirma - + Are sure you want to delete "%1"? Estas seguro de querer borrar "%1"? - + Are sure you want to delete the selected files? Etas seguro de querer borrar los ficheros seleccionados? - - + + New Folder Nueva Carpeta - + Failed to create "%1" Fallo al crear "%1" - - + + Replace file? ¿Reemplazar archivo? - + There already is a hidden version of this file. Replace it? Ya existe una versión oculta de este archivo. Reemplazarlo? - - + + File operation failed La operación de archivo falló. - - + + Failed to remove "%1". Maybe you lack the required file permissions? Fallo al eliminar "%1". Tal vez no tienes los permisos necesarios? - - + + failed to rename %1 to %2 Fallo al renombrar %1 a %2 - + There already is a visible version of this file. Replace it? Ya existe una versión visible de este archivo. ¿Reemplazarlo? - + Un-Hide Desocultar - + Hide Ocultar - + Name Nombre - + Please enter a name Por favor, introduzca un nombre - - + + Error Error - + Invalid name. Must be a valid file name Nombre no válido. Debe ser un nombre de archivo válido - + A tweak by that name exists Existe un ajuste con ese nombre - + Create Tweak Crear Ajuste Fino @@ -3453,15 +3491,15 @@ p, li { white-space: pre-wrap; } ModInfoForeign - + This pseudo mod represents content managed outside MO. It isn't modified by MO. - + Esta seudo mod representa contenido administrado fuera MO. No se modifica por MO. ModInfoOverwrite - + This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit) Esta pseudo-mod contiene archivos en el árbol de datos virtual que fue modificado (es decir, mediante el kit de construcción) @@ -3469,18 +3507,18 @@ p, li { white-space: pre-wrap; } ModInfoRegular - - + + failed to write %1/meta.ini: error %2 - fallo al escribir %1/meta.ini: %2 + error al escribir %1/meta.ini: error %2 - + %1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory %1 no contiene ningún esp/esm y ningún directorio activo (textures, meshes, interface, ...) - + Categories: <br> Categorias: <br> @@ -3490,52 +3528,52 @@ p, li { white-space: pre-wrap; } Game plugins (esp/esm) - + Plugins de Juego (esp/esm) Interface - + Interfaz Meshes - + Meshes Music - + Music Scripts (Papyrus) - + Scripts (Papyrus) Script Extender Plugin - + Script Extender Plugin SkyProc Patcher - + SkyProc Patcher Sound - + Sound Strings - + Strings Textures - + Texturas @@ -3580,7 +3618,7 @@ p, li { white-space: pre-wrap; } Non-MO - + Non-MO @@ -3590,7 +3628,6 @@ p, li { white-space: pre-wrap; } installed version: "%1", newest version: "%2" - installed version: %1, newest version: %2 version instalada: "%1", nueva version: "%2" @@ -3631,7 +3668,7 @@ p, li { white-space: pre-wrap; } Content - Contenido + Contenido @@ -3702,7 +3739,7 @@ p, li { white-space: pre-wrap; } Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> - + Representa el contenido del mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> @@ -3739,22 +3776,22 @@ p, li { white-space: pre-wrap; } NXMAccessManager - + Logging into Nexus Inicio de sesión en Nexus - + timeout Tiempo de espera - + Unknown error - + Error desconocido - + Please check your password Por favor introduzca su contraseña @@ -3812,7 +3849,7 @@ p, li { white-space: pre-wrap; } %1 not found - %1 no encontrado + %1 no encontrado @@ -3850,114 +3887,114 @@ p, li { white-space: pre-wrap; } PluginList - + Name Nombre - + Priority Prioridad - + Mod Index Índice de Mod - + Flags Banderas - - + + unknown Desconocido - + Name of your mods Nombre de tus mods - + Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority. Prioridad de carga de tu mod. Cuanto mayor sea, más "importante" es y por lo tanto sobrescribe los datos del plugins con menor prioridad. - + The modindex determins the formids of objects originating from this mods. El índice de mod determins la forma ids de objetos que provienen de este mods. - + failed to update esp info for file %1 (source id: %2), error: %3 fallo al actualizar información del esp del archivo %1 (fuente id: %2), error: %3 - + esp not found: %1 ESP no encontrado: %1 - - + + Confirm Confirmar - + Really enable all plugins? ¿Realmente habilitar todos los plugins? - + Really disable all plugins? ¿Realmente deshabilitar todos los plugins? - + The file containing locked plugin indices is broken El fichero que contiene los índices del plugin están bloqueados o rotos - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. Algunos de los plugins tienen nombres no válidos! Estos plugins no pueden ser cargados por el juego. Por favor, consulte mo_interface.log para ver una lista de plugins afectados y cambiarles el nombre. - <b>Origin</b>: %1 - + This plugin can't be disabled (enforced by the game) + Este plugin no se puede desactivar (impuesto por el juego) + <b>Origin</b>: %1 + <b>Origen</b>: %1 + + + Author Autor - + Description Descripcion - - This plugin can't be disabled (enforced by the game) - Este plugin no se puede desactivar (impuesto por el juego) - - - + Missing Masters Maestros Desaparecidos - + Enabled Masters Activar Maestros - + failed to restore load order for %1 fallo al restaurar el orden de carga %1 @@ -3987,7 +4024,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!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"> @@ -4042,7 +4079,7 @@ p, li { white-space: pre-wrap; } "%1" is missing or inaccessible - + "%1" no se encuentra o inaccesible @@ -4135,7 +4172,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html> @@ -4168,7 +4205,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4469,62 +4506,62 @@ p, li { white-space: pre-wrap; } Fallo al configurar la carga por proxy-dll - + Permissions required Se requieren permisos - + 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. La cuenta de usuario actual no tiene los permisos de acceso requeridos para ejecutar Mod Organizer. Los cambios necesarios se pueden hacer de forma automática (el directorio MO hará escritura para la cuenta de usuario actual). Se le pedirá ejecutar "helper.exe" con derechos administrativos. - - + + Woops Woops - + ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened ¡ModOrganizer se ha estrellado! ¿Se debe crear un archivo de diagnóstico? Si me envía el fichero (%1) a sherb@gmx.net, el error es mucho más probable que se arregle. Por favor, incluya una breve descripción de lo que estaba haciendo cuando ocurrió el accidente - + ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1 ¡ModOrganizer se ha estrellado! Lamentablemente no fue capaz de escribir un archivo de diagnóstico: %1 - + Mod Organizer Mod Organizer - + An instance of Mod Organizer is already running Ya se está ejecutando una instancia de Mod Organizer - + No game identified in "%1". The directory is required to contain the game binary and its launcher. Juego no identificado en "%1". Se requiere que el directorio contenga el binario del juego y su lanzador. - - + + Please select the game to manage Por favor seleccione el juego - + Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!) Por favor selecciona la edición del juego que tienes (MO no puede iniciar el juego correctamente si esto está mal ajustado!) - + failed to start application: %1 - + Error al iniciar la aplicación: %1 @@ -4532,28 +4569,28 @@ p, li { white-space: pre-wrap; } Por favor utilice "Ayuda" en la barra superior para obtener informacion sobre todos los elementos - - + + <Manage...> - <Definir...> + <Gestionar...> - + failed to parse profile %1: %2 no se pudo analizar el perfil %1: %2 - + failed to find "%1" fallo al encontrar %1 - + failed to access %1 Fallo al acceder %1 - + failed to set file time %1 Fallo al definir la hora al fihcero %1 @@ -4565,8 +4602,7 @@ p, li { white-space: pre-wrap; } "%1" is missing or inaccessible - "%1" is missing - + "%1" no se encuentra o inaccesible @@ -4579,6 +4615,11 @@ p, li { white-space: pre-wrap; } Error Error + + + failed to open temporary file + Fallo al abrir el archivo temporal + @@ -4602,17 +4643,17 @@ p, li { white-space: pre-wrap; } Proxy DLL - + failed to spawn "%1" Fallo al crear "%1" - + Elevation required Elevación requerida - + This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" @@ -4627,30 +4668,25 @@ puede ser instalado para trabajar sin elevación. ¿Comenzar elevación de todos modos? (se le preguntará si desea permitir a Mod Organizer.exe realizar cambios en el sistema) - + failed to spawn "%1": %2 Fallo al crear "%1": %2 - + "%1" doesn't exist "%1" no existe - + failed to inject dll into "%1": %2 Fallo al injectar la dll en "%1": %2 - + failed to run "%1" Fallo al abrir %1 - - - failed to open temporary file - Fallo al abrir el archivo temporal - QueryOverwriteDialog @@ -4868,12 +4904,12 @@ puede ser instalado para trabajar sin elevación. Failed - Fallo + Error Sorry, failed to start the helper application - + Lo sentimos, no se pudo iniciar la aplicación auxiliar @@ -4919,7 +4955,7 @@ puede ser instalado para trabajar sin elevación. <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html> <!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"> @@ -5013,27 +5049,27 @@ p, li { white-space: pre-wrap; } User interface - + Interfaz de usuario If checked, the download interface will be more compact. - + Si se marca, la interfaz de descarga será más compacto. Compact Download Interface - + Interfaz de Descarga Compacto If checked, the download list will display meta information instead of file names. - + Si se selecciona, la lista de descargas mostrará la información de metadatos en lugar de nombres de archivo. Download Meta Information - + Descarga Información Meta @@ -5077,7 +5113,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html> <!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"> @@ -5205,7 +5241,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5243,7 +5279,7 @@ p, li { white-space: pre-wrap; } 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. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam. Mod Organizer necesita una dll que se inyecta en el juego para que todos los mods sean visibles a ella. @@ -5267,8 +5303,8 @@ Si utilizas la versión Steam de Oblivion por defecto NO funcionará. En este ca 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. +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. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again. Mod Organizer utiliza una API proporcionada por Nexus para proporcionar características como la comprobación de actualizaciones y descarga de archivos. Por desgracia, esta API no ha sido puesta a disposición oficialmente a terceros, como MO por lo que tenemos que pasar por el Nexus Mod Manager para ser permitido. @@ -5284,7 +5320,7 @@ tl;dr-version: Si Nexus-features no funciona, introduzca el número de la versi - It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + 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. Parece que los juegos ocasionalmente cargan archivos ESP o ESM, incluso si ellos todavía no se ha activado como plugins. No, pero sabe cuáles son las circunstancias, pero informes de usuario implican en algunos casos no deseados. Si esto se comprueba, ESPs ESMs no marcadas en la lista son invisibles para el juego y no se pueden cargar. @@ -5314,20 +5350,23 @@ Desactiva esta opción si deseas utilizar Mod Organizer con conversiones totales 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. - + Desactiva esto para más no mostrar mods instalado fuera de MO en la lista de mod (panel izquierdo). El activo de esos mods entonces serán tratados como si tuvieran prioridad más baja junto con el contenido original del juego. 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. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature. - + Por defecto Mod Organizer mostrará esp+bsa instalados con herramientas extranjeras como mods (panel izquierdo). Esto le permite controlar su prioridad en relación con otros mods. Esto es particularmente útil si también usas Steam Workshop para instalar mods. +Sin embargo, si has instalado mods de archivos sueltos fuera de MO que están en conflicto con BSA también instalara fuera de MO esos conflictos no se pueden resolver correctamente. + +i se desactiva esta función, MO sólo mostrará DLCs oficiales de esta manera. Tenga en cuenta que los plugins (ESP y ESM) que aparecen en el panel derecho seran completamente afectado por esta característica. Display mods installed outside MO - + Mostrar mods instalados fuera MO @@ -5422,7 +5461,7 @@ Para el resto de los juegos no es un sustituto suficiente para AI failed to communicate with running instance: %1 - Error al conectarse a la instancia en ejecución: %1 + Error al comunicarse con instancia en ejecución: %1 @@ -5585,4 +5624,4 @@ C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves Mover todas las partidas guardadas "%1" para la localización global? Tenga en cuenta que esto se hace un lío con el número consecutivo de juegos salvados. - + \ No newline at end of file diff --git a/src/organizer_fr.ts b/src/organizer_fr.ts index 9e5af1af..004499e8 100644 --- a/src/organizer_fr.ts +++ b/src/organizer_fr.ts @@ -1,48 +1,46 @@ - - - + AboutDialog About - + A propros Revision: - + Révision : Used Software - + Logiciel utilisé Credits - + Crédits Translators - + Traducteurs Others - + Autres Close - Fermer + Fermer No license - + Pas de license @@ -62,7 +60,7 @@ <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -159,22 +157,22 @@ Si un composant est nommée "00 Core"; il est habituellement nécessai Some Page - + Quelques pages Search - + Rechercher new - + nouveau failed to start download - + échec du lancement du téléchargement @@ -225,7 +223,7 @@ Si un composant est nommée "00 Core"; il est habituellement nécessai <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> @@ -296,7 +294,7 @@ p, li { white-space: pre-wrap; } failed to read bsa: %1 - Échec de lecture bsa: %1 + échec de lecture du bsa: %1 @@ -314,7 +312,7 @@ p, li { white-space: pre-wrap; } Done - Terminé + Terminé @@ -324,7 +322,7 @@ p, li { white-space: pre-wrap; } pending download - + téléchargement en attente @@ -333,7 +331,7 @@ p, li { white-space: pre-wrap; } Placeholder - substitut + *Substitut* @@ -367,7 +365,7 @@ p, li { white-space: pre-wrap; } Placeholder - *substitut* + *Substitut* @@ -380,17 +378,17 @@ p, li { white-space: pre-wrap; } < mod %1 file %2 > - + < mod %1 file %2 > Pending - + En attente Paused - En pause + En pause @@ -458,17 +456,17 @@ p, li { white-space: pre-wrap; } Delete - Supprimer + Supprimer Un-Hide - + Montrer Remove from View - Enlever de la liste + Cacher de la liste @@ -493,7 +491,7 @@ p, li { white-space: pre-wrap; } Delete Installed... - Supprimer ceux installés... + Supprimer ceux installés... @@ -516,12 +514,12 @@ p, li { white-space: pre-wrap; } < mod %1 file %2 > - + < mod %1 file %2 > Pending - + En attente @@ -539,7 +537,7 @@ p, li { white-space: pre-wrap; } Are you sure? - Êtes-vous certain? + Êtes-vous certain ? @@ -574,17 +572,17 @@ p, li { white-space: pre-wrap; } Delete - Supprimer + Supprimer Un-Hide - + Montrer Remove from View - Enlever de la liste + Cacher de la liste @@ -619,12 +617,12 @@ p, li { white-space: pre-wrap; } Remove Installed... - Enlever de la liste ceux installés... + Enlever ceux installés de la liste ... Remove All... - Enlever tout de la liste... + Tour enlever de la liste... @@ -632,12 +630,12 @@ p, li { white-space: pre-wrap; } failed to rename "%1" to "%2" - Impossible de renommer "%1" en "%2" + impossible de renommer "%1" en "%2" Memory allocation error (in refreshing directory). - + Erreur d'allocation de la mémoire (dans le répertoire d'actualisation). @@ -652,17 +650,17 @@ p, li { white-space: pre-wrap; } failed to download %1: could not open output file: %2 - impossible de télécharger %1: impossible d'écrire le fichier: %2 + impossible de télécharger %1: l'écriture sur le fichier à échouée : %2 Wrong Game - + Jeu incorrect The download link is for a mod for "%1" but this instance of MO has been set up for "%2". - + Le lien de téléchargement est pour un mod pour "%1", mais cette instance de MO à été installée pour "%2". @@ -707,7 +705,7 @@ p, li { white-space: pre-wrap; } No known download urls. Sorry, this download can't be resumed. - + Aucune adresse de téléchargement connue. Désolé, ce téléchargement ne peut être repris. @@ -722,42 +720,42 @@ p, li { white-space: pre-wrap; } Main - Principal + Principal Update - + Mise à jour Optional - Optionnel + Optionnel Old - Ancien + Obsolète Misc - Divers + Divers Unknown - Inconnu + Inconnu Memory allocation error (in processing progress event). - + Erreur d'allocation de la mémoire (lors du traitement de la progression événementielle). Memory allocation error (in processing downloaded data). - + Erreur d'allocation de la mémoire (lors du traitement des données de téléchargement). @@ -783,12 +781,12 @@ p, li { white-space: pre-wrap; } Failed to request file info from nexus: %1 - Impossible de demander l'info du fichier sur Nexus: %1 + Impossible de demander l'information du fichier sur Nexus: %1 Download failed. Server reported: %1 - + Téléchargement échoué : rapport du serveur : %1 @@ -943,7 +941,7 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat Close - Fermer + Fermer @@ -953,7 +951,7 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat Executable (%1) - Executable (%1) + Exécutable (%1) @@ -989,13 +987,13 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat Save Changes? - + Enregistrer les changements ? You made changes to the current executable, do you want to save them? - + Vous avez appliqué des modifications aux exécutables courants, voulez vous les enregistrer ? @@ -1013,19 +1011,19 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat Find what: - Rechercher: + Rechercher : Search term - Expression à rechercher + Terme à rechercher Find next occurence from current file position. - Rechercher le suivant à partir de l'emplacement présent. + Rechercher l’occurrence suivante à partir de l'emplacement présent. @@ -1135,7 +1133,7 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html> <!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"> @@ -1146,7 +1144,7 @@ p, li { white-space: pre-wrap; } Placeholder - *substitut* + *Substitut* @@ -1179,87 +1177,87 @@ p, li { white-space: pre-wrap; } - + Extracting files Extraction des fichiers - + failed to create backup - Impossible de créer une sauvegarde + Impossible de créer une sauvegarde de backup - + Mod Name Nom du mod - + Name Nom - + Invalid name Nom incorrect - + The name you entered is invalid, please enter a different one. Le nom que vous avez entré est invalide, essayez-en un autre SVP. - + File format "%1" not supported Format de fichier "%1" non supporté - + None of the available installer plugins were able to handle that archive Aucun des plugins installés n'arrive à traiter cette archive - + no error aucune erreur - + 7z.dll not found 7z.dll introuvable - + 7z.dll isn't valid 7z.dll invalide - + archive not found archive introuvable - + failed to open archive impossible d'ouvrir l'archive - + unsupported archive type type d'archive non supporté - + internal library error erreur de bibliothèque interne - + archive invalid archive invalide - + unknown archive error erreur d'archive inconnue @@ -1319,27 +1317,27 @@ p, li { white-space: pre-wrap; } Click blank area to deselect - + Cliquer sur une zone blanche pour désélectionner If checked, only mods that match all selected categories are displayed. - + Si coché, seul les mods correspondants à toutes les catégories sélectionnées sont affichés. And - + Et If checked, all mods that match at least one of the selected categories are displayed. - + Si coché, tout les mods correspondants à au moins une des catégories sélectionnées sont affichés. Or - + Ou @@ -1356,7 +1354,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1366,6 +1364,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Créez les profils ici. Chaque profil contient sa propre liste de mods et d'ESPs activés. Vous pouvez ainsi basculer rapidement entre les configurations pour différentes parties.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Veuillez noter que pour l'instant, l'ordre de chargement des ESPs est commun à tous les profils.</span></p></body></html> + + + Open list options... + Ouvre les options de liste... + Refresh list. This is usually not necessary unless you modified data outside the program. @@ -1375,13 +1378,13 @@ p, li { white-space: pre-wrap; } Restore Backup... - + Restaurer Sauvegarde Create Backup - + Créer Sauvegarde @@ -1425,7 +1428,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1445,7 +1448,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html> <!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"> @@ -1468,7 +1471,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html> <!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"> @@ -1484,7 +1487,12 @@ p, li { white-space: pre-wrap; } Plugins - + Plugins + + + + Sort + Ordonner @@ -1496,7 +1504,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html> <!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"> @@ -1504,35 +1512,25 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Cette liste contient tous les ESPs et ESMs contenus dans les mods actifs. Ceux-ci requièrent leur propre ordre de chargement. Utilisez le glisser-déposer pour modifier cet ordre. Veuillez noter que MO enregistre l'ordre de chargement seulement pour les mods actif/cochés.<br />Il y a un excellent outil nommé &quot;BOSS&quot; qui classe automatiquement ces fichiers.</span></p></body></html> - - - Sort - - - - - Open list options... - - Archives - + Archives <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>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html> - + List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order. - + Liste des Besthesda Softworks Archives. Les archives non cochées ici ne sont pas gérées par MO et ignorent l’ordre d'installation. @@ -1540,226 +1538,223 @@ p, li { white-space: pre-wrap; } 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. - + Les fichiers BSA sont des archives (comparables aux fichiers .zip) qui contiennent les données de ressource (meshes, textures,...) qui sont utilisées par le jeu. Ainsi, ils sont en "compétition" avec les fichiers "lâches" -non compressés- dans votre répertoire DATA. +Par défaut, les BSAs qui partagent leur nom de base avec un ESP actif (ex : plugin.esp et plugin.bsa) sont automatiquement chargés et ont la précédence sur tout les fichiers lâches; l'ordre d'installation que vous établissez sur la partie gauche est alors ignoré ! + +Les BSAs cochés ici sont chargés d'une telle manière que votre ordre d'installation est correctement respecté. File - Fichier + Fichier Data - DATA + Data refresh data-directory overview - Actualiser la vue d'ensemble du dossier DATA + actualiser la vue d’ensemble du répertoire data Refresh the overview. This may take a moment. - Actualiser la vue d'ensemble. Ceci peut demander un moment. + Actualiser la vue d'ensemble. Ceci peut prendre un moment. - - + + Refresh - Actualiser + Actualiser This is an overview of your data directory as visible to the game (and tools). - Ceci est une vue d'ensemble du dossier DATA tel qu'il apparaît pour le jeu (et les outils). + Ceci est une vue d’ensemble du répertoire Data, tel qu'il apparaît à votre jeu (et outils) lancés dans MO. Mod - Mod + Mod Filter the above list so that only conflicts are displayed. - Filtrer la liste ci-dessus pour afficher seulement les conflits. + Filtrer la liste ci-dessus afin que seuls les conflits soient affichés. Show only conflicts - Afficher seulement les conflits + Uniquement afficher les conflits Saves - Sauvegardes + Sauvegardes <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Ceci est une liste de toutes les parties sauvegardées pour ce jeu. Survolez une entrée de la liste pour obtenir des informations détaillées sur la sauvegarde, incluant une liste de tous les ESPs/EMSs utilisés lors de la sauvegarde mais actuellement désactivés ou absents.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Si vous cliquez &quot;Réparer Mods...&quot; dans le menu contextuel, MO tentera d'activer tous les mods, ESPs et ESMs nécessaires pour résoudre le problème. Rien ne sera désactivé!</span></p></body></html> + Downloads - Téléchargements + Téléchargements This is a list of mods you downloaded from Nexus. Double click one to install it. - Ceci est une liste de mods que vous avez téléchargé de Nexus. Double-cliquez en un pour l'installer. + Ceci est une liste de mods que vous avez téléchargé depuis de Nexus. Double-clic sur un mod pour l'installer. Show Hidden - + Montrer les éléments cachés Tool Bar - Barre d'outils + Barre d'outil Install Mod - Installer mod + Installer le Mod Install &Mod - Installer &mod + Installer &Mod Install a new mod from an archive - Installer un nouveau mod à partir d'une archive + Installe un nouveau mod depuis une archive Ctrl+M - Ctrl+M + Ctrl+M Profiles - Profils + Profils &Profiles - &Profils + &Profils Configure Profiles - Configurer les profils + Configurer les Profils Ctrl+P - Ctrl+P + Ctrl+P Executables - Programmes + Exécutables &Executables - Programm&es + &Exécutables Configure the executables that can be started through Mod Organizer - Configure les programmes pouvant être lancés via Mod Organizer + Configure les exécutables qui peuvent êtres lancés à travers Mod Organizer Ctrl+E - Ctrl+E + Ctrl+E Tools - + Outils &Tools - + &Outils Ctrl+I - Ctrl+H + Ctrl+I Settings - Réglages + Paramètres &Settings - Réglage&s + &Paramètres Configure settings and workarounds - Configurer les réglages et solutions de rechange + Configure les paramètres et solutions alternatives Ctrl+S - Ctrl+S + Ctrl+S Nexus - Nexus + Nexus Search nexus network for more mods - Effectuer une recherche sur Nexus pour plus de mods + Recherche sur le réseau nexus pour plus de mods Ctrl+N - Ctrl+N + Ctrl+N - + Update Mise-à-jour Mod Organizer is up-to-date - Mod Organizer est à jour + Mod Organizer est à jour. No Problems - + Aucun problèmes @@ -1767,1101 +1762,1107 @@ p, li { white-space: pre-wrap; } !Work in progress! Right now this has very limited functionality - + Ce bouton apparaît en surbrillance si MO découvre des problèmes potentiels avec votre configuration et offre une aide pour les résoudre. +!Work in progress! +Actuellement une fonctionnalité encore très limitée. Help - Aide + Aide Ctrl+H - Ctrl+H + Ctrl+H Endorse MO - + Recommander MO - + Endorse Mod Organizer - + Recommander Mod Organizer Copy Log to Clipboard - + Copier les Logs dans le Presse-papier Ctrl+C - + Ctrl+C Toolbar - Barre d'outils + Barre d'outil Desktop - + Bureau Start Menu - + Menu démarrer Problems - + Problèmes There are potential problems with your setup - + Il y a des problèmes potentiels dans votre configuration Everything seems to be in order - + Tout semble en ordre Help on UI - + Aide sur l'interface Documentation Wiki - + Wiki de Documentation Report Issue - + Reporter un problème Tutorials - + Tutoriels About - + A propos About Qt - + A propos de Qt failed to save load order: %1 - impossible d'enregistrer l'ordre de chargement: %1 + Échec de l'enregistrement de l’ordre de chargement : %1 Name - Nom + Nom Please enter a name for the new profile - Veuillez inscrire un nom pour le nouveau profil + Veuillez entrer un nom pour le nouveau profil failed to create profile: %1 - impossible de créer le profil: %1 + création de profil échouée : %1 Show tutorial? - + Afficher le tutoriel ? You are starting Mod Organizer for the first time. Do you want to show a tutorial of its basic features? If you choose no you can always start the tutorial from the "Help"-menu. - + Vous lancez Mod Organizer pour la première fois. Voulez-vous afficher un tutoriel concernant ses fonctionnalité élémentaires ? Si vous choisissez non, vous pouvez toujours démarrer le tutoriel depuis le menu "Aide". Downloads in progress - Téléchargements en cours + Téléchargement en cours There are still downloads in progress, do you really want to quit? - Il encore des téléchargements en cours, voulez-vous vraiment quitter? + Il y a toujours des téléchargements en cours, voulez vous vraiment quitter ? failed to read savegame: %1 - impossible de lire la sauvegarde: %1 + échec de lecture de la sauvegarde : %1 Plugin "%1" failed: %2 - + Le Plugin "%1" à échoué: %2 Plugin "%1" failed - + Le Plugin "%1" à échoué + + + + Download? + Télécharger ? + + + + A download has been started but no installed page plugin recognizes it. +If you download anyway no information (i.e. version) will be associated with the download. +Continue? + + + + + Browse Mod Page + Consulter la page-web du Mod failed to init plugin %1: %2 - + impossible d'initialiser le plugin %1: %2 Plugin error - + Erreur de plugin It appears the plugin "%1" failed to load last startup and caused MO to crash. Do you want to disable it? (Please note: If this is the first time you see this message for this plugin you may want to give it another try. The plugin may be able to recover from the problem) - + Il semble que le plugin "%1" n'a pas pu être chargé lors du démarrage précédent, provoquant un crash de MO. Voulez vous le désactiver ? +(Note : si il s'agit de la première fois que vous voyez ce message pour ce plugin, vous devriez tenter à nouveau l'opération. Le plugin pourrait cette fois être en mesure de corriger le problème). Failed to start "%1" - impossible de lancer "%1" + Échec du lancement de "%1" Waiting - Attente + Attente Please press OK once you're logged into steam. - Veuillez cliquer OK une fois connecté à steam. + Veuillez appuyer sur OK une fois connecté à Steam. + + + + Executable "%1" not found + Exécutable "%1" introuvable Start Steam? - + Démarrer Steam ? Steam is required to be running already to correctly start the game. Should MO try to start steam now? - + Steam doit être déjà démarré afin de correctement lancer le jeu. MO devrait-il essayer de lancer Steam maintenant ? - + Also in: <br> - + Aussi dans : <br> - + No conflict - Aucun conflit + Aucun conflit - + <Edit...> - <Modifier...> + <Editer...> - - This bsa is enabled in the ini file so it may be required! - + + Failed to refresh list of esps: %1 + Impossible d'actualiser la liste des esps : %1 - - Activating Network Proxy - + + This bsa is enabled in the ini file so it may be required! + Ce bsa étant activé dans le fichier ini, cela devrait être requis ! - - - Installation successful - Installation réussie + + Activating Network Proxy + Activation du Proxy de Réseau. - - - Configure Mod - Configurer mod + + + Failed to write settings + Échec de l'écriture des paramètres - - - This mod contains ini tweaks. Do you want to configure them now? - Ce mod contient des ajustement pour les fichiers ini. Désirez-vous les configurer maintenant? + + + An error occured trying to write back MO settings: %1 + Une erreur est survenue lors de la récupération des paramètres de MO : %1 - - - mod "%1" not found - "%1" introuvable + + File is write protected + Le fichier est protégé en écriture - - - Installation cancelled - + + Invalid file format (probably a bug) + Format de fichier invalide (probablement un bug) - - - The mod was not installed completely. - + + Unknown error %1 + Erreur inconnue %1 - + Some plugins could not be loaded - + Certains plugins n'ont pas pu être chargés - + Too many esps and esms enabled - + Trop d'esps et d'esms activés - - + + Description missing - + Description manquante - + The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: - + Les plugins suivants n'ont pas pu être chargés. Cela peut être dû à des dépendances manquantes (ex : python) ou une version obsolète : - + The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + Le jeu n'autorise pas le plus de 255 plugins actifs (plugins officiels inclus) à être chargés. Vous devriez désactiver les plugins inusités ou fusionner certains plugins dans un seul. Vous pouvez trouver un guide ici : <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + Choose Mod - Choisir mod + Choisissez un Mod - + Mod Archive - Archive de mod + Archive de Mod + + + + + Installation successful + Installation réussie - + + + Configure Mod + Configurer le Mod + + + + + This mod contains ini tweaks. Do you want to configure them now? + Ce mod contient des ini tweaks. Désirez-vous les configurer maintenant? + + + + + mod "%1" not found + mod "%1" introuvable + + + + + Installation cancelled + Installation annulée + + + + + The mod was not installed completely. + Le mod n'a pas été installé complètement + + + Start Tutorial? - + Démarrer le Tutoriel ? - + You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue? - + Vous allez commencer un tutoriel. Pour des raisons techniques, il n'est pas possible de quitter le tutoriel en cours de route. Continuer ? - - + + Download started - Téléchargement commencé + Le téléchargement vient de démarrer - + failed to update mod list: %1 - impossible de mettre à jour la liste de mods: %1 + échec lors de l'actualisation de la liste de Mod: %1 - + failed to spawn notepad.exe: %1 - impossible de lancer notepad.exe: %1 + impossible d'invoquer notepad.exe : %1 - + failed to open %1 - impossible d'ouvrir %1 + impossible d'ouvrir %1 - + failed to change origin name: %1 - impossible de changer le nom d'origine: %1 + impossible de changer le nom d'origine : %1 - - Executable "%1" not found - - - - - Failed to refresh list of esps: %1 - + + failed to move "%1" from mod "%2" to "%3": %4 + impossible de déplacer "%1" depuis le mod "%2" vers "%3" : %4 - - failed to move "%1" from mod "%2" to "%3": %4 - + + <Contains %1> + <Contient %1> - + <Checked> - <Cochés> + <Coché> - + <Unchecked> - <Décochés> + <Décoché> - + <Update> - <Rafraichir> + <Mise à jour disponible> - + + <Managed by MO> + <Géré par MO> + + + + <Managed outside MO> + <Géré à l’extérieur de MO> + + + <No category> - + <Sans catégorie> - + <Conflicted> - + <Conflits> - + <Not Endorsed> - + <Non Recommandé> - + failed to rename mod: %1 - impossible de renommer le mod: %1 + impossible de renommer le Mod: %1 - + Overwrite? - + Écraser ? - + This will replace the existing mod "%1". Continue? - + Cela va remplacer le Mod existant "%1". Continuer ? - + failed to remove mod "%1" - Impossible de supprimer %1 + Impossible de supprimer le Mod "%1" - - - + + + failed to rename "%1" to "%2" - Impossible de renommer %1 en %2 + Impossible de renommer "%1" en "%2" - + Multiple esps activated, please check that they don't conflict. - + Plusieurs esps activés, veuillez vérifier qu'ils n'entrent pas en conflit. - - - - + + + + Confirm - Confirmer + Confirmer - + Remove the following mods?<br><ul>%1</ul> - + Supprimer les Mods suivants?<br><ul>%1</ul> - + failed to remove mod: %1 - impossible de renommer le mod: %1 + Impossible de supprimer le Mod: %1 - - + + Failed - + Échec - + Installation file no longer exists - + Les fichiers d'installations n'existent plus - + Mods installed with old versions of MO can't be reinstalled in this way. - - - - - - You need to be logged in with Nexus to endorse - - - - - Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. - - - - - - - - Delete %n save(s) - - - - + Les Mods installés avec une anciennes versions de MO ne peuvent être réinstaller de cette manière. - - Extract BSA - + + You need to be logged in with Nexus to resume a download + Vous devez être connecté à Nexus pour continuer le téléchargement - - - failed to read %1: %2 - Échec de lecture %1: %2 + + + You need to be logged in with Nexus to endorse + Vous devez être connecté à Nexus pour recommander un mod. - - This archive contains invalid hashes. Some files may be broken. - + + Failed to display overwrite dialog: %1 + Impossible d'afficher la boite de dialogue overwrite : %1 - + Nexus ID for this Mod is unknown - - - - - Download? - - - - - A download has been started but no installed page plugin recognizes it. -If you download anyway no information (i.e. version) will be associated with the download. -Continue? - - - - - Browse Mod Page - - - - - - Failed to write settings - - - - - - An error occured trying to write back MO settings: %1 - - - - - File is write protected - - - - - Invalid file format (probably a bug) - - - - - Unknown error %1 - - - - - <Managed by MO> - - - - - <Managed outside MO> - - - - - You need to be logged in with Nexus to resume a download - - - - - Failed to display overwrite dialog: %1 - + L'ID Nexus de ce Mod est inconnu - - + + Create Mod... - + Crée le Mod... - + This will move all files from overwrite into a new, regular mod. Please enter a name: - + Ceci va déplacer tout les fichiers présent dans Overwrite dans un nouveau mod ordinaire. +Veuillez nommer ce mod : - + A mod with this name already exists - + Un Mod avec ce nom existe déjà - + Continue? - + Continuer ? - + The versioning scheme decides which version is considered newer than another. This function will guess the versioning scheme under the assumption that the installed version is outdated. - + Le système de syntaxe de version décide quelle version est considérée plus récente qu'une autre. +Cette fonction va deviner quel système de version utiliser dans l'hypothèse que la version installée est obsolète. - - + + Sorry - + Désolé - + I don't know a versioning scheme where %1 is newer than %2. - + Je ne connait pas un système de version dans lequel %1 est plus récent que %2. - + Really enable all visible mods? - + Voulez vous vraiment activer tout les mods visibles ? - + Really disable all visible mods? - + Voulez vous vraiment désactiver tout les mods visibles ? - + Choose what to export - + Choisissez ce que vous voulez exporter - + Everything - + Tout - + All installed mods are included in the list - + Tous les Mods installés sont inclus dans cette liste - + Active Mods - Activer Mods + Mods actifs - + Only active (checked) mods from your current profile are included - + Seuls les mods actifs (cochés) de votre profil actif seront inclus - + Visible - + Visible - + All mods visible in the mod list are included - + Tout les mods visible dans la liste de mod sont inclus - + export failed: %1 - + échec de l'exportation : %1 - + Install Mod... - Installer mod... + Installer le Mod... - + Enable all visible - Activer tous les mods visibles + Activer tout mod visible - + Disable all visible - Désactiver tous les mods visibles + Désactiver tout mod visible - + Check all for update - Vérifier toutes les mises à jour + Vérifier toutes les mises à jour - + Export to csv... - + Exporter en csv... - + All Mods - + Tout les Mods - + Sync to Mods... - + Synchroniser vers les Mods... - + Restore Backup - + Restaurer la sauvegarde - + Remove Backup... - + Supprimer la sauvegarde... - + Add/Remove Categories - + Ajouter/Enlever des catégories - + Replace Categories - + Remplacer les catégories - + Primary Category - + Catégorie primaire - + Change versioning scheme - + Changer le système de version - + Un-ignore update - + Ne plus ignorer les mises à jour - + Ignore update - + Ignorer la MàJ - + Rename Mod... - Renommer mod... + Renommer le Mod... - + Remove Mod... - Supprimer mod... + Supprimer le Mod... - + Reinstall Mod - Installer mod + Réinstaller le Mod - + Un-Endorse - + Ne plus recommander - - + + Endorse - + Recommander - + Won't endorse - + Ne vais pas recommander - + Endorsement state unknown - + Statut de recommandation inconnu - + Ignore missing data - + Ignorer les données manquantes - + Visit on Nexus - + Aller à la page Nexus - + Open in explorer - + Ouvrir dans l'exploreur - + Information... - Information... + Informations... - - + + Exception: - + Exception : - - + + Unknown exception - + Exception Inconnue - + <All> - <Tous> + <Tous> - + <Multiple> - + <Multiple> + + + + Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. + Voulez vraiment supprimer les/la sauvegarde(s) suivante %n ?<br> +<ul>%1</ul> <br>Les sauvegardes supprimées seront envoyée dans la corbeille.Voulez vraiment supprimer les/la sauvegarde(s) suivante %n ?<br> +<ul>%1</ul> <br>Les sauvegardes supprimées seront envoyée dans la corbeille. - + Please wait while LOOT is running - + Veuillez patienter pendant que LOOT s'exécute - + Fix Mods... - Réparer mods... + Corriger les Mods... + + + + Delete %n save(s) + Supprimer %n sauvegarde(s)Supprimer %n sauvegarde(s) - + failed to remove %1 - Impossible de supprimer %1 + Impossible d'enlever %1 - - + + failed to create %1 - impossible de créer %1 + Impossible de créer %1 - + Can't change download directory while downloads are in progress! - + Vous ne pouvez pas changer le répertoire de téléchargement pendant qu'un téléchargement est en cours ! - + Download failed - Téléchargement commencé + Téléchargement échoué - + failed to write to file %1 - impossible d'écrire dans le fichier %1 + Échec de l'écriture sur le fichier %1 - + %1 written - %1 écrit + %1 écrit - + Select binary - Choisir un programme + Sélectionner un exécutable binaire - + Binary - Programme + Exécutable binaire - + Enter Name - + Entrez un nom - + Please enter a name for the executable - Veuillez inscrire un nom pour le nouveau profil + Veuillez entrer un nom pour l'exécutable - + Not an executable - Ajouter un programme + Pas un exécutable - + This is not a recognized executable. - + Ceci n'est pas un exécutable reconnu. - - + + Replace file? - + Remplacer le fichier? - + There already is a hidden version of this file. Replace it? - + Ceci est déjà une version cachée de ce fichier. La remplacer ? - - + + File operation failed - + Échec de l'opération sur les fichiers - - + + Failed to remove "%1". Maybe you lack the required file permissions? - + Impossible de retirer "%1". Peut-être n'avez vous pas les permissions nécessaires sur le fichier. - + There already is a visible version of this file. Replace it? - + Il existe déjà une version visible de ce fichier. La remplacer ? - + file not found: %1 - + fichier introuvable : %1 - + failed to generate preview for %1 - + impossible de générer l'aperçu de %1 - + Sorry, can't preview anything. This function currently does not support extracting from bsas. - + Désolé, impossible de générer tout aperçu. Cette fonction ne supporte actuellement pas l'extraction d'un bsa. - + Update available - Mise à jour disponible + Mise à jour disponible - + Open/Execute - + Ouvrir/Exécuter - + Add as Executable - Ajouter un programme + Ajouter en tant qu'Exécutable - + Preview - + Aperçu - + Un-Hide - + Montrer - + Hide - + Cacher - + Write To File... - Écriture du fichier... + Écriture du fichier... - + Do you want to endorse Mod Organizer on %1 now? - + Désirez vous recommander Mod Organizer sur %1 maintenant ? - + Thank you! - + Merci ! - + Thank you for your endorsement! - + Merci de votre recommandation ! - + Request to Nexus failed: %1 - + La requête au Nexus à échouée : %1 - - + + login successful - + connexion réussie - + login failed: %1. Trying to download anyway - + échec de login : %1. Tentative de téléchargement malgré tout - + login failed: %1 - + échec de login : %1 - + login failed: %1. You need to log-in with Nexus to update MO. - + échec de login : %1. Vous devez vous connecter au Nexus pour mettre à jour MO. - + + + failed to read %1: %2 + impossible de lire %1 : %2 + + + Error - Erreur + Erreur - + failed to extract %1 (errorcode %2) - + impossible d'extraire %1 (code d'erreur %2) - + + Extract BSA + Extraire le BSA + + + + This archive contains invalid hashes. Some files may be broken. + Cette archive contient des données de hachages invalides. Certains fichiers peuvent être corrompus. + + + Extract... - + Extraire... - + Edit Categories... - + Modfier les catégories - + Deselect filter - + Filtre de déselection - + Remove Supprimer - + Enable all - + Activer tout - + Disable all - + Désactiver tout - + Unlock load order - + Déverrouiller l'ordre de chargement - + Lock load order - + Verrouiller l’ordre de chargement - + depends on missing "%1" - + dépend de "%1" manquant - + incompatible with "%1" - + incompatible avec "%1" - + No profile set - + Aucun profil - + loot failed. Exit code was: %1 - + échec de LOOT. Le code de fermeture était : %1 - + failed to start loot - + impossible de démarrer LOOT - + failed to run loot: %1 - + impossible d'exécuter LOOT : %1 - + Errors occured - + Erreurs survenues - + Backup of load order created - + Backup de l'ordre de chargement créé - + Choose backup to restore - + Choisissez le backup à restaurer - + No Backups - + Aucun Backups - + There are no backups to restore - + Il n'y a aucun backup à restaurer - - + + Restore failed - + Restauration échouée - - + + Failed to restore the backup. Errorcode: %1 - + Échec de la restauration du backup. Code d'erreur : %1 - + Backup of modlist created - + Backup de la liste de mods créé @@ -2870,14 +2871,69 @@ This function will guess the versioning scheme under the assumption that the ins Placeholder - Signet + *Substitut* ModInfo - - + + Plugins + Plugins + + + + Textures + Textures + + + + Meshes + Meshes + + + + UI Changes + Modifications de l'UI + + + + Music + Musiques + + + + Sound Effects + Sons + + + + Scripts + Scripts + + + + SKSE Plugins + Plugins SKSE + + + + SkyProc Tools + Outils SkyProc + + + + Strings + Strings + + + + invalid content type %1 + type de contenu invalide %1 + + + + invalid index %1 index invalide %1 @@ -2885,9 +2941,9 @@ This function will guess the versioning scheme under the assumption that the ins ModInfoBackup - + This is the backup of a mod - + Ceci est le backup d'un mod @@ -2926,7 +2982,7 @@ This function will guess the versioning scheme under the assumption that the ins Ini Files - + Fichiers INI @@ -2941,17 +2997,17 @@ This function will guess the versioning scheme under the assumption that the ins Ini Tweaks - + Tweaks INI This is a list of ini tweaks (ini modifications that can be toggled). - + Ceci est une liste des tweaks ini (modifications d'ini qui peuvent être activées). This is a list of ini tweaks. Ini Tweaks are (usually small) fragments of ini files that are applied over existing settings in skyrim.ini/skyrimprefs.ini. Each tweak can be toggled individually. You should check the description of the mod wether the tweaks are really optional. - + Ceci est une liste des tweaks ini. Les tweaks ini sont des fragments de fichiers INI (usuellement petits) qui sont appliqués par dessus les paramètres existants dans skyrim.ini/skyrimprefs.ini. Chaque tweak peut être activé individuellement. Vous devriez vérifier la description du mod quand à savoir si les tweaks sont réellement optionnels. @@ -2976,7 +3032,7 @@ This function will guess the versioning scheme under the assumption that the ins This lists all the images (.jpg and .png) in the mod directory, like screenshots and such. Click one to get a larger view. - + Ceci liste toutes les images (.jpg et .png) présentes dans le répertoire du mod, comme les screenshots et autres. Cliquez sur l'objet pour obtenir une vue plus large. @@ -2995,7 +3051,7 @@ This function will guess the versioning scheme under the assumption that the ins They usually contain optional functionality, see the readme. Most mods do not have optional esps, so chances are good you are looking at an empty list. - + @@ -3035,48 +3091,48 @@ Most mods do not have optional esps, so chances are good you are looking at an e Conflicts - + Conflits The following conflicted files are provided by this mod - + Les fichiers conflictuels suivants sont originaire de ce mod File - Fichier + Fichier Overwritten Mods - + Mods écrasés The following conflicted files are provided by other mods - + Les fichiers conflictuels suivants sont originaires d'autres mods Providing Mod - + Mod source Non-Conflicted files - + Fichiers non conflictuels Categories - Catégories + Catégories Primary Category - + Catégorie primaire @@ -3098,20 +3154,16 @@ Most mods do not have optional esps, so chances are good you are looking at an e <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ID de ce mod sur Nexus. Rempli automatiquement si vous téléchargez et installez un mod à partir de MO. Sinon, vous pouvez l'inscrire manuellement. Pour connaître le bon ID, trouvez le mod sur Nexus. L'URL ressemblera à ceci: <a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" text-decoration: underline; color:#0000ff;">http://www.skyrimnexus.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" color:#000000;">. Dans cet example, 1334 est l'ID que vous cherchez. En passant: Ce lien est celui de Mod Organizer sur le Nexus. Pourquoi ne pas le visiter et lui donner votre aval?</span></a></p></body></html> + <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html> <!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"> @@ -3127,12 +3179,12 @@ p, li { white-space: pre-wrap; } Refresh - Actualiser + Actualiser Refresh all information from Nexus. - + Actualiser toutes les informations provenant du Nexus @@ -3144,19 +3196,23 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - + <!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; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> Endorse - + Recommander Notes - + Notes @@ -3173,7 +3229,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3186,7 +3242,7 @@ p, li { white-space: pre-wrap; } Previous - + Précédant @@ -3199,264 +3255,264 @@ p, li { white-space: pre-wrap; } Fermer - + &Delete Supprimer - + &Rename &Renommer - + &Hide - + &Cacher - + &Unhide - + &Ne plus cacher - + &Open &Ouvrir - + &New Folder &Nouveau dossier - - + + Save changes? - Enregistrer les changements? + Enregistrer les changements? - - + + Save changes to "%1"? - + Enregistrer les changements sur "%1" ? - + File Exists Un fichier du même nom existe - + A file with that name exists, please enter a new one Un fichier ainsi nommé existe déjà, veuillez entrer un nouveau nom - + failed to move file impossible de déplacer le fchier - + failed to create directory "optional" - Impossible de créer le dossier "optional" + impossible de créer le dossier "optional" - - + + Info requested, please wait Info demandée, veuillez patienter - + Main Principal - + Update Mise-à-jour - + Optional Optionnel - + Old Ancien - + Misc Divers - + Unknown Inconnu - + Current Version: %1 Version courante: %1 - + No update available Aucune mise-à-jour disponible - + (description incomplete, please visit nexus) - + (description incomplète, veuillez aller sur le Nexus) - + <a href="%1">Visit on Nexus</a> <a href="%1">Visiter sur Nexus</a> - + Failed to delete %1 - impossible d'effacer %1 + Impossible d'effacer %1 - - + + Confirm Confirmer - + Are sure you want to delete "%1"? - Voulez-vous vraiment supprimer "%1"? + Voulez-vous vraiment supprimer "%1" ? - + Are sure you want to delete the selected files? - Voulez-vous vraiment supprimer les fichiers sélectionnés? + Voulez-vous vraiment supprimer les fichiers sélectionnés ? - - + + New Folder Nouveau dossier - + Failed to create "%1" Impossible de créer "%1" - - + + Replace file? - + Remplacer le fichier ? - + There already is a hidden version of this file. Replace it? - + Ceci est déjà une version cachée de ce fichier. La remplacer ? - - + + File operation failed - + Opération de fichier échouée - - + + Failed to remove "%1". Maybe you lack the required file permissions? - + Impossible de supprimer "%1". Peut-être n'avez vous pas les permissions nécessaires sur le fichier. - - + + failed to rename %1 to %2 - Impossible de renommer %1 en %2 + impossible de renommer %1 en %2 - + There already is a visible version of this file. Replace it? - + Il existe déjà une version visible de ce fichier. La remplacer ? - + Un-Hide - + Ne plus cacher - + Hide - + Cacher - + Name Nom - + Please enter a name - + Veuillez entrer un nom - - + + Error - Erreur + Erreur - + Invalid name. Must be a valid file name - + Nom invalide. Veuillez entrer un nom valide - + A tweak by that name exists - + Un tweak de ce nom existe déjà - + Create Tweak - + Créer un Tweak ModInfoForeign - + This pseudo mod represents content managed outside MO. It isn't modified by MO. - + Ce pseudo mod représente un contenu géré à l’extérieur de MO. Il n'est pas modifié par MO. ModInfoOverwrite - + This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit) - + Ce pseudo mod contient des fichiers provenant du répertoire Data virtualisé qui ont été modifiés (ex : par le construction kit) ModInfoRegular - - + + failed to write %1/meta.ini: error %2 - + impossible d'écrire %1/meta.ini : erreur %2 - + %1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory - %1 ne contient ni esp/esm, ni dossier d'éléments de jeu (textures, meshes, interface, ...) + %1 ne contient ni esp/esm, ni dossier d'éléments de jeu (textures, meshes, interface, ...) - + Categories: <br> - + Catégories : <br> @@ -3464,118 +3520,117 @@ p, li { white-space: pre-wrap; } Game plugins (esp/esm) - + Elder Scrolls Plugins (esp/esm) Interface - + Interface Meshes - + Meshes Music - + Music Scripts (Papyrus) - + Scripts (Papyrus) Script Extender Plugin - + Script Extender Plugin SkyProc Patcher - + SkyProc Patcher Sound - + Sound Strings - + Strings Textures - + Textures This entry contains files that have been created inside the virtual data tree (i.e. by the construction kit) - + Cette entrée contient des fichiers qui ont été créés à l'intérieur du répertoire Data virtualisé (ex : par le construction kit) Backup - + Backup No valid game data - + Aucune donnée de jeu valide Not endorsed yet - + Pas encore recommandé Overwrites files - + Fichiers d'Overwrite Overwritten files - + Fichiers écrasés Overwrites & Overwritten - + Overwrites & Overwritten Redundant - + Redondant Non-MO - + Non-MO invalid - + invalide installed version: "%1", newest version: "%2" - installed version: %1, newest version: %2 - + version installée : "%1", nouvelle version : "%2" The newest version on Nexus seems to be older than the one you have installed. This could either mean the version you have has been withdrawn (i.e. due to a bug) or the author uses a non-standard versioning scheme and that newest version is actually newer. Either way you may want to "upgrade". - + La version la plus récente disponible sur le Nexus semble être plus ancienne que celle que vous avez installée. Ceci peut signifier que la version que vous utiliser à été retirée (ex : pour cause de bug) ou que l'auteur utilise une syntaxe de version non standardisée et que la dernière version est en fait plus récente. D'une manière ou d'une autre vous pourriez vouloir "mettre à jour". Categories: <br> - + Catégories : <br> @@ -3585,7 +3640,7 @@ p, li { white-space: pre-wrap; } drag&drop failed: %1 - + le glissé&déposé à échoué : %1 @@ -3600,12 +3655,12 @@ p, li { white-space: pre-wrap; } Flags - + Flags Content - Contenu + Contenu @@ -3625,28 +3680,28 @@ p, li { white-space: pre-wrap; } Category - + Catégorie Nexus ID - IDs Nexus + ID Nexus Installation - + Installation unknown - Inconnu + inconnu Name of your mods - + Nom de vos mods @@ -3661,27 +3716,27 @@ p, li { white-space: pre-wrap; } Category of the mod. - + Catégorie du mod. Id of the mod as used on Nexus. - + ID du mod sur le Nexus Emblemes to highlight things that might require attention. - + Emblèmes pour mettre en évidence les choses qui pourraient devoir retenir votre attention. Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> - + Représente le contenu du mod ::<br><img src=":/MO/gui/content/plugin" width=32/>Plugins de jeu (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> Time this mod was installed - + Date à laquelle le mod a été installé @@ -3689,12 +3744,12 @@ p, li { white-space: pre-wrap; } Message of the Day - + Message du Jour OK - OK + OK @@ -3702,35 +3757,35 @@ p, li { white-space: pre-wrap; } Overwrites - + Overwrites not implemented - + non implémenté NXMAccessManager - + Logging into Nexus - + Connexion au Nexus - + timeout - + session expirée - + Unknown error - + Erreur inconnue - + Please check your password - + Veuillez vérifier votre mot de passe @@ -3738,17 +3793,17 @@ p, li { white-space: pre-wrap; } Failed to guess mod id for "%1", please pick the correct one - + Impossible de deviner l'ID de mod pour "%1", veuillez déterminer la bonne empty response - + réponse nulle invalid response - + réponse invalide @@ -3756,184 +3811,184 @@ p, li { white-space: pre-wrap; } Overwrite - + Overwrite You can use drag&drop to move files and directories to regular mods. - + Vous pouvez glisser&déposer pour déplacer les fichiers et les répertoires dans les mods usuels. &Delete - Supprimer + &Supprimer &Rename - &Renommer + &Renommer &Open - &Ouvrir + &Ouvrir &New Folder - &Nouveau dossier + &Nouveau dossier %1 not found - %1 introuvable + %1 introuvable Failed to delete "%1" - impossible d'effacer %1 + impossible d'effacer "%1" Confirm - Confirmer + Confirmer Are sure you want to delete "%1"? - Voulez-vous vraiment supprimer "%1"? + Voulez-vous vraiment supprimer "%1" ? Are sure you want to delete the selected files? - Voulez-vous vraiment supprimer les fichiers sélectionnés? + Voulez-vous vraiment supprimer les fichiers sélectionnés ? New Folder - Nouveau dossier + Nouveau dossier Failed to create "%1" - Impossible de créer "%1" + Impossible de créer "%1" PluginList - + Name Nom - + Priority Priorité - + Mod Index - + Index du mod - + Flags - + Flags - - + + unknown - Inconnu + inconnu - + Name of your mods - + Nom de vos mods - + Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority. - + Priorité de chargement de votre mod. Plus elle est élevée, plus le mod est "important" et écrasera donc les fichiers des mods de priorité inférieure. - + The modindex determins the formids of objects originating from this mods. - + L'index des mods détermine les "formids" des objets provenant de ces mods. - + failed to update esp info for file %1 (source id: %2), error: %3 - + impossible de mettre à jour les informations d'esp pour le fichier %1 (source ID : %2), erreur : %3 - + esp not found: %1 ESP introuvable: %1 - - + + Confirm Confirmer - + Really enable all plugins? - + Voulez vous vraiment activer tout les plugins ? - + Really disable all plugins? - + Voulez vous vraiment désactiver tout les plugins ? - + The file containing locked plugin indices is broken - + Le fichier contenant l'indice des plugins verrouillés est corrompu - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + Certains de vos plugins ont un nom invalide ! Ces plugions ne peuvent pas être chargés par le jeu. Veuillez vous référer à mo_interface.log pour la liste de tout les plugins affectés et les renommer. - <b>Origin</b>: %1 - + This plugin can't be disabled (enforced by the game) + Ce plugin ne peut être désactivé (forcé par le jeu) - Author - Auteur + <b>Origin</b>: %1 + <b>Origine</b> : %1 - - Description - Description + + Author + Auteur - - This plugin can't be disabled (enforced by the game) - + + Description + Description - + Missing Masters - + Masters manquants - + Enabled Masters - + Masters activés - + failed to restore load order for %1 - + La restauration de l’ordre de chargement à échouée pour %1 @@ -3941,12 +3996,12 @@ p, li { white-space: pre-wrap; } Preview - + Aperçu Close - Fermer + Fermer @@ -3954,16 +4009,20 @@ p, li { white-space: pre-wrap; } Problems - + Problèmes <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - + <!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; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> @@ -3974,12 +4033,12 @@ p, li { white-space: pre-wrap; } Fix - + Corriger No guided fix - + Aucune guide de correction @@ -3987,32 +4046,32 @@ p, li { white-space: pre-wrap; } invalid profile name %1 - + nom du profil invalide %1 failed to create %1 - impossible de créer %1 + impossible de créer %1 failed to write mod list: %1 - impossible de mettre à jour la liste de mods: %1 + impossible d'écrire la liste de mod : %1 failed to update tweaked ini file, wrong settings may be used: %1 - + impossible de mettre à jour le fichier de tweak ini : des paramètres incorrects pourraient être utilisés : %1 failed to create tweaked ini: %1 - + impossible de créer le fichier de tweak ini : %1 "%1" is missing or inaccessible - + "%1" est manquant ou inaccessible @@ -4026,7 +4085,7 @@ p, li { white-space: pre-wrap; } Overwrite directory couldn't be parsed - + le répertoire Overwrite n'a pas pu être traité @@ -4041,23 +4100,23 @@ p, li { white-space: pre-wrap; } failed to parse ini file (%1): %2 - impossible d'analyser le profil %1: %2 + impossible de traiter le fichier ini (%1) : %2 failed to modify "%1" - impossible de trouver "%1" + impossible de modifier "%1" Delete savegames? - + Supprimer les sauvegardes ? Do you want to delete local savegames? (If you select "No", the save games will show up again if you re-enable local savegames) - + @@ -4065,27 +4124,27 @@ p, li { white-space: pre-wrap; } Dialog - + Dialogue Please enter a name for the new profile - Veuillez inscrire un nom pour le nouveau profil + Veuillez entrer un nom pour le nouveau profil If checked, the new profile will use the default game settings. - + Si coché, le nouveau profil utilisera les paramètres de jeu par défaut. If checked, the new profile will use the default game settings instead of the "global" settings. Global settings are the settings you configure when running the game launcher directly, without MO. - + Default Game Settings - + Paramètres de jeu par défaut @@ -4105,7 +4164,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html> @@ -4121,12 +4180,12 @@ p, li { white-space: pre-wrap; } If checked, savegames are local to this profile and will not appear when starting with a different profile. - + Local Savegames - + Sauvegardes locales @@ -4138,7 +4197,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4147,7 +4206,7 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Les jeux Oblivion, Fallout 3 et Fallout NV contiennent un bug empêchant le fonctionnement des textures et modèles remplaceant ceux déjà existants dans le jeu.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Les jeux Oblivion, Fallout 3 et Fallout NV contiennent un bug empêchant le fonctionnement des textures et modèles remplaçant ceux déjà existants dans le jeu.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod Organizer utilise une méthode nommée &quot;BSA redirection&quot; (google est votre ami) pour circonvenir le problème une fois pour toute. Activez simplement et n'y pensez plus.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Avec Skyrim, le problème semble partiellement résolu, mais l'activation d'un mod dans le jeu dépends toujours des dates des fichiers. Il est donc encore préférable de l'activer..</span></p></body></html> @@ -4197,18 +4256,18 @@ p, li { white-space: pre-wrap; } Rename - &Renommer + Renommer Transfer save games to the selected profile. - + Transférer les sauvegardes de jeu vers le profil sélectionné. Transfer Saves - + Transférer les Sauvegardes @@ -4239,7 +4298,7 @@ p, li { white-space: pre-wrap; } failed to copy profile: %1 - impossible de copier le profil: %1 + impossible de copier le profil : %1 @@ -4249,7 +4308,7 @@ p, li { white-space: pre-wrap; } Invalid profile name - + Nom de profil invalide @@ -4259,27 +4318,27 @@ p, li { white-space: pre-wrap; } Are you sure you want to remove this profile (including local savegames if any)? - + Voulez-vous vraiment supprimer ce profil (y compris ses sauvegardes locales s'il y en a) ? Profile broken - + Profil corrompu 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? - + Rename Profile - + Renommer le Profil New Name - + Nouveau Nom @@ -4310,52 +4369,52 @@ p, li { white-space: pre-wrap; } invalid category id %1 - + ID de catégorie invalide %1 invalid field name "%1" - + nom de champ invalide "%1" invalid type for "%1" (should be integer) - + type invalide pour "%1" (devrait être entier) invalid type for "%1" (should be string) - + type invalide pour "%1" (devrait être un "string") invalid type for "%1" (should be float) - + type invalide pour "%1" (devrait être "flottant") no fields set up yet! - + encore aucun champs installé ! field not set "%1" - + champ non déterminé "%1" invalid character in field "%1" - + caractère invalide dans le champ "%1" empty field name - + nom du champ vide invalid game type %1 - + type de jeu invalide %1 @@ -4439,62 +4498,62 @@ p, li { white-space: pre-wrap; } Impossible de mettre en place le chargement via DLL par procuration - + Permissions required Permissions requises - + 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. - + - - + + Woops - + Oups - + ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened - + - + ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1 - + - + Mod Organizer Mod Organizer - + An instance of Mod Organizer is already running Une copie du Mod Organizer tourne déjà - + No game identified in "%1". The directory is required to contain the game binary and its launcher. - + - - + + Please select the game to manage Veuillez choisir le jeu à gérer - + Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!) - + - + failed to start application: %1 - + impossible de démarrer l'application : %1 @@ -4502,28 +4561,28 @@ p, li { white-space: pre-wrap; } Veuillez utiliser l'aide dans la barre d'outil pour obtenir des instructions à propos de tous les éléments - - + + <Manage...> <Gérer...> - + failed to parse profile %1: %2 impossible d'analyser le profil %1: %2 - + failed to find "%1" impossible de trouver "%1" - + failed to access %1 impossible d'accéder à %1 - + failed to set file time %1 impossible de changer la date du fichier %1 @@ -4535,13 +4594,12 @@ p, li { white-space: pre-wrap; } "%1" is missing or inaccessible - "%1" is missing - + "%1" est manquant ou innacessible Before you can use ModOrganizer, you need to create at least one profile. ATTENTION: Run the game at least once before creating a profile! - + Avant de pouvoir utiliser ModOrganizer, vous devez créer au moins un profile. ATTENTION : Lancer le jeu une fois avant de créer un profile! @@ -4549,6 +4607,11 @@ p, li { white-space: pre-wrap; } Error Erreur + + + failed to open temporary file + impossible d'ouvrir le fichier temporaire + @@ -4564,7 +4627,7 @@ p, li { white-space: pre-wrap; } Script Extender - Extenseur de script + Script Extender @@ -4572,87 +4635,82 @@ p, li { white-space: pre-wrap; } DLL par procuration - + failed to spawn "%1" impossible de lancer "%1" - + Elevation required - + Permissions requises - + This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" can be installed to work without elevation. Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe to make changes to the system) - + - + failed to spawn "%1": %2 impossible de lancer "%1": %2 - + "%1" doesn't exist "%1" inexistant - + failed to inject dll into "%1": %2 impossible d'injecter le DLL dans "%1": %2 - + failed to run "%1" impossible de lancer "%1" - - - failed to open temporary file - - QueryOverwriteDialog Mod Exists - + Le Mod existe déjà This mod seems to be installed already. Do you want to add files from this archive (overwriting existing ones) or do you want to completely replace the existing files (old files are deleted)? Alternatively you can install this mod under a different name. - + Ce Mod semble déjà installé. Voulez-vous ajouter les fichiers provenants de cette archive (écrase les fichiers existants) ou voulez-vous remplacer complètement les fichiers existants (les vieux fichiers seront effacés)? Alternativement vous pouvez installer ce Mod sous un nom différend. Keep Backup - + Garder une sauvegarde Merge - + Fusionner Replace - + Remplacer Rename - &Renommer + Renommer Cancel - Annuler + Annuler @@ -4660,27 +4718,27 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Save # - + Enregistrer # Character - + Personnage Level - + Niveau Location - + Location Date - DATA + Date @@ -4688,7 +4746,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Missing ESPs - ESP manquant + ESPs manquants @@ -4696,37 +4754,37 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Dialog - + Dialogue Copy To Clipboard - + Copier dans le presse papier Save As... - + Sauvegarder en tant que... Close - Fermer + Fermer Save CSV - + Sauvegarder le CSV Text Files - Fichiers texte + Fichiers Textes failed to open "%1" for writing - + impossible d'ouvrir "%1" pour écriture @@ -4734,17 +4792,17 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Select - + Sélectionner Placeholder - Signet + *Substitut* Cancel - Annuler + Annuler @@ -4790,7 +4848,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe failed to move outdated files: %1. Please update manually. - + impossible de déplacer les fichiers obsolètes : %1. Veuillez les mettre à jour manuellement. @@ -4805,22 +4863,22 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Failed to parse response. Please report this as a bug and include the file mo_interface.log. - + Échec du traitement de la réponse. Veuillez s'il vous plait reporter ceci comme un bug, en incluant le fichier mo_interface.log. No incremental update available for this version, the complete package needs to be downloaded (%1 kB) - + no file for update found. Please update manually. - + aucun fichier de mise à jour trouvé. Veuillez mettre à jour manuellement. Failed to retrieve update information: %1 - + Impossible de récupérer les informations de mise à jour : %1 @@ -4833,28 +4891,28 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Failed - + Échec Sorry, failed to start the helper application - + Désolé, impossible de démarrer l'application d'aide attempt to store setting for unknown plugin "%1" - + Confirm - Confirmer + Confimer 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? - + @@ -4862,7 +4920,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Settings - Réglages + Paramètres @@ -4884,7 +4942,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html> <!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"> @@ -4895,124 +4953,124 @@ p, li { white-space: pre-wrap; } Style - + Style graphical style - + Style graphique graphical style of the MO user interface - + Style graphique de l'interface utilise de MO Log Level - + Niveau de log Decides the amount of data printed to "ModOrganizer.log" - + Décide de la quantité de donnée écrite dans "ModOrganizer.log" Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty. - + Debug - + Débogage Info - + Information Error - Erreur + Erreur Advanced - + Avancé Directory where downloads are stored. - + Répertoire où les Mods sont stockés Mod Directory - + Répertoire de Mod Directory where mods are stored. - + Répertoire où les Mods sont stockés. 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 - + Répertoire de téléchargement Cache Directory - + Répertoire en cache User interface - + Interface utiliser If checked, the download interface will be more compact. - + Si coché, l'interface des téléchargements sera plus compacte. Compact Download Interface - + Interface de téléchargent compacte If checked, the download list will display meta information instead of file names. - + Download Meta Information - + Télécharger les Informations Meta Reset stored information from dialogs. - + This will make all dialogs show up again where you checked the "Remember selection"-box. - + Reset Dialogs - + Réinitialiser les dialogues @@ -5041,7 +5099,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html> <!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"> @@ -5052,7 +5110,7 @@ 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. - + @@ -5072,82 +5130,82 @@ p, li { white-space: pre-wrap; } Disable automatic internet features - + Désactive les fonctionnalités automatiques nécessitant une connexion internet 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 - + Mode hors-connection Use a proxy for network connections. - + Utiliser un proxy pour les connections sur le réseau. 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) - + Utiliser un Proxy HTTP (Utilise les propriétés du système) Associate with "Download with manager" links - + Associer avec les liens "Download with manager" Known Servers (updated on download) - + Serveurs connus (MàJ tout les téléchargements) Preferred Servers (Drag & Drop) - + Serveurs préférés (Glisser & Déposer) Plugins - + Plugins Author: - Auteur + Auteur: Version: - Version + Version: Description: - Description + Description: Key - + Clé Value - + Valeur Blacklisted Plugins (use <del> to remove): - + Plugin black-listé (utilisez <del> pour le supprimer) : @@ -5169,7 +5227,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5207,29 +5265,29 @@ p, li { white-space: pre-wrap; } 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. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam. - + NMM Version - + Version de NMM The Version of Nexus Mod Manager to impersonate. - + La Version de Nexus Mod Manager à impersonnaliser. 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. +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. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again. - + @@ -5238,7 +5296,7 @@ tl;dr-version: If Nexus-features don't work, insert the current version num - It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + 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. Il semble que les jeux chargent parfois des fichiers ESP ou ESM même s'ils ne sont pas activés. Je n'en connais pas encore les circonstances, mais les rapports des usagers impliquent que dans certains cas, ce comportement est indésirable. Si vous cochez ceci, les ESPs et ESMs qui ne sotn pas cochés seront invisible pour le jeu et ne pourront pas être chargés. @@ -5251,36 +5309,36 @@ Je n'en connais pas encore les circonstances, mais les rapports des usagers 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 - + Forcer l'activation des fichiers de jeu. 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. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature. - + Display mods installed outside MO - + Affichers les Mods qui n'ont pas été installer par MO @@ -5298,32 +5356,32 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar These are workarounds for problems with Mod Organizer. Please make sure you read the help text before changing anything here. - + Il s'agit de solutions alternatives pour des problèmes internes à Mod Organizer. Veuillez d'abord vous assurer de lire le texte d'aide avant de modifier quoi que ce soit ici. Select download directory - Sélectionnez un répertoire + Sélectionner le répertoire de téléchargement Select mod directory - Sélectionnez un répertoire + Sélectionner le répertoire de Mod Select cache directory - Sélectionnez un répertoire + Sélectionner le répertoire en cache Confirm? - Confirmer + Confirmer ? This will make all dialogs show up again where you checked the "Remember selection"-box. Continue? - + @@ -5375,7 +5433,7 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar failed to communicate with running instance: %1 - + Communication échouée avec l'instance active: %1 @@ -5388,32 +5446,32 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar Sync Overwrite - + Synchroniser Overwrite Name - Nom + Nom Sync To - + Synchroniser Vers <don't sync> - + <ne pas synchroniser> failed to remove %1 - Impossible de supprimer %1 + Impossible de supprimer %1 failed to move %1 to %2 - impossible de copier %1 vers %2 + Impossible de déplacer de %1 à %1 @@ -5421,17 +5479,17 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar Transfer Savegames - + Transférer les sauvegardes de jeux Global Characters - + Personnages Globaux This is a list of characters in the global location. - + Ceci est une liste des personnages globaux. @@ -5443,7 +5501,7 @@ On Windows Vista/Windows 7: On Windows XP: C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves - + @@ -5456,47 +5514,47 @@ On Windows XP: C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves - + Move -> - + Déplacer -> Copy -> - + Copier -> <- Move - + <- Déplacer <- Copy - + <- Copier Done - Terminé + Terminé Profile Characters - + Profil des personnages Overwrite - + Écraser Overwrite the file "%1" - + Écraser le fichier "%1" @@ -5504,23 +5562,23 @@ On Windows XP: Confirm - Confirmer + Confirmer Copy all save games of character "%1" to the profile? - + Copier toutes les sauvegardes du personnage "%1" vers le profil ? Move all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games. - + Copy all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games. - + - + \ No newline at end of file diff --git a/src/organizer_ru.ts b/src/organizer_ru.ts index 47978e40..7fc47167 100644 --- a/src/organizer_ru.ts +++ b/src/organizer_ru.ts @@ -1,6 +1,4 @@ - - - + AboutDialog @@ -62,7 +60,7 @@ <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -225,7 +223,7 @@ If there is a component called "00 Core" it is usually required. Optio <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> @@ -989,7 +987,7 @@ Right now the only case I know of where this needs to be overwritten is for the Save Changes? - Сохранить изменения? + Сохранить изменения? @@ -1135,7 +1133,7 @@ Right now the only case I know of where this needs to be overwritten is for the <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html> <!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"> @@ -1156,7 +1154,7 @@ p, li { white-space: pre-wrap; } Cancel - Отмена + Отмена @@ -1179,87 +1177,87 @@ p, li { white-space: pre-wrap; } - + Extracting files Извлечение файлов - + failed to create backup не удалось создать резервную копию - + Mod Name Имя мода - + Name - Имя + Имя - + Invalid name Недопустимое имя - + The name you entered is invalid, please enter a different one. Введенное вами имя недопустимо, пожалуйста введите другое. - + File format "%1" not supported Формат файла "%1" не поддерживается - + None of the available installer plugins were able to handle that archive Не один из доступных плагинов-установщиков не смог просмотреть этот архив - + no error ошибки отсутствуют - + 7z.dll not found 7z.dll не найден - + 7z.dll isn't valid 7z.dll поврежден - + archive not found архив не найден - + failed to open archive не удалось открыть архив - + unsupported archive type не поддерживаемый тип архива - + internal library error внутренняя ошибка библиотеки - + archive invalid архив поврежден - + unknown archive error неизвестная ошибка архива @@ -1314,7 +1312,7 @@ p, li { white-space: pre-wrap; } Categories - Категории + Категории @@ -1356,7 +1354,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1366,6 +1364,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Создать профили здесь. Каждый профиль включает свой собственный список активных модов и esp. Таким образом, вы можете быстро переключаться между установками для различных прохождений игры.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Обратите внимание, что порядок загрузки esp одинаков для всех профилей.</span></p></body></html> + + + Open list options... + Открыть список вариантов... + Refresh list. This is usually not necessary unless you modified data outside the program. @@ -1425,7 +1428,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1445,7 +1448,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html> <!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"> @@ -1468,7 +1471,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html> <!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"> @@ -1486,6 +1489,11 @@ p, li { white-space: pre-wrap; } Plugins Плагины + + + Sort + Сортировать + List of available esp/esm files @@ -1496,7 +1504,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html> <!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"> @@ -1504,16 +1512,6 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Этот список содержит esp и esm файлы активных модов. Для них требуется определенный порядок загрузки. Используйте перетаскивание для изменения порядка загрузки. Обратите внимание, что MO сохранит порядок загрузки только для активными/проверенных модов.<br />Существует замечательная утилита, называющаяся &quot;BOSS&quot; , которая автоматически сортирует эти файлы.</span></p></body></html> - - - Sort - Сортировать - - - - Open list options... - Открыть список вариантов... - Archives @@ -1549,7 +1547,7 @@ BSA, отмеченные здесь, загружаются так, чтобы File - Файл + Файл @@ -1568,8 +1566,8 @@ BSA, отмеченные здесь, загружаются так, чтобы - - + + Refresh Обновить @@ -1581,7 +1579,7 @@ BSA, отмеченные здесь, загружаются так, чтобы Mod - Мод + Мод @@ -1604,8 +1602,8 @@ BSA, отмеченные здесь, загружаются так, чтобы <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1749,7 +1747,7 @@ p, li { white-space: pre-wrap; } - + Update Обновление @@ -1793,7 +1791,7 @@ Right now this has very limited functionality - + Endorse Mod Organizer Одобрить Mod Organizer @@ -1875,7 +1873,7 @@ Right now this has very limited functionality Name - Имя + Имя @@ -1922,6 +1920,25 @@ Right now this has very limited functionality Plugin "%1" failed Плагин "%1" не удалось + + + Download? + Загрузить? + + + + A download has been started but no installed page plugin recognizes it. +If you download anyway no information (i.e. version) will be associated with the download. +Continue? + Загрузка началась, но не была установлена страница плагина. +Если вы все равно загрузите, то никакой информации (т.е. версия) не будет ассоциировано с загрузкой. +Продолжить? + + + + Browse Mod Page + Смотреть страницу мода + failed to init plugin %1: %2 @@ -1954,6 +1971,11 @@ Right now this has very limited functionality Please press OK once you're logged into steam. Нажмите OK как только вы войдете в Steam. + + + Executable "%1" not found + Исполняемый файл "%1" не найден + Start Steam? @@ -1965,926 +1987,887 @@ Right now this has very limited functionality Требуется запущенный Steam, для корректного запуска игры. Должен ли MO попытаться запустить Steam сейчас? - + Also in: <br> Также в: <br> - + No conflict Конфликтов нет - + <Edit...> <Правка...> - + + Failed to refresh list of esps: %1 + Не удалось обновить список esp: %1 + + + This bsa is enabled in the ini file so it may be required! Этот bsa подключен через ini, так что он может быть необходим! - + Activating Network Proxy Подключение сетевого прокси - - - Installation successful - Установка завершена - - - - - Configure Mod - Настройка мода + + + Failed to write settings + Не удалось записать настройки - - - This mod contains ini tweaks. Do you want to configure them now? - Этот мод включает настройки ini. Вы хотите настроить их сейчас? + + + An error occured trying to write back MO settings: %1 + Ошибка при попытке записать обратно настройки MO: %1 - - - mod "%1" not found - мод "%1" не найден + + File is write protected + Файл защищён от записи - - - Installation cancelled - Установка отменена + + Invalid file format (probably a bug) + Неверный формат файла (возможно баг) - - - The mod was not installed completely. - Мод не был установлен полностью. + + Unknown error %1 + Неизвестная ошибка %1 - + Some plugins could not be loaded Некоторые плагины не могут быть загружены - + Too many esps and esms enabled Подключено слишком много esp и esm - - + + Description missing Описание отсутствует - + The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: Следующие плагины не могут быть загружены. Причина возможно в отсутствующих зависимостях (таких как python) или в устаревшей версии: - + The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> Игра не позволяет загрузить больше 255 активных плагинов (включая официальные). Вам нужно отключить некоторые ненужные плагины или объединить несколько небольших плагинов в один. Инструкция может быть найдена здесь: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + Choose Mod Выберете мод - + Mod Archive Архив мода - + + + Installation successful + Установка завершена + + + + + Configure Mod + Настройка мода + + + + + This mod contains ini tweaks. Do you want to configure them now? + Этот мод включает настройки ini. Вы хотите настроить их сейчас? + + + + + mod "%1" not found + мод "%1" не найден + + + + + Installation cancelled + Установка отменена + + + + + The mod was not installed completely. + Мод не был установлен полностью. + + + Start Tutorial? Начать урок? - + You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue? Вы собираетесь открыть урок. По техническим причинам будет невозможно закончить его досрочно. Продолжить? - - + + Download started Загрузка начата - + failed to update mod list: %1 не удалось обновить список модов: %1 - + failed to spawn notepad.exe: %1 не удалось вызвать notepad.exe: %1 - + failed to open %1 не удалось открыть %1 - + failed to change origin name: %1 не удалось изменить оригинальное имя: %1 - - Executable "%1" not found - Исполняемый файл "%1" не найден - - - - Failed to refresh list of esps: %1 - Не удалось обновить список esp: %1 - - - + failed to move "%1" from mod "%2" to "%3": %4 не удалось переместить "%1" из мода "%2" в "%3": %4 - + + <Contains %1> + <Содержит %1> + + + <Checked> <Подключен> - + <Unchecked> <Отключен> - + <Update> <Обновлен> - + + <Managed by MO> + <Управляется в MO> + + + + <Managed outside MO> + <Управляется вне MO> + + + <No category> <Без категории> - + <Conflicted> <Конфликтует> - + <Not Endorsed> <Не одобрено> - + failed to rename mod: %1 не удалось переименовать мод: %1 - + Overwrite? Перезаписать? - + This will replace the existing mod "%1". Continue? Это заменит существующий мод "%1". Продолжить? - + failed to remove mod "%1" не удалось удалить мод "%1" - - - + + + failed to rename "%1" to "%2" не удалось переименовать "%1" в "%2" - + Multiple esps activated, please check that they don't conflict. Подключено несколько esp, выберете из них не конфликтующие. - - - - + + + + Confirm Подтверждение - + Remove the following mods?<br><ul>%1</ul> Удалить следующие моды?<br><ul>%1</ul> - + failed to remove mod: %1 не удалось удалить мод: %1 - - + + Failed Неудача - + Installation file no longer exists Установочный файл больше не существует - + Mods installed with old versions of MO can't be reinstalled in this way. Моды, установленные с использованием старых версий MO не могут быть переустановленны таким образом. - - - You need to be logged in with Nexus to endorse - Вы должны быть авторизированы на Nexus, чтобы одобрять. - - - - Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. - - - - - - - - - Delete %n save(s) - - - - - - - - - Extract BSA - Распаковать BSA + + You need to be logged in with Nexus to resume a download + Вы должны быть авторизированы на Nexus, чтобы продолжить загрузку - - - failed to read %1: %2 - не удалось прочесть %1: %2 + + + You need to be logged in with Nexus to endorse + Вы должны быть авторизированы на Nexus, чтобы одобрять. - - This archive contains invalid hashes. Some files may be broken. - Архив содержит неверные хеш-суммы. Некоторые файлы могут быть испорчены. + + Failed to display overwrite dialog: %1 + Ошибка при отображении диалогового окна перезаписи: %1 - + Nexus ID for this Mod is unknown Nexus ID для этого мода неизвестен - - Download? - Загрузить? - - - - A download has been started but no installed page plugin recognizes it. -If you download anyway no information (i.e. version) will be associated with the download. -Continue? - Загрузка началась, но не была установлена страница плагина. -Если вы все равно загрузите, то никакой информации (т.е. версия) не будет ассоциировано с загрузкой. -Продолжить? - - - - Browse Mod Page - Смотреть страницу мода - - - - - Failed to write settings - Не удалось записать настройки - - - - - An error occured trying to write back MO settings: %1 - Ошибка при попытке записать обратно настройки MO: %1 - - - - File is write protected - Файл защищён от записи - - - - Invalid file format (probably a bug) - Неверный формат файла (возможно баг) - - - - Unknown error %1 - Неизвестная ошибка %1 - - - - <Managed by MO> - <Управляется в MO> - - - - <Managed outside MO> - <Управляется вне MO> - - - - You need to be logged in with Nexus to resume a download - Вы должны быть авторизированы на Nexus, чтобы продолжить загрузку - - - - Failed to display overwrite dialog: %1 - - - - - + + Create Mod... Создать мод... - + This will move all files from overwrite into a new, regular mod. Please enter a name: Это переместит все файлы из перезаписи в новый, стандартный мод. Пожалуйста введите имя: - + A mod with this name already exists Мод с таким именем уже существует - + Continue? Продолжить? - + The versioning scheme decides which version is considered newer than another. This function will guess the versioning scheme under the assumption that the installed version is outdated. Схема управления версиями принимает решение, какая версия считается новее другой. Функция может попробовать угадать схему управления версиями, при условии, что установленная версия является устаревшей. - - + + Sorry Извините - + I don't know a versioning scheme where %1 is newer than %2. Мне неизвестна схема управления версиями, где %1 новее %2. - + Really enable all visible mods? Действительно подключить все видимые моды? - + Really disable all visible mods? Действительно отключить все видимые моды? - + Choose what to export Выберете, что экспортировать - + Everything Всё - + All installed mods are included in the list Все установленные моды, включенные в список - + Active Mods Активные моды - + Only active (checked) mods from your current profile are included Включены все активные (подключенные) моды вашего текущего профиля - + Visible Видимые - + All mods visible in the mod list are included Включены все моды, видимые в списке модов - + export failed: %1 экспорт не удался: %1 - + Install Mod... Установить мод... - + Enable all visible Включить все видимые - + Disable all visible Отключить все видимые - + Check all for update Проверить все на обновления - + Export to csv... Экспорт в csv... - + All Mods Все моды - + Sync to Mods... Синхронизировать с модами... - + Restore Backup Восстановить из резервной копии - + Remove Backup... Удалить резервную копию... - + Add/Remove Categories Добавить/Удалить категории - + Replace Categories Заменить категории - + Primary Category Основная категория - + Change versioning scheme Изменить схему управления версиями - + Un-ignore update Снять игнорирование обновления - + Ignore update Игнорировать обновление - + Rename Mod... Переименовать мод... - + Remove Mod... Удалить мод... - + Reinstall Mod Переустановить мод - + Un-Endorse Отменить одобрение - - + + Endorse Одобрить - + Won't endorse Не одобрять - + Endorsement state unknown Статус одобрения неизвестен - + Ignore missing data Игнорировать отсутствующие данные - + Visit on Nexus Перейти на Nexus - + Open in explorer Открыть в проводнике - + Information... Информация... - - + + Exception: Исключение: - - + + Unknown exception Неизвестное исключение - + <All> <Все> - + <Multiple> <Несколько> - - - Please wait while LOOT is running - + + + Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. + Вы уверены, что хотите удалить следующие %n сохранения?<br><ul>%1</ul><br>Удаленные сохранения будут помещены в Корзину.Вы уверены, что хотите удалить следующие %n сохранения?<br><ul>%1</ul><br>Удаленные сохранения будут помещены в Корзину.Вы уверены, что хотите удалить следующие %n сохранения?<br><ul>%1</ul><br>Удаленные сохранения будут помещены в Корзину. - Really delete "%1"? - Действительно удалить "%1"? + + Please wait while LOOT is running + Пожалуйста, подождите, пока LOOT работает - + Fix Mods... Исправить моды... - - Delete - Удалить + + + Delete %n save(s) + Удалить сохранение(я)Удалить сохранение(я)Удалить сохранение(я) - + failed to remove %1 не удалось удалить %1 - - + + failed to create %1 не удалось создать %1 - + Can't change download directory while downloads are in progress! Нельзя изменить каталог для загрузок, когда загрузки ещё не завершены! - + Download failed Загрузка не удалась - + failed to write to file %1 ошибка записи в файл %1 - + %1 written %1 записан - + Select binary Выберете исполняемый файл - + Binary Исполняемый файл - + Enter Name Введите имя - + Please enter a name for the executable Введите название для программы - + Not an executable Не является исполняемым - + This is not a recognized executable. Это неверный исполняемый файл. - - + + Replace file? Заменить файл? - + There already is a hidden version of this file. Replace it? Уже существует скрытая версия этого файла. Заменить? - - + + File operation failed Операция с файлом не удалась - - + + Failed to remove "%1". Maybe you lack the required file permissions? Не удалось удалить "%1". Может быть, вам не хватает необходимых прав доступа к файлу? - + There already is a visible version of this file. Replace it? Видимая версия этого файла уже существует. Заменить? - + file not found: %1 файл не найден: %1 - + failed to generate preview for %1 не удалось получить предосмотр для %1 - + Sorry, can't preview anything. This function currently does not support extracting from bsas. Невозможно получить предосмотр чего-либо. Функция на данный момент не поддерживает извлечение из bsa. - + Update available Доступно обновление - + Open/Execute Открыть/Выполнить - + Add as Executable Добавить как исполняемый - + Preview Предосмотр - + Un-Hide Показать - + Hide Скрыть - + Write To File... Записать в файл... - + Do you want to endorse Mod Organizer on %1 now? Вы хотите одобрить Mod Organizer на %1 сейчас? - + Thank you! Спасибо Вам! - + Thank you for your endorsement! Спасибо Вам за одобрение! - + Request to Nexus failed: %1 Запрос на Nexus не удался: %1 - - + + login successful успешный вход - + login failed: %1. Trying to download anyway вход не удался: %1. Пытаюсь загрузить всё равно - + login failed: %1 войти не удалось: %1 - + login failed: %1. You need to log-in with Nexus to update MO. войти не удалось: %1. Вам нужно войти на Nexus, чтобы обновить MO. - + + + failed to read %1: %2 + не удалось прочесть %1: %2 + + + Error Ошибка - + failed to extract %1 (errorcode %2) не удалось распаковать %1 (код ошибки %2) - + + Extract BSA + Распаковать BSA + + + + This archive contains invalid hashes. Some files may be broken. + Архив содержит неверные хеш-суммы. Некоторые файлы могут быть испорчены. + + + Extract... Распаковать... - + Edit Categories... Изменить категории... - + Deselect filter Снять выбор с фильтра - + Remove Удалить - + Enable all Включить все - + Disable all Отключить все - + Unlock load order Снять фиксацию порядка загрузки - + Lock load order Зафиксировать порядок загрузки - + depends on missing "%1" зависит от отсутствующего "%1" - + incompatible with "%1" - + несовместимый с "%1" - + No profile set Нет установленного профиля - LOOT working - LOOT работает - - - + loot failed. Exit code was: %1 Запуск LOOT не удался. Код завершения: %1 - + failed to start loot - + Не удалось запустить LOOT - + failed to run loot: %1 не удалось запустить LOOT: %1 - + Errors occured Возникли ошибки - + Backup of load order created Резервная копия порядка загрузки создана - + Choose backup to restore Выберите резервную копию для восстановления - + No Backups Резервных копий нет - + There are no backups to restore Резервные копии для восстановления отсутствуют - - + + Restore failed Восстановление не удалось - - + + Failed to restore the backup. Errorcode: %1 Не удалось восстановить резервную копию. Код ошибки: %1 - + Backup of modlist created Резервная копия списка модов создана @@ -2901,8 +2884,63 @@ This function will guess the versioning scheme under the assumption that the ins ModInfo - - + + Plugins + Плагины + + + + Textures + Текстуры + + + + Meshes + Полигональные сетки + + + + UI Changes + Изменения интерфейса + + + + Music + Музыка + + + + Sound Effects + Звуковые эффекты + + + + Scripts + Скрипты + + + + SKSE Plugins + Плагины SKSE + + + + SkyProc Tools + Инструменты SkyProc + + + + Strings + Строки + + + + invalid content type %1 + Некорректный тип содержания %1 + + + + invalid index %1 неверный индекс %1 @@ -2910,7 +2948,7 @@ This function will guess the versioning scheme under the assumption that the ins ModInfoBackup - + This is the backup of a mod Это резервная копия мода @@ -3126,7 +3164,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html> <!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"> @@ -3139,7 +3177,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html> <!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"> @@ -3172,7 +3210,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> <!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"> @@ -3205,7 +3243,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3228,230 +3266,230 @@ p, li { white-space: pre-wrap; } Close - Закрыть + Закрыть - + &Delete &Удалить - + &Rename &Переименовать - + &Hide &Скрыть - + &Unhide &Показать - + &Open - &Открыть + &Открыть - + &New Folder &Новая папка - - + + Save changes? Сохранить изменения? - - + + Save changes to "%1"? Сохранить изменения в "%1"? - + File Exists Файл уже существует - + A file with that name exists, please enter a new one Файл с таким именем уже существует, укажите другое - + failed to move file не удалось переместить файл - + failed to create directory "optional" не удалось создать папку "optional" - - + + Info requested, please wait Информация запрошена, пожалуйста, подождите - + Main Главное - + Update Обновление - + Optional Опционально - + Old Старые - + Misc Разное - + Unknown Неизвестно - + Current Version: %1 Текущая версия: %1 - + No update available Нет доступных обновлений - + (description incomplete, please visit nexus) (описание не завершено, смотрите на nexus) - + <a href="%1">Visit on Nexus</a> <a href="%1">Перейти на Nexus</a> - + Failed to delete %1 - Не удалось удалить %1 + Не удалось удалить %1 - - + + Confirm Подтверждение - + Are sure you want to delete "%1"? Вы уверены, что хотите удалить "%1"? - + Are sure you want to delete the selected files? Вы уверены, что хотите удалить выбранные файлы? - - + + New Folder Новая папка - + Failed to create "%1" Не удалось создать "%1" - - + + Replace file? Заменить файл? - + There already is a hidden version of this file. Replace it? Скрытая версия этого файла уже существует. Заменить? - - + + File operation failed Не удалась операция с файлом - - + + Failed to remove "%1". Maybe you lack the required file permissions? Не удалось удалить "%1". Может быть, вам не хватает необходимых прав доступа к файлу? - - + + failed to rename %1 to %2 не удалось переименовать %1 в %2 - + There already is a visible version of this file. Replace it? Видимая версия этого файла уже существует. Заменить? - + Un-Hide Показать - + Hide Скрыть - + Name Имя - + Please enter a name Пожалуйста, введите имя - - + + Error Ошибка - + Invalid name. Must be a valid file name Неверное имя. Необходимо допустимое имя файла. - + A tweak by that name exists Настройка с таким именем существует - + Create Tweak Создать настройку @@ -3459,7 +3497,7 @@ p, li { white-space: pre-wrap; } ModInfoForeign - + This pseudo mod represents content managed outside MO. It isn't modified by MO. Этот псевдо-мод отображает содержимое, управляемое из вне MO. Оно не модифицировано в MO. @@ -3467,7 +3505,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) Этот псевдо-мод содержит файлы из виртуального древа данных, которые были изменены (в Construction Kit и других программах) @@ -3475,18 +3513,18 @@ p, li { white-space: pre-wrap; } ModInfoRegular - - + + failed to write %1/meta.ini: error %2 не удалось записать %1/meta.ini: ошибка %2 - + %1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory %1 не содержит ни esp/esm, ни папок ресурсов (textures, meshes, interface, ...) - + Categories: <br> Категории: <br> @@ -3496,52 +3534,52 @@ p, li { white-space: pre-wrap; } Game plugins (esp/esm) - + Игровые плагины (esp/esm) Interface - + Интерфейс Meshes - + Полигональные сетки Music - + Музыка Scripts (Papyrus) - + Скрипты (Papyrus) Script Extender Plugin - + Script Extender плагин SkyProc Patcher - + Патч SkyProc Sound - + Звук Strings - + Строки Textures - + Текстуры @@ -3596,7 +3634,6 @@ p, li { white-space: pre-wrap; } installed version: "%1", newest version: "%2" - installed version: %1, newest version: %2 установлена версия: %1, новейшая версия: %2 @@ -3637,7 +3674,7 @@ p, li { white-space: pre-wrap; } Content - Содержание + Содержание @@ -3647,7 +3684,7 @@ p, li { white-space: pre-wrap; } Version - Версия + Версия @@ -3708,7 +3745,7 @@ p, li { white-space: pre-wrap; } Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> - + Показывает содержимое мода:<br><img src=":/MO/gui/content/plugin" width=32/>Плагины (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>интерфейс<br><img src=":/MO/gui/content/mesh" width=32/>Полигональные сетки<br><img src=":/MO/gui/content/texture" width=32/>Текстуры<br><img src=":/MO/gui/content/sound" width=32/>Звуки<br><img src=":/MO/gui/content/music" width=32/>Музыка<br><img src=":/MO/gui/content/string" width=32/>Строки<br><img src=":/MO/gui/content/script" width=32/>Скрипты (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Плагины Script Extender<br><img src=":/MO/gui/content/skyproc" width=32/>Патч SkyProc<br> @@ -3745,22 +3782,22 @@ p, li { white-space: pre-wrap; } NXMAccessManager - + Logging into Nexus Авторизация на Nexus - + timeout задержка - + Unknown error Неизвестная ошибка - + Please check your password Проверьте ваш пароль @@ -3808,7 +3845,7 @@ p, li { white-space: pre-wrap; } &Open - &Открыть + &Открыть @@ -3818,7 +3855,7 @@ p, li { white-space: pre-wrap; } %1 not found - %1 не найден + %1 не найден @@ -3856,114 +3893,114 @@ p, li { white-space: pre-wrap; } PluginList - + Name - Имя + Имя - + Priority Приоритет - + Mod Index Индекс - + Flags Флаги - - + + unknown неизвестно - + Name of your mods Имена ваших модов - + Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority. Приоритет загрузки ваших модов. Моды с большим приоритетом перезапишут данные модов с меньшим приоритетом. - + The modindex determins the formids of objects originating from this mods. Индекс модов, определяющий formid объектов, происходящих из этих модов. - + failed to update esp info for file %1 (source id: %2), error: %3 не удалось обновить информацию о esp для файла %1 (id источника: %2), ошибка: %3 - + esp not found: %1 esp не найден: %1 - - + + Confirm Подтвердить - + Really enable all plugins? Действительно подключить все плагины? - + Really disable all plugins? Действительно отключить все плагины? - + The file containing locked plugin indices is broken Файл, содержащий индексы заблокированного плагина, не работает. - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. Некоторые из ваших плагинов имеют неверные имена. Эти плагины не могут быть загружены игрой. Смотрите mo_interface.log для получения списка таких плагинов и переименуйте их. + This plugin can't be disabled (enforced by the game) + Этот плагин не может быть отключен (грузится игрой принудительно) + + + <b>Origin</b>: %1 <b>Источник</b>: %1 - + Author Автор - + Description Описание - - This plugin can't be disabled (enforced by the game) - Этот плагин не может быть отключен (грузится игрой принудительно) - - - + Missing Masters Отсутствующие мастерфайлы - + Enabled Masters Подключенные мастерфайлы - + failed to restore load order for %1 не удалось восстановить порядок загрузки для %1 @@ -3993,7 +4030,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!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"> @@ -4141,7 +4178,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html> @@ -4174,7 +4211,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4249,7 +4286,7 @@ p, li { white-space: pre-wrap; } Close - Закрыть + Закрыть @@ -4265,7 +4302,7 @@ p, li { white-space: pre-wrap; } Name - Имя + Имя @@ -4424,7 +4461,7 @@ p, li { white-space: pre-wrap; } Failed to delete %1 - Не удалось удалить %1 + Не удалось удалить %1 @@ -4475,60 +4512,60 @@ p, li { white-space: pre-wrap; } Не удалось установить загрузку proxy-dll - + Permissions required Требуются права доступа - + 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. Текущий аккаунт пользователя не имеет требуемых прав доступа для запуска Mod Organizer. Необходимые изменения могут быть сделаны автоматически (папка MO будет сделана записываемой для текущего аккаунта пользователя). Вы получите запрос о запуске "helper.exe" с правами администратора. - - + + Woops Упс - + ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened Mod Organizer вышел из строя! Нужно ли создать диагностический файл? Если вы вышлите файл (%1) по адресу sherb@gmx.net, ошибка с намного большей вероятностью будет исправлена. Пожалуйста, добавьте краткое описание своих действий, перед тем, как произошла ошибка - + ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1 ModOrganizer вышел из строя! К сожалению не удалось записать диагностический файл: %1 - + Mod Organizer Mod Organizer - + An instance of Mod Organizer is already running Другой экземпляр Mod Organizer уже запущен - + No game identified in "%1". The directory is required to contain the game binary and its launcher. Игра не обнаружена в "%1". Требуется, чтобы папка содержала исполняемые файлы игры. - - + + Please select the game to manage Выберете игру для управления - + Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!) Пожалуйста, выберете редакцию игры, которую вы имеете (MO не сможет правильно запустить игру, если это будет установлено неверно!) - + failed to start application: %1 не удалось запустить приложение: %1 @@ -4538,28 +4575,28 @@ p, li { white-space: pre-wrap; } Используйте пункт "Справка" на панели инструментов, чтобы получить инструкции по использованию всех элементов. - - + + <Manage...> <Управлять...> - + failed to parse profile %1: %2 не удалось обработать профиль %1: %2 - + failed to find "%1" не удалось найти "%1" - + failed to access %1 не удалось получить доступ к %1 - + failed to set file time %1 не удалось изменить дату модификации для %1 @@ -4571,7 +4608,6 @@ p, li { white-space: pre-wrap; } "%1" is missing or inaccessible - "%1" is missing "%1" отсутствует или недоступен @@ -4585,6 +4621,11 @@ p, li { white-space: pre-wrap; } Error Ошибка + + + failed to open temporary file + не удалось открыть временный файл + @@ -4608,17 +4649,17 @@ p, li { white-space: pre-wrap; } Proxy DLL - + failed to spawn "%1" не удалось вызвать "%1" - + Elevation required Требуется повышение прав - + This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" @@ -4633,30 +4674,25 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Запустить с повышенными правами в любом случае? (будет выведен запрос о разрешении ModOrganizer.exe сделать изменения в системе) - + failed to spawn "%1": %2 не удалось вызвать "%1": %2 - + "%1" doesn't exist "%1" не существует - + failed to inject dll into "%1": %2 не удалось подключить dll к "%1": %2 - + failed to run "%1" не удалось запустить "%1" - - - failed to open temporary file - не удалось открыть временный файл - QueryOverwriteDialog @@ -4683,7 +4719,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Replace - Заменить + Заменить @@ -4693,7 +4729,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Cancel - Отмена + Отмена @@ -4752,7 +4788,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Close - Закрыть + Закрыть @@ -4762,7 +4798,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Text Files - Текстовые файлы + Текстовые файлы @@ -4780,12 +4816,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Placeholder - Заполнитель + Метка-заполнитель Cancel - Отмена + Отмена @@ -4874,12 +4910,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Failed - Неудача + Неудача Sorry, failed to start the helper application - + Не удалось запустить программу-помощник @@ -4925,7 +4961,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html> <!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"> @@ -5083,7 +5119,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html> <!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"> @@ -5104,12 +5140,12 @@ p, li { white-space: pre-wrap; } Username - Имя пользователя + Имя пользователя Password - Пароль + Пароль @@ -5211,7 +5247,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5249,7 +5285,7 @@ p, li { white-space: pre-wrap; } 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. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam. Mod Organizer необходимо подключить dll к игре, чтобы все моды были видны в ней. @@ -5273,8 +5309,8 @@ If you use the Steam version of Oblivion the default will NOT work. In this case 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. +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. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again. Mod Organizer использует API Nexus , для использования таких возможностей, как проверка обновлений и загрузка файлов. К сожалению этот API не был сделан официально доступным прочим утилитам, вроде MO, так что нужно представляться как Nexus Mod Manager, чтобы получить доступ. @@ -5290,7 +5326,7 @@ tl;dr-версия: Если возможности Nexus не работают, - It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + 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. Кажется, что иногда игры загружают ESP и ESM файлы, даже если они не были не подключены как плагины Обстоятельства этого пока не известны, но отчеты пользователей подразумевают, что это в ряде случаев нежелательно. Если этот флажок отмечен, не отмеченные в списке ESP и ESM не будут видимы в списке и не будут загружены. @@ -5325,7 +5361,7 @@ Uncheck this if you want to use Mod Organizer with total conversions (like Nehri 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. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature. По умолчанию Mod Organizer отобразит пакеты esp+bsa, установленные из других инструментов, как моды (левая панель). Это позволяет вам контроллировать их приоритет по отношению к другим модам. Это особенно полезно, если вы используете Steam Workshop, для установки модов. @@ -5392,7 +5428,7 @@ For the other games this is not a sufficient replacement for AI! Name - Имя + Имя @@ -5413,7 +5449,7 @@ For the other games this is not a sufficient replacement for AI! Cancel - Отмена + Отмена @@ -5431,7 +5467,7 @@ For the other games this is not a sufficient replacement for AI! failed to communicate with running instance: %1 - не удалось подключиться к запущенному экземпляру: %1 + Не удалось подключиться к запущенному экземпляру: %1 @@ -5449,7 +5485,7 @@ For the other games this is not a sufficient replacement for AI! Name - Имя + Имя @@ -5477,7 +5513,7 @@ For the other games this is not a sufficient replacement for AI! Transfer Savegames - Передать сохранения + Перенести сохранения @@ -5552,7 +5588,7 @@ On Windows XP: Done - Готово + Готово @@ -5594,4 +5630,4 @@ On Windows XP: Скопировать все сохранения с персонажем "%1" в общее месторасположение? Имейте ввиду, что это запутает текущую нумерацию сохранений. - + \ No newline at end of file diff --git a/src/organizer_zh_CN.ts b/src/organizer_zh_CN.ts index 9b8754bb..ae964233 100644 --- a/src/organizer_zh_CN.ts +++ b/src/organizer_zh_CN.ts @@ -1,38 +1,36 @@ - - - + AboutDialog About - + 关于 Revision: - + 版本 Used Software - + 用到的软件 Credits - + 制作组 Translators - + 翻译机 Others - + 其它 @@ -42,7 +40,7 @@ No license - + 无授权 @@ -62,7 +60,7 @@ <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -160,22 +158,22 @@ If there is a component called "00 Core" it is usually required. Optio Some Page - + 某些页面 Search - + 搜索 new - + 新建 failed to start download - + 启动下载失败 @@ -226,7 +224,7 @@ If there is a component called "00 Core" it is usually required. Optio <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> @@ -289,7 +287,7 @@ p, li { white-space: pre-wrap; } Never ask again - 无法读取bsa + 不再过问 @@ -325,7 +323,7 @@ p, li { white-space: pre-wrap; } pending download - + 挂起下载 @@ -381,12 +379,12 @@ p, li { white-space: pre-wrap; } < mod %1 file %2 > - + < mod %1 file %2 > Pending - + 挂起 @@ -401,12 +399,12 @@ p, li { white-space: pre-wrap; } Fetching Info 2 - 抓取信息 2 + 抓取信息 2 Installed - 抓取信息 2 + 已安装 @@ -459,7 +457,7 @@ p, li { white-space: pre-wrap; } Delete - &删除 + 删除 @@ -517,22 +515,22 @@ p, li { white-space: pre-wrap; } < mod %1 file %2 > - + < mod %1 file %2 > Pending - + 挂起 Fetching Info 1 - 抓取信息 1 + 抓取信息 1 Fetching Info 2 - 抓取信息 2 + 抓取信息 2 @@ -638,7 +636,7 @@ p, li { white-space: pre-wrap; } Memory allocation error (in refreshing directory). - + 地址分配错误(刷新目录时). @@ -658,12 +656,12 @@ p, li { white-space: pre-wrap; } Wrong Game - + 错误的游戏 The download link is for a mod for "%1" but this instance of MO has been set up for "%2". - + @@ -708,7 +706,7 @@ p, li { white-space: pre-wrap; } No known download urls. Sorry, this download can't be resumed. - + 未知的下载地址。很抱歉,下载无法继续。 @@ -728,7 +726,7 @@ p, li { white-space: pre-wrap; } Update - 更新 + 更新 @@ -753,12 +751,12 @@ p, li { white-space: pre-wrap; } Memory allocation error (in processing progress event). - + 地址分配错误(处理程序事件时). Memory allocation error (in processing downloaded data). - + 地址分配错误(处理下载数据时). @@ -789,7 +787,7 @@ p, li { white-space: pre-wrap; } Download failed. Server reported: %1 - + 下载失败。服务器报告: %1 @@ -964,7 +962,7 @@ Right now the only case I know of where this needs to be overwritten is for the MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe from that installation as the binary. - + MO需要32位java来运行该应用程序。如果你已经安装,在安装目录下选择javaw.exe。 @@ -990,13 +988,13 @@ Right now the only case I know of where this needs to be overwritten is for the Save Changes? - 保存更改吗? + 保存修改? You made changes to the current executable, do you want to save them? - + 当前可执行文件被修改,是否需要保存? @@ -1136,7 +1134,7 @@ Right now the only case I know of where this needs to be overwritten is for the <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html> <!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"> @@ -1180,87 +1178,87 @@ p, li { white-space: pre-wrap; } - + Extracting files 正在解压文件 - + failed to create backup 创建备份失败。 - + Mod Name 模组名称 - + Name 名称 - + Invalid name 无效名称 - + The name you entered is invalid, please enter a different one. 你输入的名称无效,请重新输入。 - + File format "%1" not supported 暂不支持文件格式: "%1" - + None of the available installer plugins were able to handle that archive 没有可用的安装插件能够处理此压缩包 - + no error 没有错误 - + 7z.dll not found 未找到 7z.dll - + 7z.dll isn't valid 无效的 7z.dll - + archive not found 未找到压缩包 - + failed to open archive 无法打开压缩包 - + unsupported archive type 不支持的压缩包类型 - + internal library error 内部库错误 - + archive invalid 无效的压缩包 - + unknown archive error 未知压缩包错误 @@ -1301,7 +1299,7 @@ p, li { white-space: pre-wrap; } an error occured: %1 - 发生错误: %1 + 发生错误: %1 @@ -1320,27 +1318,27 @@ p, li { white-space: pre-wrap; } Click blank area to deselect - + 点击空白处取消选择 If checked, only mods that match all selected categories are displayed. - + 如果选中,仅匹配所有选定类别的 Mod 会被显示。 And - + If checked, all mods that match at least one of the selected categories are displayed. - + 如果选中,匹配任意一个选定类别的 Mod 会被显示。 Or - + @@ -1350,22 +1348,22 @@ p, li { white-space: pre-wrap; } Pick a module collection - 选择一个配置文件 + <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在这里创建配置文件,每个配置文件都包含了它们自己的 Mod 和 esp 的激活方案。这样您就可以通过快速切换设置来体验不同的游戏历程了。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">请注意: 当前您的配置文件的 esp 加载顺序并不是分开保存的。</span></p></body></html> + + + + + Open list options... + 打开选项列表... @@ -1376,13 +1374,13 @@ p, li { white-space: pre-wrap; } Restore Backup... - 还原备份 + 还原备份 Create Backup - + 创建备份 @@ -1397,7 +1395,7 @@ p, li { white-space: pre-wrap; } Filter - 过滤器 + 过滤器 @@ -1426,15 +1424,10 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">选择要运行的程序。一旦您开始使用 Mod Organizer,您应该始终从这里或通过在这里创建的快捷方式来运行您的游戏和工具,否则任何经由 MO 安装的 Mod 都会变得不可见。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">您可以添加新的工具到此列表中,但我不能保证一些我没有测试过的工具能够正常工作。</span></p></body></html> + @@ -1446,13 +1439,9 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在 Mod Organizer 启用的状态下运行指定的程序。</span></p></body></html> + @@ -1469,13 +1458,9 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">创建一个开始菜单快捷方式,使您可以直接在 MO 激活状态下运行指定的程序。</span></p></body></html> + @@ -1487,6 +1472,11 @@ p, li { white-space: pre-wrap; } Plugins 插件 + + + Sort + 排序 + List of available esp/esm files @@ -1497,43 +1487,29 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">这个列表中包含了位于已激活 Mod 里的 esp 和 esm 文件。这些文件都需要它们自己的加载顺序,您可以使用拖放来修改加载顺序。请注意: MO 将只保存已激活或已勾选状态的 Mod 的加载顺序。<br />有个非常棒的工具叫作 &quot;BOSS&quot;,它可以自动对这些文件进行排序。</span></p></body></html> - - - - Sort - - - - - Open list options... - + Archives - + 压缩包 <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>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html> - + <html><head/><body><p>使用 MO 管理压缩包 (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">查看更多</span></a>)</p></body></html> List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order. - 可用 BSA 文件的列表。未勾选的项目不会被 MO 管理并且会忽略安装顺序。 + 可用 BSA 压缩包的列表。未勾选的项目不会被 MO 管理并且会忽略安装顺序。 @@ -1541,10 +1517,7 @@ p, li { white-space: pre-wrap; } 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. - BSA 文件是 Bethesda 专用的压缩包文件 (区别于 .zip 文件),里面包含了游戏所用的 Data 内的文件 (meshes, textures 等)。这与 Data 目录里分散的文件是不同的。 -默认情况下,BSA 文件的名称取决于 ESP 插件的名称 (例: plugins.esp 对应 plugins.bsa)。游戏运行时,ESP 对应的 BSA 将会自动加载,并且比所有分散的文件优先级都高,左边您设置的安装顺序最终会被忽略掉。 - -这里勾选的 BSA 将会依从您的安装顺序,并且会自行调整加载顺序。 + @@ -1555,7 +1528,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye Data - Data + Data @@ -1569,8 +1542,8 @@ BSAs checked here are loaded in such a way that your installation order is obeye - - + + Refresh 刷新 @@ -1605,17 +1578,11 @@ BSAs checked here are loaded in such a way that your installation order is obeye <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html> - <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">这是此游戏所有存档的列表,将鼠标悬停在项目上来获取该存档的详细信息,里面包含了现在没有被激活但是当存档被创建时所使用的 esp 或 esm 的清单。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您在右键菜单中点击“修复 Mod”,那么 MO 便会尝试激活所有 Mod 和 esp 来修复那些缺失的 esp,它并不会禁用任何东西!</span></p></body></html> + @@ -1630,7 +1597,7 @@ p, li { white-space: pre-wrap; } Show Hidden - + 显示隐藏 @@ -1645,7 +1612,7 @@ p, li { white-space: pre-wrap; } Install &Mod - 安装 &Mod + 安装 &Mod @@ -1665,12 +1632,12 @@ p, li { white-space: pre-wrap; } &Profiles - &配置文件 + &配置文件 Configure Profiles - 设置配置文件 + 设置配置文件 @@ -1685,7 +1652,7 @@ p, li { white-space: pre-wrap; } &Executables - &可执行程序 + &可执行程序 @@ -1706,7 +1673,7 @@ p, li { white-space: pre-wrap; } &Tools - 工具(&T) + &工具 @@ -1721,12 +1688,12 @@ p, li { white-space: pre-wrap; } &Settings - &设置 + &设置 Configure settings and workarounds - 配置设定和解决方案 + 配置设定和解决方案 @@ -1750,9 +1717,9 @@ p, li { white-space: pre-wrap; } - + Update - 更新 + 更新 @@ -1763,7 +1730,7 @@ p, li { white-space: pre-wrap; } No Problems - 没有问题 + 没有问题 @@ -1794,19 +1761,19 @@ Right now this has very limited functionality - + Endorse Mod Organizer 称赞 Mod Organizer Copy Log to Clipboard - 复制到剪贴板 + 复制到剪贴板 Ctrl+C - Ctrl+M + Ctrl+C @@ -1826,7 +1793,7 @@ Right now this has very limited functionality Problems - 问题 + 问题 @@ -1836,17 +1803,17 @@ Right now this has very limited functionality Everything seems to be in order - 一切井然有序 + Help on UI - 界面帮助 + 界面帮助 Documentation Wiki - 说明文档 (维基) + 说明文档 (维基) @@ -1861,17 +1828,17 @@ Right now this has very limited functionality About - + About Qt - + 关于 Qt failed to save load order: %1 - 无法保存加载顺序: %1 + 无法保存加载顺序: %1 @@ -1886,7 +1853,7 @@ Right now this has very limited functionality failed to create profile: %1 - 无法创建配置文件: %1 + 无法创建配置文件: %1 @@ -1911,49 +1878,71 @@ Right now this has very limited functionality failed to read savegame: %1 - 无法读取存档: %1 + 无法读取存档: %1 Plugin "%1" failed: %2 - 插件 "%1" 失败: %2 + 插件 "%1" 失败: %2 Plugin "%1" failed - 插件 "%1" 失败 + 插件 "%1" 失败 + + + + Download? + 下载? + + + + A download has been started but no installed page plugin recognizes it. +If you download anyway no information (i.e. version) will be associated with the download. +Continue? + + + + + Browse Mod Page + failed to init plugin %1: %2 - 插件初始化失败 %1: %2 + 插件初始化失败 %1: %2 Plugin error - + 插件错误 It appears the plugin "%1" failed to load last startup and caused MO to crash. Do you want to disable it? (Please note: If this is the first time you see this message for this plugin you may want to give it another try. The plugin may be able to recover from the problem) - + Failed to start "%1" - 无法启动 "%1" + 无法启动 "%1" Waiting - 稍等 + 稍等 Please press OK once you're logged into steam. 当您登录 Steam 时请点击确定。 + + + Executable "%1" not found + 可执行程序 "%1" 未找到 + Start Steam? @@ -1965,912 +1954,888 @@ Right now this has very limited functionality 想要正确地启动游戏,Steam 必须处于运行状态。需要MO尝试启动 Steam 吗? - + Also in: <br> - 也在: <br> + 也在: <br> - + No conflict 没有冲突 - + <Edit...> - <编辑...> + <编辑...> - + + Failed to refresh list of esps: %1 + 无法刷新 esp 列表 : %1 + + + This bsa is enabled in the ini file so it may be required! 该 BSA 已在 ini 文件中启用,因此它可能是必需的。 - + Activating Network Proxy 激活网络代理 - - - Installation successful - 安装成功 - - - - - Configure Mod - 配置 Mod + + + Failed to write settings + 无法写入设置 - - - This mod contains ini tweaks. Do you want to configure them now? - 此 Mod 中包含 ini 设定文件,您想现在就对它们进行配置吗? + + + An error occured trying to write back MO settings: %1 + - - - mod "%1" not found - Mod "%1" 未找到 + + File is write protected + - - - Installation cancelled - 安装已取消 + + Invalid file format (probably a bug) + - - - The mod was not installed completely. - 该模组没有完全安装。 + + Unknown error %1 + 未知错误 %1 - + Some plugins could not be loaded 一些插件无法载入 - + Too many esps and esms enabled - + esp 和 esm 开启太多 - - + + Description missing - + 描述丢失 - + The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: - + - + The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + - + Choose Mod 选择模组 - + Mod Archive - Mod 压缩包 + + + + + + Installation successful + 安装成功 + + + + + Configure Mod + 配置 Mod + + + + + This mod contains ini tweaks. Do you want to configure them now? + 此 Mod 中包含 ini 设定文件,您想现在就对它们进行配置吗? + + + + + mod "%1" not found + Mod "%1" 未找到 - + + + Installation cancelled + 安装已取消 + + + + + The mod was not installed completely. + 该模组没有完全安装。 + + + Start Tutorial? 开始教程? - + You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue? 即将开始帮助教程。因为技术原因可能无法随时中断。是否继续? - - + + Download started 开始下载 - + failed to update mod list: %1 - 无法更新 Mod 列表: %1 + 无法更新 Mod 列表: %1 - + failed to spawn notepad.exe: %1 - 无法生成 notepad.exe: %1 + 无法生成 notepad.exe: %1 - + failed to open %1 - 无法打开 %1 + - + failed to change origin name: %1 - 无法更改原始文件名: %1 - - - - Executable "%1" not found - + 无法更改原始文件名: %1 - - Failed to refresh list of esps: %1 - + + failed to move "%1" from mod "%2" to "%3": %4 + 无法移动 "%1" 从 mod "%2" 到 "%3": %4 - - failed to move "%1" from mod "%2" to "%3": %4 - + + <Contains %1> + <Contains %1> - + <Checked> - <已勾选> + <Checked> - + <Unchecked> - <未勾选> + - + <Update> - <有更新> + - + + <Managed by MO> + + + + + <Managed outside MO> + + + + <No category> - <无类别> + - + <Conflicted> - <有冲突> + - + <Not Endorsed> - + - + failed to rename mod: %1 - 无法重命名 Mod: %1 + 无法重命名 Mod: %1 - + Overwrite? 覆盖 - + This will replace the existing mod "%1". Continue? - 这将会覆盖已存在的mod "%1"。是否继续? + 这将会覆盖已存在的mod "%1"。是否继续? - + failed to remove mod "%1" - 无法移动 Mod: %1 + 无法移动 mod %1 - - - + + + failed to rename "%1" to "%2" 重命名 "%1 "为 "%2" 时出错 - + Multiple esps activated, please check that they don't conflict. 多个esp已激活,请检查以确保不冲突。 - - - - + + + + Confirm 确认 - + Remove the following mods?<br><ul>%1</ul> - 是否删除下列mod?<br><ul>%1</ul> + 是否删除下列mod?<br><ul>%1</ul> - + failed to remove mod: %1 - 无法移动 Mod: %1 + 无法移动 Mod: %1 - - + + Failed - 失败 + 失败 - + Installation file no longer exists - 安装文件不复存在 + 安装文件不复存在 - + Mods installed with old versions of MO can't be reinstalled in this way. - 旧版 MO 安装的 Mod 无法使用此方法重新安装。 + 旧版 MO 安装的 Mod 无法使用此方法重新安装。 - - - You need to be logged in with Nexus to endorse + + You need to be logged in with Nexus to resume a download 你必须登录 Nexus 才能点“称赞” - - - Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. - - - - - - - Delete %n save(s) - - - - - - - Extract BSA - 解压 BSA - - - - failed to read %1: %2 - 无法读取 %1: %2 + + + You need to be logged in with Nexus to endorse + 你必须登录 Nexus 才能点“称赞” - - This archive contains invalid hashes. Some files may be broken. - 压缩包 Hash 值错误。部分文件可能已经损坏。 + + Failed to display overwrite dialog: %1 + 无法显示 overwrite 对话: %1 - + Nexus ID for this Mod is unknown 此模组的Nexus ID未知 - - Download? - 下载 - - - - A download has been started but no installed page plugin recognizes it. -If you download anyway no information (i.e. version) will be associated with the download. -Continue? - - - - - Browse Mod Page - - - - - - Failed to write settings - - - - - - An error occured trying to write back MO settings: %1 - - - - - File is write protected - - - - - Invalid file format (probably a bug) - - - - - Unknown error %1 - - - - - <Managed by MO> - - - - - <Managed outside MO> - - - - - You need to be logged in with Nexus to resume a download - 你必须登录 Nexus 才能点“称赞” - - - - Failed to display overwrite dialog: %1 - - - - - + + Create Mod... 创建Mod... - + This will move all files from overwrite into a new, regular mod. Please enter a name: - + 这会移动所有的 overwirite 文件成为一个新建的 mod。 +请输入名称: - + A mod with this name already exists 同名模组已存在。 - + Continue? - + 继续? - + The versioning scheme decides which version is considered newer than another. This function will guess the versioning scheme under the assumption that the installed version is outdated. - + - - + + Sorry - + 抱歉 - + I don't know a versioning scheme where %1 is newer than %2. - + - + Really enable all visible mods? 确定要启用全部可见的模组吗? - + Really disable all visible mods? 确定要禁用全部可见的模组吗? - + Choose what to export 选择要导出的内容 - + Everything - 全部 + 全部 - + All installed mods are included in the list - 所有包含在列表的已安装mod + 所有包含在列表的已安装mod - + Active Mods 激活模组 - + Only active (checked) mods from your current profile are included 仅包含当前配置文件中已激活(打勾)的mod - + Visible - 可见的 + 可见的 - + All mods visible in the mod list are included - 包含列表中所有可见的mod + 包含列表中所有可见的mod - + export failed: %1 - 导出失败: %1 + 导出失败: %1 - + Install Mod... 安装模组... - + Enable all visible 启用所有可见项目 - + Disable all visible 禁用所有可见项目 - + Check all for update 检查所有更新 - + Export to csv... 导出为 CSV... - + All Mods - + 所有模组 - + Sync to Mods... - 同步到 Mod... + 同步到模组... - + Restore Backup 还原备份 - + Remove Backup... - 还原备份... + 移除备份 - + Add/Remove Categories - + 添加/移除 类别 - + Replace Categories - + 更换类别 - + Primary Category 主分类 - + Change versioning scheme - + - + Un-ignore update - + - + Ignore update - + - + Rename Mod... 重命名模组... - + Remove Mod... 移除模组... - + Reinstall Mod 重新安装模组 - + Un-Endorse 取消称赞 - - + + Endorse 称赞 - + Won't endorse 不想称赞 - + Endorsement state unknown 称赞状态不明 - + Ignore missing data 忽略丢失的数据 - + Visit on Nexus 在Nexus上浏览 - + Open in explorer 在资源管理器中打开 - + Information... - 信息... + - - + + Exception: - 例外: + - - + + Unknown exception - 未知的例外 + - + <All> - <全部> + - + <Multiple> - XX + + + + + Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. + - + Please wait while LOOT is running - + - + Fix Mods... 修复模组... - - Delete - &删除 + + + Delete %n save(s) + - + failed to remove %1 - 无法删除 %1 + - - + + failed to create %1 - 无法创建 %1 + - + Can't change download directory while downloads are in progress! 下载文件时不能修改下载目录! - + Download failed 下载失败 - + failed to write to file %1 - 无法写入文件 %1 + - + %1 written - 已写入 %1 + - + Select binary - 选择可执行文件 + - + Binary 程序 - + Enter Name 输入名称 - + Please enter a name for the executable 请为该可执行程序输入一个名称 - + Not an executable - 不是可执行程序 + - + This is not a recognized executable. - 无法识别的可执行文件 + - - + + Replace file? - 替换文件? + - + There already is a hidden version of this file. Replace it? 已存在同名文件,但该文件被隐藏了。确定要覆盖吗? - - + + File operation failed 文件操作错误 - - + + Failed to remove "%1". Maybe you lack the required file permissions? 无法移除 "%1"。也许您需要足够的文件权限? - + There already is a visible version of this file. Replace it? 已存在同名文件。确定要覆盖吗? - + file not found: %1 - esp未找到:%1 + - + failed to generate preview for %1 - + - + Sorry, can't preview anything. This function currently does not support extracting from bsas. - + - + Update available 更新可用 - + Open/Execute 打开/执行 - + Add as Executable 添加为可执行文件 - + Preview - + - + Un-Hide 取消隐藏 - + Hide 隐藏 - + Write To File... - 写入文件... + - + Do you want to endorse Mod Organizer on %1 now? - 是否现在就在 %1 点赞支持 Mod Organizer? + - + Thank you! - + - + Thank you for your endorsement! - + - + Request to Nexus failed: %1 - 发往 Nexus 的请求失败: %1 + - - + + login successful 登录成功 - + login failed: %1. Trying to download anyway - 登录失败: %1,请尝试使用别的方法下载 + - + login failed: %1 无法登录: %1 - + login failed: %1. You need to log-in with Nexus to update MO. - 登录失败: %1。您需要登录到N网才能更新 MO + - + + + failed to read %1: %2 + + + + Error 错误 - + failed to extract %1 (errorcode %2) - 无法解压 %1 (错误代码 %2) + + + + + Extract BSA + 解压 BSA - + + This archive contains invalid hashes. Some files may be broken. + + + + Extract... 解压... - + Edit Categories... 编辑类别... - + Deselect filter - + - + Remove 移除 - + Enable all 全部启用 - + Disable all 全部禁用 - + Unlock load order 解锁加载顺序 - + Lock load order 锁定加载顺序 - + depends on missing "%1" - + - + incompatible with "%1" - + - + No profile set - + - + loot failed. Exit code was: %1 - + - + failed to start loot - + - + failed to run loot: %1 - + - + Errors occured - + - + Backup of load order created - + - + Choose backup to restore - + - + No Backups - + - + There are no backups to restore - + - - + + Restore failed - + - - + + Failed to restore the backup. Errorcode: %1 - + - + Backup of modlist created - + @@ -2885,8 +2850,63 @@ This function will guess the versioning scheme under the assumption that the ins ModInfo - - + + Plugins + + + + + Textures + + + + + Meshes + + + + + UI Changes + + + + + Music + + + + + Sound Effects + + + + + Scripts + + + + + SKSE Plugins + + + + + SkyProc Tools + + + + + Strings + + + + + invalid content type %1 + + + + + invalid index %1 无效的索引 %1 @@ -2894,7 +2914,7 @@ This function will guess the versioning scheme under the assumption that the ins ModInfoBackup - + This is the backup of a mod 这是模组的备份 @@ -2935,7 +2955,7 @@ This function will guess the versioning scheme under the assumption that the ins Ini Files - + @@ -2950,17 +2970,17 @@ This function will guess the versioning scheme under the assumption that the ins Ini Tweaks - + This is a list of ini tweaks (ini modifications that can be toggled). - + This is a list of ini tweaks. Ini Tweaks are (usually small) fragments of ini files that are applied over existing settings in skyrim.ini/skyrimprefs.ini. Each tweak can be toggled individually. You should check the description of the mod wether the tweaks are really optional. - + @@ -2985,7 +3005,7 @@ This function will guess the versioning scheme under the assumption that the ins This lists all the images (.jpg and .png) in the mod directory, like screenshots and such. Click one to get a larger view. - + @@ -3004,7 +3024,7 @@ This function will guess the versioning scheme under the assumption that the ins They usually contain optional functionality, see the readme. Most mods do not have optional esps, so chances are good you are looking at an empty list. - + @@ -3107,7 +3127,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html> <!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"> @@ -3120,7 +3140,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html> <!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"> @@ -3153,19 +3173,19 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - + Endorse - 称赞 + Notes - 笔记 + @@ -3182,7 +3202,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3208,264 +3228,264 @@ p, li { white-space: pre-wrap; } 关闭 - + &Delete &删除 - + &Rename &重命名 - + &Hide &隐藏 - + &Unhide &取消隐藏 - + &Open &打开 - + &New Folder &新建文件夹 - - + + Save changes? 保存更改吗? - - + + Save changes to "%1"? - 将更改保存到“%1”吗? + - + File Exists 文件已存在 - + A file with that name exists, please enter a new one 文件名已存在,请输入其它名称 - + failed to move file 无法移动文件 - + failed to create directory "optional" 无法创建 "optional" 目录 - - + + Info requested, please wait 请求信息已发出,请稍后 - + Main 主要文件 - + Update 更新 - + Optional 可选文件 - + Old 旧档 - + Misc 杂项 - + Unknown 未知 - + Current Version: %1 当前版本: %1 - + No update available 没有可用的更新 - + (description incomplete, please visit nexus) (描述信息不完整,请访问N网) - + <a href="%1">Visit on Nexus</a> <a href="%1">访问N网</a> - + Failed to delete %1 无法删除 %1 - - + + Confirm 确认 - + Are sure you want to delete "%1"? 确定要删除 "%1" 吗? - + Are sure you want to delete the selected files? 确定要删除所选的文件吗? - - + + New Folder 新建文件夹 - + Failed to create "%1" 无法创建 "%1" - - + + Replace file? 替换文件? - + There already is a hidden version of this file. Replace it? 已存在同名文件,但该文件被隐藏了。确定要覆盖吗? - - + + File operation failed 文件操作错误 - - + + Failed to remove "%1". Maybe you lack the required file permissions? 无法移除 "%1"。也许您需要足够的文件权限? - - + + failed to rename %1 to %2 无法重命名 %1 为 %2 - + There already is a visible version of this file. Replace it? 已存在同名文件。确定要覆盖吗? - + Un-Hide 取消隐藏 - + Hide 隐藏 - + Name 名称 - + Please enter a name - + - - + + Error 错误 - + Invalid name. Must be a valid file name - + - + A tweak by that name exists - + - + Create Tweak - + ModInfoForeign - + This pseudo mod represents content managed outside MO. It isn't modified by MO. - + ModInfoOverwrite - + This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit) - 此虚拟安装包内包含来自虚拟 Data 树的文件,但文件发生了变化 (例: 被CK修改了) + ModInfoRegular - - + + failed to write %1/meta.ini: error %2 - 无法写入 %1/meta.ini: %2 + - + %1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory - %1 中未包含 esp 或 esm 和有效的目录 (textures, meshes, interface, ...) + - + Categories: <br> - 种类: <br> + @@ -3473,52 +3493,52 @@ p, li { white-space: pre-wrap; } Game plugins (esp/esm) - + Interface - + Meshes - + Music - + Scripts (Papyrus) - + Script Extender Plugin - + SkyProc Patcher - + Sound - + Strings - + Textures - + @@ -3543,12 +3563,12 @@ p, li { white-space: pre-wrap; } Overwrites files - Overwrites文件 + Overwritten files - 覆盖的 Mod + @@ -3558,12 +3578,12 @@ p, li { white-space: pre-wrap; } Redundant - 冗余 + Non-MO - + @@ -3573,13 +3593,12 @@ p, li { white-space: pre-wrap; } installed version: "%1", newest version: "%2" - installed version: %1, newest version: %2 - 当前版本: %1,最新版本: %2 + The newest version on Nexus seems to be older than the one you have installed. This could either mean the version you have has been withdrawn (i.e. due to a bug) or the author uses a non-standard versioning scheme and that newest version is actually newer. Either way you may want to "upgrade". - + @@ -3594,7 +3613,7 @@ p, li { white-space: pre-wrap; } drag&drop failed: %1 - 拖拽失败: %1 + @@ -3609,12 +3628,12 @@ p, li { white-space: pre-wrap; } Flags - 标志 + Content - 内容 + @@ -3644,7 +3663,7 @@ p, li { white-space: pre-wrap; } Installation - 安装 + @@ -3680,17 +3699,17 @@ p, li { white-space: pre-wrap; } Emblemes to highlight things that might require attention. - 需要注意被标记为高亮的 + Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> - + Time this mod was installed - + @@ -3722,22 +3741,22 @@ p, li { white-space: pre-wrap; } NXMAccessManager - + Logging into Nexus - + - + timeout 超时 - + Unknown error - + - + Please check your password 请检查您的密码 @@ -3747,7 +3766,7 @@ p, li { white-space: pre-wrap; } Failed to guess mod id for "%1", please pick the correct one - 提取mod "%1"的ID编号失败,请自行选择正确项。 + @@ -3795,7 +3814,7 @@ p, li { white-space: pre-wrap; } %1 not found - 找不到 %1 + @@ -3833,116 +3852,116 @@ p, li { white-space: pre-wrap; } PluginList - + Name 名称 - + Priority 优先级 - + Mod Index Mod 索引 - + Flags - 标志 + - - + + unknown - 未知 + - + Name of your mods 你的mod名称 - + Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority. - + - + The modindex determins the formids of objects originating from this mods. - + - + failed to update esp info for file %1 (source id: %2), error: %3 - + - + esp not found: %1 - esp未找到:%1 + - - + + Confirm 确认 - + Really enable all plugins? - + - + Really disable all plugins? - + - + The file containing locked plugin indices is broken - + - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. 您的一些插件名称无效!这些插件无法被游戏载入。请查看 mo_interface.log 来确认那些受影响的插件并重命名它们。 - <b>Origin</b>: %1 - + This plugin can't be disabled (enforced by the game) + 这个插件不能被禁用 (由游戏执行) + <b>Origin</b>: %1 + + + + Author 作者 - + Description 描述 - - This plugin can't be disabled (enforced by the game) - 这个插件不能被禁用 (由游戏执行) - - - + Missing Masters - + - + Enabled Masters - + - + failed to restore load order for %1 - 恢复 %1 加载顺序失败 + @@ -3950,7 +3969,7 @@ p, li { white-space: pre-wrap; } Preview - + @@ -3963,16 +3982,16 @@ p, li { white-space: pre-wrap; } Problems - 问题 + <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - + @@ -3983,12 +4002,12 @@ p, li { white-space: pre-wrap; } Fix - 修复 + No guided fix - + @@ -3996,32 +4015,32 @@ p, li { white-space: pre-wrap; } invalid profile name %1 - + failed to create %1 - 无法创建 %1 + failed to write mod list: %1 - 无法更新 Mod 列表: %1 + failed to update tweaked ini file, wrong settings may be used: %1 - 更新tweaked ini文件失败,可能会应用错误的设置: %1 + failed to create tweaked ini: %1 - 创建 tweaked ini: %1 失败 + "%1" is missing or inaccessible - + @@ -4045,7 +4064,7 @@ p, li { white-space: pre-wrap; } failed to parse ini file (%1) - 无法解析 Ini 文件 (%1) + @@ -4056,7 +4075,7 @@ p, li { white-space: pre-wrap; } failed to modify "%1" - 未能找到 "%1" + @@ -4114,7 +4133,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html> @@ -4147,7 +4166,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4206,7 +4225,7 @@ p, li { white-space: pre-wrap; } Rename - &重命名 + @@ -4258,7 +4277,7 @@ p, li { white-space: pre-wrap; } Invalid profile name - + @@ -4268,17 +4287,17 @@ p, li { white-space: pre-wrap; } Are you sure you want to remove this profile (including local savegames if any)? - + Profile broken - + 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? - + @@ -4324,47 +4343,47 @@ p, li { white-space: pre-wrap; } invalid field name "%1" - 无效的名称 "%1" + invalid type for "%1" (should be integer) - 无效的类型 "%1" (应该是整数) + invalid type for "%1" (should be string) - 无效的类型 "%1" (应该是字符串) + invalid type for "%1" (should be float) - 无效的类型 "%1" (应该是浮点数) + no fields set up yet! - + field not set "%1" - + invalid character in field "%1" - + empty field name - + invalid game type %1 - + @@ -4448,62 +4467,62 @@ p, li { white-space: pre-wrap; } 无法设置代理DLL加载 - + Permissions required 需要权限 - + 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. - + - - + + Woops 糟糕 - + ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened - ModOrganizer已经崩溃。诊断文件是否已经产生?如果你将文件(%1)发送至 sherb@gmx.net ,这个bug有可能会被修复。最好加入崩溃发生时情况的简短说明(用英文吧)。 + - + ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1 Mod Organizer 崩溃了!遗憾的是,我无法生成诊断文件: %1 - + Mod Organizer Mod Organizer - + An instance of Mod Organizer is already running Mod Organizer 的一个实例正在运行 - + No game identified in "%1". The directory is required to contain the game binary and its launcher. "%1" 中未检测到游戏。请确保该路径中包含游戏执行程序以及对应的 Launcher 文件。 - - + + Please select the game to manage 请选择想要管理的游戏 - + Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!) - + - + failed to start application: %1 - + @@ -4511,28 +4530,28 @@ p, li { white-space: pre-wrap; } 请使用工具栏上的“帮助”来获得所有元素的使用说明 - - + + <Manage...> <管理...> - + failed to parse profile %1: %2 无法解析配置文件 %1: %2 - + failed to find "%1" 未能找到 "%1" - + failed to access %1 无法访问 %1 - + failed to set file time %1 无法设置文件时间 %1 @@ -4544,8 +4563,7 @@ p, li { white-space: pre-wrap; } "%1" is missing or inaccessible - "%1" is missing - + @@ -4558,6 +4576,11 @@ p, li { white-space: pre-wrap; } Error 错误 + + + failed to open temporary file + + @@ -4581,62 +4604,57 @@ p, li { white-space: pre-wrap; } 代理DLL - + failed to spawn "%1" 无法生成 "%1" - + Elevation required - + - + This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" can be installed to work without elevation. Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe to make changes to the system) - + - + failed to spawn "%1": %2 无法生成 "%1": %2 - + "%1" doesn't exist "%1" 不存在 - + failed to inject dll into "%1": %2 无法注入 dll 到 "%1": %2 - + failed to run "%1" 无法运行 "%1" - - - failed to open temporary file - - QueryOverwriteDialog Mod Exists - Mod 已存在 + This mod seems to be installed already. Do you want to add files from this archive (overwriting existing ones) or do you want to completely replace the existing files (old files are deleted)? Alternatively you can install this mod under a different name. - 这个mod看上去已经存在。你是希望将本次压缩包文件添加(覆盖已存在文件)或完全覆盖(旧的文件全删除)?另外你还可以起别的名称安装本mod。 + @@ -4651,17 +4669,17 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Replace - 替换 + Rename - &重命名 + Cancel - 取消 + @@ -4669,27 +4687,27 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Save # - + Character - + Level - 等级 + Location - 位置 + Date - 时间 + @@ -4697,7 +4715,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Missing ESPs - 缺失的 ESP + @@ -4705,7 +4723,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Dialog - 对话框 + @@ -4730,12 +4748,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Text Files - 文本文件 + failed to open "%1" for writing - + @@ -4761,7 +4779,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe archive.dll not loaded: "%1" - archive.dll 没有载入: "%1" + @@ -4799,7 +4817,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe failed to move outdated files: %1. Please update manually. - 移除过时文件失败: %1。请手动更新 + @@ -4824,7 +4842,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe no file for update found. Please update manually. - 没有发现可更新。请手动更新。 + @@ -4842,18 +4860,18 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Failed - 失败 + Sorry, failed to start the helper application - + attempt to store setting for unknown plugin "%1" - + @@ -4893,7 +4911,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html> <!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"> @@ -4904,12 +4922,12 @@ p, li { white-space: pre-wrap; } Style - + graphical style - 界面样式 + @@ -4919,23 +4937,23 @@ p, li { white-space: pre-wrap; } Log Level - + Decides the amount of data printed to "ModOrganizer.log" - + Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty. - + Debug - + @@ -4986,37 +5004,37 @@ p, li { white-space: pre-wrap; } User interface - + If checked, the download interface will be more compact. - + Compact Download Interface - + If checked, the download list will display meta information instead of file names. - + Download Meta Information - + Reset stored information from dialogs. - 重设对话框信息。 + This will make all dialogs show up again where you checked the "Remember selection"-box. - 全部对话框将全部重新显示,包括你已勾取过“记住选择”的对话框。 + @@ -5050,7 +5068,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html> <!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"> @@ -5061,7 +5079,7 @@ 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. - 勾取并在下面输入正确账户,将自动登录Nexus (浏览和下载)。 + @@ -5086,7 +5104,7 @@ p, li { white-space: pre-wrap; } 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) - 取消自动联网功能。这并不影响用户调用功能(如检查mod更新,点赞支持mod,打开网页浏览)。 + @@ -5101,7 +5119,7 @@ p, li { white-space: pre-wrap; } 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. - + @@ -5111,12 +5129,12 @@ p, li { white-space: pre-wrap; } Associate with "Download with manager" links - + Known Servers (updated on download) - + @@ -5146,17 +5164,17 @@ p, li { white-space: pre-wrap; } Key - 关键 + Value - + Blacklisted Plugins (use <del> to remove): - + @@ -5178,7 +5196,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5216,10 +5234,10 @@ p, li { white-space: pre-wrap; } 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. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam. - + @@ -5234,8 +5252,8 @@ If you use the Steam version of Oblivion the default will NOT work. In this case 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. +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. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again. Mod Organizer 使用了一个N网所提供的 API 来进行类似于检查更新和下载文件这样的操作。遗憾的是这个 API 并没有给第三方工具 (比如 MO) 正式的授权,所以我们需要模拟 NMM 来进行这些操作。 @@ -5251,7 +5269,7 @@ tl;dr-version: If Nexus-features don't work, insert the current version num - It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + 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. 看来,游戏偶尔会加载一些没有被激活成插件的 ESP 或 ESM 文件。 我还尚不知道它在什么情况下会这样,但是有用户报告说它在某些情况下是很不必要的。如果这个选项被选中,那么在列表中没有被勾选的 ESP 和 ESM 将不会在游戏中出现,并且也不会被载入。 @@ -5264,36 +5282,36 @@ I don't yet know what the circumstances are, but user reports imply it is i 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. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature. - + Display mods installed outside MO - + @@ -5311,7 +5329,7 @@ For the other games this is not a sufficient replacement for AI! These are workarounds for problems with Mod Organizer. Please make sure you read the help text before changing anything here. - + @@ -5388,7 +5406,7 @@ For the other games this is not a sufficient replacement for AI! failed to communicate with running instance: %1 - 无法连接到正在运行的实例: %1 + @@ -5434,17 +5452,17 @@ For the other games this is not a sufficient replacement for AI! Transfer Savegames - 转移存档 + Global Characters - + This is a list of characters in the global location. - 这里是全局位置存档角色列表。 + @@ -5456,7 +5474,7 @@ On Windows Vista/Windows 7: On Windows XP: C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves - + @@ -5469,7 +5487,7 @@ On Windows XP: C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves - + @@ -5499,17 +5517,17 @@ On Windows XP: Profile Characters - 配置文件中角色 + Overwrite - 覆盖 + Overwrite the file "%1" - 覆盖文件 "%1" + @@ -5523,17 +5541,17 @@ On Windows XP: Copy all save games of character "%1" to the profile? - 是否复制角色 "%1" 的所有游戏存档到这个配置中? + Move all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games. - 是否移动角色 "%1" 的所有游戏存档到全局路径?请注意这将使游戏存档的运行编号变得混乱。 + Copy all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games. - 是否拷贝角色 "%1" 的所有游戏存档到全局路径?请注意这将使游戏存档的运行编号变得混乱。 + - + \ No newline at end of file diff --git a/src/organizer_zh_TW.ts b/src/organizer_zh_TW.ts index 00cb02ae..08c9ed2e 100644 --- a/src/organizer_zh_TW.ts +++ b/src/organizer_zh_TW.ts @@ -1,38 +1,36 @@ - - - + AboutDialog About - + 關於 Revision: - + 版本: Used Software - + 使用的軟體 Credits - + 歸功於 Translators - + 翻譯者 Others - + 其他 @@ -42,7 +40,7 @@ No license - + @@ -50,19 +48,19 @@ Activate Mods - 激活 Mod + 啟動 Mod This is a list of esps and esms that were active when the save game was created. - 這是 esp 和 esm 檔案的列表,當您的存檔被建立時將會被激活。 + 這是 esp 和 esm 檔案的列表,當您的存檔被建立時將會被啟動。 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -71,11 +69,11 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是 esp 和 esm 檔案的列表,當您的存檔被建立時將會被激活。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是 esp 和 esm 檔案的列表,當您的存檔被建立時將會被啟動。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">對於每個 esp,右列中包含了可以通過啟用來使缺失的 esp 或 esm 變得可用的 Mod。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您點擊確定,那麼所有在右列中已選的並且可用的 Mod 和缺失的 esp 都將會被激活。</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您點擊確定,那麼所有在右列中已選的並且可用的 Mod 和缺失的 esp 都將會被啟動。</span></p></body></html> @@ -160,22 +158,22 @@ If there is a component called "00 Core" it is usually required. Optio Some Page - + Search - + 搜尋 new - + failed to start download - + 下載失敗 @@ -226,7 +224,7 @@ If there is a component called "00 Core" it is usually required. Optio <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> @@ -315,7 +313,7 @@ p, li { white-space: pre-wrap; } Done - 完成 + 完成 @@ -325,7 +323,7 @@ p, li { white-space: pre-wrap; } pending download - + 等待中的下載 @@ -334,7 +332,7 @@ p, li { white-space: pre-wrap; } Placeholder - 占位符 + 預留位置 @@ -347,7 +345,7 @@ p, li { white-space: pre-wrap; } Paused - Double Click to resume - + 暫停 - 雙擊以回復 @@ -359,7 +357,7 @@ p, li { white-space: pre-wrap; } Uninstalled - Double Click to re-install - 已安裝 - 雙擊重新安裝 + 解除安裝 - 雙擊重新安裝 @@ -368,7 +366,7 @@ p, li { white-space: pre-wrap; } Placeholder - 占位符 + 預留位置 @@ -381,27 +379,27 @@ p, li { white-space: pre-wrap; } < mod %1 file %2 > - + Pending - + 等待 Paused - 暫停 + 暫停 Fetching Info 1 - + Fetching Info 2 - + @@ -411,7 +409,7 @@ p, li { white-space: pre-wrap; } Uninstalled - + 已解除安裝 @@ -439,12 +437,12 @@ p, li { white-space: pre-wrap; } This will permanently remove all finished downloads from this list (but NOT from disk). - + 這將會從列表中永久移除所有已完成的下載(但不會從硬碟中移除)。 This will permanently remove all installed downloads from this list (but NOT from disk). - + 這將會從列表中永久移除所有已安裝的下載(但不會從硬碟中移除)。 @@ -459,17 +457,17 @@ p, li { white-space: pre-wrap; } Delete - &刪除 + 刪除 Un-Hide - 取消隱藏 + 取消隱藏 Remove from View - + @@ -494,12 +492,12 @@ p, li { white-space: pre-wrap; } Delete Installed... - 移除已安裝的項目... + 刪除已安裝的項目... Delete All... - + 刪除所有... @@ -517,22 +515,22 @@ p, li { white-space: pre-wrap; } < mod %1 file %2 > - + Pending - + 等待 Fetching Info 1 - + Fetching Info 2 - + @@ -555,12 +553,12 @@ p, li { white-space: pre-wrap; } This will remove all finished downloads from this list (but NOT from disk). - 這將會從列表和磁碟中移除所有已完成的下載。 + 這將會從列表中移除所有已完成的下載(但不會從硬碟中移除)。 This will remove all installed downloads from this list (but NOT from disk). - 這將會從列表和磁碟中移除所有已安裝的下載項目。 + 這將會從列表中移除所有已安裝的下載(但不會從硬碟中移除)。 @@ -575,17 +573,17 @@ p, li { white-space: pre-wrap; } Delete - &刪除 + 刪除 Un-Hide - 取消隱藏 + 取消隱藏 Remove from View - + @@ -610,12 +608,12 @@ p, li { white-space: pre-wrap; } Delete Installed... - 移除已安裝的項目... + 刪除已安裝的項目... Delete All... - + 刪除所有... @@ -638,7 +636,7 @@ p, li { white-space: pre-wrap; } Memory allocation error (in refreshing directory). - + 記憶體分配錯誤(於重新整理目錄時)。 @@ -658,12 +656,12 @@ p, li { white-space: pre-wrap; } Wrong Game - + The download link is for a mod for "%1" but this instance of MO has been set up for "%2". - + @@ -708,7 +706,7 @@ p, li { white-space: pre-wrap; } No known download urls. Sorry, this download can't be resumed. - + 沒有已知的下載url。抱歉,無法回復這個下載。 @@ -728,7 +726,7 @@ p, li { white-space: pre-wrap; } Update - 更新 + 更新 @@ -753,12 +751,12 @@ p, li { white-space: pre-wrap; } Memory allocation error (in processing progress event). - + 記憶體分配錯誤(於處理程序時)。 Memory allocation error (in processing downloaded data). - + 記憶體分配錯誤(於處理已下載資料時)。 @@ -789,7 +787,7 @@ p, li { white-space: pre-wrap; } Download failed. Server reported: %1 - + 下載失敗。伺服器回報: %1 @@ -959,12 +957,12 @@ Right now the only case I know of where this needs to be overwritten is for the Java (32-bit) required - + 需要Java (32位元) MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe from that installation as the binary. - + MO需要32位元java來執行這個程式。如果你已經安裝了,選擇那個安裝下的binary中的javaw.exe。 @@ -990,13 +988,13 @@ Right now the only case I know of where this needs to be overwritten is for the Save Changes? - 儲存更改嗎? + 儲存修改? You made changes to the current executable, do you want to save them? - + 你對現在的可執行檔案做出了改變,你想要保存它們嗎? @@ -1104,7 +1102,7 @@ Right now the only case I know of where this needs to be overwritten is for the New Mod - 新增 + 新增 Mod @@ -1136,7 +1134,7 @@ Right now the only case I know of where this needs to be overwritten is for the <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html> <!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"> @@ -1147,17 +1145,17 @@ p, li { white-space: pre-wrap; } Placeholder - 占位符 + 預留位置 OK - 確定 + 確定 Cancel - 取消 + 取消 @@ -1165,7 +1163,7 @@ p, li { white-space: pre-wrap; } archive.dll not loaded: "%1" - + archive.dll 並未載入: "%1" @@ -1180,87 +1178,87 @@ p, li { white-space: pre-wrap; } - + Extracting files 正在解壓檔案 - + failed to create backup - + 產生備份失敗 - + Mod Name - + Mod 名稱 - + Name - 名稱 + 名稱 - + Invalid name - + 無效的名稱 - + The name you entered is invalid, please enter a different one. - + 你輸入的名稱是無效的,請輸入不同的名稱。 - + File format "%1" not supported 暫不支持檔案格式: "%1" - + None of the available installer plugins were able to handle that archive - + 沒有任何可用的安裝插件能夠處理那個壓縮檔 - + no error 沒有錯誤 - + 7z.dll not found 未找到 7z.dll - + 7z.dll isn't valid 無效的 7z.dll - + archive not found 未找到壓縮包 - + failed to open archive 無法開啟壓縮包 - + unsupported archive type 不支持的壓縮包類型 - + internal library error 內部庫錯誤 - + archive invalid 無效的壓縮包 - + unknown archive error 未知壓縮包錯誤 @@ -1301,12 +1299,12 @@ p, li { white-space: pre-wrap; } an error occured: %1 - 發生錯誤: %1 + 發生錯誤: %1 an error occured - 發生錯誤 + 發生錯誤 @@ -1320,89 +1318,94 @@ p, li { white-space: pre-wrap; } Click blank area to deselect - + 點擊空白區域以取消選擇 If checked, only mods that match all selected categories are displayed. - + 如果打勾,符合所有選擇的類別的mod會被顯示。 And - + 以及 If checked, all mods that match at least one of the selected categories are displayed. - + 如果打勾,符合至少一項選擇的類別的mod會被顯示。 Or - + 或者 Profile - 配置檔案 + 配置檔案 Pick a module collection - 選擇一個配置檔案 + 選擇一個配置檔案 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!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; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在這裡建立配置檔案,每個配置檔案都包含了它們自己的 Mod 和 esp 的激活方案。這樣您就可以通過快速切換設定來體驗不同的遊戲歷程了。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">請注意: 當前您的配置檔案的 esp 加載順序並不是分開儲存的。</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在這裡建立配置檔案,每個配置檔案都包含了它們自己的 Mod 和 esp 的啟動方案。這樣您就可以通過快速切換設定來體驗不同的遊戲歷程了。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">請注意: 當前您的配置檔案的 esp 載入順序並不是分開儲存的。</span></p></body></html> + + + + Open list options... + 打開名單選項... Refresh list. This is usually not necessary unless you modified data outside the program. - 重新整理列表,這通常不是必須的,除非您在程式之外修改了檔案的數據。 + 重新整理列表,除非您在程式之外修改了檔案的資料,否則這通常是不必要的。 Restore Backup... - + 回復備份... Create Backup - + 產生備份 List of available mods. - + 可用 Mod 名單 This is a list of installed mods. Use the checkboxes to activate/deactivate mods and drag & drop mods to change their "installation" orders. - + 這是已安裝的 Mod 名單。使用複選框來啟動/關閉 Mod 並拖曳 Mod 來改變它們的"安裝"順序。 Filter - 過濾器 + 篩選 No groups - + 無群組 @@ -1414,126 +1417,121 @@ p, li { white-space: pre-wrap; } Namefilter - + Pick a program to run. - 選擇要運行的程式。 + 選擇要執行的程式。 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!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; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">選擇要運行的程式。一旦您開始使用 Mod Organizer,您應該始終從這裡或通過在這裡建立的捷徑來運行您的遊戲和工具,否則任何經由 MO 安裝的 Mod 都會變得不可見。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">您可以添加新的工具到此列表中,但我不能保證一些我沒有測試過的工具能够正常工作。</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">選擇要執行的程式。一旦您開始使用 Mod Organizer,您應該始終從這裡或通過在這裡建立的捷徑來運行您的遊戲和工具,否則任何經由 MO 安裝的 Mod 都會變得不可見。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">您可以添加新的工具到此列表中,但我不能保證一些我沒有測試過的工具能夠正常工作。</span></p></body></html> Run program - 運行程式 + 執行程式 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!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; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在 Mod Organizer 啟用的狀態下運行指定的程式。</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在 Mod Organizer 啟用的狀態下執行指定的程式。</span></p></body></html> Run - 運行 + 執行 Create a shortcut in your start menu or on the desktop to the specified program - + 為特定的程式在開始功能列或桌面上產生一個捷徑 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!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; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">建立一個開始菜單捷徑,使您可以直接在 MO 激活狀態下運行指定的程式。</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">建立一個開始功能列捷徑,使您可以直接在 MO 啟動狀態下執行指定的程式。</span></p></body></html> Shortcut - + 捷徑 Plugins - + 插件 + + + + Sort + 排序 List of available esp/esm files - 可用 esp 或 esm 檔案的列表 + 可用 esp/esm 檔案名單 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!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; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這個列表中包含了位于已激活 Mod 裡的 esp 和 esm 檔案。這些檔案都需要它們自己的加載順序,您可以使用拖放來修改加載順序。請注意: MO 將只儲存已激活或已勾選狀態的 Mod 的加載順序。<br />有個非常棒的工具叫作 &quot;BOSS&quot;,它可以自動對這些檔案進行排序。</span></p></body></html> - - - - Sort - - - - - Open list options... - +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這個列表中包含了位於已啟動 Mod 裡的 esp 和 esm 檔案。這些檔案都需要它們自己的載入順序,您可以拖曳來修改載入順序。請注意: MO 將只儲存已啟動或已勾選狀態的 Mod 的載入順序。<br />有個非常棒的工具叫作 "BOSS",它可以自動對這些檔案進行排序。</span></p></body></html> Archives - + 壓縮包 <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>BSA 檔案是遊戲資源的包裹(材質、腳本......)。預設情況下,遊戲引擎自分散的檔案中分別載入這些包裹。MO 可以透過分散的檔案來管理這些壓縮包以調整它們的載入順序:</p><p>如果壓縮包<span style=" font-weight:600;">有被管理</span>,它們的載入順序是被對應的 Mod(左側的面板)決定其優先程度,分散的檔案也是如此。您可以手動啟用任何沒有對應插件於啟動狀態的 BSA 檔案。<br/></p><p>如果壓縮包 <span style=" font-weight:600;">沒有被管理</span>,它們的載入順序是被對應的插件(右側的面板,插件選項)決定其優先程度。您就不可以手動啟用沒有插件於啟動狀態的 BSA 檔案。</p><p>在兩種狀況下您都不可以關閉有對應插件的壓縮包,遊戲仍然會載入它們。</p></body></html> <html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html> - + List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order. - 可用 BSA 檔案的列表。未勾選的項目不會被 MO 管理並且會忽略安裝順序。 + 可用 BSA 檔案的列表。未勾選的項目不會被 MO 管理並且會忽略安裝順序。 @@ -1541,229 +1539,229 @@ p, li { white-space: pre-wrap; } 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. - BSA 檔案是 Bethesda 專用的壓縮包檔案 (區別於 .zip 檔案),裡面包含了遊戲所用的 Data 內的檔案 (meshes, textures 等)。這與 Data 目錄裡分散的檔案是不同的。 + BSA 檔案是 Bethesda 專用的壓縮包檔案 (區別於 .zip 檔案),裡面包含了遊戲所用的 Data 內的檔案 (meshes, textures 等)。這與 Data 目錄裡分散的檔案是不同的。 默認情況下,BSA 檔案的名稱取決於 ESP 插件的名稱 (例: plugins.esp 對應 plugins.bsa)。遊戲運行時,ESP 對應的 BSA 將會自動加載,並且比所有分散的檔案優先級都高,左邊您設定的安裝順序最終會被忽略掉。 -這裡勾選的 BSA 將會依從您的安裝順序,並且會自行調整加載順序。 +這裡勾選的 BSA 將會依從您的安裝順序,並且會自行調整載入順序。 File - 檔案 + 檔案 Data - Data + 資料 refresh data-directory overview - 重新整理 Data 目錄總覽 + 重新整理 Data 目錄總覽 Refresh the overview. This may take a moment. - 重新整理總覽,這可能需要一些時間。 + 重新整理總覽,這可能需要一些時間。 - - + + Refresh - 重新整理 + 重新整理 This is an overview of your data directory as visible to the game (and tools). - 這是在遊戲中可見的 Data 目錄 (和工具) 的總覽。 + 這是在遊戲中可見的 Data 目錄 (和工具) 的總覽。 Mod - Mod + Mod Filter the above list so that only conflicts are displayed. - 過濾上面的列表,使您只能看到有衝突的檔案。 + 篩選上面的列表,使您只能看到有衝突的檔案。 Show only conflicts - 只顯示衝突 + 只顯示衝突 Saves - 存檔 + 存檔 <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!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; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是此遊戲所有存檔的列表,將滑鼠懸停在項目上來獲取該存檔的詳細信息,裡面包含了現在沒有被激活但是當存檔被建立時所使用的 esp 或 esm 的清單。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是此遊戲所有存檔的列表,將滑鼠懸停在項目上來獲取該存檔的詳細信息,裡面包含了現在沒有被啟動但是當存檔被建立時所使用的 esp 或 esm 的清單。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您在右鍵菜單中點擊“修復 Mod”,那麼 MO 便會嘗試激活所有 Mod 和 esp 來修復那些缺失的 esp,它並不會禁用任何東西!</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您在右鍵選項中點擊“修復 Mod”,那麼 MO 便會嘗試啟動所有 Mod 和 esp 來修復那些缺失的 esp,它並不會禁用任何東西!</span></p></body></html> Downloads - 下載 + 下載 This is a list of mods you downloaded from Nexus. Double click one to install it. - 這是當前已下載的 Mod 的列表,雙擊進行安裝。 + 這是自N網下載的 Mod 的列表,雙擊進行安裝。 Show Hidden - + 顯示隱藏 Tool Bar - 工具欄 + 工具欄 Install Mod - 安裝 Mod + 安裝 Mod Install &Mod - 安裝 &Mod + 安裝 &Mod Install a new mod from an archive - 通過壓縮包來安裝一個新 Mod + 通過壓縮包來安裝一個新 Mod Ctrl+M - Ctrl+M + Ctrl+M Profiles - 配置檔案 + 配置檔案 &Profiles - &配置檔案 + &配置檔案 Configure Profiles - 設定配置檔案 + 設定配置檔案 Ctrl+P - Ctrl+P + Ctrl+P Executables - 可執行程式 + 可執行程式 &Executables - &可執行程式 + &可執行程式 Configure the executables that can be started through Mod Organizer - 配置可通過 MO 來啟動的程式 + 配置可透過 Mod Organizer 來啟動的程式 Ctrl+E - Ctrl+E + Ctrl+E Tools - + 工具 &Tools - + &工具 Ctrl+I - Ctrl+I + Ctrl+I Settings - 設定 + 設定 &Settings - &設定 + &設定 Configure settings and workarounds - 配置設定和解決方案 + 配置設定和解決方案 Ctrl+S - Ctrl+S + Ctrl+S Nexus - N網 + N網 Search nexus network for more mods - 搜尋N網以獲取更多 Mod + 搜尋N網以獲取更多 Mod Ctrl+N - Ctrl+N + Ctrl+N - + Update - 更新 + 更新 Mod Organizer is up-to-date - Mod Organizer 現在是最新版本 + Mod Organizer 現在是最新版本 No Problems - 沒有問題 + 沒有問題 @@ -1771,7 +1769,7 @@ p, li { white-space: pre-wrap; } !Work in progress! Right now this has very limited functionality - 如果 MO 檢測到您的安裝中存在潛在的問題,那麼此按鈕將會高亮顯示,同時 MO 也會給您相應的修復提示。 + 如果 MO 檢測到您的安裝中存在潛在的問題,那麼此按鈕將會高亮顯示,同時 MO 也會給您相應的修復提示。 !此功能尚未完善! 當前此功能所能提供的項目非常有限 @@ -1780,103 +1778,103 @@ Right now this has very limited functionality Help - 幫助 + 幫助 Ctrl+H - Ctrl+M + Ctrl+M Endorse MO - + 贊同 MO - + Endorse Mod Organizer - + 贊同 Mod Organizer Copy Log to Clipboard - + 複製紀錄到剪貼簿上 Ctrl+C - Ctrl+M + Ctrl+C Toolbar - 工具欄 + 工具欄 Desktop - + 桌面 Start Menu - + 開始功能列 Problems - 問題 + 問題 There are potential problems with your setup - 您的安裝中存在潛在的問題 + 您的安裝中存在潛在的問題 Everything seems to be in order - 一切井然有序 + 一切看來井然有序 Help on UI - 介面幫助 + 使用者介面幫助 Documentation Wiki - 說明文檔 (維基) + 說明文檔 (Wiki) Report Issue - 報告問題 + 回報問題 Tutorials - + 教學 About - + 關於 About Qt - + 關於 Qt failed to save load order: %1 - 無法儲存加載順序: %1 + 儲存加載順序失敗: %1 Name - 名稱 + 名稱 @@ -1886,991 +1884,990 @@ Right now this has very limited functionality failed to create profile: %1 - 無法建立配置檔案: %1 + 建立配置檔案失敗: %1 Show tutorial? - + 顯示教學? You are starting Mod Organizer for the first time. Do you want to show a tutorial of its basic features? If you choose no you can always start the tutorial from the "Help"-menu. - + 您正第一次啟動 Mod Organizer。您想要顯示其基本功能的教學嗎?如果你選擇不要,您仍然可以自"幫助"選單開啟教學。 Downloads in progress - 正在下載 + 正在下載 There are still downloads in progress, do you really want to quit? - 仍有正在進行中的下載,您確定要退出嗎? + 仍有正在進行中的下載,您確定要退出嗎? failed to read savegame: %1 - 無法讀取存檔: %1 + 讀取存檔失敗: %1 Plugin "%1" failed: %2 - + 插件 "%1" 無效: %2 Plugin "%1" failed - + 插件 "%1" 無效 + + + + Download? + 下載? + + + + A download has been started but no installed page plugin recognizes it. +If you download anyway no information (i.e. version) will be associated with the download. +Continue? + + + + + Browse Mod Page + 瀏覽 Mod 頁面 failed to init plugin %1: %2 - + 初始化插件 %1 失敗: %2 Plugin error - + 插件錯誤 It appears the plugin "%1" failed to load last startup and caused MO to crash. Do you want to disable it? (Please note: If this is the first time you see this message for this plugin you may want to give it another try. The plugin may be able to recover from the problem) - + 插件 "%1" 在開始時載入失敗並導致 MO 崩潰。您想要關閉它嗎? +(請注意:如果這是您第一次看到有關這個插件的訊息,您最好再讓它試一次。這個插件可能有辦法自問題中修復。) Failed to start "%1" - 無法啟動 "%1" + 啟動 "%1" 失敗 Waiting - 稍等 + 稍等 Please press OK once you're logged into steam. - 當您登入 Steam 時請點擊確定。 + 當您登入 Steam 後請點擊確定。 + + + + Executable "%1" not found + 找不到可執行程式 "%1" Start Steam? - 啟動 Steam? + 啟動 Steam? Steam is required to be running already to correctly start the game. Should MO try to start steam now? - 想要正確地啟動遊戲,Steam 必須處於運行狀態,MO 要立即啟動 Steam 嗎? + Steam 必須處於運行狀態以正確地啟動遊戲,MO 要立即啟動 Steam 嗎? - + Also in: <br> - 也在: <br> + 也在: <br> - + No conflict - 沒有衝突 + 沒有衝突 - + <Edit...> - <編輯...> + <編輯...> - - This bsa is enabled in the ini file so it may be required! - 該 BSA 已在 Ini 檔案中啟用,因此它可能是必需的。 + + Failed to refresh list of esps: %1 + 重新整理 esp 列表失敗: %1 - - Activating Network Proxy - + + This bsa is enabled in the ini file so it may be required! + 該 BSA 已在 Ini 檔案中啟用,因此它可能是必需的。 - - - Installation successful - 安裝成功 + + Activating Network Proxy + - - - Configure Mod - 配置 Mod + + + Failed to write settings + 寫入設定失敗 - - - This mod contains ini tweaks. Do you want to configure them now? - 此 Mod 中包含 Ini 設定檔案,您想現在就對它們進行配置嗎? + + + An error occured trying to write back MO settings: %1 + - - - mod "%1" not found - Mod "%1" 未找到 + + File is write protected + 檔案是唯獨的狀態 - - - Installation cancelled - 安裝已取消 + + Invalid file format (probably a bug) + 無效的檔案格式 (可能是 bug) - - - The mod was not installed completely. - Mod 沒有完全安裝。 + + Unknown error %1 + 未知錯誤 %1 - + Some plugins could not be loaded - + 有些插件無法被載入 - + Too many esps and esms enabled - + 過多的 esp 和 esm 啟動 - - + + Description missing - + 描述遺失 - + The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: - + 以下的插件無法被載入。原因可能是因為遺失了它的依存檔案(例如 python)或是過期的版本: - + The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + 遊戲不允許超過 255 個啟動的插件(包括正式的)被載入。您必須關閉一些未使用的插件或是合併一些插件。您可以在此找到導覽:<a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a> - + Choose Mod - 選擇 Mod + 選擇 Mod - + Mod Archive - Mod 壓縮包 + Mod 壓縮包 + + + + + Installation successful + 安裝成功 + + + + + Configure Mod + 配置 Mod + + + + + This mod contains ini tweaks. Do you want to configure them now? + 此 Mod 中包含 ini 設定檔案,您想現在就對它們進行配置嗎? + + + + + mod "%1" not found + Mod "%1" 未找到 + + + + + Installation cancelled + 安裝已取消 + + + + + The mod was not installed completely. + Mod 沒有完全安裝。 - + Start Tutorial? - + 開始教學? - + You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue? - + 您即將開始教學。因為技術上的原因所已無法提前結束教學。繼續? - - + + Download started - 開始下載 + 開始下載 - + failed to update mod list: %1 - 無法更新 Mod 列表: %1 + 更新 Mod 列表失敗: %1 - + failed to spawn notepad.exe: %1 - 無法生成 notepad.exe: %1 + 生成 notepad.exe 失敗: %1 - + failed to open %1 - 無法開啟 %1 + 開啟 %1 失敗 - + failed to change origin name: %1 - 無法更改原始檔案名: %1 + 更改原始檔名失敗: %1 - - Executable "%1" not found - - - - - Failed to refresh list of esps: %1 - + + failed to move "%1" from mod "%2" to "%3": %4 + 自 Mod "%2" 移動 "%1" 到 Mod "%3" 失敗: %4 - - failed to move "%1" from mod "%2" to "%3": %4 - + + <Contains %1> + - + <Checked> - <已勾選> + <已勾選> - + <Unchecked> - <未勾選> + <未勾選> - + <Update> - <有更新> + <有更新> + + + + <Managed by MO> + <由 MO 管理> - + + <Managed outside MO> + <非由 MO 管理> + + + <No category> - <無類別> + <無類別> - + <Conflicted> - + <有衝突> - + <Not Endorsed> - + <尚未贊同> - + failed to rename mod: %1 - 無法重新命名 Mod: %1 + 重新命名 Mod 失敗: %1 - + Overwrite? - 覆蓋 + 覆蓋? - + This will replace the existing mod "%1". Continue? - + 即將取代已存在的 Mod "%1"。繼續? - + failed to remove mod "%1" - 無法移動 Mod: %1 + 移除 Mod 失敗 "%1" - - - + + + failed to rename "%1" to "%2" 重新命名 "%1 "為 "%2" 時出錯 - + Multiple esps activated, please check that they don't conflict. - + - - - - + + + + Confirm - 確認 + 確認 - + Remove the following mods?<br><ul>%1</ul> - + - + failed to remove mod: %1 - 無法移動 Mod: %1 + 移除 Mod 失敗: %1 - - + + Failed - 失敗 + 失敗 - + Installation file no longer exists - 安裝檔案不複存在 + 安裝檔案不復存在 - + Mods installed with old versions of MO can't be reinstalled in this way. - 舊版 MO 安裝的 Mod 無法使用此方法重新安裝。 - - - - - You need to be logged in with Nexus to endorse - - - - - Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. - - - - - - - Delete %n save(s) - - - + 舊版 MO 安裝的 Mod 無法使用此方法重新安裝。 - - Extract BSA - 解壓 BSA + + You need to be logged in with Nexus to resume a download + 您必須登入N網以回復下載。 - - - failed to read %1: %2 - 無法讀取 %1: %2 + + + You need to be logged in with Nexus to endorse + 您必須登入N網以贊同。 - - This archive contains invalid hashes. Some files may be broken. - 壓縮包 Hash 值錯誤。部分檔案可能已經損壞。 + + Failed to display overwrite dialog: %1 + 顯示覆蓋的對話失敗: %1 - + Nexus ID for this Mod is unknown - 此 Mod 的N網 ID 未知 - - - - Download? - 下載 - - - - A download has been started but no installed page plugin recognizes it. -If you download anyway no information (i.e. version) will be associated with the download. -Continue? - - - - - Browse Mod Page - - - - - - Failed to write settings - - - - - - An error occured trying to write back MO settings: %1 - - - - - File is write protected - - - - - Invalid file format (probably a bug) - - - - - Unknown error %1 - - - - - <Managed by MO> - - - - - <Managed outside MO> - - - - - You need to be logged in with Nexus to resume a download - - - - - Failed to display overwrite dialog: %1 - + 此 Mod 的N網 ID 未知 - - + + Create Mod... - + 創造 Mod... - + This will move all files from overwrite into a new, regular mod. Please enter a name: - + 即將移動所有在 overwrite 的檔案到一個新的、正常的 Mod。 +請輸入一個名稱: - + A mod with this name already exists - + - + Continue? - + 繼續? - + The versioning scheme decides which version is considered newer than another. This function will guess the versioning scheme under the assumption that the installed version is outdated. - + - - + + Sorry - + 抱歉 - + I don't know a versioning scheme where %1 is newer than %2. - + - + Really enable all visible mods? - 確定要啟用全部可見的 Mod 嗎? + 確定要啟用所有可見的 Mod 嗎? - + Really disable all visible mods? - 確定要禁用全部可見的 Mod 嗎? + 確定要禁用所有可見的 Mod 嗎? - + Choose what to export - + - + Everything - + - + All installed mods are included in the list - + - + Active Mods - 激活 Mod + 啟動 Mod - + Only active (checked) mods from your current profile are included - + - + Visible - + 可見的 - + All mods visible in the mod list are included - + - + export failed: %1 - + - + Install Mod... - 安裝 Mod... + 安裝 Mod... - + Enable all visible - 啟用所有可見項目 + 啟用所有可見項目 - + Disable all visible - 禁用所有可見項目 + 禁用所有可見項目 - + Check all for update - 檢查更新 + 檢查所有的更新 - + Export to csv... - + - + All Mods - + 所有 Mod - + Sync to Mods... - 同步到 Mod... + 同步到 Mod... - + Restore Backup - + 回復備份 - + Remove Backup... - + 移除備份 - + Add/Remove Categories - + 增加/移除類別 - + Replace Categories - + 取代類別 - + Primary Category - + 主要類別 - + Change versioning scheme - + - + Un-ignore update - + 取消忽略更新 - + Ignore update - + 忽略更新 - + Rename Mod... - 重新命名... + 重新命名 Mod... - + Remove Mod... - 移除 Mod... + 移除 Mod... - + Reinstall Mod - 重新安裝 Mod + 重新安裝 Mod - + Un-Endorse - + 取消贊同 - - + + Endorse - + 贊同 - + Won't endorse - + 拒絕贊同 - + Endorsement state unknown - + 贊同狀態不明 - + Ignore missing data - + 忽略遺失的檔案 - + Visit on Nexus - 在N網上流覽 + 在N網上訪問 - + Open in explorer - 在檔案總管中開啟 + 在檔案總管中開啟 - + Information... - 訊息... + 訊息... - - + + Exception: - 例外: + 例外: - - + + Unknown exception - 未知的例外 + 未知的例外 - + <All> - <全部> + <全部> - + <Multiple> - + + + + + Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin. + - + Please wait while LOOT is running - + 在 LOOT 執行時請等待 - + Fix Mods... - 修復 Mod... + 修復 Mod... - - Delete - &刪除 + + + Delete %n save(s) + 刪除存檔 %n - + failed to remove %1 - 無法刪除 %1 + 刪除 %1 失敗 - - + + failed to create %1 - 無法建立 %1 + 建立 %1 失敗 - + Can't change download directory while downloads are in progress! - 下載檔案時不能修改下載目錄! + 下載檔案時不能修改下載路徑! - + Download failed - 下載失敗 + 下載失敗 - + failed to write to file %1 - 無法寫入檔案 %1 + 寫入檔案 %1 失敗 - + %1 written - 已寫入 %1 + 已寫入 %1 - + Select binary - 選擇可執行檔案 + 選擇可執行檔案 - + Binary 程式 - + Enter Name - 輸入名稱 + 輸入名稱 - + Please enter a name for the executable - 請為程式輸入一個名稱 + 請為程式輸入一個名稱 - + Not an executable - 不是可執行程式 + 不是可執行程式 - + This is not a recognized executable. - 無法識別的可執行檔案 + 無法識別的可執行檔案 - - + + Replace file? - 取代檔案? + 取代檔案? - + There already is a hidden version of this file. Replace it? - 已存在同名檔案,但該檔案被隱藏了。確定要覆蓋嗎? + 已存在同名檔案,但該檔案被隱藏了。確定要覆蓋嗎? - - + + File operation failed - 檔案操作錯誤 + 檔案操作失敗 - - + + Failed to remove "%1". Maybe you lack the required file permissions? 無法移除 "%1"。也許您需要足夠的檔案權限? - + There already is a visible version of this file. Replace it? 已存在同名檔案。確定要覆蓋嗎? - + file not found: %1 - + 找不到檔案: %1 - + failed to generate preview for %1 - + - + Sorry, can't preview anything. This function currently does not support extracting from bsas. - + - + Update available - 更新可用 + 有可用的更新 - + Open/Execute - 開啟/執行 + 開啟/執行 - + Add as Executable - 添加為可執行檔案 + 添加為可執行檔案 - + Preview - + 預覽 - + Un-Hide - 取消隱藏 + 取消隱藏 - + Hide - 隱藏 + 隱藏 - + Write To File... - 寫入檔案... + 寫入檔案... - + Do you want to endorse Mod Organizer on %1 now? - + - + Thank you! - + 謝謝您! - + Thank you for your endorsement! - + 感謝您的贊同! - + Request to Nexus failed: %1 - + - - + + login successful - 登入成功 + 登入成功 - + login failed: %1. Trying to download anyway - 登入失敗: %1,請嘗試使用別的方法下載 + 登入失敗: %1,仍然嘗試下載 - + login failed: %1 無法登入: %1 - + login failed: %1. You need to log-in with Nexus to update MO. - 登入失敗: %1。您需要登入到N網才能更新 MO + 登入失敗: %1。您需要登入到N網才能更新 MO - + + + failed to read %1: %2 + 讀取 %1 失敗: %2 + + + Error - 錯誤 + 錯誤 - + failed to extract %1 (errorcode %2) - 無法解壓 %1 (錯誤代碼 %2) + 解壓 %1 失敗(錯誤代碼 %2) + + + + Extract BSA + 解壓 BSA + + + + This archive contains invalid hashes. Some files may be broken. + 壓縮包的 Hash 值錯誤。部分檔案可能已經損壞。 - + Extract... - 解壓... + 解壓... - + Edit Categories... - 編輯類別... + 編輯類別... - + Deselect filter - + - + Remove 移除 - + Enable all - 全部啟用 + 全部啟用 - + Disable all - 全部禁用 + 全部禁用 - + Unlock load order - + 解鎖載入順序 - + Lock load order - + 鎖定載入順序 - + depends on missing "%1" - + - + incompatible with "%1" - + 與 "%1" 不相容 - + No profile set - + - + loot failed. Exit code was: %1 - + - + failed to start loot - + - + failed to run loot: %1 - + - + Errors occured - + - + Backup of load order created - + 產生的載入順序備份 - + Choose backup to restore - + - + No Backups - + - + There are no backups to restore - + - - + + Restore failed - + - - + + Failed to restore the backup. Errorcode: %1 - + - + Backup of modlist created - + @@ -2879,14 +2876,69 @@ This function will guess the versioning scheme under the assumption that the ins Placeholder - 占位符 + 預留位置 ModInfo - - + + Plugins + + + + + Textures + + + + + Meshes + + + + + UI Changes + + + + + Music + + + + + Sound Effects + + + + + Scripts + + + + + SKSE Plugins + + + + + SkyProc Tools + + + + + Strings + + + + + invalid content type %1 + + + + + invalid index %1 無效的索引 %1 @@ -2894,9 +2946,9 @@ This function will guess the versioning scheme under the assumption that the ins ModInfoBackup - + This is the backup of a mod - + @@ -2935,7 +2987,7 @@ This function will guess the versioning scheme under the assumption that the ins Ini Files - + @@ -2950,17 +3002,17 @@ This function will guess the versioning scheme under the assumption that the ins Ini Tweaks - + This is a list of ini tweaks (ini modifications that can be toggled). - + This is a list of ini tweaks. Ini Tweaks are (usually small) fragments of ini files that are applied over existing settings in skyrim.ini/skyrimprefs.ini. Each tweak can be toggled individually. You should check the description of the mod wether the tweaks are really optional. - + @@ -2985,7 +3037,7 @@ This function will guess the versioning scheme under the assumption that the ins This lists all the images (.jpg and .png) in the mod directory, like screenshots and such. Click one to get a larger view. - + @@ -3004,7 +3056,7 @@ This function will guess the versioning scheme under the assumption that the ins They usually contain optional functionality, see the readme. Most mods do not have optional esps, so chances are good you are looking at an empty list. - + @@ -3024,7 +3076,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e This moves a esp to the esp directory so it can be enabled in the main window. Please note that the ESP merely becomes "available", it will not necessarily be loaded! That is configured in the main window of omo. - 移動一個 esp 檔案到 esp 目錄,這樣它就可以在主窗口中啟用了。請注意: ESP 只是變得“可用”,它并不一定會被載入!想要载入请在 MO 的主窗口中勾選。 + 移動一個 esp 檔案到 esp 目錄,這樣它就可以在主視窗中啟用了。請注意: ESP 只是變得“可用”,它並不一定會被載入!想要載入請在 MO 的主視窗中調整。 @@ -3085,7 +3137,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e Primary Category - + @@ -3107,7 +3159,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html> <!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"> @@ -3120,7 +3172,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html> <!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"> @@ -3136,12 +3188,12 @@ p, li { white-space: pre-wrap; } Refresh - 重新整理 + Refresh all information from Nexus. - + @@ -3153,19 +3205,19 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - + Endorse - + Notes - + @@ -3182,7 +3234,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3195,7 +3247,7 @@ p, li { white-space: pre-wrap; } Previous - + @@ -3208,264 +3260,264 @@ p, li { white-space: pre-wrap; } 關閉 - + &Delete &刪除 - + &Rename &重新命名 - + &Hide &隱藏 - + &Unhide &取消隱藏 - + &Open &開啟 - + &New Folder &新增資料夾 - - + + Save changes? 儲存更改嗎? - - + + Save changes to "%1"? - + - + File Exists 檔案已存在 - + A file with that name exists, please enter a new one 檔案名已存在,請輸入其它名稱 - + failed to move file 無法移動檔案 - + failed to create directory "optional" 無法建立 "optional" 目錄 - - + + Info requested, please wait 請求訊息已發出,請稍後 - + Main 主要檔案 - + Update 更新 - + Optional 可選檔案 - + Old 舊檔 - + Misc 雜項 - + Unknown 未知 - + Current Version: %1 當前版本: %1 - + No update available 沒有可用的更新 - + (description incomplete, please visit nexus) (描述訊息不完整,請訪問N網) - + <a href="%1">Visit on Nexus</a> <a href="%1">訪問N網</a> - + Failed to delete %1 無法刪除 %1 - - + + Confirm 確認 - + Are sure you want to delete "%1"? 確定要刪除 "%1" 嗎? - + Are sure you want to delete the selected files? 確定要刪除所選的檔案嗎? - - + + New Folder 新增資料夾 - + Failed to create "%1" 無法建立 "%1" - - + + Replace file? 取代檔案? - + There already is a hidden version of this file. Replace it? 已存在同名檔案,但該檔案被隱藏了。確定要覆蓋嗎? - - + + File operation failed 檔案操作錯誤 - - + + Failed to remove "%1". Maybe you lack the required file permissions? 無法移除 "%1"。也許您需要足夠的檔案權限? - - + + failed to rename %1 to %2 無法重新命名 %1 為 %2 - + There already is a visible version of this file. Replace it? 已存在同名檔案。確定要覆蓋嗎? - + Un-Hide 取消隱藏 - + Hide 隱藏 - + Name 名稱 - + Please enter a name - + - - + + Error - 錯誤 + - + Invalid name. Must be a valid file name - + - + A tweak by that name exists - + - + Create Tweak - + ModInfoForeign - + This pseudo mod represents content managed outside MO. It isn't modified by MO. - + ModInfoOverwrite - + This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit) - 此虛擬安裝包內包含來自虛擬 Data 樹的檔案,但檔案發生了變化 (例: 被CK修改了) + ModInfoRegular - - + + failed to write %1/meta.ini: error %2 - 無法寫入 %1/meta.ini: %2 + - + %1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory - %1 中未包含 esp 或 esm 和有效的目錄 (textures, meshes, interface, ...) + - + Categories: <br> - 種類: <br> + @@ -3473,52 +3525,52 @@ p, li { white-space: pre-wrap; } Game plugins (esp/esm) - + Interface - + Meshes - + Music - + Scripts (Papyrus) - + Script Extender Plugin - + SkyProc Patcher - + Sound - + Strings - + Textures - + @@ -3528,58 +3580,57 @@ p, li { white-space: pre-wrap; } Backup - + No valid game data - + 無有效的遊戲資料 Not endorsed yet - + Overwrites files - 覆蓋的 Mod + 覆蓋檔案 Overwritten files - 覆蓋的 Mod + Overwrites & Overwritten - + 覆蓋與被覆蓋 Redundant - + Non-MO - + invalid - + installed version: "%1", newest version: "%2" - installed version: %1, newest version: %2 - 當前版本: %1,最新版本: %2 + The newest version on Nexus seems to be older than the one you have installed. This could either mean the version you have has been withdrawn (i.e. due to a bug) or the author uses a non-standard versioning scheme and that newest version is actually newer. Either way you may want to "upgrade". - + @@ -3589,12 +3640,12 @@ p, li { white-space: pre-wrap; } Invalid name - + drag&drop failed: %1 - + @@ -3609,17 +3660,17 @@ p, li { white-space: pre-wrap; } Flags - + Content - 內容 + Mod Name - + @@ -3634,28 +3685,28 @@ p, li { white-space: pre-wrap; } Category - + Nexus ID - N網 ID + Installation - + unknown - 未知 + Name of your mods - + @@ -3670,27 +3721,27 @@ p, li { white-space: pre-wrap; } Category of the mod. - + Id of the mod as used on Nexus. - + Emblemes to highlight things that might require attention. - + Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br> - + Time this mod was installed - + @@ -3722,22 +3773,22 @@ p, li { white-space: pre-wrap; } NXMAccessManager - + Logging into Nexus - + - + timeout 超時 - + Unknown error - + - + Please check your password 請檢查您的密碼 @@ -3747,7 +3798,7 @@ p, li { white-space: pre-wrap; } Failed to guess mod id for "%1", please pick the correct one - + @@ -3770,7 +3821,7 @@ p, li { white-space: pre-wrap; } You can use drag&drop to move files and directories to regular mods. - + @@ -3795,7 +3846,7 @@ p, li { white-space: pre-wrap; } %1 not found - 找不到 %1 + @@ -3833,116 +3884,116 @@ p, li { white-space: pre-wrap; } PluginList - + Name 名稱 - + Priority 優先級 - + Mod Index - + - + Flags - + - - + + unknown - 未知 + - + Name of your mods - + - + Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority. - + - + The modindex determins the formids of objects originating from this mods. - + - + failed to update esp info for file %1 (source id: %2), error: %3 - + - + esp not found: %1 - + - - + + Confirm 確認 - + Really enable all plugins? - + - + Really disable all plugins? - + - + The file containing locked plugin indices is broken - + - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. 您的一些插件名稱無效!這些插件無法被遊戲載入。請查看 mo_interface.log 來確認那些受影響的插件並重新命名它們。 - <b>Origin</b>: %1 - + This plugin can't be disabled (enforced by the game) + 這個插件不能被禁用 (由遊戲執行) + <b>Origin</b>: %1 + + + + Author 作者 - + Description 描述 - - This plugin can't be disabled (enforced by the game) - 這個插件不能被禁用 (由遊戲執行) - - - + Missing Masters - + - + Enabled Masters - + - + failed to restore load order for %1 - + 為 %1 回復載入順序失敗 @@ -3950,7 +4001,7 @@ p, li { white-space: pre-wrap; } Preview - + @@ -3963,16 +4014,16 @@ p, li { white-space: pre-wrap; } Problems - 問題 + <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - + @@ -3983,12 +4034,12 @@ p, li { white-space: pre-wrap; } Fix - + No guided fix - + @@ -3996,32 +4047,32 @@ p, li { white-space: pre-wrap; } invalid profile name %1 - + failed to create %1 - 無法建立 %1 + failed to write mod list: %1 - 無法更新 Mod 列表: %1 + failed to update tweaked ini file, wrong settings may be used: %1 - + failed to create tweaked ini: %1 - + "%1" is missing or inaccessible - + @@ -4035,7 +4086,7 @@ p, li { white-space: pre-wrap; } Overwrite directory couldn't be parsed - + @@ -4045,7 +4096,7 @@ p, li { white-space: pre-wrap; } failed to parse ini file (%1) - 無法解析 Ini 檔案 (%1) + @@ -4056,17 +4107,17 @@ p, li { white-space: pre-wrap; } failed to modify "%1" - 未能找到 "%1" + Delete savegames? - + Do you want to delete local savegames? (If you select "No", the save games will show up again if you re-enable local savegames) - + @@ -4114,28 +4165,28 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html> <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">這是配置檔案的列表,每個配置檔案都包含了它們自己的已激活 Mod 的列表和安裝順序 (從共享區域)、一個已激活的 esp 或 esm 的配置、一個遊戲 Ini 檔案的拷貝和一個可選的存檔過濾器。</p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">這是配置檔案的列表,每個配置檔案都包含了它們自己的已啟動 Mod 的列表和安裝順序 (從共享區域)、一個已啟動的 esp 或 esm 的配置、一個遊戲 Ini 檔案的拷貝和一個可選的存檔過濾器。</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">注意: </span>由于技術上的原因,目前不可能有分開儲存的插件加載順序。這意味著您不能同时在兩個配置檔案裡使用兩種不同的插件配置方案。</p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">注意: </span>由於技術上的原因,目前不可能有分開儲存的插件載入順序。這意味著您不能同時在兩個配置檔案裡使用兩種不同的插件配置方案。</p></body></html> If checked, savegames are local to this profile and will not appear when starting with a different profile. - + Local Savegames - + @@ -4147,7 +4198,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4206,18 +4257,18 @@ p, li { white-space: pre-wrap; } Rename - &重新命名 + Transfer save games to the selected profile. - + Transfer Saves - + @@ -4253,12 +4304,12 @@ p, li { white-space: pre-wrap; } Invalid name - + Invalid profile name - + @@ -4268,27 +4319,27 @@ p, li { white-space: pre-wrap; } Are you sure you want to remove this profile (including local savegames if any)? - + Profile broken - + 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? - + Rename Profile - + New Name - + @@ -4324,47 +4375,47 @@ p, li { white-space: pre-wrap; } invalid field name "%1" - + invalid type for "%1" (should be integer) - + invalid type for "%1" (should be string) - + invalid type for "%1" (should be float) - + no fields set up yet! - + field not set "%1" - + invalid character in field "%1" - + empty field name - + invalid game type %1 - + @@ -4402,7 +4453,7 @@ p, li { white-space: pre-wrap; } Failed to deactivate script extender loading - 無法停用脚本扩展加載 + 停用腳本擴充載入失敗 @@ -4418,7 +4469,7 @@ p, li { white-space: pre-wrap; } Failed to deactivate proxy-dll loading - 無法停用代理DLL加載 + 停用代理DLL載入失敗 @@ -4430,7 +4481,7 @@ p, li { white-space: pre-wrap; } Failed to set up script extender loading - 無法設定腳本拓展加載 + 設定腳本擴充載入失敗 @@ -4445,65 +4496,65 @@ p, li { white-space: pre-wrap; } Failed to set up proxy-dll loading - 無法設定代理DLL加載 + 設定代理DLL載入失敗 - + Permissions required 需要權限 - + 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. - + - - + + Woops 糟糕 - + ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened - + - + ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1 Mod Organizer 崩潰了!遺憾的是,我無法生成診斷檔案: %1 - + Mod Organizer Mod Organizer - + An instance of Mod Organizer is already running Mod Organizer 的一個實例正在運行 - + No game identified in "%1". The directory is required to contain the game binary and its launcher. "%1" 中未檢測到遊戲。請確保該路徑中包含遊戲執行程式以及對應的 Launcher 檔案。 - - + + Please select the game to manage 請選擇想要管理的遊戲 - + Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!) - + - + failed to start application: %1 - + @@ -4511,28 +4562,28 @@ p, li { white-space: pre-wrap; } 請使用工具列上的“幫助”來獲得所有元素的使用說明 - - + + <Manage...> <管理...> - + failed to parse profile %1: %2 無法解析配置檔案 %1: %2 - + failed to find "%1" 未能找到 "%1" - + failed to access %1 無法訪問 %1 - + failed to set file time %1 無法設定檔案時間 %1 @@ -4544,8 +4595,7 @@ p, li { white-space: pre-wrap; } "%1" is missing or inaccessible - "%1" is missing - + @@ -4558,6 +4608,11 @@ p, li { white-space: pre-wrap; } Error 錯誤 + + + failed to open temporary file + + @@ -4581,87 +4636,82 @@ p, li { white-space: pre-wrap; } 代理DLL - + failed to spawn "%1" 無法生成 "%1" - + Elevation required - + - + This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" can be installed to work without elevation. Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe to make changes to the system) - + - + failed to spawn "%1": %2 無法生成 "%1": %2 - + "%1" doesn't exist "%1" 不存在 - + failed to inject dll into "%1": %2 無法注入 dll 到 "%1": %2 - + failed to run "%1" 無法運行 "%1" - - - failed to open temporary file - - QueryOverwriteDialog Mod Exists - + This mod seems to be installed already. Do you want to add files from this archive (overwriting existing ones) or do you want to completely replace the existing files (old files are deleted)? Alternatively you can install this mod under a different name. - + Keep Backup - + Merge - + Replace - 取代 + Rename - &重新命名 + Cancel - 取消 + @@ -4669,27 +4719,27 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Save # - + Character - + Level - + Location - + Date - Data + @@ -4697,7 +4747,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Missing ESPs - 缺失的 ESP + @@ -4705,37 +4755,37 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Dialog - 對話方塊 + Copy To Clipboard - + Save As... - + Close - 關閉 + Save CSV - + Text Files - 文字文件 + failed to open "%1" for writing - + @@ -4748,7 +4798,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Placeholder - 占位符 + 預留位置 @@ -4761,7 +4811,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe archive.dll not loaded: "%1" - + archive.dll 並未載入: "%1" @@ -4799,7 +4849,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe failed to move outdated files: %1. Please update manually. - + @@ -4819,12 +4869,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe No incremental update available for this version, the complete package needs to be downloaded (%1 kB) - 沒有可用于此版本的更新檔案,需要下載完整的安裝包 (%1 KB) + 沒有可用於此版本的更新檔案,需要下載完整的安裝包 (%1 kB) no file for update found. Please update manually. - + @@ -4834,7 +4884,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe No download server available. Please try again later. - 沒有可用的下載伺服器,請稍後再嘗試下載。 + 沒有可用的下載伺服器,請稍後再嘗試下載。 @@ -4842,18 +4892,18 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe Failed - 失敗 + Sorry, failed to start the helper application - + attempt to store setting for unknown plugin "%1" - + @@ -4893,7 +4943,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html> <!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"> @@ -4904,48 +4954,48 @@ p, li { white-space: pre-wrap; } Style - + graphical style - + graphical style of the MO user interface - + Log Level - + Decides the amount of data printed to "ModOrganizer.log" - + Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty. - + Debug - + Info - + Error - 錯誤 + @@ -4986,37 +5036,37 @@ p, li { white-space: pre-wrap; } User interface - + If checked, the download interface will be more compact. - + 如果勾選,下載介面將會更簡潔。 Compact Download Interface - + 壓縮下載介面 If checked, the download list will display meta information instead of file names. - + Download Meta Information - + Reset stored information from dialogs. - + This will make all dialogs show up again where you checked the "Remember selection"-box. - + @@ -5050,7 +5100,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html> <!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"> @@ -5061,7 +5111,7 @@ 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. - + @@ -5081,82 +5131,82 @@ p, li { white-space: pre-wrap; } 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) - + Plugins - + Author: - 作者 + Version: - 版本 + Description: - 描述 + Key - + Value - + Blacklisted Plugins (use <del> to remove): - + @@ -5178,7 +5228,7 @@ p, li { white-space: pre-wrap; } <!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; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5191,8 +5241,8 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Steam App ID 是必須的,它被用來直接啟動一些遊戲。對於天際,如果沒有設定或設定錯誤,&quot;Mod Organizer&quot; 的加載機制可能會無法正常工作。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">此預設是應用程式 ID 的“常規”版本,因此在大多數情況下,您應該要重新設定一下。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Steam App ID 是必須的,它被用來直接啟動一些遊戲。對於 Skyrim,如果沒有設定或設定錯誤,&quot;Mod Organizer&quot; 的加載機制可能會無法正常工作。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">此預設是應用程式 ID 的“正常”版本,因此在大多數情況下,您應該要重新設定一下。</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您認為您有不同的版本 (年度版或其它版本),那麼請參照下列的步驟來獲取 ID: </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">1. 進入 Steam 裡的遊戲庫</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">2. 右鍵點擊您想要獲取 ID 的遊戲,選擇</span><span style=" font-size:9pt; font-weight:600;">建立桌面捷徑</span></p> @@ -5203,12 +5253,12 @@ p, li { white-space: pre-wrap; } Load Mechanism - 加載機制 + 載入機制 Select loading mechanism. See help for details. - 選擇加載機制,使用幫助查看更多細節。 + 選擇載入機制,使用幫助查看更多細節。 @@ -5216,10 +5266,10 @@ p, li { white-space: pre-wrap; } 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. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam. - + @@ -5234,11 +5284,11 @@ If you use the Steam version of Oblivion the default will NOT work. In this case 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. +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. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again. - Mod Organizer 使用了一個N網所提供的 API 來進行類似於檢查更新和下載檔案這樣的操作。遺憾的是這個 API 並沒有給第三方工具 (比如 MO) 正式的授權,所以我們需要模擬 NMM 來進行這些操作。 + Mod Organizer 使用了N網所提供的 API 來進行類似於檢查更新和下載檔案這樣的操作。遺憾的是這個 API 並沒有給第三方工具 (比如 MO) 正式的授權,所以我們需要模擬 NMM 來進行這些操作。 在此之前,N網使用了客戶端辨識系統鎖定了舊版本的 NMM,強制用戶更新版本。這意味著 MO 也要模擬新版本的 NMM,即便 MO 自己並不需要更新。因此您需要在這裡配置版本號來進行辨識。 請注意: MO 辨識自己為 MO 到網路伺服器,這並不是欺騙。它僅僅是為用戶代理添加了一個“兼容”的 NMM 版本。 @@ -5247,13 +5297,13 @@ tl;dr-version: If Nexus-features don't work, insert the current version num Enforces that inactive ESPs and ESMs are never loaded. - 強制執行,未激活的 ESP 和 ESM 將不會被加載。 + 強制執行,未啟用的 ESP 和 ESM 將不會被載入。 - It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + 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. - 看來,遊戲偶爾會加載一些沒有被激活成插件的 ESP 或 ESM 檔案。 + 看來遊戲偶爾會載入一些沒有被啟動成插件的 ESP 或 ESM 檔案。 我還尚不知道它在什麼情況下會這樣,但是有用戶報告說它在某些情況下是很不必要的。如果這個選項被選中,那麼在列表中沒有被勾選的 ESP 和 ESM 將不會在遊戲中出現,並且也不會被載入。 @@ -5264,36 +5314,36 @@ I don't yet know what the circumstances are, but user reports imply it is i 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. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature. - + Display mods installed outside MO - + @@ -5311,7 +5361,7 @@ For the other games this is not a sufficient replacement for AI! These are workarounds for problems with Mod Organizer. Please make sure you read the help text before changing anything here. - + @@ -5388,7 +5438,7 @@ For the other games this is not a sufficient replacement for AI! failed to communicate with running instance: %1 - 無法連接到正在運行的實例: %1 + @@ -5434,17 +5484,17 @@ For the other games this is not a sufficient replacement for AI! Transfer Savegames - + Global Characters - + This is a list of characters in the global location. - + @@ -5456,7 +5506,7 @@ On Windows Vista/Windows 7: On Windows XP: C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves - + @@ -5469,47 +5519,47 @@ On Windows XP: C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves - + Move -> - + Copy -> - + <- Move - + <- Copy - + Done - 完成 + 完成 Profile Characters - + Overwrite - 覆蓋 + 覆蓋 Overwrite the file "%1" - + 覆蓋檔案 "%1" @@ -5517,23 +5567,23 @@ On Windows XP: Confirm - 確認 + 確認 Copy all save games of character "%1" to the profile? - + Move all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games. - + Copy all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games. - + - + \ No newline at end of file -- cgit v1.3.1 From f2f9e11fdd876821107cff0c1c5b9d8ecf66691f Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 21 Nov 2014 14:45:30 +0100 Subject: - started on a refactoring moving functionality out of the MainWindow class - started on support for game-plugins --- src/browserdialog.cpp | 1 - src/editexecutablesdialog.cpp | 18 +- src/editexecutablesdialog.ui | 3 + src/executableslist.cpp | 32 +- src/executableslist.h | 13 +- src/installationmanager.cpp | 13 +- src/installationmanager.h | 4 +- src/iuserinterface.h | 39 + src/main.cpp | 36 +- src/mainwindow.cpp | 1851 +++++++++-------------------------------- src/mainwindow.h | 152 +--- src/messagedialog.cpp | 2 +- src/organizer.pro | 11 +- src/organizercore.cpp | 1249 +++++++++++++++++++++++++++ src/organizercore.h | 239 ++++++ src/organizerproxy.cpp | 108 +-- src/organizerproxy.h | 12 +- src/plugincontainer.cpp | 329 ++++++++ src/plugincontainer.h | 102 +++ src/selfupdater.cpp | 11 +- src/selfupdater.h | 4 +- src/shared/fallout3info.cpp | 4 +- src/shared/fallout3info.h | 2 +- src/shared/falloutnvinfo.cpp | 4 +- src/shared/falloutnvinfo.h | 2 +- src/shared/gameinfo.h | 10 +- src/shared/oblivioninfo.cpp | 4 +- src/shared/oblivioninfo.h | 2 +- src/shared/skyriminfo.cpp | 4 +- src/shared/skyriminfo.h | 2 +- 30 files changed, 2509 insertions(+), 1754 deletions(-) create mode 100644 src/iuserinterface.h create mode 100644 src/organizercore.cpp create mode 100644 src/organizercore.h create mode 100644 src/plugincontainer.cpp create mode 100644 src/plugincontainer.h (limited to 'src/mainwindow.cpp') diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp index f93ffcae..933b4bc0 100644 --- a/src/browserdialog.cpp +++ b/src/browserdialog.cpp @@ -202,7 +202,6 @@ void BrowserDialog::unsupportedContent(QNetworkReply *reply) return; } - qDebug("unsupported: %s - %s", view->url().toString().toUtf8().constData(), reply->url().toString().toUtf8().constData()); emit requestDownload(view->url(), reply); } catch (const std::exception &e) { if (isVisible()) { diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index fe548a9a..3cc749d6 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -53,9 +53,7 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const void EditExecutablesDialog::refreshExecutablesWidget() { - QListWidget *executablesWidget = findChild("executablesListBox"); - - executablesWidget->clear(); + ui->executablesListBox->clear(); std::vector::const_iterator current, end; m_ExecutablesList.getExecutables(current, end); @@ -65,7 +63,7 @@ void EditExecutablesDialog::refreshExecutablesWidget() temp.setValue(*current); newItem->setData(Qt::UserRole, temp); newItem->setTextColor(current->m_Custom ? QColor(Qt::black) : QColor(Qt::darkGray)); - executablesWidget->addItem(newItem); + ui->executablesListBox->addItem(newItem); } ui->addButton->setEnabled(false); @@ -96,7 +94,8 @@ void EditExecutablesDialog::saveExecutable() { m_ExecutablesList.addExecutable(ui->titleEdit->text(), QDir::fromNativeSeparators(ui->binaryEdit->text()), ui->argumentsEdit->text(), QDir::fromNativeSeparators(ui->workingDirEdit->text()), - (ui->closeCheckBox->checkState() == Qt::Checked) ? DEFAULT_CLOSE : DEFAULT_STAY, + (ui->closeCheckBox->checkState() == Qt::Checked) ? ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE + : ExecutableInfo::CloseMOStyle::DEFAULT_STAY, ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "", true, false); } @@ -212,14 +211,14 @@ bool EditExecutablesDialog::executableChanged() || selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text() || selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text()) || selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text()) - || (selectedExecutable.m_CloseMO == DEFAULT_CLOSE) != ui->closeCheckBox->isChecked(); + || (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked(); } else { return false; } } -void EditExecutablesDialog::on_executablesListBox_currentItemChanged(QListWidgetItem *current, QListWidgetItem*) +void EditExecutablesDialog::on_executablesListBox_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) { if (current == NULL) { resetInput(); @@ -249,8 +248,8 @@ void EditExecutablesDialog::on_executablesListBox_currentItemChanged(QListWidget 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 { @@ -286,4 +285,3 @@ void EditExecutablesDialog::on_closeButton_clicked() } this->accept(); } - diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui index 4f0462db..8e70c1c0 100644 --- a/src/editexecutablesdialog.ui +++ b/src/editexecutablesdialog.ui @@ -28,6 +28,9 @@ Qt::MoveAction + + QAbstractItemView::SingleSelection + diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 2c6754d7..11158c5b 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -31,8 +31,14 @@ using namespace MOShared; QDataStream &operator<<(QDataStream &out, const Executable &obj) { - out << obj.m_Title << obj.m_BinaryInfo.absoluteFilePath() << obj.m_Arguments << obj.m_CloseMO - << obj.m_SteamAppID << obj.m_WorkingDirectory << obj.m_Custom << obj.m_Toolbar; + out << obj.m_Title + << obj.m_BinaryInfo.absoluteFilePath() + << obj.m_Arguments + << static_cast::type>(obj.m_CloseMO) + << obj.m_SteamAppID + << obj.m_WorkingDirectory + << obj.m_Custom + << obj.m_Toolbar; return out; } @@ -43,7 +49,7 @@ QDataStream &operator>>(QDataStream &in, Executable &obj) in >> obj.m_Title >> binaryTemp >> obj.m_Arguments >> closeStyleTemp >> obj.m_SteamAppID >> obj.m_WorkingDirectory >> obj.m_Custom >> obj.m_Toolbar; - obj.m_CloseMO = (CloseMOStyle)closeStyleTemp; + obj.m_CloseMO = static_cast(closeStyleTemp); obj.m_BinaryInfo.setFile(binaryTemp); return in; } @@ -64,14 +70,16 @@ ExecutablesList::~ExecutablesList() { } -void ExecutablesList::init() +void ExecutablesList::init(IPluginGame *game) { - std::vector executables = GameInfo::instance().getExecutables(); - for (std::vector::const_iterator iter = executables.begin(); iter != executables.end(); ++iter) { - addExecutableInternal(ToQString(iter->title), - QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())).append("/").append(ToQString(iter->binary)), - ToQString(iter->arguments), ToQString(iter->workingDirectory), - iter->closeMO, ToQString(iter->steamAppID)); + m_Executables.clear(); + for (const ExecutableInfo &info : game->executables()) { + addExecutableInternal(info.title(), + info.binary().absoluteFilePath(), + info.arguments().join(" "), + info.workingDirectory().absolutePath(), + info.closeMO(), + info.steamAppID()); } } @@ -143,7 +151,7 @@ void ExecutablesList::addExecutable(const Executable &executable) void ExecutablesList::addExecutable(const QString &title, const QString &executableName, const QString &arguments, - const QString &workingDirectory, CloseMOStyle closeMO, const QString &steamAppID, + const QString &workingDirectory, ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID, bool custom, bool toolbar) { QFileInfo file(executableName); @@ -185,7 +193,7 @@ void ExecutablesList::remove(const QString &title) void ExecutablesList::addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, - CloseMOStyle closeMO, const QString &steamAppID) + ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID) { QFileInfo file(executableName); if (file.exists()) { diff --git a/src/executableslist.h b/src/executableslist.h index 6f7771e5..207190c4 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -25,6 +25,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include /*! @@ -34,7 +35,7 @@ struct Executable { QString m_Title; QFileInfo m_BinaryInfo; QString m_Arguments; - MOShared::CloseMOStyle m_CloseMO; + MOBase::ExecutableInfo::CloseMOStyle m_CloseMO; QString m_SteamAppID; QString m_WorkingDirectory; @@ -64,7 +65,7 @@ public: /** * @brief initialise the list with the executables preconfigured for this game **/ - void init(); + void init(MOBase::IPluginGame *game); /** * @brief retrieve an executable by index @@ -114,7 +115,9 @@ public: * @param arguments arguments to pass to the executable * @param closeMO if true, MO will be closed when the binary is started **/ - void addExecutable(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, MOShared::CloseMOStyle closeMO, const QString &steamAppID, bool custom, bool toolbar); + void addExecutable(const QString &title, const QString &executableName, const QString &arguments, + const QString &workingDirectory, MOBase::ExecutableInfo::CloseMOStyle closeMO, + const QString &steamAppID, bool custom, bool toolbar); /** * @brief remove the executable with the specified file name. This needs to be an absolute file path @@ -144,7 +147,9 @@ private: Executable *findExe(const QString &title); - void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, MOShared::CloseMOStyle closeMO, const QString &steamAppID); + void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, + const QString &workingDirectory, MOBase::ExecutableInfo::CloseMOStyle closeMO, + const QString &steamAppID); private: diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index d6435e57..0fb1b78d 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -67,9 +67,8 @@ template T resolveFunction(QLibrary &lib, const char *name) } -InstallationManager::InstallationManager(QWidget *parent) - : QObject(parent), m_ParentWidget(parent), - m_InstallationProgress(parent), m_SupportedExtensions(boost::assign::list_of("zip")("rar")("7z")("fomod")("001")) +InstallationManager::InstallationManager() + : m_InstallationProgress(nullptr), m_SupportedExtensions(boost::assign::list_of("zip")("rar")("7z")("fomod")("001")) { QLibrary archiveLib("dlls\\archive.dll"); if (!archiveLib.load()) { @@ -92,6 +91,14 @@ InstallationManager::~InstallationManager() delete m_CurrentArchive; } +void InstallationManager::setParentWidget(QWidget *widget) +{ + m_InstallationProgress.setParent(widget); + for (IPluginInstaller *installer : m_Installers) { + installer->setParentWidget(widget); + } +} + void InstallationManager::queryPassword(LPSTR password) { diff --git a/src/installationmanager.h b/src/installationmanager.h index 336c1ce3..cd20f0dd 100644 --- a/src/installationmanager.h +++ b/src/installationmanager.h @@ -53,10 +53,12 @@ public: * * @param parent parent object. **/ - explicit InstallationManager(QWidget *parent); + explicit InstallationManager(); virtual ~InstallationManager(); + void setParentWidget(QWidget *widget); + /** * @brief update the directory where mods are to be installed * @param modsDirectory the mod directory diff --git a/src/iuserinterface.h b/src/iuserinterface.h new file mode 100644 index 00000000..76d4c75a --- /dev/null +++ b/src/iuserinterface.h @@ -0,0 +1,39 @@ +#ifndef IUSERINTERFACE_H +#define IUSERINTERFACE_H + + +#include "modinfo.h" +#include +#include + + +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 bool waitForProcessOrJob(HANDLE processHandle, LPDWORD exitCode = NULL) = 0; + + virtual void registerPluginTool(MOBase::IPluginTool *tool) = 0; + virtual void registerModPage(MOBase::IPluginModPage *modPage) = 0; + + virtual void installTranslator(const QString &name) = 0; + + 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; + + virtual bool saveArchiveList() = 0; + +}; + +#endif // IUSERINTERFACE_H diff --git a/src/main.cpp b/src/main.cpp index b4139f09..f292eac7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,6 +42,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include "mainwindow.h" #include "report.h" @@ -398,6 +399,11 @@ int main(int argc, char *argv[]) QSettings settings(dataPath + "/ModOrganizer.ini", QSettings::IniFormat); + OrganizerCore organizer(settings); + + PluginContainer pluginContainer(&organizer); + pluginContainer.loadPlugins(); + QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); bool done = false; @@ -473,9 +479,7 @@ int main(int argc, char *argv[]) #pragma message("edition isn't used?") qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath))); - ExecutablesList executablesList; - - executablesList.init(); + organizer.updateExecutablesList(settings); if (!bootstrap()) { // requires gameinfo to be initialised! return -1; @@ -483,24 +487,6 @@ int main(int argc, char *argv[]) cleanupDir(); - qDebug("setting up configured executables"); - - int numCustomExecutables = settings.beginReadArray("customExecutables"); - for (int i = 0; i < numCustomExecutables; ++i) { - settings.setArrayIndex(i); - CloseMOStyle closeMO = settings.value("closeOnStart").toBool() ? DEFAULT_CLOSE : DEFAULT_STAY; - executablesList.addExecutable(settings.value("title").toString(), - settings.value("binary").toString(), - settings.value("arguments").toString(), - settings.value("workingDirectory", "").toString(), - closeMO, - settings.value("steamAppID", "").toString(), - settings.value("custom", true).toBool(), - settings.value("toolbar", false).toBool()); - } - - settings.endArray(); - qDebug("initializing tutorials"); TutorialManager::init(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getTutorialDir())).append("/")); @@ -512,11 +498,11 @@ 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); + MainWindow mainWindow(argv[0], settings, organizer, pluginContainer); + QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString))); - QObject::connect(&instance, SIGNAL(messageSent(QString)), &mainWindow, SLOT(externalMessage(QString))); + QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer, SLOT(externalMessage(QString))); - mainWindow.setExecutablesList(executablesList); mainWindow.readSettings(); QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray()); @@ -571,7 +557,7 @@ int main(int argc, char *argv[]) if ((arguments.size() > 1) && (isNxmLink(arguments.at(1)))) { qDebug("starting download from command line: %s", qPrintable(arguments.at(1))); - mainWindow.externalMessage(arguments.at(1)); + organizer.externalMessage(arguments.at(1)); } splash.finish(&mainWindow); res = application.exec(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 024e2510..4762358e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -16,10 +16,10 @@ 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 Q_MOC_RUN #include "mainwindow.h" #include "ui_mainwindow.h" -#include #include "spawn.h" #include "report.h" #include "modlist.h" @@ -61,14 +61,16 @@ along with Mod Organizer. If not, see . #include "aboutdialog.h" #include "safewritefile.h" #include "organizerproxy.h" +#include #include #include #include #include #include +#include +#endif // Q_MOC_RUN #include #include -#include #include #include #include @@ -123,6 +125,7 @@ along with Mod Organizer. If not, see . #include #endif #include +#include #ifdef TEST_MODELS #include "modeltest.h" @@ -136,46 +139,28 @@ using namespace MOShared; -static bool isOnline() -{ - QList interfaces = QNetworkInterface::allInterfaces(); - - bool connected = false; - for (auto iter = interfaces.begin(); iter != interfaces.end() && !connected; ++iter) { - if ( (iter->flags() & QNetworkInterface::IsUp) && - (iter->flags() & QNetworkInterface::IsRunning) && - !(iter->flags() & QNetworkInterface::IsLoopBack)) { - auto addresses = iter->addressEntries(); - if (addresses.count() == 0) { - continue; - } - qDebug("interface %s seems to be up (address: %s)", - qPrintable(iter->humanReadableName()), - qPrintable(addresses[0].ip().toString())); - connected = true; - } - } - - return connected; -} - - -MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent) - : QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"), - m_ExeName(exeName), m_OldProfileIndex(-1), - m_DirectoryStructure(new DirectoryEntry(L"data", NULL, 0)), - m_ModList(this), m_ModListGroupingProxy(NULL), m_ModListSortProxy(NULL), - m_PluginList(this), m_OldExecutableIndex(-1), m_GamePath(ToQString(GameInfo::instance().getGameDirectory())), - m_DownloadManager(NexusInterface::instance(), this), m_InstallationManager(this), - m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()), - m_CurrentProfile(NULL), m_AskForNexusPW(false), - m_ArchivesInit(false), m_DirectoryUpdate(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL), - m_GameInfo(new GameInfoImpl()), m_AboutToRun(), m_ModInstalled(), m_DidUpdateMasterList(false) +MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, OrganizerCore &organizerCore, PluginContainer &pluginContainer, QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) + , m_Tutorial(this, "MainWindow") + , m_ExeName(exeName) + , m_OldProfileIndex(-1) + , m_ModListGroupingProxy(nullptr) + , m_ModListSortProxy(nullptr) + , m_OldExecutableIndex(-1) + , m_GamePath(ToQString(GameInfo::instance().getGameDirectory())) + , m_CategoryFactory(CategoryFactory::instance()) + , m_ContextItem(nullptr) + , m_ContextAction(nullptr) + , m_CurrentSaveView(nullptr) + , m_OrganizerCore(organizerCore) + , m_PluginContainer(pluginContainer) + , m_DidUpdateMasterList(false) { ui->setupUi(this); - this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_Updater.getVersion().displayString()); + this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_OrganizerCore.getVersion().displayString()); - languageChange(m_Settings.language()); + languageChange(m_OrganizerCore.settings().language()); ui->logList->setModel(LogBuffer::instance()); ui->logList->setColumnWidth(0, 100); @@ -202,16 +187,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget updateToolBar(); - ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign()); - // set up mod list - m_ModListSortProxy = new ModListSortProxy(m_CurrentProfile, this); - m_ModListSortProxy->setSourceModel(&m_ModList); - -#ifdef TEST_MODELS - new ModelTest(&m_ModList, this); - new ModelTest(m_ModListSortProxy, this); -#endif //TEST_MODELS + m_ModListSortProxy = m_OrganizerCore.createModListProxyModel(); ui->modList->setModel(m_ModListSortProxy); @@ -221,7 +198,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->modList->setItemDelegateForColumn(ModList::COL_FLAGS, new ModFlagIconDelegate(ui->modList)); ui->modList->setItemDelegateForColumn(ModList::COL_CONTENT, contentDelegate); //ui->modList->setAcceptDrops(true); - ui->modList->header()->installEventFilter(&m_ModList); + ui->modList->header()->installEventFilter(m_OrganizerCore.modList()); if (initSettings.contains("mod_list_state")) { ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray()); @@ -236,11 +213,10 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget } ui->modList->header()->setSectionHidden(ModList::COL_NAME, false); // prevent the name-column from being hidden - ui->modList->installEventFilter(&m_ModList); + ui->modList->installEventFilter(m_OrganizerCore.modList()); // set up plugin list - m_PluginListSortProxy = new PluginListSortProxy(this); - m_PluginListSortProxy->setSourceModel(&m_PluginList); + m_PluginListSortProxy = m_OrganizerCore.createPluginListProxyModel(); ui->espList->setModel(m_PluginListSortProxy); ui->espList->sortByColumn(PluginList::COL_PRIORITY, Qt::AscendingOrder); @@ -248,7 +224,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget if (initSettings.contains("plugin_list_state")) { ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray()); } - ui->espList->installEventFilter(&m_PluginList); + ui->espList->installEventFilter(m_OrganizerCore.pluginList()); ui->bsaList->setLocalMoveOnly(true); @@ -265,70 +241,50 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->listOptionsBtn->setMenu(modListContextMenu()); - m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory()); - m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers()); - - NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory()); - NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion()); - - m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); - m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory()); - updateDownloadListDelegate(); ui->savegameList->installEventFilter(this); ui->savegameList->setMouseTracking(true); - connect(&m_DownloadManager, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString))); - connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString,int)), this, SLOT(downloadSpeed(QString,int))); - connect(&m_DownloadManager, SIGNAL(downloadAdded()), ui->downloadView, SLOT(scrollToBottom())); connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*))); - connect(&m_ModList, SIGNAL(modorder_changed()), this, SLOT(modorder_changed())); - connect(&m_ModList, SIGNAL(removeOrigin(QString)), this, SLOT(removeOrigin(QString))); - connect(&m_ModList, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString))); - connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), this, SLOT(modRenamed(QString,QString))); - connect(&m_ModList, SIGNAL(modUninstalled(QString)), this, SLOT(modRemoved(QString))); - connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int))); - connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked())); - connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), this, SLOT(displayColumnSelection(QPoint))); - connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), this, SLOT(fileMoved(QString, QString, QString))); - connect(ui->modList, SIGNAL(dropModeUpdate(bool)), &m_ModList, SLOT(dropModeUpdate(bool))); + connect(ui->modList, SIGNAL(dropModeUpdate(bool)), m_OrganizerCore.modList(), SLOT(dropModeUpdate(bool))); connect(ui->modList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(modlistSelectionChanged(QModelIndex,QModelIndex))); connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool))); connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), m_PluginListSortProxy, SLOT(updateFilter(QString))); connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(espFilterChanged(QString))); - connect(&m_PluginList, SIGNAL(saveTimer()), this, SLOT(savePluginList())); + connect(m_OrganizerCore.pluginList(), SIGNAL(saveTimer()), this, SLOT(savePluginList())); connect(ui->bsaList, SIGNAL(itemsMoved()), this, SLOT(bsaList_itemMoved())); connect(ui->dataTree, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(expandDataTreeItem(QTreeWidgetItem*))); - connect(&m_DirectoryRefresher, SIGNAL(refreshed()), this, SLOT(directory_refreshed())); - connect(&m_DirectoryRefresher, SIGNAL(progress(int)), this, SLOT(refresher_progress(int))); - connect(&m_DirectoryRefresher, SIGNAL(error(QString)), this, SLOT(showError(QString))); + connect(m_OrganizerCore.directoryRefresher(), SIGNAL(refreshed()), this, SLOT(directory_refreshed())); + connect(m_OrganizerCore.directoryRefresher(), SIGNAL(progress(int)), this, SLOT(refresher_progress(int))); + connect(m_OrganizerCore.directoryRefresher(), SIGNAL(error(QString)), this, SLOT(showError(QString))); connect(&m_SavesWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(refreshSavesIfOpen())); - connect(&m_Settings, SIGNAL(languageChanged(QString)), this, SLOT(languageChange(QString))); - connect(&m_Settings, SIGNAL(styleChanged(QString)), this, SIGNAL(styleChanged(QString))); + connect(&m_OrganizerCore.settings(), SIGNAL(languageChanged(QString)), this, SLOT(languageChange(QString))); + connect(&m_OrganizerCore.settings(), SIGNAL(styleChanged(QString)), this, SIGNAL(styleChanged(QString))); - connect(&m_Updater, SIGNAL(restart()), this, SLOT(close())); - connect(&m_Updater, SIGNAL(updateAvailable()), this, SLOT(updateAvailable())); - connect(&m_Updater, SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString))); + connect(m_OrganizerCore.updater(), SIGNAL(restart()), this, SLOT(close())); + connect(m_OrganizerCore.updater(), SIGNAL(updateAvailable()), this, SLOT(updateAvailable())); + connect(m_OrganizerCore.updater(), SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString))); - connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool))); - connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString))); connect(NexusInterface::instance(), SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString))); connect(NexusInterface::instance(), SIGNAL(nxmDownloadURLsAvailable(int,int,QVariant,QVariant,int)), this, SLOT(nxmDownloadURLs(int,int,QVariant,QVariant,int))); connect(NexusInterface::instance(), SIGNAL(needLogin()), this, SLOT(nexusLogin())); + connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString))); connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString))); connect(ui->modList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(modListSortIndicatorChanged(int,Qt::SortOrder))); connect(ui->toolBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(toolBar_customContextMenuRequested(QPoint))); + connect(&m_OrganizerCore, &OrganizerCore::modInstalled, this, &MainWindow::modInstalled); + connect(&m_IntegratedBrowser, SIGNAL(requestDownload(QUrl,QNetworkReply*)), this, SLOT(requestDownload(QUrl,QNetworkReply*))); connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString))); @@ -343,42 +299,44 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_SaveMetaTimer, SIGNAL(timeout()), this, SLOT(saveModMetas())); m_SaveMetaTimer.start(5000); - m_DirectoryRefresher.moveToThread(&m_RefresherThread); - m_RefresherThread.start(); - - m_AskForNexusPW = initSettings.value("ask_for_nexuspw", true).toBool(); setCategoryListVisible(initSettings.value("categorylist_visible", true).toBool()); FileDialogMemory::restore(initSettings); fixCategories(); - if (isOnline() && !m_Settings.offlineMode()) { - m_Updater.testForUpdate(); - } else { - qDebug("user doesn't seem to be connected to the internet"); - } - m_StartTime = QTime::currentTime(); - m_Tutorial.expose("modList", &m_ModList); - m_Tutorial.expose("espList", &m_PluginList); + m_Tutorial.expose("modList", m_OrganizerCore.modList()); + m_Tutorial.expose("espList", m_OrganizerCore.pluginList()); // before we start loading plugins we, add the dll path to the dll search order ::SetDllDirectoryW(ToWString(QDir::toNativeSeparators(qApp->applicationDirPath() + "/dlls")).c_str()); - loadPlugins(); + + m_OrganizerCore.setUserInterface(this, this); + + for (const QString &fileName : m_PluginContainer.pluginFileNames()) { + installTranslator(QFileInfo(fileName).baseName()); + } + + refreshExecutablesList(); + updateToolBar(); } MainWindow::~MainWindow() { - m_AboutToRun.disconnect_all_slots(); - m_ModInstalled.disconnect_all_slots(); - m_RefresherThread.exit(); - m_RefresherThread.wait(); + m_PluginContainer.setUserInterface(nullptr, nullptr); + m_OrganizerCore.setUserInterface(nullptr, nullptr); m_IntegratedBrowser.close(); delete ui; - delete m_GameInfo; - delete m_DirectoryStructure; +} + + +void MainWindow::disconnectPlugins() +{ + if (ui->actionTool->menu() != NULL) { + ui->actionTool->menu()->clear(); + } } @@ -537,7 +495,7 @@ void MainWindow::updateToolBar() ui->toolBar->insertWidget(action, spacer); std::vector::iterator begin, end; - m_ExecutablesList.getExecutables(begin, end); + m_OrganizerCore.executablesList()->getExecutables(begin, end); for (auto iter = begin; iter != end; ++iter) { if (iter->m_Toolbar) { QAction *exeAction = new QAction(iconForExecutable(iter->m_BinaryInfo.filePath()), @@ -623,7 +581,7 @@ bool MainWindow::errorReported(QString &logFile) int MainWindow::checkForProblems() { int numProblems = 0; - foreach (IPluginDiagnose *diagnose, m_DiagnosisPlugins) { + for (IPluginDiagnose *diagnose : m_PluginContainer.plugins()) { numProblems += diagnose->activeProblems().size(); } return numProblems; @@ -631,7 +589,7 @@ int MainWindow::checkForProblems() void MainWindow::about() { - AboutDialog dialog(m_Updater.getVersion().displayString(), this); + AboutDialog dialog(m_OrganizerCore.getVersion().displayString(), this); dialog.exec(); } @@ -701,47 +659,10 @@ void MainWindow::createHelpWidget() } -bool MainWindow::saveArchiveList() -{ - if (m_ArchivesInit) { - SafeWriteFile archiveFile(m_CurrentProfile->getArchivesFileName()); - for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { - QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i); - for (int j = 0; j < tlItem->childCount(); ++j) { - QTreeWidgetItem *item = tlItem->child(j); - if (item->checkState(0) == Qt::Checked) { - // in managed mode, "register" all enabled archives, otherwise register only the files registered in the ini - if (ui->manageArchivesBox->isChecked() - || item->data(0, Qt::UserRole).toBool()) { - archiveFile->write(item->text(0).toUtf8().append("\r\n")); - } - } - } - } - if (archiveFile.commitIfDifferent(m_ArchiveListHash)) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_CurrentProfile->getArchivesFileName()))); - return true; - } - } else { - qWarning("archive list not initialised"); - } - return false; -} - -void MainWindow::savePluginList() -{ - m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(), - m_CurrentProfile->getLoadOrderFileName(), - m_CurrentProfile->getLockedOrderFileName(), - m_CurrentProfile->getDeleterFileName(), - m_Settings.hideUncheckedPlugins()); - m_PluginList.saveLoadOrder(*m_DirectoryStructure); -} - void MainWindow::modFilterActive(bool filterActive) { if (filterActive) { - m_ModList.setOverwriteMarkers(std::set(), std::set()); + m_OrganizerCore.modList()->setOverwriteMarkers(std::set(), std::set()); ui->modList->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); } else if (ui->groupCombo->currentIndex() != 0) { ui->modList->setStyleSheet("QTreeView { border: 2px ridge #337733; }"); @@ -781,22 +702,6 @@ void MainWindow::expandModList(const QModelIndex &index) } } -bool MainWindow::saveCurrentLists() -{ - if (m_DirectoryUpdate) { - qWarning("not saving lists during directory update"); - return false; - } - - try { - savePluginList(); - saveArchiveList(); - } catch (const std::exception &e) { - reportError(tr("failed to save load order: %1").arg(e.what())); - } - - return true; -} bool MainWindow::addProfile() { @@ -834,7 +739,7 @@ void MainWindow::hookUpWindowTutorials() QString firstLine = QString::fromUtf8(file.readLine()); if (firstLine.startsWith("//WIN")) { QString windowName = firstLine.mid(6).trimmed(); - if (!m_Settings.directInterface().value("CompletedWindowTutorials/" + windowName, false).toBool()) { + if (!m_OrganizerCore.settings().directInterface().value("CompletedWindowTutorials/" + windowName, false).toBool()) { TutorialManager::instance().activateTutorial(windowName, fileName); } } @@ -850,7 +755,7 @@ void MainWindow::showEvent(QShowEvent *event) hookUpWindowTutorials(); - if (m_Settings.directInterface().value("first_start", true).toBool()) { + if (m_OrganizerCore.settings().directInterface().value("first_start", true).toBool()) { QString firstStepsTutorial = ToQString(AppConfig::firstStepsTutorial()); if (TutorialManager::instance().hasTutorial(firstStepsTutorial)) { if (QMessageBox::question(this, tr("Show tutorial?"), @@ -869,48 +774,35 @@ void MainWindow::showEvent(QShowEvent *event) QObject::tr("Please use \"Help\" from the toolbar to get usage instructions to all elements")); } - m_Settings.directInterface().setValue("first_start", false); + m_OrganizerCore.settings().directInterface().setValue("first_start", false); } // this has no visible impact when called before the ui is visible - int grouping = m_Settings.directInterface().value("group_state").toInt(); + int grouping = m_OrganizerCore.settings().directInterface().value("group_state").toInt(); ui->groupCombo->setCurrentIndex(grouping); allowListResize(); - m_Settings.registerAsNXMHandler(false); + m_OrganizerCore.settings().registerAsNXMHandler(false); } void MainWindow::closeEvent(QCloseEvent* event) { - if (m_DownloadManager.downloadsInProgress()) { + if (m_OrganizerCore.downloadManager()->downloadsInProgress()) { if (QMessageBox::question(this, tr("Downloads in progress"), tr("There are still downloads in progress, do you really want to quit?"), QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel) { event->ignore(); return; } else { - m_DownloadManager.pauseAll(); + m_OrganizerCore.downloadManager()->pauseAll(); } } setCursor(Qt::WaitCursor); m_IntegratedBrowser.close(); - - storeSettings(); - -// unloadPlugins(); - - // profile has to be cleaned up before the modinfo-buffer is cleared - delete m_CurrentProfile; - m_CurrentProfile = NULL; - - ModInfo::clear(); - LogBuffer::cleanQuit(); - m_ModList.setProfile(NULL); - NexusInterface::instance()->cleanup(); } @@ -952,7 +844,7 @@ SaveGameGamebryo *MainWindow::getSaveGame(QListWidgetItem *item) void MainWindow::displaySaveGameInfo(const SaveGameGamebryo *save, QPoint pos) { if (m_CurrentSaveView == NULL) { - m_CurrentSaveView = new SaveGameInfoWidgetGamebryo(save, &m_PluginList, this); + m_CurrentSaveView = new SaveGameInfoWidgetGamebryo(save, m_OrganizerCore.pluginList(), this); } else { m_CurrentSaveView->setSave(save); } @@ -1012,53 +904,6 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) } -bool MainWindow::testForSteam() -{ - DWORD processIDs[1024]; - DWORD bytesReturned; - if (!::EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned)) { - qWarning("failed to determine if steam is running"); - return true; - } - - TCHAR processName[MAX_PATH]; - for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) { - memset(processName, '\0', sizeof(TCHAR) * MAX_PATH); - if (processIDs[i] != 0) { - HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]); - - if (process != NULL) { - HMODULE module; - DWORD ignore; - - // first module in a process is always the binary - 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; - } - } - } - } - } - - return false; -} - - -bool MainWindow::verifyPlugin(IPlugin *plugin) -{ - if (plugin == NULL) { - return false; - } else if (!plugin->init(new OrganizerProxy(this, plugin->name()))) { - qWarning("plugin failed to initialize"); - return false; - } - return true; -} - - void MainWindow::toolPluginInvoke() { QAction *triggeredAction = qobject_cast(sender()); @@ -1073,55 +918,6 @@ void MainWindow::toolPluginInvoke() } -void MainWindow::requestDownload(const QUrl &url, QNetworkReply *reply) -{ - QToolButton *browserBtn = qobject_cast(ui->toolBar->widgetForAction(ui->actionNexus)); - if (browserBtn->menu() != NULL) { - // go through modpage plugins, find one to handle the download. - QList browserActions = browserBtn->menu()->actions(); - foreach (QAction *action, browserActions) { - // the nexus action doesn't have a plugin connected currently - if (action->data().isValid()) { - IPluginModPage *plugin = qobject_cast(qvariant_cast(action->data())); - if (plugin == NULL) { - qCritical("invalid mod page. This is a bug"); - continue; - } - ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo(); - if (plugin->handlesDownload(url, reply->url(), *fileInfo)) { - fileInfo->repository = plugin->name(); - m_DownloadManager.addDownload(reply, fileInfo); - return; - } - } - } - } - - // no mod found that could handle the download. Is it a nexus mod? - if (url.host() == "www.nexusmods.com") { - int modID = 0; - int fileID = 0; - QRegExp modExp("mods/(\\d+)"); - if (modExp.indexIn(url.toString()) != -1) { - modID = modExp.cap(1).toInt(); - } - QRegExp fileExp("fid=(\\d+)"); - if (fileExp.indexIn(reply->url().toString()) != -1) { - fileID = fileExp.cap(1).toInt(); - } - m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo(modID, fileID)); - } else { - if (QMessageBox::question(this, tr("Download?"), - tr("A download has been started but no installed page plugin recognizes it.\n" - "If you download anyway no information (i.e. version) will be associated with the download.\n" - "Continue?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo()); - } - } -} - - void MainWindow::modPagePluginInvoke() { QAction *triggeredAction = qobject_cast(sender()); @@ -1134,6 +930,7 @@ void MainWindow::modPagePluginInvoke() } } + void MainWindow::registerPluginTool(IPluginTool *tool) { QAction *action = new QAction(tool->icon(), tool->displayName(), ui->toolBar); @@ -1171,366 +968,24 @@ void MainWindow::registerModPage(IPluginModPage *modPage) } -bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) -{ - { // generic treatment for all plugins - IPlugin *pluginObj = qobject_cast(plugin); - if (pluginObj == NULL) { - qDebug("not an IPlugin"); - return false; - } - plugin->setProperty("filename", fileName); - m_Settings.registerPlugin(pluginObj); - installTranslator(QFileInfo(fileName).baseName()); - } - - { // diagnosis plugins - IPluginDiagnose *diagnose = qobject_cast(plugin); - if (diagnose != NULL) { - m_DiagnosisPlugins.push_back(diagnose); - m_DiagnosisConnections.push_back( - diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); }) - ); - } - } - { // mod page plugin - IPluginModPage *modPage = qobject_cast(plugin); - if (verifyPlugin(modPage)) { - registerModPage(modPage); - return true; - } - } - { // tool plugins - IPluginTool *tool = qobject_cast(plugin); - if (verifyPlugin(tool)) { - registerPluginTool(tool); - return true; - } - } - { // installer plugins - IPluginInstaller *installer = qobject_cast(plugin); - if (verifyPlugin(installer)) { - installer->setParentWidget(this); - m_InstallationManager.registerInstaller(installer); - return true; - } - } - { // preview plugins - IPluginPreview *preview = qobject_cast(plugin); - if (verifyPlugin(preview)) { - m_PreviewGenerator.registerPlugin(preview); - return true; - } - } - { // proxy plugins - IPluginProxy *proxy = qobject_cast(plugin); - if (verifyPlugin(proxy)) { - proxy->setParentWidget(this); - QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath())); - foreach (const QString &pluginName, pluginNames) { - try { - QObject *proxiedPlugin = proxy->instantiate(pluginName); - if (proxiedPlugin != NULL) { - if (registerPlugin(proxiedPlugin, pluginName)) { - qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); - } else { - qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); - } - } - } catch (const std::exception &e) { - reportError(tr("failed to init plugin %1: %2").arg(pluginName).arg(e.what())); - } - } - return true; - } - } - - { // dummy plugins - // only initialize these, no processing otherwise - IPlugin *dummy = qobject_cast(plugin); - if (verifyPlugin(dummy)) { - return true; - } - } - - qDebug("no matching plugin interface"); - - return false; -} - -void MainWindow::unloadPlugins() -{ - // disconnect all slots before unloading plugins so plugins don't have to take care of that - m_AboutToRun.disconnect_all_slots(); - m_ModInstalled.disconnect_all_slots(); - m_ModList.disconnectSlots(); - m_PluginList.disconnectSlots(); - - m_DiagnosisPlugins.clear(); - - foreach (const boost::signals2::connection &connection, m_DiagnosisConnections) { - connection.disconnect(); - } - m_DiagnosisConnections.clear(); - - m_Settings.clearPlugins(); - - if (ui->actionTool->menu() != NULL) { - ui->actionTool->menu()->clear(); - } - - while (!m_PluginLoaders.empty()) { - QPluginLoader *loader = m_PluginLoaders.back(); - m_PluginLoaders.pop_back(); - if (!loader->unload()) { - qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString())); - } - delete loader; - } -} - -void MainWindow::loadPlugins() -{ - unloadPlugins(); - - foreach (QObject *plugin, QPluginLoader::staticInstances()) { - registerPlugin(plugin, ""); - } - - QFile loadCheck(qApp->property("dataPath").toString() + "/plugin_loadcheck.tmp"); - if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) { - // oh, there was a failed plugin load last time. Find out which plugin was loaded last - QString fileName; - while (!loadCheck.atEnd()) { - fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed(); - } - if (QMessageBox::question(this, tr("Plugin error"), - tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n" - "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. " - "The plugin may be able to recover from the problem)").arg(fileName), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { - m_Settings.addBlacklistPlugin(fileName); - } - loadCheck.close(); - } - - loadCheck.open(QIODevice::WriteOnly); - - QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); - qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData()); - QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot); - - while (iter.hasNext()) { - iter.next(); - if (m_Settings.pluginBlacklisted(iter.fileName())) { - qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName())); - continue; - } - loadCheck.write(iter.fileName().toUtf8()); - loadCheck.write("\n"); - loadCheck.flush(); - QString pluginName = iter.filePath(); - if (QLibrary::isLibrary(pluginName)) { - QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this); - if (pluginLoader->instance() == NULL) { - m_FailedPlugins.push_back(pluginName); - qCritical("failed to load plugin %s: %s", - qPrintable(pluginName), qPrintable(pluginLoader->errorString())); - } else { - if (registerPlugin(pluginLoader->instance(), pluginName)) { - qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); - m_PluginLoaders.push_back(pluginLoader); - } else { - m_FailedPlugins.push_back(pluginName); - qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); - } - } - } - } - - // remove the load check file on success - loadCheck.remove(); - - m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions()); - - m_DiagnosisPlugins.push_back(this); -} - - -void MainWindow::startSteam() -{ - QSettings steamSettings("HKEY_CURRENT_USER\\Software\\Valve\\Steam", - QSettings::NativeFormat); - QString exe = steamSettings.value("SteamExe", "").toString(); - if (!exe.isEmpty()) { - QString temp = QString("\"%1\"").arg(exe); - if (!QProcess::startDetached(temp)) { - reportError(tr("Failed to start \"%1\"").arg(temp)); - } else { - QMessageBox::information(this, tr("Waiting"), tr("Please press OK once you're logged into steam.")); - } - } -} - - -HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, - const QDir ¤tDirectory, const QString &steamAppID) -{ - storeSettings(); - - if (!binary.exists()) { - reportError(tr("Executable \"%1\" not found").arg(binary.fileName())); - return INVALID_HANDLE_VALUE; - } - - if (!steamAppID.isEmpty()) { - ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(steamAppID).c_str()); - } else { - ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(m_Settings.getSteamAppID()).c_str()); - } - - if ((GameInfo::instance().requiresSteam()) && - (m_Settings.getLoadMechanism() == LoadMechanism::LOAD_MODORGANIZER)) { - if (!testForSteam()) { - if (QuestionBoxMemory::query(this->isVisible() ? this : NULL, - "steamQuery", 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(); - } - } - } - - while (m_DirectoryUpdate) { - ::Sleep(100); - QCoreApplication::processEvents(); - } - - // need to make sure all data is saved before we start the application - if (m_CurrentProfile != nullptr) { - m_CurrentProfile->writeModlistNow(true); - } - - // TODO: should also pass arguments - if (m_AboutToRun(binary.absoluteFilePath())) { - return startBinary(binary, arguments, profileName, m_Settings.logLevel(), currentDirectory, true); - } else { - qDebug("start of \"%s\" canceled by plugin", qPrintable(binary.absoluteFilePath())); - return INVALID_HANDLE_VALUE; - } -} - -std::wstring getProcessName(DWORD processId) -{ - HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, processId); - - wchar_t buffer[MAX_PATH]; - if (::GetProcessImageFileNameW(process, buffer, MAX_PATH) != 0) { - wchar_t *fileName = wcsrchr(buffer, L'\\'); - if (fileName == nullptr) { - fileName = buffer; - } else { - fileName += 1; - } - return fileName; - } else { - return std::wstring(L"unknown"); - } -} - -void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID) -{ - LockedDialog *dialog = new LockedDialog(this); - dialog->show(); - ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); }); - - HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->getName(), currentDirectory, steamAppID); - if (processHandle != INVALID_HANDLE_VALUE) { - if (closeAfterStart) { - close(); - } else { - this->setEnabled(false); - // re-enable the locked dialog because what'd be the point otherwise? - dialog->setEnabled(true); - - QCoreApplication::processEvents(); - - DWORD retLen; - JOBOBJECT_BASIC_PROCESS_ID_LIST info; - - { - DWORD currentProcess = 0UL; - bool isJobHandle = true; - - 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); - } - } - ::CloseHandle(processHandle); - - this->setEnabled(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 - if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) { - QFile::remove(m_CurrentProfile->getLoadOrderFileName()); - refreshESPList(); - } - } - } -} - - void MainWindow::startExeAction() { QAction *action = qobject_cast(sender()); if (action != NULL) { Executable selectedExecutable = action->data().value(); - spawnBinary(selectedExecutable.m_BinaryInfo, - selectedExecutable.m_Arguments, - selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory - : selectedExecutable.m_BinaryInfo.absolutePath(), - selectedExecutable.m_CloseMO == DEFAULT_CLOSE, - selectedExecutable.m_SteamAppID); + m_OrganizerCore.spawnBinary( + selectedExecutable.m_BinaryInfo, + selectedExecutable.m_Arguments, + selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory + : selectedExecutable.m_BinaryInfo.absolutePath(), + selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE, + selectedExecutable.m_SteamAppID); } else { qCritical("not an action?"); } } -void MainWindow::setExecutablesList(const ExecutablesList &executablesList) -{ - m_ExecutablesList = executablesList; - refreshExecutablesList(); - updateToolBar(); -} - void MainWindow::setExecutableIndex(int index) { QComboBox *executableBox = findChild("executablesListBox"); @@ -1548,13 +1003,11 @@ void MainWindow::activateSelectedProfile() qDebug("activate profile \"%s\"", qPrintable(profileName)); QString profileDir = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())) .append("/").append(profileName); - delete m_CurrentProfile; - m_CurrentProfile = new Profile(QDir(profileDir)); - m_ModList.setProfile(m_CurrentProfile); + m_OrganizerCore.setCurrentProfile(new Profile(QDir(profileDir))); - m_ModListSortProxy->setProfile(m_CurrentProfile); + m_ModListSortProxy->setProfile(m_OrganizerCore.currentProfile()); - connect(m_CurrentProfile, SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint))); + connect(m_OrganizerCore.currentProfile(), SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint))); refreshSaveList(); refreshModList(); @@ -1567,9 +1020,9 @@ void MainWindow::on_profileBox_currentIndexChanged(int index) m_OldProfileIndex = index; if ((previousIndex != -1) && - (m_CurrentProfile != NULL) && - m_CurrentProfile->exists()) { - saveCurrentLists(); + (m_OrganizerCore.currentProfile() != NULL) && + m_OrganizerCore.currentProfile()->exists()) { + m_OrganizerCore.saveCurrentLists(); } // ensure the new index is valid @@ -1590,7 +1043,6 @@ void MainWindow::on_profileBox_currentIndexChanged(int index) } } - void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &directorySoFar, const DirectoryEntry &directoryEntry, bool conflictsOnly) { { @@ -1605,7 +1057,7 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director QStringList columns(fileName); bool isArchive = false; int originID = current->getOrigin(isArchive); - FilesOrigin origin = m_DirectoryStructure->getOriginByID(originID); + FilesOrigin origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID); QString source("data"); unsigned int modIndex = ModInfo::getIndex(ToQString(origin.getName())); if (modIndex != UINT_MAX) { @@ -1645,7 +1097,7 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director if (altIter != alternatives.begin()) { altString << " , "; } - altString << "" << m_DirectoryStructure->getOriginByID(*altIter).getName() << ""; + altString << "" << m_OrganizerCore.directoryStructure()->getOriginByID(*altIter).getName() << ""; } fileChild->setToolTip(1, QString("%1").arg(ToQString(altString.str()))); fileChild->setForeground(1, QBrush(Qt::red)); @@ -1706,7 +1158,7 @@ void MainWindow::expandDataTreeItem(QTreeWidgetItem *item) bool conflictsOnly = onDemandDataItem->data(0, Qt::UserRole + 2).toBool(); std::wstring virtualPath = (path + L"\\").substr(6) + ToWString(item->text(0)); - DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(virtualPath); + DirectoryEntry *dir = m_OrganizerCore.directoryStructure()->findSubDirectoryRecursive(virtualPath); if (dir != NULL) { updateTo(item, path, *dir, conflictsOnly); } else { @@ -1769,31 +1221,6 @@ bool MainWindow::refreshProfiles(bool selectProfile) } } -std::set MainWindow::enabledArchives() -{ - std::set result; - QFile archiveFile(m_CurrentProfile->getArchivesFileName()); - if (archiveFile.open(QIODevice::ReadOnly)) { - while (!archiveFile.atEnd()) { - result.insert(QString::fromUtf8(archiveFile.readLine()).trimmed()); - } - archiveFile.close(); - } - return result; -} - -void MainWindow::refreshDirectoryStructure() -{ - m_DirectoryUpdate = true; - std::vector > activeModList = m_CurrentProfile->getActiveMods(); - - m_DirectoryRefresher.setMods(activeModList, enabledArchives()); - - statusBar()->show(); - m_RefreshProgress->setRange(0, 100); - - QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh())); -} #if QT_VERSION >= 0x050000 extern QPixmap qt_pixmapFromWinHICON(HICON icon); @@ -1824,7 +1251,7 @@ void MainWindow::refreshExecutablesList() QAbstractItemModel *model = executablesList->model(); std::vector::const_iterator current, end; - m_ExecutablesList.getExecutables(current, end); + m_OrganizerCore.executablesList()->getExecutables(current, end); for(int i = 0; current != end; ++current, ++i) { QVariant temp; temp.setValue(*current); @@ -1846,7 +1273,7 @@ void MainWindow::refreshDataTree() QStringList columns("data"); columns.append(""); QTreeWidgetItem *subTree = new QTreeWidgetItem(columns); - updateTo(subTree, L"", *m_DirectoryStructure, conflictsBox->isChecked()); + updateTo(subTree, L"", *m_OrganizerCore.directoryStructure(), conflictsBox->isChecked()); tree->insertTopLevelItem(0, subTree); subTree->setExpanded(true); tree->header()->resizeSection(0, 200); @@ -1866,13 +1293,13 @@ void MainWindow::refreshSaveList() ui->savegameList->clear(); QDir savesDir; - if (m_CurrentProfile->localSavesEnabled()) { - savesDir.setPath(m_CurrentProfile->getPath() + "/saves"); + if (m_OrganizerCore.currentProfile()->localSavesEnabled()) { + savesDir.setPath(m_OrganizerCore.currentProfile()->getPath() + "/saves"); } else { wchar_t path[MAX_PATH]; ::GetPrivateProfileStringW(L"General", L"SLocalSavePath", L"Saves", path, MAX_PATH, - (ToWString(m_CurrentProfile->getPath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str()); + (ToWString(m_OrganizerCore.currentProfile()->getPath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str()); savesDir.setPath(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getDocumentsDir() + L"\\" + path))); } @@ -1895,67 +1322,15 @@ void MainWindow::refreshSaveList() } -void MainWindow::refreshLists() -{ - if ((m_CurrentProfile != NULL) && m_DirectoryStructure->isPopulated()) { - refreshESPList(); - refreshBSAList(); - } // no point in refreshing lists if no files have been added to the directory tree -} - - -void MainWindow::refreshESPList() -{ - m_CurrentProfile->writeModlist(); - - // clear list - try { - m_PluginList.refresh(m_CurrentProfile->getName(), - *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())); - } -} - -void MainWindow::refreshModList(bool saveChanges) -{ - // don't lose changes! - if (saveChanges) { - m_CurrentProfile->writeModlistNow(true); - } - ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign()); - - m_CurrentProfile->refreshModStatus(); - - m_ModList.notifyChange(-1); - - refreshDirectoryStructure(); -} - - static bool BySortValue(const std::pair &LHS, const std::pair &RHS) { return LHS.first < RHS.first; } -template -QStringList toStringList(InputIterator current, InputIterator end) +void MainWindow::updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives) { - QStringList result; - for (; current != end; ++current) { - result.append(*current); - } - return result; -} - -void MainWindow::refreshBSAList() -{ - m_ArchivesInit = false; ui->bsaList->clear(); #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) ui->bsaList->header()->setSectionResizeMode(QHeaderView::ResizeToContents); @@ -1963,40 +1338,9 @@ void MainWindow::refreshBSAList() ui->bsaList->header()->setResizeMode(QHeaderView::ResizeToContents); #endif - m_DefaultArchives.clear(); - - wchar_t buffer[256]; - std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName())); - if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - L"", buffer, 256, iniFileName.c_str()) != 0) { - m_DefaultArchives = ToQString(buffer).split(','); - } else { - std::vector vanillaBSAs = GameInfo::instance().getVanillaBSAs(); - for (auto iter = vanillaBSAs.begin(); iter != vanillaBSAs.end(); ++iter) { - m_DefaultArchives.append(ToQString(*iter)); - } - } - - 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(); - m_ActiveArchives = toStringList(iter.begin(), iter.end()); - if (m_ActiveArchives.isEmpty()) { - m_ActiveArchives = m_DefaultArchives; - } - std::vector > items; - std::vector files = m_DirectoryStructure->getFiles(); + std::vector files = m_OrganizerCore.directoryStructure()->getFiles(); for (auto iter = files.begin(); iter != files.end(); ++iter) { FileEntry::Ptr current = *iter; @@ -2004,7 +1348,7 @@ void MainWindow::refreshBSAList() QString extension = filename.right(3).toLower(); if (extension == "bsa") { - int index = m_ActiveArchives.indexOf(filename); + int index = activeArchives.indexOf(filename); if (index == -1) { index = 0xFFFF; } @@ -2012,20 +1356,20 @@ void MainWindow::refreshBSAList() QStringList strings(filename); bool isArchive = false; int origin = current->getOrigin(isArchive); - strings.append(ToQString(m_DirectoryStructure->getOriginByID(origin).getName())); + strings.append(ToQString(m_OrganizerCore.directoryStructure()->getOriginByID(origin).getName())); QTreeWidgetItem *newItem = new QTreeWidgetItem(strings); newItem->setData(0, Qt::UserRole, index); newItem->setData(1, Qt::UserRole, origin); 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_Settings.forceEnableCoreFiles() - && m_DefaultArchives.contains(filename)) { + if (m_OrganizerCore.settings().forceEnableCoreFiles() + && defaultArchives.contains(filename)) { newItem->setCheckState(0, Qt::Checked); newItem->setDisabled(true); newItem->setData(0, Qt::UserRole, true); - } else if ((m_PluginList.state(basename + ".esp") == IPluginList::STATE_ACTIVE) - || (m_PluginList.state(basename + ".esm") == IPluginList::STATE_ACTIVE)) { + } else if ((m_OrganizerCore.pluginList()->state(basename + ".esp") == IPluginList::STATE_ACTIVE) + || (m_OrganizerCore.pluginList()->state(basename + ".esm") == IPluginList::STATE_ACTIVE)) { newItem->setCheckState(0, Qt::Checked); newItem->setDisabled(true); } else { @@ -2039,7 +1383,7 @@ void MainWindow::refreshBSAList() if (index < 0) index = 0; - UINT32 sortValue = ((m_DirectoryStructure->getOriginByID(origin).getPriority() & 0xFFFF) << 16) | (index & 0xFFFF); + UINT32 sortValue = ((m_OrganizerCore.directoryStructure()->getOriginByID(origin).getPriority() & 0xFFFF) << 16) | (index & 0xFFFF); items.push_back(std::make_pair(sortValue, newItem)); } } @@ -2049,7 +1393,7 @@ void MainWindow::refreshBSAList() for (std::vector >::iterator iter = items.begin(); iter != items.end(); ++iter) { int originID = iter->second->data(1, Qt::UserRole).toInt(); - FilesOrigin origin = m_DirectoryStructure->getOriginByID(originID); + FilesOrigin origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID); QString modName("data"); unsigned int modIndex = ModInfo::getIndex(ToQString(origin.getName())); if (modIndex != UINT_MAX) { @@ -2069,12 +1413,11 @@ void MainWindow::refreshBSAList() subItem->setExpanded(true); } - checkBSAList(); - m_ArchivesInit = true; + m_OrganizerCore.checkBSAList(); } -void MainWindow::checkBSAList() +void MainWindow::checkBSAList(const QStringList &defaultArchives) { ui->bsaList->blockSignals(true); @@ -2090,7 +1433,7 @@ void MainWindow::checkBSAList() item->setToolTip(0, QString()); if (item->checkState(0) == Qt::Unchecked) { - if (m_DefaultArchives.contains(filename)) { + 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; @@ -2183,130 +1526,51 @@ void MainWindow::readSettings() } bool filtersVisible = settings.value("filters_visible", false).toBool(); - setCategoryListVisible(filtersVisible); - ui->displayCategoriesBtn->setChecked(filtersVisible); - - int selectedExecutable = settings.value("selected_executable").toInt(); - setExecutableIndex(selectedExecutable); - - if (settings.value("Settings/use_proxy", false).toBool()) { - activateProxy(true); - } - - ui->manageArchivesBox->blockSignals(true); - ui->manageArchivesBox->setChecked(settings.value("manage_bsas", true).toBool()); - ui->manageArchivesBox->blockSignals(false); -} - - -bool renameFile(const QString &oldName, const QString &newName, bool overwrite = true) -{ - if (overwrite && QFile::exists(newName)) { - QFile::remove(newName); - } - return QFile::rename(oldName, newName); -} - - -void MainWindow::storeSettings() -{ - if (m_CurrentProfile == NULL) { - return; - } - m_CurrentProfile->writeModlist(); - m_CurrentProfile->createTweakedIniFile(); - saveCurrentLists(); - m_Settings.setupLoadMechanism(); - - QString iniFile = ToQString(GameInfo::instance().getIniFilename()); - shellCopy(iniFile, iniFile + ".new", true, this); - - QSettings::Status result = QSettings::NoError; - { - QSettings settings(iniFile + ".new", QSettings::IniFormat); - settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData()); - - settings.setValue("mod_list_state", ui->modList->header()->saveState()); - settings.setValue("plugin_list_state", ui->espList->header()->saveState()); + setCategoryListVisible(filtersVisible); + ui->displayCategoriesBtn->setChecked(filtersVisible); - settings.setValue("group_state", ui->groupCombo->currentIndex()); + int selectedExecutable = settings.value("selected_executable").toInt(); + setExecutableIndex(selectedExecutable); - settings.setValue("ask_for_nexuspw", m_AskForNexusPW); + if (settings.value("Settings/use_proxy", false).toBool()) { + activateProxy(true); + } - settings.setValue("window_geometry", saveGeometry()); - settings.setValue("window_split", ui->splitter->saveState()); - settings.setValue("log_split", ui->topLevelSplitter->saveState()); + ui->manageArchivesBox->blockSignals(true); + ui->manageArchivesBox->setChecked(settings.value("manage_bsas", true).toBool()); + ui->manageArchivesBox->blockSignals(false); +} - settings.setValue("browser_geometry", m_IntegratedBrowser.saveGeometry()); - settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked()); - settings.setValue("manage_bsas", ui->manageArchivesBox->isChecked()); +void MainWindow::storeSettings(QSettings &settings) +{ + settings.setValue("mod_list_state", ui->modList->header()->saveState()); + settings.setValue("plugin_list_state", ui->espList->header()->saveState()); - settings.remove("customExecutables"); - settings.beginWriteArray("customExecutables"); - std::vector::const_iterator current, end; - m_ExecutablesList.getExecutables(current, end); - int count = 0; - for (; current != end; ++current) { - const Executable &item = *current; - if (item.m_Custom || item.m_Toolbar) { - settings.setArrayIndex(count++); - 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 == DEFAULT_CLOSE); - settings.setValue("steamAppID", item.m_SteamAppID); - settings.setValue("custom", item.m_Custom); - settings.setValue("toolbar", item.m_Toolbar); - } - } - settings.endArray(); + settings.setValue("group_state", ui->groupCombo->currentIndex()); - QComboBox *executableBox = findChild("executablesListBox"); - settings.setValue("selected_executable", executableBox->currentIndex()); + settings.setValue("window_geometry", saveGeometry()); + settings.setValue("window_split", ui->splitter->saveState()); + settings.setValue("log_split", ui->topLevelSplitter->saveState()); - FileDialogMemory::save(settings); + settings.setValue("browser_geometry", m_IntegratedBrowser.saveGeometry()); - settings.sync(); - result = settings.status(); - } - if (result == QSettings::NoError) { - if (!shellRename(iniFile + ".new", iniFile, true, this)) { - DWORD err = ::GetLastError(); - // make a second attempt using qt functions but if that fails print the error from the first attempt - if (!renameFile(iniFile + ".new", iniFile)) { - QMessageBox::critical(this, tr("Failed to write settings"), - tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(err))); - } - } - } else { - QString reason = result == QSettings::AccessError ? tr("File is write protected") - : result == QSettings::FormatError ? tr("Invalid file format (probably a bug)") - : tr("Unknown error %1").arg(result); - QMessageBox::critical(this, tr("Failed to write settings"), - tr("An error occured trying to write back MO settings: %1").arg(reason)); - } + settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked()); + settings.setValue("manage_bsas", ui->manageArchivesBox->isChecked()); } void MainWindow::on_btnRefreshData_clicked() { - if (!m_DirectoryUpdate) { - // save the mod list so changes don't get lost - m_CurrentProfile->writeModlistNow(true); - refreshDirectoryStructure(); - } else { - qDebug("directory update"); - } + m_OrganizerCore.refreshDirectoryStructure(); } void MainWindow::on_tabWidget_currentChanged(int index) { if (index == 0) { - refreshESPList(); + m_OrganizerCore.refreshESPList(); } else if (index == 1) { - refreshBSAList(); + m_OrganizerCore.refreshBSAList(); } else if (index == 2) { refreshDataTree(); } else if (index == 3) { @@ -2316,67 +1580,11 @@ void MainWindow::on_tabWidget_currentChanged(int index) } } -std::vector MainWindow::activeProblems() const -{ - std::vector problems; - if (m_FailedPlugins.size() != 0) { - problems.push_back(PROBLEM_PLUGINSNOTLOADED); - } - if (m_PluginList.enabledCount() > 255) { - problems.push_back(PROBLEM_TOOMANYPLUGINS); - } - return problems; -} - -QString MainWindow::shortDescription(unsigned int key) const -{ - switch (key) { - case PROBLEM_PLUGINSNOTLOADED: { - return tr("Some plugins could not be loaded"); - } break; - case PROBLEM_TOOMANYPLUGINS: { - return tr("Too many esps and esms enabled"); - } break; - default: { - return tr("Description missing"); - } break; - } -} - -QString MainWindow::fullDescription(unsigned int key) const -{ - switch (key) { - case PROBLEM_PLUGINSNOTLOADED: { - QString result = tr("The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:") + "
        "; - foreach (const QString &plugin, m_FailedPlugins) { - result += "
      • " + plugin + "
      • "; - } - result += "
          "; - return result; - } break; - case PROBLEM_TOOMANYPLUGINS: { - return tr("The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or " - "merge some plugins into one. You can find a guide here: http://wiki.step-project.com/Guide:Merging_Plugins"); - } break; - default: { - return tr("Description missing"); - } break; - } -} - -bool MainWindow::hasGuidedFix(unsigned int) const -{ - return false; -} - -void MainWindow::startGuidedFix(unsigned int) const -{ -} void MainWindow::installMod() { try { - QStringList extensions = m_InstallationManager.getSupportedExtensions(); + QStringList extensions = m_OrganizerCore.installationManager()->getSupportedExtensions(); for (auto iter = extensions.begin(); iter != extensions.end(); ++iter) { *iter = "*." + *iter; } @@ -2387,114 +1595,13 @@ void MainWindow::installMod() if (fileName.length() == 0) { return; } else { - installMod(fileName); + m_OrganizerCore.installMod(fileName); } } catch (const std::exception &e) { reportError(e.what()); } } -IModInterface *MainWindow::installMod(const QString &fileName) -{ - if (m_CurrentProfile == NULL) { - return NULL; - } - - bool hasIniTweaks = false; - GuessedValue modName; - m_CurrentProfile->writeModlistNow(); - m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); - if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) { - MessageDialog::showMessage(tr("Installation successful"), this); - refreshModList(); - - QModelIndexList posList = m_ModList.match(m_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); - 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); - return modInfo.data(); - } else { - reportError(tr("mod \"%1\" not found").arg(modName)); - } - } else if (m_InstallationManager.wasCancelled()) { - QMessageBox::information(this, tr("Installation cancelled"), tr("The mod was not installed completely."), QMessageBox::Ok); - } - return NULL; -} - -IModInterface *MainWindow::getMod(const QString &name) -{ - unsigned int index = ModInfo::getIndex(name); - if (index == UINT_MAX) { - return NULL; - } else { - return ModInfo::getByIndex(index).data(); - } -} - -IModInterface *MainWindow::createMod(GuessedValue &name) -{ - if (!m_InstallationManager.testOverwrite(name)) { - return NULL; - } - - m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); - - QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(name); - - QSettings settingsFile(targetDirectory.mid(0).append("/meta.ini"), QSettings::IniFormat); - - 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(); -} - -bool MainWindow::removeMod(IModInterface *mod) -{ - unsigned int index = ModInfo::getIndex(mod->name()); - if (index == UINT_MAX) { - return mod->remove(); - } else { - return ModInfo::removeMod(index); - } -} - -QList MainWindow::findFileInfos(const QString &path, const std::function &filter) const -{ - QList result; - DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path)); - if (dir != NULL) { - std::vector files = dir->getFiles(); - foreach (FileEntry::Ptr file, files) { - IOrganizer::FileInfo info; - info.filePath = ToQString(file->getFullPath()); - bool fromArchive = false; - info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive)).getName())); - info.archive = fromArchive ? ToQString(file->getArchive()) : ""; - foreach (int idx, file->getAlternatives()) { - info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(idx).getName())); - } - - if (filter(info)) { - result.append(info); - } - } - } - return result; -} void MainWindow::on_startButton_clicked() { @@ -2502,12 +1609,13 @@ void MainWindow::on_startButton_clicked() Executable selectedExecutable = executablesList->itemData(executablesList->currentIndex()).value(); - spawnBinary(selectedExecutable.m_BinaryInfo, - selectedExecutable.m_Arguments, - selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory - : selectedExecutable.m_BinaryInfo.absolutePath(), - selectedExecutable.m_CloseMO == DEFAULT_CLOSE, - selectedExecutable.m_SteamAppID); + m_OrganizerCore.spawnBinary( + selectedExecutable.m_BinaryInfo, + selectedExecutable.m_Arguments, + selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory + : selectedExecutable.m_BinaryInfo.absolutePath(), + selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE, + selectedExecutable.m_SteamAppID); } @@ -2584,9 +1692,9 @@ bool MainWindow::modifyExecutablesDialog() { bool result = false; try { - EditExecutablesDialog dialog(m_ExecutablesList); + EditExecutablesDialog dialog(m_OrganizerCore.executablesList()); if (dialog.exec() == QDialog::Accepted) { - m_ExecutablesList = dialog.getExecutablesList(); + m_OrganizerCore.setExecutablesDialog(dialog.getExecutablesList()); result = true; } refreshExecutablesList(); @@ -2698,26 +1806,6 @@ void MainWindow::setESPListSorting(int index) } -bool MainWindow::queryLogin(QString &username, QString &password) -{ - CredentialsDialog dialog(this); - int res = dialog.exec(); - if (dialog.neverAsk()) { - m_AskForNexusPW = false; - } - if (res == QDialog::Accepted) { - username = dialog.username(); - password = dialog.password(); - if (dialog.store()) { - m_Settings.setNexusLogin(username, password); - } - return true; - } else { - return false; - } -} - - bool MainWindow::setCurrentProfile(int index) { QComboBox *profilesBox = findChild("profileBox"); @@ -2746,136 +1834,45 @@ bool MainWindow::setCurrentProfile(const QString &name) void MainWindow::refresher_progress(int percent) { - m_RefreshProgress->setValue(percent); + if (percent == 100) { + m_RefreshProgress->setVisible(false); + } else if (!m_RefreshProgress->isVisible()) { + m_RefreshProgress->setVisible(true); + m_RefreshProgress->setRange(0, 100); + m_RefreshProgress->setValue(percent); + } } - void MainWindow::directory_refreshed() { - DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure(); - Q_ASSERT(newStructure != m_DirectoryStructure); - if (newStructure != NULL) { - std::swap(m_DirectoryStructure, newStructure); - delete newStructure; - refreshDataTree(); - } else { - // TODO: don't know why this happens, this slot seems to get called twice with only one emit - return; - } - m_DirectoryUpdate = false; - if (m_CurrentProfile != NULL) { - refreshLists(); - } - // some problem-reports may rely on the virtual directory tree so they need to be updated // now + refreshDataTree(); updateProblemsButton(); - - for (int i = 0; i < m_ModList.rowCount(); ++i) { - ModInfo::Ptr modInfo = ModInfo::getByIndex(i); - modInfo->clearCaches(); - } statusBar()->hide(); } -void MainWindow::externalMessage(const QString &message) -{ - if (message.left(6).toLower() == "nxm://") { - MessageDialog::showMessage(tr("Download started"), this); - downloadRequestedNXM(message); - } -} - -void MainWindow::updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo) -{ - // add files of the bsa to the directory structure - m_DirectoryRefresher.addModFilesToStructure(m_DirectoryStructure - , modInfo->name() - , m_CurrentProfile->getModPriority(index) - , modInfo->absolutePath() - , modInfo->stealFiles() - ); - DirectoryRefresher::cleanStructure(m_DirectoryStructure); - // need to refresh plugin list now so we can activate esps - refreshESPList(); - // activate all esps of the specified mod so the bsas get activated along with it - updateModActiveState(index, true); - // now we need to refresh the bsa list and save it so there is no confusion about what archives are avaiable and active - refreshBSAList(); - saveArchiveList(); - m_DirectoryRefresher.setMods(m_CurrentProfile->getActiveMods(), enabledArchives()); - - // finally also add files from bsas to the directory structure - m_DirectoryRefresher.addModBSAToStructure(m_DirectoryStructure - , modInfo->name() - , m_CurrentProfile->getModPriority(index) - , modInfo->absolutePath() - , modInfo->archives() - ); -} - -void MainWindow::modStatusChanged(unsigned int index) -{ - try { - ModInfo::Ptr modInfo = ModInfo::getByIndex(index); - if (m_CurrentProfile->modEnabled(index)) { - updateModInDirectoryStructure(index, modInfo); - } else { - updateModActiveState(index, false); - refreshESPList(); - if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) { - FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())); - origin.enable(false); - } - } - modInfo->clearCaches(); - - for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) { - ModInfo::Ptr modInfo = ModInfo::getByIndex(i); - int priority = m_CurrentProfile->getModPriority(i); - if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) { - // priorities in the directory structure are one higher because data is 0 - m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1); - } - } - m_DirectoryStructure->getFileRegister()->sortOrigins(); - - refreshLists(); - } catch (const std::exception& e) { - reportError(tr("failed to update mod list: %1").arg(e.what())); - } -} - - -void MainWindow::removeOrigin(const QString &name) -{ - FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(name)); - origin.enable(false); - refreshLists(); -} - - void MainWindow::modorder_changed() { - for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) { - int priority = m_CurrentProfile->getModPriority(i); - if (m_CurrentProfile->modEnabled(i)) { + for (unsigned int i = 0; i < m_OrganizerCore.currentProfile()->numMods(); ++i) { + int priority = m_OrganizerCore.currentProfile()->getModPriority(i); + if (m_OrganizerCore.currentProfile()->modEnabled(i)) { ModInfo::Ptr modInfo = ModInfo::getByIndex(i); // priorities in the directory structure are one higher because data is 0 - m_DirectoryStructure->getOriginByName(ToWString(modInfo->internalName())).setPriority(priority + 1); + m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(modInfo->internalName())).setPriority(priority + 1); } } - refreshBSAList(); - m_CurrentProfile->writeModlist(); - saveArchiveList(); - m_DirectoryStructure->getFileRegister()->sortOrigins(); + m_OrganizerCore.refreshBSAList(); + m_OrganizerCore.currentProfile()->writeModlist(); + m_OrganizerCore.saveArchiveList(); + m_OrganizerCore.directoryStructure()->getFileRegister()->sortOrigins(); { // refresh selection QModelIndex current = ui->modList->currentIndex(); if (current.isValid()) { ModInfo::Ptr modInfo = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt()); modInfo->doConflictCheck(); - m_ModList.setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten()); + m_OrganizerCore.modList()->setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten()); if (m_ModListSortProxy != NULL) { m_ModListSortProxy->invalidate(); } @@ -2884,6 +1881,16 @@ void MainWindow::modorder_changed() } } +void MainWindow::modInstalled() +{ + 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)); + } +} + void MainWindow::procError(QProcess::ProcessError error) { reportError(tr("failed to spawn notepad.exe: %1").arg(error)); @@ -2895,15 +1902,6 @@ void MainWindow::procFinished(int, QProcess::ExitStatus) this->sender()->deleteLater(); } -void MainWindow::profileRefresh() -{ - // have to refresh mods twice (again in refreshModList), otherwise the refresh isn't complete. Not sure why - ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign()); - m_CurrentProfile->refreshModStatus(); - - refreshModList(); -} - void MainWindow::showMessage(const QString &message) { MessageDialog::showMessage(message, this); @@ -2987,12 +1985,12 @@ void MainWindow::modRenamed(const QString &oldName, const QString &newName) } // immediately refresh the active profile because the data in memory is invalid - m_CurrentProfile->refreshModStatus(); + m_OrganizerCore.currentProfile()->refreshModStatus(); // also fix the directory structure try { - if (m_DirectoryStructure->originExists(ToWString(oldName))) { - FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(oldName)); + if (m_OrganizerCore.directoryStructure()->originExists(ToWString(oldName))) { + FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(oldName)); origin.setName(ToWString(newName)); } else { @@ -3011,11 +2009,11 @@ void MainWindow::modlistChanged(int) void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName) { - const FileEntry::Ptr filePtr = m_DirectoryStructure->findFile(ToWString(filePath)); + const FileEntry::Ptr filePtr = m_OrganizerCore.directoryStructure()->findFile(ToWString(filePath)); if (filePtr.get() != NULL) { try { - if (m_DirectoryStructure->originExists(ToWString(newOriginName))) { - FilesOrigin &newOrigin = m_DirectoryStructure->getOriginByName(ToWString(newOriginName)); + if (m_OrganizerCore.directoryStructure()->originExists(ToWString(newOriginName))) { + FilesOrigin &newOrigin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(newOriginName)); QString fullNewPath = ToQString(newOrigin.getPath()) + "\\" + filePath; WIN32_FIND_DATAW findData; @@ -3023,8 +2021,8 @@ void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L""); } - if (m_DirectoryStructure->originExists(ToWString(oldOriginName))) { - FilesOrigin &oldOrigin = m_DirectoryStructure->getOriginByName(ToWString(oldOriginName)); + if (m_OrganizerCore.directoryStructure()->originExists(ToWString(oldOriginName))) { + FilesOrigin &oldOrigin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(oldOriginName)); filePtr->removeOrigin(oldOrigin.getID()); } } catch (const std::exception &e) { @@ -3140,7 +2138,7 @@ void MainWindow::restoreBackup_clicked() ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); if (backupRegEx.indexIn(modInfo->name()) != -1) { QString regName = backupRegEx.cap(1); - QDir modDir(QDir::fromNativeSeparators(m_Settings.getModDirectory())); + QDir modDir(QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory())); if (!modDir.exists(regName) || (QMessageBox::question(this, tr("Overwrite?"), tr("This will replace the existing mod \"%1\". Continue?").arg(regName), @@ -3148,7 +2146,7 @@ void MainWindow::restoreBackup_clicked() if (modDir.exists(regName) && !shellDelete(QStringList(modDir.absoluteFilePath(regName)))) { reportError(tr("failed to remove mod \"%1\"").arg(regName)); } else { - QString destinationPath = QDir::fromNativeSeparators(m_Settings.getModDirectory()) + "/" + regName; + QString destinationPath = QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory()) + "/" + regName; if (!modDir.rename(modInfo->absolutePath(), destinationPath)) { reportError(tr("failed to rename \"%1\" to \"%2\"").arg(modInfo->absolutePath()).arg(destinationPath)); } @@ -3158,43 +2156,18 @@ void MainWindow::restoreBackup_clicked() } } -void MainWindow::updateModActiveState(int index, bool active) -{ - ModInfo::Ptr modInfo = ModInfo::getByIndex(index); - - QDir dir(modInfo->absolutePath()); - foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) { - m_PluginList.enableESP(esm, active); - } - int enabled = 0; - QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files); - foreach (const QString &esp, esps) { - if (active != m_PluginList.isEnabled(esp)) { - m_PluginList.enableESP(esp, active); - ++enabled; - } - } - if (active && (enabled > 1)) { - MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this); - } - m_PluginList.refreshLoadOrder(); - // immediately save affected lists - savePluginList(); -// refreshBSAList(); -} - void MainWindow::modlistChanged(const QModelIndex&, int) { - m_CurrentProfile->writeModlist(); + m_OrganizerCore.currentProfile()->writeModlist(); } void MainWindow::modlistSelectionChanged(const QModelIndex ¤t, const QModelIndex&) { if (current.isValid()) { ModInfo::Ptr selectedMod = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt()); - m_ModList.setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten()); + m_OrganizerCore.modList()->setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten()); } else { - m_ModList.setOverwriteMarkers(std::set(), std::set()); + m_OrganizerCore.modList()->setOverwriteMarkers(std::set(), std::set()); } if ((m_ModListSortProxy != NULL) && !m_ModListSortProxy->beingInvalidated()) { @@ -3229,11 +2202,11 @@ void MainWindow::removeMod_clicked() QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // use mod names instead of indexes because those become invalid during the removal foreach (QString name, modNames) { - m_ModList.removeRowForce(ModInfo::getIndex(name)); + m_OrganizerCore.modList()->removeRowForce(ModInfo::getIndex(name)); } } } else { - m_ModList.removeRow(m_ContextRow, QModelIndex()); + m_OrganizerCore.modList()->removeRow(m_ContextRow, QModelIndex()); } } catch (const std::exception &e) { reportError(tr("failed to remove mod: %1").arg(e.what())); @@ -3244,9 +2217,9 @@ void MainWindow::removeMod_clicked() void MainWindow::modRemoved(const QString &fileName) { if (!fileName.isEmpty() && !QFileInfo(fileName).isAbsolute()) { - int index = m_DownloadManager.indexByName(fileName); + int index = m_OrganizerCore.downloadManager()->indexByName(fileName); if (index >= 0) { - m_DownloadManager.markUninstalled(index); + m_OrganizerCore.downloadManager()->markUninstalled(index); } } } @@ -3263,10 +2236,10 @@ void MainWindow::reinstallMod_clicked() if (fileInfo.exists()) { fullInstallationFile = installationFile; } else { - fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(fileInfo.fileName()); + fullInstallationFile = m_OrganizerCore.downloadManager()->getOutputDirectory().append("/").append(fileInfo.fileName()); } } else { - fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(installationFile); + fullInstallationFile = m_OrganizerCore.downloadManager()->getOutputDirectory().append("/").append(installationFile); } if (QFile::exists(fullInstallationFile)) { installMod(fullInstallationFile); @@ -3283,11 +2256,12 @@ void MainWindow::reinstallMod_clicked() void MainWindow::resumeDownload(int downloadIndex) { if (NexusInterface::instance()->getAccessManager()->loggedIn()) { - m_DownloadManager.resumeDownload(downloadIndex); + m_OrganizerCore.downloadManager()->resumeDownload(downloadIndex); } else { QString username, password; - if (m_Settings.getNexusLogin(username, password)) { - m_PostLoginTasks.push_back(boost::bind(&MainWindow::resumeDownload, _1, downloadIndex)); + 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)); NexusInterface::instance()->getAccessManager()->login(username, password); } else { MessageDialog::showMessage(tr("You need to be logged in with Nexus to resume a download"), this); @@ -3302,7 +2276,7 @@ void MainWindow::endorseMod(ModInfo::Ptr mod) mod->endorse(true); } else { QString username, password; - if (m_Settings.getNexusLogin(username, password)) { + if (m_OrganizerCore.settings().getNexusLogin(username, password)) { m_PostLoginTasks.push_back(boost::bind(&MainWindow::endorseMod, _1, mod)); NexusInterface::instance()->getAccessManager()->login(username, password); } else { @@ -3329,7 +2303,7 @@ void MainWindow::unendorse_clicked() if (NexusInterface::instance()->getAccessManager()->loggedIn()) { ModInfo::getByIndex(m_ContextRow)->endorse(false); } else { - if (m_Settings.getNexusLogin(username, password)) { + if (m_OrganizerCore.settings().getNexusLogin(username, password)) { m_PostLoginTasks.push_back(boost::mem_fn(&MainWindow::unendorse_clicked)); NexusInterface::instance()->getAccessManager()->login(username, password); } else { @@ -3338,12 +2312,21 @@ void MainWindow::unendorse_clicked() } } +void MainWindow::loginFailed(const QString &message) +{ + statusBar()->hide(); +} + +void MainWindow::windowTutorialFinished(const QString &windowName) +{ + m_OrganizerCore.settings().directInterface().setValue(QString("CompletedWindowTutorials/") + windowName, this); +} void MainWindow::overwriteClosed(int) { OverwriteInfoDialog *dialog = this->findChild("__overwriteDialog"); if (dialog != NULL) { - m_ModList.modInfoChanged(dialog->modInfo()); + m_OrganizerCore.modList()->modInfoChanged(dialog->modInfo()); dialog->deleteLater(); } } @@ -3351,7 +2334,7 @@ void MainWindow::overwriteClosed(int) void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab) { - m_ModList.modInfoAboutToChange(modInfo); + m_OrganizerCore.modList()->modInfoAboutToChange(modInfo); std::vector flags = modInfo->getFlags(); if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) { QDialog *dialog = this->findChild("__overwriteDialog"); @@ -3371,7 +2354,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, } } else { modInfo->saveMeta(); - ModInfoDialog dialog(modInfo, m_DirectoryStructure, modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this); + ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this); connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString))); connect(&dialog, SIGNAL(downloadRequest(QString)), this, SLOT(downloadRequestedNXM(QString))); connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection); @@ -3381,31 +2364,31 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, connect(&dialog, SIGNAL(endorseMod(ModInfo::Ptr)), this, SLOT(endorseMod(ModInfo::Ptr))); dialog.openTab(tab); - dialog.restoreTabState(m_Settings.directInterface().value("mod_info_tabs").toByteArray()); + dialog.restoreTabState(m_OrganizerCore.settings().directInterface().value("mod_info_tabs").toByteArray()); dialog.exec(); - m_Settings.directInterface().setValue("mod_info_tabs", dialog.saveTabState()); + m_OrganizerCore.settings().directInterface().setValue("mod_info_tabs", dialog.saveTabState()); modInfo->saveMeta(); emit modInfoDisplayed(); - m_ModList.modInfoChanged(modInfo); + m_OrganizerCore.modList()->modInfoChanged(modInfo); } - if (m_CurrentProfile->modEnabled(index)) { - FilesOrigin& origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())); + if (m_OrganizerCore.currentProfile()->modEnabled(index)) { + FilesOrigin& origin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(modInfo->name())); origin.enable(false); - if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) { - FilesOrigin& origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())); + if (m_OrganizerCore.directoryStructure()->originExists(ToWString(modInfo->name()))) { + FilesOrigin& origin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(modInfo->name())); origin.enable(false); - m_DirectoryRefresher.addModToStructure(m_DirectoryStructure + m_OrganizerCore.directoryRefresher()->addModToStructure(m_OrganizerCore.directoryStructure() , modInfo->name() - , m_CurrentProfile->getModPriority(index) + , m_OrganizerCore.currentProfile()->getModPriority(index) , modInfo->absolutePath() , modInfo->stealFiles() , modInfo->archives()); - DirectoryRefresher::cleanStructure(m_DirectoryStructure); - refreshLists(); + DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure()); + m_OrganizerCore.refreshLists(); } } } @@ -3413,7 +2396,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, void MainWindow::modOpenNext() { - QModelIndex index = m_ModListSortProxy->mapFromSource(m_ModList.index(m_ContextRow, 0)); + QModelIndex index = m_ModListSortProxy->mapFromSource(m_OrganizerCore.modList()->index(m_ContextRow, 0)); index = m_ModListSortProxy->index((index.row() + 1) % m_ModListSortProxy->rowCount(), 0); m_ContextRow = m_ModListSortProxy->mapToSource(index).row(); @@ -3430,7 +2413,7 @@ void MainWindow::modOpenNext() void MainWindow::modOpenPrev() { - QModelIndex index = m_ModListSortProxy->mapFromSource(m_ModList.index(m_ContextRow, 0)); + QModelIndex index = m_ModListSortProxy->mapFromSource(m_OrganizerCore.modList()->index(m_ContextRow, 0)); int row = index.row() - 1; if (row == -1) { row = m_ModListSortProxy->rowCount() - 1; @@ -3473,15 +2456,15 @@ 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_ModList, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + connect(this, SIGNAL(modListDataChanged(QModelIndex,QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex,QModelIndex))); - emit modListDataChanged(m_ModList.index(m_ContextRow, 0), m_ModList.index(m_ContextRow, m_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::visitOnNexus_clicked() { - int modID = m_ModList.data(m_ModList.index(m_ContextRow, 0), Qt::UserRole).toInt(); + int modID = m_OrganizerCore.modList()->data(m_OrganizerCore.modList()->index(m_ContextRow, 0), Qt::UserRole).toInt(); if (modID > 0) { nexusLinkActivated(QString("%1/mods/%2").arg(ToQString(GameInfo::instance().getNexusPage(false))).arg(modID)); } else { @@ -3508,9 +2491,9 @@ void MainWindow::information_clicked() void MainWindow::syncOverwrite() { ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); - SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_DirectoryStructure, this); + SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_OrganizerCore.directoryStructure(), this); if (syncDialog.exec() == QDialog::Accepted) { - syncDialog.apply(QDir::fromNativeSeparators(m_Settings.getModDirectory())); + syncDialog.apply(QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory())); modInfo->testValid(); refreshDirectoryStructure(); } @@ -3533,12 +2516,12 @@ void MainWindow::createModFromOverwrite() } } - if (getMod(name) != NULL) { + if (m_OrganizerCore.getMod(name) != NULL) { reportError(tr("A mod with this name already exists")); return; } - IModInterface *newMod = createMod(name); + IModInterface *newMod = m_OrganizerCore.createMod(name); if (newMod == NULL) { return; } @@ -3561,7 +2544,7 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index) if (!index.isValid()) { return; } - QModelIndex sourceIdx = mapToModel(&m_ModList, index); + QModelIndex sourceIdx = mapToModel(m_OrganizerCore.modList(), index); if (!sourceIdx.isValid()) { return; } @@ -3675,14 +2658,14 @@ void MainWindow::addRemoveCategories_MenuHandler() { if (selected.size() > 0) { foreach (const QPersistentModelIndex &idx, selected) { qDebug("change categories on: %s (ref: %s)", qPrintable(idx.data().toString()), qPrintable(m_ContextIdx.data().toString())); - QModelIndex modIdx = mapToModel(&m_ModList, idx); + QModelIndex modIdx = mapToModel(m_OrganizerCore.modList(), idx); if (modIdx.row() != m_ContextIdx.row()) { addRemoveCategoriesFromMenu(menu, modIdx.row(), m_ContextIdx.row()); } } replaceCategoriesFromMenu(menu, m_ContextIdx.row()); - m_ModList.notifyChange(-1); + m_OrganizerCore.modList()->notifyChange(-1); foreach (const QPersistentModelIndex &idx, selected) { ui->modList->selectionModel()->select(idx, QItemSelectionModel::Select | QItemSelectionModel::Rows); @@ -3690,7 +2673,7 @@ void MainWindow::addRemoveCategories_MenuHandler() { } else { //For single mod selections, just do a replace replaceCategoriesFromMenu(menu, m_ContextRow); - m_ModList.notifyChange(m_ContextRow); + m_OrganizerCore.modList()->notifyChange(m_ContextRow); } refreshFilters(); @@ -3708,12 +2691,12 @@ void MainWindow::replaceCategories_MenuHandler() { if (selected.size() > 0) { QStringList selectedMods; for (int i = 0; i < selected.size(); ++i) { - QModelIndex temp = mapToModel(&m_ModList, selected.at(i)); + QModelIndex temp = mapToModel(m_OrganizerCore.modList(), selected.at(i)); selectedMods.append(temp.data().toString()); - replaceCategoriesFromMenu(menu, mapToModel(&m_ModList, selected.at(i)).row()); + replaceCategoriesFromMenu(menu, mapToModel(m_OrganizerCore.modList(), selected.at(i)).row()); } - m_ModList.notifyChange(-1); + m_OrganizerCore.modList()->notifyChange(-1); // find mods by their name because indices are invalidated QAbstractItemModel *model = ui->modList->model(); @@ -3727,7 +2710,7 @@ void MainWindow::replaceCategories_MenuHandler() { } else { //For single mod selections, just do a replace replaceCategoriesFromMenu(menu, m_ContextRow); - m_ModList.notifyChange(m_ContextRow); + m_OrganizerCore.modList()->notifyChange(m_ContextRow); } refreshFilters(); @@ -3757,6 +2740,33 @@ void MainWindow::savePrimaryCategory() } } +bool MainWindow::saveArchiveList() +{ + if (m_ArchivesInit) { + SafeWriteFile archiveFile(m_OrganizerCore.currentProfile()->getArchivesFileName()); + for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { + QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i); + for (int j = 0; j < tlItem->childCount(); ++j) { + QTreeWidgetItem *item = tlItem->child(j); + if (item->checkState(0) == Qt::Checked) { + // in managed mode, "register" all enabled archives, otherwise register only the files registered in the ini + if (ui->manageArchivesBox->isChecked() + || item->data(0, Qt::UserRole).toBool()) { + archiveFile->write(item->text(0).toUtf8().append("\r\n")); + } + } + } + } + if (archiveFile.commitIfDifferent(m_ArchiveListHash)) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_OrganizerCore.currentProfile()->getArchivesFileName()))); + return true; + } + } else { + qWarning("archive list not initialised"); + } + return false; +} + void MainWindow::checkModsForUpdates() { statusBar()->show(); @@ -3765,8 +2775,8 @@ void MainWindow::checkModsForUpdates() m_RefreshProgress->setRange(0, m_ModsToUpdate); } else { QString username, password; - if (m_Settings.getNexusLogin(username, password)) { - m_PostLoginTasks.push_back(boost::mem_fn(&MainWindow::checkModsForUpdates)); + if (m_OrganizerCore.settings().getNexusLogin(username, password)) { + m_OrganizerCore.doAfterLogin(boost::mem_fn(&MainWindow::checkModsForUpdates)); NexusInterface::instance()->getAccessManager()->login(username, password); } else { // otherwise there will be no endorsement info m_ModsToUpdate = ModInfo::checkAllForUpdate(this); @@ -3891,7 +2901,7 @@ void MainWindow::exportModListCSV() for (unsigned int i = 0; i < numMods; ++i) { ModInfo::Ptr info = ModInfo::getByIndex(i); - bool enabled = m_CurrentProfile->modEnabled(i); + bool enabled = m_OrganizerCore.currentProfile()->modEnabled(i); if ((selection.getChoiceData().toInt() == 1) && !enabled) { continue; } else if ((selection.getChoiceData().toInt() == 2) && !m_ModListSortProxy->filterMatchesMod(info, enabled)) { @@ -3936,7 +2946,7 @@ QMenu *MainWindow::modListContextMenu() menu->addAction(tr("Check all for update"), this, SLOT(checkModsForUpdates())); - menu->addAction(tr("Refresh"), this, SLOT(profileRefresh())); + menu->addAction(tr("Refresh"), &m_OrganizerCore, SLOT(profileRefresh())); menu->addAction(tr("Export to csv..."), this, SLOT(exportModListCSV())); return menu; @@ -3947,7 +2957,7 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) try { QTreeView *modList = findChild("modList"); - m_ContextIdx = mapToModel(&m_ModList, modList->indexAt(pos)); + m_ContextIdx = mapToModel(m_OrganizerCore.modList(), modList->indexAt(pos)); m_ContextRow = m_ContextIdx.row(); QMenu *menu = NULL; @@ -4123,7 +3133,7 @@ void MainWindow::fixMods_clicked() for (int i = 0; i < save->numPlugins(); ++i) { const QString &pluginName = save->plugin(i); - if (!m_PluginList.isEnabled(pluginName)) { + if (!m_OrganizerCore.pluginList()->isEnabled(pluginName)) { missingPlugins[pluginName] = std::vector(); } } @@ -4145,8 +3155,8 @@ void MainWindow::fixMods_clicked() } // search in mods - for (unsigned int i = 0; i < m_CurrentProfile->numRegularMods(); ++i) { - int modIndex = m_CurrentProfile->modIndexByPriority(i); + for (unsigned int i = 0; i < m_OrganizerCore.currentProfile()->numRegularMods(); ++i) { + int modIndex = m_OrganizerCore.currentProfile()->modIndexByPriority(i); ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex); QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); @@ -4178,18 +3188,18 @@ void MainWindow::fixMods_clicked() for (std::set::iterator iter = modsToActivate.begin(); iter != modsToActivate.end(); ++iter) { if ((*iter != "") && (*iter != "")) { unsigned int modIndex = ModInfo::getIndex(*iter); - m_CurrentProfile->setModEnabled(modIndex, true); + m_OrganizerCore.currentProfile()->setModEnabled(modIndex, true); } } - m_CurrentProfile->writeModlist(); - refreshLists(); + m_OrganizerCore.currentProfile()->writeModlist(); + m_OrganizerCore.refreshLists(); std::set espsToActivate = dialog.getESPsToActivate(); for (std::set::iterator iter = espsToActivate.begin(); iter != espsToActivate.end(); ++iter) { - m_PluginList.enableESP(*iter); + m_OrganizerCore.pluginList()->enableESP(*iter); } - saveCurrentLists(); + m_OrganizerCore.saveCurrentLists(); } } @@ -4216,7 +3226,7 @@ void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) void MainWindow::linkToolbar() { const Executable &selectedExecutable = ui->executablesListBox->itemData(ui->executablesListBox->currentIndex()).value(); - Executable &exe = m_ExecutablesList.find(selectedExecutable.m_Title); + Executable &exe = m_OrganizerCore.executablesList()->find(selectedExecutable.m_Title); exe.m_Toolbar = !exe.m_Toolbar; ui->linkButton->menu()->actions().at(2)->setIcon(exe.m_Toolbar ? QIcon(":/MO/gui/remove") : QIcon(":/MO/gui/link")); updateToolBar(); @@ -4289,44 +3299,44 @@ void MainWindow::linkMenu() void MainWindow::downloadSpeed(const QString &serverName, int bytesPerSecond) { - m_Settings.setDownloadSpeed(serverName, bytesPerSecond); + m_OrganizerCore.settings().setDownloadSpeed(serverName, bytesPerSecond); } void MainWindow::on_actionSettings_triggered() { - QString oldModDirectory(m_Settings.getModDirectory()); - QString oldCacheDirectory(m_Settings.getCacheDirectory()); - bool oldDisplayForeign(m_Settings.displayForeign()); - bool proxy = m_Settings.useProxy(); - m_Settings.query(this); - m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); - m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory()); + QString oldModDirectory(m_OrganizerCore.settings().getModDirectory()); + QString oldCacheDirectory(m_OrganizerCore.settings().getCacheDirectory()); + bool oldDisplayForeign(m_OrganizerCore.settings().displayForeign()); + bool proxy = m_OrganizerCore.settings().useProxy(); + m_OrganizerCore.settings().query(this); + m_OrganizerCore.installationManager()->setModsDirectory(m_OrganizerCore.settings().getModDirectory()); + m_OrganizerCore.installationManager()->setDownloadDirectory(m_OrganizerCore.settings().getDownloadDirectory()); fixCategories(); refreshFilters(); - if (QDir::fromNativeSeparators(m_DownloadManager.getOutputDirectory()) != QDir::fromNativeSeparators(m_Settings.getDownloadDirectory())) { - if (m_DownloadManager.downloadsInProgress()) { + 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); } else { - m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory()); + m_OrganizerCore.downloadManager()->setOutputDirectory(m_OrganizerCore.settings().getDownloadDirectory()); } } - m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers()); + m_OrganizerCore.downloadManager()->setPreferredServers(m_OrganizerCore.settings().getPreferredServers()); - if ((m_Settings.getModDirectory() != oldModDirectory) - || (m_Settings.displayForeign() != oldDisplayForeign)) { - profileRefresh(); + if ((m_OrganizerCore.settings().getModDirectory() != oldModDirectory) + || (m_OrganizerCore.settings().displayForeign() != oldDisplayForeign)) { + m_OrganizerCore.profileRefresh(); } - if (m_Settings.getCacheDirectory() != oldCacheDirectory) { - NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory()); + if (m_OrganizerCore.settings().getCacheDirectory() != oldCacheDirectory) { + NexusInterface::instance()->setCacheDirectory(m_OrganizerCore.settings().getCacheDirectory()); } - if (proxy != m_Settings.useProxy()) { - activateProxy(m_Settings.useProxy()); + if (proxy != m_OrganizerCore.settings().useProxy()) { + activateProxy(m_OrganizerCore.settings().useProxy()); } - NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion()); + NexusInterface::instance()->setNMMVersion(m_OrganizerCore.settings().getNMMVersion()); updateDownloadListDelegate(); } @@ -4351,49 +3361,6 @@ void MainWindow::linkClicked(const QString &url) } -bool MainWindow::nexusLogin() -{ - QString username, password; - - NXMAccessManager *accessManager = NexusInterface::instance()->getAccessManager(); - - if (!accessManager->loginAttempted() - && !accessManager->loggedIn() - && (m_Settings.getNexusLogin(username, password) - || (m_AskForNexusPW - && queryLogin(username, password)))) { - accessManager->login(username, password); - return true; - } else { - return false; - } -} - - -void MainWindow::downloadRequestedNXM(const QString &url) -{ - qDebug("download requested: %s", qPrintable(url)); - if (nexusLogin()) { - m_PendingDownloads.append(url); - } else { - m_DownloadManager.addNXMDownload(url); - } -} - - -void MainWindow::downloadRequested(QNetworkReply *reply, int modID, const QString &fileName) -{ - try { - if (m_DownloadManager.addDownload(reply, QStringList(), fileName, modID, 0, new ModRepositoryFileInfo(modID))) { - MessageDialog::showMessage(tr("Download started"), this); - } - } catch (const std::exception &e) { - MessageDialog::showMessage(tr("Download failed"), this); - qCritical("exception starting download: %s", e.what()); - } -} - - void MainWindow::installTranslator(const QString &name) { QTranslator *translator = new QTranslator(this); @@ -4436,8 +3403,8 @@ void MainWindow::languageChange(const QString &newLanguage) void MainWindow::installDownload(int index) { try { - QString fileName = m_DownloadManager.getFilePath(index); - int modID = m_DownloadManager.getModID(index); + QString fileName = m_OrganizerCore.downloadManager()->getFilePath(index); + int modID = m_OrganizerCore.downloadManager()->getModID(index); GuessedValue modName; // see if there already are mods with the specified mod id @@ -4452,15 +3419,15 @@ void MainWindow::installDownload(int index) } } - m_CurrentProfile->writeModlistNow(); + m_OrganizerCore.currentProfile()->writeModlistNow(); bool hasIniTweaks = false; - m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); - if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) { + 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_ModList.match(m_ModList.index(0, 0), Qt::DisplayRole, static_cast(modName)); + 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)); } @@ -4479,10 +3446,10 @@ void MainWindow::installDownload(int index) } else { reportError(tr("mod \"%1\" not found").arg(modName)); } - m_DownloadManager.markInstalled(index); + m_OrganizerCore.downloadManager()->markInstalled(index); emit modInstalled(); - } else if (m_InstallationManager.wasCancelled()) { + } 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) { @@ -4512,7 +3479,7 @@ void MainWindow::writeDataToFile(QFile &file, const QString &directory, const Di file.write(fullName.toUtf8()); file.write("\t("); - file.write(ToQString(m_DirectoryStructure->getOriginByID(origin).getName()).toUtf8()); + file.write(ToQString(m_OrganizerCore.directoryStructure()->getOriginByID(origin).getName()).toUtf8()); file.write(")\r\n"); } } @@ -4535,7 +3502,7 @@ void MainWindow::writeDataToFile() reportError(tr("failed to write to file %1").arg(fileName)); } - writeDataToFile(file, "data", *m_DirectoryStructure); + writeDataToFile(file, "data", *m_OrganizerCore.directoryStructure()); file.close(); MessageDialog::showMessage(tr("%1 written").arg(QDir::toNativeSeparators(fileName)), this); @@ -4607,9 +3574,9 @@ void MainWindow::addAsExecutable() tr("Please enter a name for the executable"), QLineEdit::Normal, targetInfo.baseName()); if (!name.isEmpty()) { - m_ExecutablesList.addExecutable(name, binaryInfo.absoluteFilePath(), + m_OrganizerCore.executablesList()->addExecutable(name, binaryInfo.absoluteFilePath(), arguments, targetInfo.absolutePath(), - DEFAULT_STAY, QString(), + ExecutableInfo::CloseMOStyle::DEFAULT_STAY, QString(), true, false); refreshExecutablesList(); } @@ -4627,10 +3594,10 @@ void MainWindow::addAsExecutable() void MainWindow::originModified(int originID) { - FilesOrigin &origin = m_DirectoryStructure->getOriginByID(originID); + FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID); origin.enable(false); - m_DirectoryStructure->addFromOrigin(origin.getName(), origin.getPath(), origin.getPriority()); - DirectoryRefresher::cleanStructure(m_DirectoryStructure); + m_OrganizerCore.directoryStructure()->addFromOrigin(origin.getName(), origin.getPath(), origin.getPriority()); + DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure()); } @@ -4691,11 +3658,11 @@ void MainWindow::previewDataFile() // what we want is the path relative to the virtual data directory // crude: we search for the next slash after the base mod directory to skip everything up to the data-relative directory - int offset = m_Settings.getModDirectory().size() + 1; + int offset = m_OrganizerCore.settings().getModDirectory().size() + 1; offset = fileName.indexOf("/", offset); fileName = fileName.mid(offset + 1); - const FileEntry::Ptr file = m_DirectoryStructure->searchFile(ToWString(fileName), NULL); + const FileEntry::Ptr file = m_OrganizerCore.directoryStructure()->searchFile(ToWString(fileName), NULL); if (file.get() == NULL) { reportError(tr("file not found: %1").arg(fileName)); @@ -4705,12 +3672,12 @@ void MainWindow::previewDataFile() // set up preview dialog PreviewDialog preview(fileName); auto addFunc = [&] (int originId) { - FilesOrigin &origin = m_DirectoryStructure->getOriginByID(originId); + FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByID(originId); QString filePath = QDir::fromNativeSeparators(ToQString(origin.getPath())) + "/" + fileName; if (QFile::exists(filePath)) { // it's very possible the file doesn't exist, because it's inside an archive. we don't support that - QWidget *wid = m_PreviewGenerator.genPreview(filePath); - if (wid == NULL) { + QWidget *wid = m_PluginContainer.previewGenerator().genPreview(filePath); + if (wid == nullptr) { reportError(tr("failed to generate preview for %1").arg(filePath)); } else { preview.addVariant(ToQString(origin.getName()), wid); @@ -4737,7 +3704,7 @@ void MainWindow::openDataFile() QString arguments; switch (getBinaryExecuteInfo(targetInfo, binaryInfo, arguments)) { case 1: { - spawnBinaryDirect(binaryInfo, arguments, m_CurrentProfile->getName(), targetInfo.absolutePath(), ""); + 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); @@ -4769,10 +3736,10 @@ void MainWindow::motdReceived(const QString &motd) // internet connection is faster next time if (m_StartTime.secsTo(QTime::currentTime()) < 5) { uint hash = qHash(motd); - if (hash != m_Settings.getMotDHash()) { + if (hash != m_OrganizerCore.settings().getMotDHash()) { MotDDialog dialog(motd); dialog.exec(); - m_Settings.setMotDHash(hash); + m_OrganizerCore.settings().setMotDHash(hash); } } @@ -4797,7 +3764,7 @@ void MainWindow::on_dataTree_customContextMenuRequested(const QPoint &pos) menu.addAction(tr("Add as Executable"), this, SLOT(addAsExecutable())); QString fileName = m_ContextItem->text(0); - if (m_PreviewGenerator.previewSupported(QFileInfo(fileName).completeSuffix())) { + if (m_PluginContainer.previewGenerator().previewSupported(QFileInfo(fileName).completeSuffix())) { menu.addAction(tr("Preview"), this, SLOT(previewDataFile())); } @@ -4826,11 +3793,7 @@ void MainWindow::on_conflictsCheckBox_toggled(bool) void MainWindow::on_actionUpdate_triggered() { - if (nexusLogin()) { - m_PostLoginTasks.push_back([&](MainWindow*) { m_Updater.startUpdate(); }); - } else { - m_Updater.startUpdate(); - } + m_OrganizerCore.startMOUpdate(); } @@ -4846,16 +3809,22 @@ void MainWindow::on_actionEndorseMO_triggered() void MainWindow::updateDownloadListDelegate() { - if (m_Settings.compactDownloads()) { - ui->downloadView->setItemDelegate(new DownloadListWidgetCompactDelegate(&m_DownloadManager, m_Settings.metaDownloads(), - ui->downloadView, ui->downloadView)); + if (m_OrganizerCore.settings().compactDownloads()) { + ui->downloadView->setItemDelegate( + new DownloadListWidgetCompactDelegate(m_OrganizerCore.downloadManager(), + m_OrganizerCore.settings().metaDownloads(), + ui->downloadView, + ui->downloadView)); } else { - ui->downloadView->setItemDelegate(new DownloadListWidgetDelegate(&m_DownloadManager, m_Settings.metaDownloads(), - ui->downloadView, ui->downloadView)); + ui->downloadView->setItemDelegate( + new DownloadListWidgetDelegate(m_OrganizerCore.downloadManager(), + m_OrganizerCore.settings().metaDownloads(), + ui->downloadView, + ui->downloadView)); } - DownloadListSortProxy *sortProxy = new DownloadListSortProxy(&m_DownloadManager, ui->downloadView); - sortProxy->setSourceModel(new DownloadList(&m_DownloadManager, ui->downloadView)); + DownloadListSortProxy *sortProxy = new DownloadListSortProxy(m_OrganizerCore.downloadManager(), ui->downloadView); + sortProxy->setSourceModel(new DownloadList(m_OrganizerCore.downloadManager(), ui->downloadView)); connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), sortProxy, SLOT(updateFilter(QString))); connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString))); @@ -4864,11 +3833,11 @@ void MainWindow::updateDownloadListDelegate() ui->downloadView->header()->resizeSections(QHeaderView::Fixed); connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), this, SLOT(installDownload(int))); - connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), &m_DownloadManager, SLOT(queryInfo(int))); - connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), &m_DownloadManager, SLOT(removeDownload(int, bool))); - connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), &m_DownloadManager, SLOT(restoreDownload(int))); - connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), &m_DownloadManager, SLOT(cancelDownload(int))); - connect(ui->downloadView->itemDelegate(), SIGNAL(pauseDownload(int)), &m_DownloadManager, SLOT(pauseDownload(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))); + connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int))); + connect(ui->downloadView->itemDelegate(), SIGNAL(pauseDownload(int)), m_OrganizerCore.downloadManager(), SLOT(pauseDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(resumeDownload(int)), this, SLOT(resumeDownload(int))); } @@ -4957,7 +3926,7 @@ void MainWindow::nxmDownloadURLs(int, int, QVariant, QVariant resultData, int) // other keys: ConnectedUsers, Country, URI servers.append(info); } - m_Settings.updateServers(servers); + m_OrganizerCore.settings().updateServers(servers); } @@ -4972,62 +3941,6 @@ void MainWindow::nxmRequestFailed(int modID, int, QVariant, int, const QString & } -void MainWindow::loginSuccessful(bool necessary) -{ - if (necessary) { - MessageDialog::showMessage(tr("login successful"), this); - } - foreach (QString url, m_PendingDownloads) { - downloadRequestedNXM(url); - } - m_PendingDownloads.clear(); - foreach (auto task, m_PostLoginTasks) { - task(this); - } - - m_PostLoginTasks.clear(); - NexusInterface::instance()->loginCompleted(); -} - - -void MainWindow::loginSuccessfulUpdate(bool necessary) -{ - if (necessary) { - MessageDialog::showMessage(tr("login successful"), this); - } - m_Updater.startUpdate(); -} - - -void MainWindow::loginFailed(const QString &message) -{ - if (!m_PendingDownloads.isEmpty()) { - MessageDialog::showMessage(tr("login failed: %1. Trying to download anyway").arg(message), this); - foreach (QString url, m_PendingDownloads) { - downloadRequestedNXM(url); - } - m_PendingDownloads.clear(); - } else { - MessageDialog::showMessage(tr("login failed: %1").arg(message), this); - m_PostLoginTasks.clear(); - statusBar()->hide(); - } - NexusInterface::instance()->loginCompleted(); -} - - -void MainWindow::loginFailedUpdate(const QString &message) -{ - MessageDialog::showMessage(tr("login failed: %1. You need to log-in with Nexus to update MO.").arg(message), this); -} - - -void MainWindow::windowTutorialFinished(const QString &windowName) -{ - m_Settings.directInterface().setValue(QString("CompletedWindowTutorials/") + windowName, true); -} - - BSA::EErrorCode MainWindow::extractBSA(BSA::Archive &archive, BSA::Folder::Ptr folder, const QString &destination, QProgressDialog &progress) { @@ -5085,7 +3998,7 @@ void MainWindow::extractBSATriggered() QString targetFolder = FileDialogMemory::getExistingDirectory("extractBSA", this, tr("Extract BSA")); if (!targetFolder.isEmpty()) { BSA::Archive archive; - QString originPath = QDir::fromNativeSeparators(ToQString(m_DirectoryStructure->getOriginByName(ToWString(item->text(1))).getPath())); + QString originPath = QDir::fromNativeSeparators(ToQString(m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(item->text(1))).getPath())); QString archivePath = QString("%1\\%2").arg(originPath).arg(item->text(0)); BSA::EErrorCode result = archive.read(archivePath.toLocal8Bit().constData(), true); @@ -5166,7 +4079,7 @@ void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) void MainWindow::on_actionProblems_triggered() { - ProblemsDialog problems(m_DiagnosisPlugins, this); + ProblemsDialog problems(m_PluginContainer.plugins(), this); if (problems.hasProblems()) { problems.exec(); updateProblemsButton(); @@ -5217,10 +4130,10 @@ void MainWindow::updateESPLock(bool locked) QItemSelection currentSelection = ui->espList->selectionModel()->selection(); if (currentSelection.count() == 0) { // this path is probably useless - m_PluginList.lockESPIndex(m_ContextRow, locked); + m_OrganizerCore.pluginList()->lockESPIndex(m_ContextRow, locked); } else { Q_FOREACH (const QModelIndex &idx, currentSelection.indexes()) { - m_PluginList.lockESPIndex(mapToModel(&m_PluginList, idx).row(), locked); + m_OrganizerCore.pluginList()->lockESPIndex(mapToModel(m_OrganizerCore.pluginList(), idx).row(), locked); } } } @@ -5240,7 +4153,7 @@ void MainWindow::unlockESPIndex() void MainWindow::removeFromToolbar() { try { - Executable &exe = m_ExecutablesList.find(m_ContextAction->text()); + Executable &exe = m_OrganizerCore.executablesList()->find(m_ContextAction->text()); exe.m_Toolbar = false; } catch (const std::runtime_error&) { qDebug("executable doesn't exist any more"); @@ -5268,16 +4181,16 @@ void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos) m_ContextRow = m_PluginListSortProxy->mapToSource(ui->espList->indexAt(pos)).row(); QMenu menu; - menu.addAction(tr("Enable all"), &m_PluginList, SLOT(enableAll())); - menu.addAction(tr("Disable all"), &m_PluginList, SLOT(disableAll())); + menu.addAction(tr("Enable all"), m_OrganizerCore.pluginList(), SLOT(enableAll())); + menu.addAction(tr("Disable all"), m_OrganizerCore.pluginList(), SLOT(disableAll())); QItemSelection currentSelection = ui->espList->selectionModel()->selection(); bool hasLocked = false; bool hasUnlocked = false; Q_FOREACH (const QModelIndex &idx, currentSelection.indexes()) { int row = m_PluginListSortProxy->mapToSource(idx).row(); - if (m_PluginList.isEnabled(row)) { - if (m_PluginList.isESPLocked(row)) { + if (m_OrganizerCore.pluginList()->isEnabled(row)) { + if (m_OrganizerCore.pluginList()->isESPLocked(row)) { hasLocked = true; } else { hasUnlocked = true; @@ -5311,11 +4224,11 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index) QAbstractProxyModel *newModel = NULL; switch (index) { case 1: { - newModel = new QtGroupingProxy(&m_ModList, QModelIndex(), ModList::COL_CATEGORY, Qt::UserRole, + newModel = new QtGroupingProxy(m_OrganizerCore.modList(), QModelIndex(), ModList::COL_CATEGORY, Qt::UserRole, 0, Qt::UserRole + 2); } break; case 2: { - newModel = new QtGroupingProxy(&m_ModList, QModelIndex(), ModList::COL_MODID, Qt::DisplayRole, + newModel = new QtGroupingProxy(m_OrganizerCore.modList(), QModelIndex(), ModList::COL_MODID, Qt::DisplayRole, QtGroupingProxy::FLAG_NOGROUPNAME | QtGroupingProxy::FLAG_NOSINGLE, Qt::UserRole + 2); } break; @@ -5333,7 +4246,7 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index) connect(ui->modList, SIGNAL(collapsed(QModelIndex)), newModel, SLOT(collapsed(QModelIndex))); connect(newModel, SIGNAL(expandItem(QModelIndex)), this, SLOT(expandModList(QModelIndex))); } else { - m_ModListSortProxy->setSourceModel(&m_ModList); + m_ModListSortProxy->setSourceModel(m_OrganizerCore.modList()); } modFilterActive(m_ModListSortProxy->isFilterActive()); } @@ -5355,7 +4268,7 @@ void MainWindow::on_linkButton_pressed() void MainWindow::on_showHiddenBox_toggled(bool checked) { - m_DownloadManager.setShowHidden(checked); + m_OrganizerCore.downloadManager()->setShowHidden(checked); } @@ -5421,11 +4334,11 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU if (std::tr1::regex_match(line, match, exRequires)) { std::string modName(match[1].first, match[1].second); std::string dependency(match[2].first, match[2].second); - m_PluginList.addInformation(modName.c_str(), tr("depends on missing \"%1\"").arg(dependency.c_str())); + m_OrganizerCore.pluginList()->addInformation(modName.c_str(), tr("depends on missing \"%1\"").arg(dependency.c_str())); } else if (std::tr1::regex_match(line, match, exIncompatible)) { std::string modName(match[1].first, match[1].second); std::string dependency(match[2].first, match[2].second); - m_PluginList.addInformation(modName.c_str(), tr("incompatible with \"%1\"").arg(dependency.c_str())); + m_OrganizerCore.pluginList()->addInformation(modName.c_str(), tr("incompatible with \"%1\"").arg(dependency.c_str())); } else { qDebug("[loot] %s", line.c_str()); } @@ -5442,8 +4355,8 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList QString currentDirectory = cwd; QString profileName = profile; if (profile.length() == 0) { - if (m_CurrentProfile != NULL) { - profileName = m_CurrentProfile->getName(); + if (m_OrganizerCore.currentProfile() != NULL) { + profileName = m_OrganizerCore.currentProfile()->getName(); } else { throw MyException(tr("No profile set")); } @@ -5459,7 +4372,7 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList } std::vector::iterator current, end; - m_ExecutablesList.getExecutables(current, end); + m_OrganizerCore.executablesList()->getExecutables(current, end); for (; current != end; ++current) { if (current->m_BinaryInfo == binary) { steamAppID = current->m_SteamAppID; @@ -5473,7 +4386,7 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList } else { // only a file name, search executables list try { - const Executable &exe = m_ExecutablesList.find(executable); + const Executable &exe = m_OrganizerCore.executablesList()->find(executable); steamAppID = exe.m_SteamAppID; if (arguments == "") { arguments = exe.m_Arguments; @@ -5555,7 +4468,7 @@ void MainWindow::on_bossButton_clicked() std::string reportURL; std::string errorMessages; - m_CurrentProfile->writeModlistNow(); + m_OrganizerCore.currentProfile()->writeModlistNow(); bool success = false; @@ -5587,8 +4500,8 @@ void MainWindow::on_bossButton_clicked() createStdoutPipe(&stdOutRead, &stdOutWrite); HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"), parameters.join(" "), - m_CurrentProfile->getName(), - m_Settings.logLevel(), + m_OrganizerCore.currentProfile()->getName(), + m_OrganizerCore.settings().logLevel(), qApp->applicationDirPath() + "/loot", true, stdOutWrite); @@ -5596,7 +4509,7 @@ void MainWindow::on_bossButton_clicked() // we don't use the write end ::CloseHandle(stdOutWrite); - m_PluginList.clearAdditionalInformation(); + m_OrganizerCore.pluginList()->clearAdditionalInformation(); DWORD retLen; JOBOBJECT_BASIC_PROCESS_ID_LIST info; @@ -5669,11 +4582,11 @@ void MainWindow::on_bossButton_clicked() QJsonArray pluginMessages = pluginObj["messages"].toArray(); for (auto msgIter = pluginMessages.begin(); msgIter != pluginMessages.end(); ++msgIter) { QJsonObject msg = (*msgIter).toObject(); - m_PluginList.addInformation(pluginObj["name"].toString(), + m_OrganizerCore.pluginList()->addInformation(pluginObj["name"].toString(), QString("%1: %2").arg(msg["type"].toString(), msg["message"].toString())); } if (pluginObj["dirty"].toString() == "yes") - m_PluginList.addInformation(pluginObj["name"].toString(), "dirty"); + m_OrganizerCore.pluginList()->addInformation(pluginObj["name"].toString(), "dirty"); } } @@ -5708,9 +4621,9 @@ void MainWindow::on_bossButton_clicked() // if the game specifies load order by file time, our own load order file needs to be removed because it's outdated. // refreshESPList will then use the file time as the load order. if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) { - QFile::remove(m_CurrentProfile->getLoadOrderFileName()); + QFile::remove(m_OrganizerCore.currentProfile()->getLoadOrderFileName()); } - refreshESPList(); + m_OrganizerCore.refreshESPList(); } } @@ -5734,11 +4647,11 @@ bool MainWindow::createBackup(const QString &filePath, const QDateTime &time) void MainWindow::on_saveButton_clicked() { - savePluginList(); + m_OrganizerCore.savePluginList(); QDateTime now = QDateTime::currentDateTime(); - if (createBackup(m_CurrentProfile->getPluginsFileName(), now) - && createBackup(m_CurrentProfile->getLoadOrderFileName(), now) - && createBackup(m_CurrentProfile->getLockedOrderFileName(), now)) { + if (createBackup(m_OrganizerCore.currentProfile()->getPluginsFileName(), now) + && createBackup(m_OrganizerCore.currentProfile()->getLoadOrderFileName(), now) + && createBackup(m_OrganizerCore.currentProfile()->getLockedOrderFileName(), now)) { MessageDialog::showMessage(tr("Backup of load order created"), this); } } @@ -5775,32 +4688,32 @@ QString MainWindow::queryRestore(const QString &filePath) void MainWindow::on_restoreButton_clicked() { - QString pluginName = m_CurrentProfile->getPluginsFileName(); + QString pluginName = m_OrganizerCore.currentProfile()->getPluginsFileName(); QString choice = queryRestore(pluginName); if (!choice.isEmpty()) { - QString loadOrderName = m_CurrentProfile->getLoadOrderFileName(); - QString lockedName = m_CurrentProfile->getLockedOrderFileName(); + QString loadOrderName = m_OrganizerCore.currentProfile()->getLoadOrderFileName(); + QString lockedName = m_OrganizerCore.currentProfile()->getLockedOrderFileName(); if (!shellCopy(pluginName + "." + choice, pluginName, true, this) || !shellCopy(loadOrderName + "." + choice, loadOrderName, true, this) || !shellCopy(lockedName + "." + choice, lockedName, true, this)) { QMessageBox::critical(this, tr("Restore failed"), tr("Failed to restore the backup. Errorcode: %1").arg(windowsErrorString(::GetLastError()))); } - refreshESPList(); + m_OrganizerCore.refreshESPList(); } } void MainWindow::on_saveModsButton_clicked() { - m_CurrentProfile->writeModlistNow(true); + m_OrganizerCore.currentProfile()->writeModlistNow(true); QDateTime now = QDateTime::currentDateTime(); - if (createBackup(m_CurrentProfile->getModlistFileName(), now)) { + if (createBackup(m_OrganizerCore.currentProfile()->getModlistFileName(), now)) { MessageDialog::showMessage(tr("Backup of modlist created"), this); } } void MainWindow::on_restoreModsButton_clicked() { - QString modlistName = m_CurrentProfile->getModlistFileName(); + QString modlistName = m_OrganizerCore.currentProfile()->getModlistFileName(); QString choice = queryRestore(modlistName); if (!choice.isEmpty()) { if (!shellCopy(modlistName + "." + choice, modlistName, true, this)) { @@ -5845,5 +4758,5 @@ void MainWindow::on_managedArchiveLabel_linkHovered(const QString&) void MainWindow::on_manageArchivesBox_toggled(bool) { - refreshBSAList(); + m_OrganizerCore.refreshBSAList(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index ea79fc37..c8cb8152 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -29,18 +29,16 @@ along with Mod Organizer. If not, see . #include #include #include -#include #include "executableslist.h" #include "modlist.h" #include "pluginlist.h" +#include "plugincontainer.h" #define WIN32_LEAN_AND_MEAN #include #include #include "directoryrefresher.h" #include -#include -#include -#include +#include #include "settings.h" #include "downloadmanager.h" #include "installationmanager.h" @@ -52,6 +50,7 @@ along with Mod Organizer. If not, see . #include "savegameinfowidgetgamebryo.h" #include "previewgenerator.h" #include "browserdialog.h" +#include "iuserinterface.h" #include #include #ifndef Q_MOC_RUN @@ -67,42 +66,24 @@ class ModListSortProxy; class ModListGroupCategoriesProxy; -class MainWindow : public QMainWindow, public MOBase::IPluginDiagnose +class MainWindow : public QMainWindow, public IUserInterface { Q_OBJECT - Q_INTERFACES(MOBase::IPluginDiagnose) friend class OrganizerProxy; -private: - - struct SignalCombinerAnd - { - typedef bool result_type; - template - bool operator()(InputIterator first, InputIterator last) const - { - while (first != last) { - if (!(*first)) { - return false; - } - ++first; - } - return true; - } - }; - - typedef boost::signals2::signal SignalAboutToRunApplication; - typedef boost::signals2::signal SignalModInstalled; public: - explicit MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent = 0); + explicit MainWindow(const QString &exeName, QSettings &initSettings, + OrganizerCore &organizerCore, PluginContainer &pluginContainer, + QWidget *parent = 0); ~MainWindow(); + void storeSettings(QSettings &settings); void readSettings(); bool addProfile(); - void refreshBSAList(); + void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives); void refreshDataTree(); void refreshSaveList(); @@ -116,21 +97,13 @@ public: void createFirstProfile(); -/* void spawnProgram(const QString &fileName, const QString &argumentsArg, - const QString &profileName, const QDir ¤tDirectory);*/ - - void loadPlugins(); + bool saveArchiveList(); - virtual std::vector activeProblems() const; - virtual QString shortDescription(unsigned int key) const; - virtual QString fullDescription(unsigned int key) const; - virtual bool hasGuidedFix(unsigned int key) const; - virtual void startGuidedFix(unsigned int key) const; + void registerPluginTool(MOBase::IPluginTool *tool); + void registerModPage(MOBase::IPluginModPage *modPage); void addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info); - bool saveArchiveList(); - void createStdoutPipe(HANDLE *stdOutRead, HANDLE *stdOutWrite); std::string readFromPipe(HANDLE stdOutRead); void processLOOTOut(const std::string &lootOut, std::string &reportURL, std::string &errorMessages, QProgressDialog &dialog); @@ -141,16 +114,21 @@ public: void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo); - QString getOriginDisplayName(int originID); - void unloadPlugins(); -public slots: - void refreshLists(); + void installTranslator(const QString &name); + + virtual void disconnectPlugins(); + + virtual bool close(); + virtual void setEnabled(bool enabled); + + void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab); + +public slots: void displayColumnSelection(const QPoint &pos); - void externalMessage(const QString &message); void modorder_changed(); void refresher_progress(int percent); void directory_refreshed(); @@ -160,11 +138,6 @@ public slots: signals: - /** - * @brief emitted after a mod has been installed - * @node this is currently only used for tutorials - */ - void modInstalled(); /** * @brief emitted after the information dialog has been closed @@ -188,41 +161,28 @@ protected: private: - void refreshESPList(); void refreshModList(bool saveChanges = true); void actionToToolButton(QAction *&sourceAction); - bool verifyPlugin(MOBase::IPlugin *plugin); - void registerPluginTool(MOBase::IPluginTool *tool); - void registerModPage(MOBase::IPluginModPage *modPage); - bool registerPlugin(QObject *pluginObj, const QString &fileName); - bool unregisterPlugin(QObject *pluginObj, const QString &fileName); void updateToolBar(); void activateSelectedProfile(); void setExecutableIndex(int index); - bool testForSteam(); void startSteam(); HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID); - void spawnBinary(const QFileInfo &binary, const QString &arguments = "", const QDir ¤tDirectory = QDir(), bool closeAfterStart = true, 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(); - MOBase::IModInterface *installMod(const QString &fileName); - MOBase::IModInterface *getMod(const QString &name); - MOBase::IModInterface *createMod(MOBase::GuessedValue &name); - bool removeMod(MOBase::IModInterface *mod); QList findFileInfos(const QString &path, const std::function &filter) const; bool modifyExecutablesDialog(); - void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab); void displayModInformation(int row, int tab = 0); void testExtractBSA(int modIndex); @@ -256,10 +216,6 @@ private: // remove invalid category-references from mods void fixCategories(); - void storeSettings(); - - bool queryLogin(QString &username, QString &password); - void createHelpWidget(); bool extractProgress(QProgressDialog &extractProgress, int percentage, std::string fileName); @@ -288,7 +244,6 @@ private: static void setupNetworkProxy(bool activate); void activateProxy(bool activate); - void installTranslator(const QString &name); void setBrowserGeometry(const QByteArray &geometry); bool createBackup(const QString &filePath, const QDateTime &time); @@ -300,13 +255,8 @@ private: void scheduleUpdateButton(); - void updateModActiveState(int index, bool active); - private: - static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1; - static const unsigned int PROBLEM_TOOMANYPLUGINS = 2; - static const char *PATTERN_BACKUP_GLOB; static const char *PATTERN_BACKUP_REGEX; static const char *PATTERN_BACKUP_DATE; @@ -321,21 +271,15 @@ private: int m_OldProfileIndex; - QThread m_RefresherThread; - DirectoryRefresher m_DirectoryRefresher; - MOShared::DirectoryEntry *m_DirectoryStructure; std::vector m_ModNameList; // the mod-list to go with the directory structure QProgressBar *m_RefreshProgress; bool m_Refreshing; - ModList m_ModList; QAbstractItemModel *m_ModListGroupingProxy; ModListSortProxy *m_ModListSortProxy; - PluginList m_PluginList; PluginListSortProxy *m_PluginListSortProxy; - ExecutablesList m_ExecutablesList; int m_OldExecutableIndex; QString m_GamePath; @@ -347,28 +291,12 @@ private: //int m_SelectedSaveGame; - Settings m_Settings; - - DownloadManager m_DownloadManager; - InstallationManager m_InstallationManager; - - SelfUpdater m_Updater; - CategoryFactory &m_CategoryFactory; - Profile *m_CurrentProfile; - int m_ModsToUpdate; - QStringList m_PendingDownloads; - QList > m_PostLoginTasks; - bool m_AskForNexusPW; bool m_LoginAttempted; - QStringList m_DefaultArchives; - QStringList m_ActiveArchives; - bool m_DirectoryUpdate; - bool m_ArchivesInit; QTimer m_CheckBSATimer; QTimer m_SaveMetaTimer; QTimer m_UpdateProblemsTimer; @@ -376,23 +304,14 @@ private: QTime m_StartTime; SaveGameInfoWidget *m_CurrentSaveView; - MOBase::IGameInfo *m_GameInfo; - - std::vector m_DiagnosisPlugins; - std::vector m_DiagnosisConnections; - std::vector m_ModPages; - std::vector m_FailedPlugins; - std::vector m_PluginLoaders; + OrganizerCore &m_OrganizerCore; + PluginContainer &m_PluginContainer; - QFile m_PluginsCheck; - - SignalAboutToRunApplication m_AboutToRun; - SignalModInstalled m_ModInstalled; + MOBase::IPluginGame *m_ActiveGame; QString m_CurrentLanguage; std::vector m_Translators; - PreviewGenerator m_PreviewGenerator; BrowserDialog m_IntegratedBrowser; QFileSystemWatcher m_SavesWatcher; @@ -447,8 +366,6 @@ private slots: void modStatusChanged(unsigned int index); void saveSelectionChanged(QListWidgetItem *newItem); - bool saveCurrentLists(); - void windowTutorialFinished(const QString &windowName); BSA::EErrorCode extractBSA(BSA::Archive &archive, BSA::Folder::Ptr folder, const QString &destination, QProgressDialog &extractProgress); @@ -457,8 +374,6 @@ private slots: void createModFromOverwrite(); - void removeOrigin(const QString &name); - void procError(QProcess::ProcessError error); void procFinished(int exitCode, QProcess::ExitStatus exitStatus); @@ -466,17 +381,9 @@ private slots: void checkModsForUpdates(); void nexusLinkActivated(const QString &link); - void linkClicked(const QString &url); - - bool nexusLogin(); - - void loginSuccessful(bool necessary); - void loginSuccessfulUpdate(bool necessary); void loginFailed(const QString &message); - void loginFailedUpdate(const QString &message); - void downloadRequestedNXM(const QString &url); - void downloadRequested(QNetworkReply *reply, int modID, const QString &fileName); + void linkClicked(const QString &url); void installDownload(int index); void updateAvailable(); @@ -495,6 +402,8 @@ private slots: void modDetailsUpdated(bool success); void modlistChanged(int row); + void modInstalled(); + void nxmUpdatesAvailable(const std::vector &modIDs, QVariant userData, QVariant resultData, int requestID); void nxmEndorsementToggled(int, QVariant, QVariant resultData, int); void nxmDownloadURLs(int modID, int fileID, QVariant userData, QVariant resultData, int requestID); @@ -527,7 +436,7 @@ private slots: void startExeAction(); - void checkBSAList(); + void checkBSAList(const QStringList &defaultArchives); void updateProblemsButton(); @@ -538,7 +447,6 @@ private slots: void modlistChanged(const QModelIndex &index, int role); void fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName); - void savePluginList(); void modFilterActive(bool active); void espFilterChanged(const QString &filter); @@ -576,7 +484,6 @@ private slots: void modListSortIndicatorChanged(int column, Qt::SortOrder order); private slots: // ui slots - void profileRefresh(); // actions void on_actionAdd_Profile_triggered(); void on_actionInstallMod_triggered(); @@ -619,6 +526,7 @@ private slots: // ui slots void on_categoriesOrBtn_toggled(bool checked); void on_managedArchiveLabel_linkHovered(const QString &link); void on_manageArchivesBox_toggled(bool checked); + }; diff --git a/src/messagedialog.cpp b/src/messagedialog.cpp index 863d7628..36902bbf 100644 --- a/src/messagedialog.cpp +++ b/src/messagedialog.cpp @@ -82,7 +82,7 @@ void MessageDialog::resizeEvent(QResizeEvent *event) void MessageDialog::showMessage(const QString &text, QWidget *reference, bool bringToFront) { qDebug("%s", qPrintable(text)); - if (reference != NULL) { + if (reference != nullptr) { if (bringToFront || (qApp->activeWindow() != NULL)) { MessageDialog *dialog = new MessageDialog(text, reference); dialog->show(); diff --git a/src/organizer.pro b/src/organizer.pro index fd1e6aad..98dbcd4a 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -94,7 +94,9 @@ SOURCES += \ modflagicondelegate.cpp \ genericicondelegate.cpp \ organizerproxy.cpp \ - viewmarkingscrollbar.cpp + viewmarkingscrollbar.cpp \ + plugincontainer.cpp \ + organizercore.cpp HEADERS += \ @@ -174,7 +176,10 @@ HEADERS += \ modflagicondelegate.h \ genericicondelegate.h \ organizerproxy.h \ - viewmarkingscrollbar.h + viewmarkingscrollbar.h \ + plugincontainer.h \ + organizercore.h \ + iuserinterface.h FORMS += \ transfersavesdialog.ui \ @@ -279,7 +284,7 @@ CONFIG(debug, debug|release) { #QMAKE_CXXFLAGS_WARN_ON -= -W3 #QMAKE_CXXFLAGS_WARN_ON += -W4 -QMAKE_CXXFLAGS += -wd4100 -wd4127 -wd4512 -wd4189 +QMAKE_CXXFLAGS += /wd4100 -wd4127 -wd4512 -wd4189 CONFIG += embed_manifest_exe diff --git a/src/organizercore.cpp b/src/organizercore.cpp new file mode 100644 index 00000000..68989c8c --- /dev/null +++ b/src/organizercore.cpp @@ -0,0 +1,1249 @@ +#include "organizercore.h" +#include "mainwindow.h" +#include "gameinfoimpl.h" +#include "messagedialog.h" +#include "logbuffer.h" +#include "credentialsdialog.h" +#include "filedialogmemory.h" +#include "lockeddialog.h" +#include "modinfodialog.h" +#include "report.h" +#include "spawn.h" +#include "safewritefile.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOShared; +using namespace MOBase; + + +static bool isOnline() +{ + QList interfaces = QNetworkInterface::allInterfaces(); + + bool connected = false; + for (auto iter = interfaces.begin(); iter != interfaces.end() && !connected; ++iter) { + if ( (iter->flags() & QNetworkInterface::IsUp) && + (iter->flags() & QNetworkInterface::IsRunning) && + !(iter->flags() & QNetworkInterface::IsLoopBack)) { + auto addresses = iter->addressEntries(); + if (addresses.count() == 0) { + continue; + } + qDebug("interface %s seems to be up (address: %s)", + qPrintable(iter->humanReadableName()), + qPrintable(addresses[0].ip().toString())); + connected = true; + } + } + + return connected; +} + +static bool renameFile(const QString &oldName, const QString &newName, bool overwrite = true) +{ + if (overwrite && QFile::exists(newName)) { + QFile::remove(newName); + } + return QFile::rename(oldName, newName); +} + +static std::wstring getProcessName(DWORD processId) +{ + HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, processId); + + wchar_t buffer[MAX_PATH]; + if (::GetProcessImageFileNameW(process, buffer, MAX_PATH) != 0) { + wchar_t *fileName = wcsrchr(buffer, L'\\'); + if (fileName == nullptr) { + fileName = buffer; + } else { + fileName += 1; + } + return fileName; + } else { + return std::wstring(L"unknown"); + } +} + +static bool testForSteam() +{ + DWORD processIDs[1024]; + DWORD bytesReturned; + if (!::EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned)) { + qWarning("failed to determine if steam is running"); + return true; + } + + TCHAR processName[MAX_PATH]; + for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) { + memset(processName, '\0', sizeof(TCHAR) * MAX_PATH); + if (processIDs[i] != 0) { + HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]); + + if (process != NULL) { + HMODULE module; + DWORD ignore; + + // first module in a process is always the binary + 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; + } + } + } + } + } + + return false; +} + +static void startSteam(QWidget *widget) +{ + QSettings steamSettings("HKEY_CURRENT_USER\\Software\\Valve\\Steam", QSettings::NativeFormat); + QString exe = steamSettings.value("SteamExe", "").toString(); + if (!exe.isEmpty()) { + QString temp = QString("\"%1\"").arg(exe); + if (!QProcess::startDetached(temp)) { + reportError(QObject::tr("Failed to start \"%1\"").arg(temp)); + } else { + QMessageBox::information(widget, QObject::tr("Waiting"), + QObject::tr("Please press OK once you're logged into steam.")); + } + } +} + +template +QStringList toStringList(InputIterator current, InputIterator end) +{ + QStringList result; + for (; current != end; ++current) { + result.append(*current); + } + return result; +} + + +OrganizerCore::OrganizerCore(const QSettings &initSettings) + : m_GameInfo(new GameInfoImpl()) + , m_UserInterface(nullptr) + , m_PluginContainer(nullptr) + , m_CurrentProfile(nullptr) + , m_Settings() + , m_Updater(NexusInterface::instance()) + , m_AboutToRun() + , m_FinishedRun() + , m_ModInstalled() + , m_ModList(this) + , m_PluginList(this) + , m_DirectoryRefresher() + , m_DirectoryStructure(new DirectoryEntry(L"data", nullptr, 0)) + , m_DownloadManager(NexusInterface::instance(), this) + , m_InstallationManager() + , m_RefresherThread() + , m_AskForNexusPW(false) + , m_DirectoryUpdate(false) + , m_ArchivesInit(false) +{ + m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory()); + m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers()); + + NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory()); + NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion()); + + m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); + m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory()); + + connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString,int)), this, SLOT(downloadSpeed(QString,int))); + connect(&m_DirectoryRefresher, SIGNAL(refreshed()), this, SLOT(directory_refreshed())); + + connect(&m_ModList, SIGNAL(removeOrigin(QString)), this, SLOT(removeOrigin(QString))); + + connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool))); + connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString))); + + ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign()); + + // make directory refresher run in a separate thread + m_RefresherThread.start(); + m_DirectoryRefresher.moveToThread(&m_RefresherThread); + + m_AskForNexusPW = initSettings.value("ask_for_nexuspw", true).toBool(); +} + +OrganizerCore::~OrganizerCore() +{ + m_RefresherThread.exit(); + m_RefresherThread.wait(); + + prepareStart(); + + // profile has to be cleaned up before the modinfo-buffer is cleared + delete m_CurrentProfile; + m_CurrentProfile = nullptr; + + ModInfo::clear(); + LogBuffer::cleanQuit(); + m_ModList.setProfile(nullptr); + NexusInterface::instance()->cleanup(); + + delete m_GameInfo; + delete m_DirectoryStructure; +} + +void OrganizerCore::storeSettings() +{ + QString iniFile = ToQString(GameInfo::instance().getIniFilename()); + shellCopy(iniFile, iniFile + ".new", true, qApp->activeWindow()); + + QSettings::Status result = QSettings::NoError; + { + QSettings settings(iniFile + ".new", QSettings::IniFormat); + if (m_UserInterface != nullptr) { + m_UserInterface->storeSettings(settings); + } + settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData()); + settings.setValue("ask_for_nexuspw", m_AskForNexusPW); + + settings.remove("customExecutables"); + settings.beginWriteArray("customExecutables"); + std::vector::const_iterator current, end; + m_ExecutablesList.getExecutables(current, end); + int count = 0; + for (; current != end; ++current) { + const Executable &item = *current; + if (item.m_Custom || item.m_Toolbar) { + settings.setArrayIndex(count++); + 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(); + + QComboBox *executableBox = findChild("executablesListBox"); + settings.setValue("selected_executable", executableBox->currentIndex()); + + FileDialogMemory::save(settings); + + settings.sync(); + result = settings.status(); + } + if (result == QSettings::NoError) { + if (!shellRename(iniFile + ".new", iniFile, true, qApp->activeWindow())) { + DWORD err = ::GetLastError(); + // make a second attempt using qt functions but if that fails print the error from the first attempt + if (!renameFile(iniFile + ".new", iniFile)) { + QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"), + tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(err))); + } + } + } else { + QString reason = result == QSettings::AccessError ? tr("File is write protected") + : result == QSettings::FormatError ? tr("Invalid file format (probably a bug)") + : tr("Unknown error %1").arg(result); + QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"), + tr("An error occured trying to write back MO settings: %1").arg(reason)); + } +} + +void OrganizerCore::updateExecutablesList(QSettings &settings) +{ + m_ExecutablesList.init(m_PluginContainer->managedGame(ToQString(GameInfo::instance().getGameName()))); + + qDebug("setting up configured executables"); + + int numCustomExecutables = settings.beginReadArray("customExecutables"); + for (int i = 0; i < numCustomExecutables; ++i) { + settings.setArrayIndex(i); + ExecutableInfo::CloseMOStyle closeMO = + settings.value("closeOnStart").toBool() ? ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE + : ExecutableInfo::CloseMOStyle::DEFAULT_STAY; + m_ExecutablesList.addExecutable(settings.value("title").toString(), + settings.value("binary").toString(), + settings.value("arguments").toString(), + settings.value("workingDirectory", "").toString(), + closeMO, + settings.value("steamAppID", "").toString(), + settings.value("custom", true).toBool(), + settings.value("toolbar", false).toBool()); + } + + settings.endArray(); +} + +void OrganizerCore::setUserInterface(IUserInterface *userInterface, QWidget *widget) +{ + storeSettings(); + + m_UserInterface = userInterface; + + connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex,int)), widget, SLOT(modorder_changed())); + connect(&m_ModList, SIGNAL(showMessage(QString)), widget, SLOT(showMessage(QString))); + connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), widget, SLOT(modRenamed(QString,QString))); + connect(&m_ModList, SIGNAL(modUninstalled(QString)), widget, SLOT(modRemoved(QString))); + connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), widget, SLOT(modlistChanged(QModelIndex, int))); + connect(&m_ModList, SIGNAL(removeSelectedMods()), widget, SLOT(removeMod_clicked())); + connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), widget, SLOT(displayColumnSelection(QPoint))); + connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), widget, SLOT(fileMoved(QString, QString, QString))); + connect(&m_DownloadManager, SIGNAL(downloadAdded()), widget, SLOT(scrollToBottom())); + connect(&m_DownloadManager, SIGNAL(showMessage(QString)), widget, SLOT(showMessage(QString))); + + m_InstallationManager.setParentWidget(widget); + m_Updater.setUserInterface(widget); + + // this currently wouldn't work reliably if the ui isn't initialized yet to display the result + if (isOnline() && !m_Settings.offlineMode()) { + m_Updater.testForUpdate(); + } else { + qDebug("user doesn't seem to be connected to the internet"); + } +} + +void OrganizerCore::connectPlugins(PluginContainer *container) +{ + m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions()); + m_PluginContainer = container; +} + +void OrganizerCore::disconnectPlugins() +{ + m_AboutToRun.disconnect_all_slots(); + m_FinishedRun.disconnect_all_slots(); + m_ModInstalled.disconnect_all_slots(); + m_ModList.disconnectSlots(); + m_PluginList.disconnectSlots(); + + m_Settings.clearPlugins(); + m_PluginContainer = nullptr; +} + +Settings &OrganizerCore::settings() +{ + return m_Settings; +} + +bool OrganizerCore::nexusLogin() +{ + QString username, password; + + NXMAccessManager *accessManager = NexusInterface::instance()->getAccessManager(); + + if (!accessManager->loginAttempted() + && !accessManager->loggedIn() + && (m_Settings.getNexusLogin(username, password) + || (m_AskForNexusPW + && queryLogin(username, password)))) { + accessManager->login(username, password); + return true; + } else { + return false; + } +} + +bool OrganizerCore::queryLogin(QString &username, QString &password) +{ + CredentialsDialog dialog(qApp->activeWindow()); + int res = dialog.exec(); + if (dialog.neverAsk()) { + m_AskForNexusPW = false; + } + if (res == QDialog::Accepted) { + username = dialog.username(); + password = dialog.password(); + if (dialog.store()) { + m_Settings.setNexusLogin(username, password); + } + return true; + } else { + return false; + } +} + +void OrganizerCore::startMOUpdate() +{ + if (nexusLogin()) { + m_PostLoginTasks.append([&]() { m_Updater.startUpdate(); }); + } else { + m_Updater.startUpdate(); + } +} + +void OrganizerCore::downloadRequestedNXM(const QString &url) +{ + qDebug("download requested: %s", qPrintable(url)); + if (nexusLogin()) { + m_PendingDownloads.append(url); + } else { + m_DownloadManager.addNXMDownload(url); + } +} + +void OrganizerCore::externalMessage(const QString &message) +{ + if (message.left(6).toLower() == "nxm://") { + MessageDialog::showMessage(tr("Download started"), qApp->activeWindow()); + downloadRequestedNXM(message); + } +} + +void OrganizerCore::downloadRequested(QNetworkReply *reply, int modID, const QString &fileName) +{ + try { + if (m_DownloadManager.addDownload(reply, QStringList(), fileName, modID, 0, new ModRepositoryFileInfo(modID))) { + MessageDialog::showMessage(tr("Download started"), qApp->activeWindow()); + } + } catch (const std::exception &e) { + MessageDialog::showMessage(tr("Download failed"), qApp->activeWindow()); + qCritical("exception starting download: %s", e.what()); + } +} + +void OrganizerCore::removeOrigin(const QString &name) +{ + FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(name)); + origin.enable(false); + refreshLists(); +} + +InstallationManager *OrganizerCore::installationManager() +{ + return &m_InstallationManager; +} + +void OrganizerCore::setCurrentProfile(Profile *profile) { + delete m_CurrentProfile; + m_CurrentProfile = profile; + m_ModList.setProfile(profile); +} + +MOBase::IGameInfo &OrganizerCore::gameInfo() const +{ + return *m_GameInfo; +} + +MOBase::IModRepositoryBridge *OrganizerCore::createNexusBridge() const +{ + return new NexusBridge(); +} + +QString OrganizerCore::profileName() const +{ + if (m_CurrentProfile != NULL) { + return m_CurrentProfile->getName(); + } else { + return ""; + } +} + +QString OrganizerCore::profilePath() const +{ + if (m_CurrentProfile != NULL) { + return m_CurrentProfile->getPath(); + } else { + return ""; + } +} + +QString OrganizerCore::downloadsPath() const +{ + return QDir::fromNativeSeparators(m_Settings.getDownloadDirectory()); +} + +MOBase::VersionInfo OrganizerCore::appVersion() const +{ + return m_Updater.getVersion(); +} + +MOBase::IModInterface *OrganizerCore::getMod(const QString &name) +{ + unsigned int index = ModInfo::getIndex(name); + if (index == UINT_MAX) { + return NULL; + } else { + return ModInfo::getByIndex(index).data(); + } +} + +MOBase::IModInterface *OrganizerCore::createMod(GuessedValue &name) +{ + if (!m_InstallationManager.testOverwrite(name)) { + return NULL; + } + + m_InstallationManager.setModsDirectory(m_Settings.getModDirectory()); + + QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(name); + + QSettings settingsFile(targetDirectory.mid(0).append("/meta.ini"), QSettings::IniFormat); + + 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(); +} + +bool OrganizerCore::removeMod(MOBase::IModInterface *mod) +{ + unsigned int index = ModInfo::getIndex(mod->name()); + if (index == UINT_MAX) { + return mod->remove(); + } else { + return ModInfo::removeMod(index); + } +} + +void OrganizerCore::modDataChanged(MOBase::IModInterface *mod) +{ + refreshModList(false); +} + +QVariant OrganizerCore::pluginSetting(const QString &pluginName, const QString &key) const +{ + return m_Settings.pluginSetting(pluginName, key); +} + +void OrganizerCore::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) +{ + m_Settings.setPluginSetting(pluginName, key, value); +} + +QVariant OrganizerCore::persistent(const QString &pluginName, const QString &key, const QVariant &def) const +{ + return m_Settings.pluginPersistent(pluginName, key, def); +} + +void OrganizerCore::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync) +{ + m_Settings.setPluginPersistent(pluginName, key, value, sync); +} + +QString OrganizerCore::pluginDataPath() const +{ + QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); + return pluginPath + "/data"; +} + +MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName) +{ + if (m_CurrentProfile == nullptr) { + return nullptr; + } + + bool hasIniTweaks = false; + GuessedValue modName; + m_CurrentProfile->writeModlistNow(); + 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); + 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); + return modInfo.data(); + } else { + reportError(tr("mod \"%1\" not found").arg(modName)); + } + } else if (m_InstallationManager.wasCancelled()) { + QMessageBox::information(qApp->activeWindow(), tr("Installation cancelled"), + tr("The mod was not installed completely."), QMessageBox::Ok); + } + return nullptr; +} + +QString OrganizerCore::resolvePath(const QString &fileName) const +{ + if (m_DirectoryStructure == nullptr) { + return QString(); + } + const FileEntry::Ptr file = m_DirectoryStructure->searchFile(ToWString(fileName), nullptr); + if (file.get() != nullptr) { + return ToQString(file->getFullPath()); + } else { + return QString(); + } +} + +QStringList OrganizerCore::listDirectories(const QString &directoryName) const +{ + QStringList result; + DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(directoryName)); + if (dir != NULL) { + std::vector::iterator current, end; + dir->getSubDirectories(current, end); + for (; current != end; ++current) { + result.append(ToQString((*current)->getName())); + } + } + return result; +} + +QStringList OrganizerCore::findFiles(const QString &path, const std::function &filter) const +{ + QStringList result; + DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path)); + if (dir != NULL) { + std::vector files = dir->getFiles(); + foreach (FileEntry::Ptr file, files) { + if (filter(ToQString(file->getFullPath()))) { + result.append(ToQString(file->getFullPath())); + } + } + } else { + qWarning("directory %s not found", qPrintable(path)); + } + return result; +} + +QStringList OrganizerCore::getFileOrigins(const QString &fileName) const +{ + QStringList result; + const FileEntry::Ptr file = m_DirectoryStructure->searchFile(ToWString(QFileInfo(fileName).fileName()), NULL); + + if (file.get() != NULL) { + result.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin()).getName())); + foreach (int i, file->getAlternatives()) { + result.append(ToQString(m_DirectoryStructure->getOriginByID(i).getName())); + } + } else { + qDebug("%s not found", qPrintable(fileName)); + } + return result; +} + +QList OrganizerCore::findFileInfos(const QString &path, const std::function &filter) const +{ + QList result; + DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path)); + if (dir != NULL) { + std::vector files = dir->getFiles(); + foreach (FileEntry::Ptr file, files) { + IOrganizer::FileInfo info; + info.filePath = ToQString(file->getFullPath()); + bool fromArchive = false; + info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive)).getName())); + info.archive = fromArchive ? ToQString(file->getArchive()) : ""; + foreach (int idx, file->getAlternatives()) { + info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(idx).getName())); + } + + if (filter(info)) { + result.append(info); + } + } + } + return result; +} + +DownloadManager *OrganizerCore::downloadManager() +{ + return &m_DownloadManager; +} + +PluginList *OrganizerCore::pluginList() +{ + return &m_PluginList; +} + +ModList *OrganizerCore::modList() +{ + return &m_ModList; +} + +void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID) +{ + LockedDialog *dialog = new LockedDialog(qApp->activeWindow()); + dialog->show(); + ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); }); + + HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->getName(), currentDirectory, steamAppID); + if (processHandle != INVALID_HANDLE_VALUE) { + if (closeAfterStart && (m_UserInterface != nullptr)) { + m_UserInterface->close(); + } else { + if (m_UserInterface != nullptr) { + m_UserInterface->setEnabled(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; + + 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->setEnabled(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 + if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) { + QFile::remove(m_CurrentProfile->getLoadOrderFileName()); + refreshESPList(); + } + + m_FinishedRun(binary.absoluteFilePath(), processExitCode); + } + } +} + +HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, + const QDir ¤tDirectory, const QString &steamAppID) +{ + prepareStart(); + + if (!binary.exists()) { + reportError(tr("Executable \"%1\" not found").arg(binary.fileName())); + return INVALID_HANDLE_VALUE; + } + + if (!steamAppID.isEmpty()) { + ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(steamAppID).c_str()); + } else { + ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(m_Settings.getSteamAppID()).c_str()); + } + + if ((GameInfo::instance().requiresSteam()) + && (m_Settings.getLoadMechanism() == LoadMechanism::LOAD_MODORGANIZER)) { + if (!testForSteam()) { + QWidget *window = qApp->activeWindow(); + if ((window != nullptr) && (!window->isVisible())) { + window = nullptr; + } + if (QuestionBoxMemory::query(window, "steamQuery", + 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()); + } + } + } + + while (m_DirectoryUpdate) { + ::Sleep(100); + QCoreApplication::processEvents(); + } + + // need to make sure all data is saved before we start the application + if (m_CurrentProfile != nullptr) { + m_CurrentProfile->writeModlistNow(true); + } + + // TODO: should also pass arguments + if (m_AboutToRun(binary.absoluteFilePath())) { + return startBinary(binary, arguments, profileName, m_Settings.logLevel(), currentDirectory, true); + } else { + qDebug("start of \"%s\" canceled by plugin", qPrintable(binary.absoluteFilePath())); + return INVALID_HANDLE_VALUE; + } +} + +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); + } +} + +bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode) const +{ + if (m_UserInterface != nullptr) { + return m_UserInterface->waitForProcessOrJob(handle, exitCode); + } +} + +bool OrganizerCore::onAboutToRun(const std::function &func) +{ + auto conn = m_AboutToRun.connect(func); + return conn.connected(); +} + +bool OrganizerCore::onFinishedRun(const std::function &func) +{ + auto conn = m_FinishedRun.connect(func); + return conn.connected(); +} + +bool OrganizerCore::onModInstalled(const std::function &func) +{ + auto conn = m_ModInstalled.connect(func); + return conn.connected(); +} + +void OrganizerCore::refreshModList(bool saveChanges) +{ + // don't lose changes! + if (saveChanges) { + m_CurrentProfile->writeModlistNow(true); + } + ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign()); + + m_CurrentProfile->refreshModStatus(); + + m_ModList.notifyChange(-1); + + refreshDirectoryStructure(); +} + +void OrganizerCore::refreshESPList() +{ + m_CurrentProfile->writeModlist(); + + // clear list + try { + m_PluginList.refresh(m_CurrentProfile->getName(), + *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())); + } +} + + +void OrganizerCore::refreshBSAList() +{ + m_ArchivesInit = false; + + m_DefaultArchives.clear(); + + wchar_t buffer[256]; + std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName())); + if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), + L"", buffer, 256, iniFileName.c_str()) != 0) { + m_DefaultArchives = ToQString(buffer).split(','); + } else { + std::vector vanillaBSAs = GameInfo::instance().getVanillaBSAs(); + for (auto iter = vanillaBSAs.begin(); iter != vanillaBSAs.end(); ++iter) { + m_DefaultArchives.append(ToQString(*iter)); + } + } + + 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(); + m_ActiveArchives = toStringList(iter.begin(), iter.end()); + if (m_ActiveArchives.isEmpty()) { + m_ActiveArchives = m_DefaultArchives; + } + + if (m_UserInterface != nullptr) { + m_UserInterface->updateBSAList(); + } + + m_ArchivesInit = true; +} + +void OrganizerCore::refreshLists() +{ + if ((m_CurrentProfile != nullptr) && m_DirectoryStructure->isPopulated()) { + refreshESPList(); + refreshBSAList(); + } // no point in refreshing lists if no files have been added to the directory tree +} + +void OrganizerCore::updateModActiveState(int index, bool active) +{ + ModInfo::Ptr modInfo = ModInfo::getByIndex(index); + + QDir dir(modInfo->absolutePath()); + foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) { + m_PluginList.enableESP(esm, active); + } + int enabled = 0; + QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files); + foreach (const QString &esp, esps) { + if (active != m_PluginList.isEnabled(esp)) { + m_PluginList.enableESP(esp, active); + ++enabled; + } + } + if (active && (enabled > 1)) { + MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), qApp->activeWindow()); + } + m_PluginList.refreshLoadOrder(); + // immediately save affected lists + savePluginList(); +// refreshBSAList(); +} + +void OrganizerCore::updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo) +{ + // add files of the bsa to the directory structure + m_DirectoryRefresher.addModFilesToStructure(m_DirectoryStructure + , modInfo->name() + , m_CurrentProfile->getModPriority(index) + , modInfo->absolutePath() + , modInfo->stealFiles() + ); + DirectoryRefresher::cleanStructure(m_DirectoryStructure); + // need to refresh plugin list now so we can activate esps + refreshESPList(); + // activate all esps of the specified mod so the bsas get activated along with it + updateModActiveState(index, true); + // now we need to refresh the bsa list and save it so there is no confusion about what archives are avaiable and active + refreshBSAList(); + if (m_UserInterface != nullptr) { + m_UserInterface->saveArchiveList(); + } + m_DirectoryRefresher.setMods(m_CurrentProfile->getActiveMods(), enabledArchives()); + + // finally also add files from bsas to the directory structure + m_DirectoryRefresher.addModBSAToStructure(m_DirectoryStructure + , modInfo->name() + , m_CurrentProfile->getModPriority(index) + , modInfo->absolutePath() + , modInfo->archives() + ); +} + +void OrganizerCore::requestDownload(const QUrl &url, QNetworkReply *reply) +{ + if (m_PluginContainer != nullptr) { + for (IPluginModPage *modPage : m_PluginContainer->plugins()) { + ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo(); + if (modPage->handlesDownload(url, reply->url(), *fileInfo)) { + fileInfo->repository = modPage->name(); + m_DownloadManager.addDownload(reply, fileInfo); + return; + } + } + } + + // no mod found that could handle the download. Is it a nexus mod? + if (url.host() == "www.nexusmods.com") { + int modID = 0; + int fileID = 0; + QRegExp modExp("mods/(\\d+)"); + if (modExp.indexIn(url.toString()) != -1) { + modID = modExp.cap(1).toInt(); + } + QRegExp fileExp("fid=(\\d+)"); + if (fileExp.indexIn(reply->url().toString()) != -1) { + fileID = fileExp.cap(1).toInt(); + } + m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo(modID, fileID)); + } else { + if (QMessageBox::question(qApp->activeWindow(), tr("Download?"), + tr("A download has been started but no installed page plugin recognizes it.\n" + "If you download anyway no information (i.e. version) will be associated with the download.\n" + "Continue?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo()); + } + } +} + +ModListSortProxy *OrganizerCore::createModListProxyModel() +{ + ModListSortProxy *result = new ModListSortProxy(m_CurrentProfile, this); + result->setSourceModel(&m_ModList); + return result; +} + +PluginListSortProxy *OrganizerCore::createPluginListProxyModel() +{ + PluginListSortProxy *result = new PluginListSortProxy(this); + result->setSourceModel(&m_PluginList); + return result; +} + +std::set OrganizerCore::enabledArchives() +{ + std::set result; + QFile archiveFile(m_CurrentProfile->getArchivesFileName()); + if (archiveFile.open(QIODevice::ReadOnly)) { + while (!archiveFile.atEnd()) { + result.insert(QString::fromUtf8(archiveFile.readLine()).trimmed()); + } + archiveFile.close(); + } + return result; +} + +void OrganizerCore::refreshDirectoryStructure() +{ + if (!m_DirectoryUpdate) { + m_CurrentProfile->writeModlistNow(true); + + m_DirectoryUpdate = true; + std::vector > activeModList = m_CurrentProfile->getActiveMods(); + + m_DirectoryRefresher.setMods(activeModList, enabledArchives()); + + QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh())); + } else { + qDebug("directory update"); + } +} + +void OrganizerCore::directory_refreshed() +{ + DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure(); + Q_ASSERT(newStructure != m_DirectoryStructure); + if (newStructure != nullptr) { + std::swap(m_DirectoryStructure, newStructure); + delete newStructure; + } else { + // TODO: don't know why this happens, this slot seems to get called twice with only one emit + return; + } + m_DirectoryUpdate = false; + if (m_CurrentProfile != nullptr) { + refreshLists(); + } + + for (int i = 0; i < m_ModList.rowCount(); ++i) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(i); + modInfo->clearCaches(); + } +} + +void OrganizerCore::profileRefresh() +{ + // have to refresh mods twice (again in refreshModList), otherwise the refresh isn't complete. Not sure why + ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign()); + m_CurrentProfile->refreshModStatus(); + + refreshModList(); +} + +void OrganizerCore::modStatusChanged(unsigned int index) +{ + try { + ModInfo::Ptr modInfo = ModInfo::getByIndex(index); + if (m_CurrentProfile->modEnabled(index)) { + updateModInDirectoryStructure(index, modInfo); + } else { + updateModActiveState(index, false); + refreshESPList(); + if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) { + FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())); + origin.enable(false); + } + } + modInfo->clearCaches(); + + for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(i); + int priority = m_CurrentProfile->getModPriority(i); + if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) { + // priorities in the directory structure are one higher because data is 0 + m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1); + } + } + m_DirectoryStructure->getFileRegister()->sortOrigins(); + + refreshLists(); + } catch (const std::exception& e) { + reportError(tr("failed to update mod list: %1").arg(e.what())); + } +} + +void OrganizerCore::loginSuccessful(bool necessary) +{ + if (necessary) { + MessageDialog::showMessage(tr("login successful"), qApp->activeWindow()); + } + foreach (QString url, m_PendingDownloads) { + downloadRequestedNXM(url); + } + m_PendingDownloads.clear(); + for (auto task : m_PostLoginTasks) { + task(); + } + + m_PostLoginTasks.clear(); + NexusInterface::instance()->loginCompleted(); +} + +void OrganizerCore::loginSuccessfulUpdate(bool necessary) +{ + if (necessary) { + MessageDialog::showMessage(tr("login successful"), qApp->activeWindow()); + } + m_Updater.startUpdate(); +} + +void OrganizerCore::loginFailed(const QString &message) +{ + if (!m_PendingDownloads.isEmpty()) { + MessageDialog::showMessage(tr("login failed: %1. Trying to download anyway").arg(message), qApp->activeWindow()); + foreach (QString url, m_PendingDownloads) { + downloadRequestedNXM(url); + } + m_PendingDownloads.clear(); + } else { + MessageDialog::showMessage(tr("login failed: %1").arg(message), qApp->activeWindow()); + m_PostLoginTasks.clear(); + } + NexusInterface::instance()->loginCompleted(); +} + + +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()); +} + + +std::vector OrganizerCore::activeProblems() const +{ + std::vector problems; + if (enabledCount() > 255) { + problems.push_back(PROBLEM_TOOMANYPLUGINS); + } + return problems; +} + +QString OrganizerCore::shortDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_TOOMANYPLUGINS: { + return tr("Too many esps and esms enabled"); + } break; + default: { + return tr("Description missing"); + } break; + } +} + +QString OrganizerCore::fullDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_TOOMANYPLUGINS: { + return tr("The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or " + "merge some plugins into one. You can find a guide here: http://wiki.step-project.com/Guide:Merging_Plugins"); + } break; + default: { + return tr("Description missing"); + } break; + } +} + +bool OrganizerCore::hasGuidedFix(unsigned int) const +{ + return false; +} + +void OrganizerCore::startGuidedFix(unsigned int) const +{ +} + +bool OrganizerCore::saveCurrentLists() +{ + if (m_DirectoryUpdate) { + qWarning("not saving lists during directory update"); + return false; + } + + try { + savePluginList(); + if (m_UserInterface != nullptr) { + m_UserInterface->saveArchiveList(); + } + } catch (const std::exception &e) { + reportError(tr("failed to save load order: %1").arg(e.what())); + } + + return true; +} + +void OrganizerCore::savePluginList() +{ + m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(), + m_CurrentProfile->getLoadOrderFileName(), + m_CurrentProfile->getLockedOrderFileName(), + m_CurrentProfile->getDeleterFileName(), + m_Settings.hideUncheckedPlugins()); + m_PluginList.saveLoadOrder(*m_DirectoryStructure); +} + +void OrganizerCore::prepareStart() { + if (m_CurrentProfile == nullptr) { + return; + } + m_CurrentProfile->writeModlist(); + m_CurrentProfile->createTweakedIniFile(); + saveCurrentLists(); + m_Settings.setupLoadMechanism(); + storeSettings(); +} + diff --git a/src/organizercore.h b/src/organizercore.h new file mode 100644 index 00000000..b362a002 --- /dev/null +++ b/src/organizercore.h @@ -0,0 +1,239 @@ +#ifndef ORGANIZERCORE_H +#define ORGANIZERCORE_H + + +#include "profile.h" +#include "selfupdater.h" +#include "iuserinterface.h" +#include "settings.h" +#include "modlist.h" +#include "pluginlist.h" +#include "directoryrefresher.h" +#include "installationmanager.h" +#include "downloadmanager.h" +#include "modlistsortproxy.h" +#include "pluginlistsortproxy.h" +#include "executableslist.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class PluginContainer; + + +class OrganizerCore : public QObject, public MOBase::IPluginDiagnose +{ + + Q_OBJECT + Q_INTERFACES(MOBase::IPluginDiagnose) + +private: + + struct SignalCombinerAnd + { + typedef bool result_type; + template + bool operator()(InputIterator first, InputIterator last) const + { + while (first != last) { + if (!(*first)) { + return false; + } + ++first; + } + return true; + } + }; + +private: + + typedef boost::signals2::signal SignalAboutToRunApplication; + typedef boost::signals2::signal SignalFinishedRunApplication; + typedef boost::signals2::signal SignalModInstalled; + +public: + + OrganizerCore(const QSettings &initSettings); + + ~OrganizerCore(); + + void setUserInterface(IUserInterface *userInterface, QWidget *widget); + void connectPlugins(PluginContainer *container); + void disconnectPlugins(); + + void updateExecutablesList(QSettings &settings); + + void startMOUpdate(); + + Settings &settings(); + SelfUpdater *updater() { return &m_Updater; } + InstallationManager *installationManager(); + MOShared::DirectoryEntry *directoryStructure() { return m_DirectoryStructure; } + DirectoryRefresher *directoryRefresher() { return &m_DirectoryRefresher; } + ExecutablesList *executablesList() { return &m_ExecutablesList; } + void setExecutablesDialog(const ExecutablesList &executablesList) { m_ExecutablesList = executablesList; } + + Profile *currentProfile() { return m_CurrentProfile; } + void setCurrentProfile(Profile *profile); + + void setExecutablesList(const ExecutablesList &executablesList); + + std::set enabledArchives(); + + MOBase::VersionInfo getVersion() const { return m_Updater.getVersion(); } + + ModListSortProxy *createModListProxyModel(); + PluginListSortProxy *createPluginListProxyModel(); + + bool isArchivesInit() const { return m_ArchivesInit; } + + bool saveCurrentLists(); + void savePluginList(); + + void prepareStart(); + + void refreshESPList(); + void refreshBSAList(); + + void refreshDirectoryStructure(); + void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo); + + void requestDownload(const QUrl &url, QNetworkReply *reply); + + void doAfterLogin(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 = ""); + + void modStatusChanged(unsigned int index); + + void loginSuccessful(bool necessary); + void loginSuccessfulUpdate(bool necessary); + void loginFailed(const QString &message); + void loginFailedUpdate(const QString &message); + +public: + virtual MOBase::IGameInfo &gameInfo() const; + virtual MOBase::IModRepositoryBridge *createNexusBridge() const; + virtual QString profileName() const; + virtual QString profilePath() const; + virtual QString downloadsPath() const; + virtual MOBase::VersionInfo appVersion() const; + virtual MOBase::IModInterface *getMod(const QString &name); + virtual MOBase::IModInterface *createMod(MOBase::GuessedValue &name); + virtual bool removeMod(MOBase::IModInterface *mod); + virtual void modDataChanged(MOBase::IModInterface *mod); + virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const; + virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value); + virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def) const; + virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync); + virtual QString pluginDataPath() const; + virtual MOBase::IModInterface *installMod(const QString &fileName); + virtual QString resolvePath(const QString &fileName) const; + virtual QStringList listDirectories(const QString &directoryName) const; + virtual QStringList findFiles(const QString &path, const std::function &filter) const; + virtual QStringList getFileOrigins(const QString &fileName) const; + virtual QList findFileInfos(const QString &path, const std::function &filter) const; + virtual DownloadManager *downloadManager(); + virtual PluginList *pluginList(); + virtual ModList *modList(); + virtual HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile); + virtual bool waitForApplication(HANDLE handle, LPDWORD exitCode) const; + virtual bool onModInstalled(const std::function &func); + virtual bool onAboutToRun(const std::function &func); + virtual bool onFinishedRun(const std::function &func); + virtual void refreshModList(bool saveChanges = true); + +public: // IPluginDiagnose interface + + virtual std::vector activeProblems() const; + virtual QString shortDescription(unsigned int key) const; + virtual QString fullDescription(unsigned int key) const; + virtual bool hasGuidedFix(unsigned int key) const; + virtual void startGuidedFix(unsigned int key) const; + +public slots: + + void profileRefresh(); + void externalMessage(const QString &message); + + void refreshLists(); + +signals: + + /** + * @brief emitted after a mod has been installed + * @node this is currently only used for tutorials + */ + void modInstalled(); + +private: + + void storeSettings(); + + bool queryLogin(QString &username, QString &password); + + 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); + +private slots: + + void directory_refreshed(); + void downloadRequestedNXM(const QString &url); + void downloadRequested(QNetworkReply *reply, int modID, const QString &fileName); + void removeOrigin(const QString &name); + +private: + + static const unsigned int PROBLEM_TOOMANYPLUGINS = 1; + +private: + + MOBase::IGameInfo *m_GameInfo; + + IUserInterface *m_UserInterface; + PluginContainer *m_PluginContainer; + + Profile *m_CurrentProfile; + + Settings m_Settings; + + SelfUpdater m_Updater; + + SignalAboutToRunApplication m_AboutToRun; + SignalFinishedRunApplication m_FinishedRun; + SignalModInstalled m_ModInstalled; + + ModList m_ModList; + PluginList m_PluginList; + + QList> m_PostLoginTasks; + + ExecutablesList m_ExecutablesList; + QStringList m_PendingDownloads; + QStringList m_DefaultArchives; + QStringList m_ActiveArchives; + + DirectoryRefresher m_DirectoryRefresher; + MOShared::DirectoryEntry *m_DirectoryStructure; + + DownloadManager m_DownloadManager; + InstallationManager m_InstallationManager; + + QThread m_RefresherThread; + + bool m_AskForNexusPW; + bool m_DirectoryUpdate; + bool m_ArchivesInit; + +}; + +#endif // ORGANIZERCORE_H diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 903c979e..07a006f5 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -7,50 +7,40 @@ using namespace MOBase; using namespace MOShared; -OrganizerProxy::OrganizerProxy(MainWindow *window, const QString &pluginName) - : m_Proxied(window) +OrganizerProxy::OrganizerProxy(OrganizerCore *organizer, const QString &pluginName) + : m_Proxied(organizer) , m_PluginName(pluginName) { } IGameInfo &OrganizerProxy::gameInfo() const { - return *m_Proxied->m_GameInfo; + return m_Proxied->gameInfo(); } - IModRepositoryBridge *OrganizerProxy::createNexusBridge() const { return new NexusBridge(m_PluginName); } - QString OrganizerProxy::profileName() const { - if (m_Proxied->m_CurrentProfile != NULL) { - return m_Proxied->m_CurrentProfile->getName(); - } else { - return ""; - } + return m_Proxied->profileName(); } QString OrganizerProxy::profilePath() const { - if (m_Proxied->m_CurrentProfile != NULL) { - return m_Proxied->m_CurrentProfile->getPath(); - } else { - return ""; - } + return m_Proxied->profilePath(); } QString OrganizerProxy::downloadsPath() const { - return QDir::fromNativeSeparators(m_Proxied->m_Settings.getDownloadDirectory()); + return m_Proxied->downloadsPath(); } VersionInfo OrganizerProxy::appVersion() const { - return m_Proxied->m_Updater.getVersion(); + return m_Proxied->appVersion(); } IModInterface *OrganizerProxy::getMod(const QString &name) @@ -68,35 +58,34 @@ bool OrganizerProxy::removeMod(IModInterface *mod) return m_Proxied->removeMod(mod); } -void OrganizerProxy::modDataChanged(IModInterface*) +void OrganizerProxy::modDataChanged(IModInterface *mod) { - m_Proxied->refreshModList(); + m_Proxied->modDataChanged(mod); } QVariant OrganizerProxy::pluginSetting(const QString &pluginName, const QString &key) const { - return m_Proxied->m_Settings.pluginSetting(pluginName, key); + return m_Proxied->pluginSetting(pluginName, key); } void OrganizerProxy::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) { - m_Proxied->m_Settings.setPluginSetting(pluginName, key, value); + m_Proxied->setPluginSetting(pluginName, key, value); } QVariant OrganizerProxy::persistent(const QString &pluginName, const QString &key, const QVariant &def) const { - return m_Proxied->m_Settings.pluginPersistent(pluginName, key, def); + return m_Proxied->persistent(pluginName, key, def); } void OrganizerProxy::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync) { - m_Proxied->m_Settings.setPluginPersistent(pluginName, key, value, sync); + m_Proxied->setPersistent(pluginName, key, value, sync); } QString OrganizerProxy::pluginDataPath() const { - QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); - return pluginPath + "/data"; + return m_Proxied->pluginDataPath(); } HANDLE OrganizerProxy::startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile) @@ -106,26 +95,31 @@ HANDLE OrganizerProxy::startApplication(const QString &executable, const QString bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const { - return m_Proxied->waitForProcessOrJob(handle, exitCode); + return m_Proxied->waitForApplication(handle, exitCode); } bool OrganizerProxy::onAboutToRun(const std::function &func) { - auto conn = m_Proxied->m_AboutToRun.connect(func); - return conn.connected(); + return m_Proxied->onAboutToRun(func); +} + +bool OrganizerProxy::onFinishedRun(const std::function &func) +{ + return m_Proxied->onFinishedRun(func); } bool OrganizerProxy::onModInstalled(const std::function &func) { - auto conn = m_Proxied->m_ModInstalled.connect(func); - return conn.connected(); + 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); @@ -133,62 +127,22 @@ IModInterface *OrganizerProxy::installMod(const QString &fileName) QString OrganizerProxy::resolvePath(const QString &fileName) const { - if (m_Proxied->m_DirectoryStructure == NULL) { - return QString(); - } - const FileEntry::Ptr file = m_Proxied->m_DirectoryStructure->searchFile(ToWString(fileName), NULL); - if (file.get() != NULL) { - return ToQString(file->getFullPath()); - } else { - return QString(); - } + return m_Proxied->resolvePath(fileName); } QStringList OrganizerProxy::listDirectories(const QString &directoryName) const { - QStringList result; - DirectoryEntry *dir = m_Proxied->m_DirectoryStructure->findSubDirectoryRecursive(ToWString(directoryName)); - if (dir != NULL) { - std::vector::iterator current, end; - dir->getSubDirectories(current, end); - for (; current != end; ++current) { - result.append(ToQString((*current)->getName())); - } - } - return result; + return m_Proxied->listDirectories(directoryName); } QStringList OrganizerProxy::findFiles(const QString &path, const std::function &filter) const { - QStringList result; - DirectoryEntry *dir = m_Proxied->m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path)); - if (dir != NULL) { - std::vector files = dir->getFiles(); - foreach (FileEntry::Ptr file, files) { - if (filter(ToQString(file->getFullPath()))) { - result.append(ToQString(file->getFullPath())); - } - } - } else { - qWarning("directory %s not found", qPrintable(path)); - } - return result; + return m_Proxied->findFiles(path, filter); } 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; + return m_Proxied->getFileOrigins(fileName); } QList OrganizerProxy::findFileInfos(const QString &path, const std::function &filter) const @@ -198,15 +152,15 @@ QList OrganizerProxy::findFileInfos(const QString MOBase::IDownloadManager *OrganizerProxy::downloadManager() { - return &m_Proxied->m_DownloadManager; + return m_Proxied->downloadManager(); } MOBase::IPluginList *OrganizerProxy::pluginList() { - return &m_Proxied->m_PluginList; + return m_Proxied->pluginList(); } MOBase::IModList *OrganizerProxy::modList() { - return &m_Proxied->m_ModList; + return m_Proxied->modList(); } diff --git a/src/organizerproxy.h b/src/organizerproxy.h index affa2d55..625e86aa 100644 --- a/src/organizerproxy.h +++ b/src/organizerproxy.h @@ -7,8 +7,10 @@ class OrganizerProxy : public MOBase::IOrganizer { + public: - OrganizerProxy(MainWindow *window, const QString &pluginName); + + OrganizerProxy(OrganizerCore *organizer, const QString &pluginName); virtual MOBase::IGameInfo &gameInfo() const; virtual MOBase::IModRepositoryBridge *createNexusBridge() const; @@ -40,10 +42,14 @@ public: virtual void refreshModList(bool saveChanges); virtual bool onAboutToRun(const std::function &func); - virtual bool onModInstalled(const std::function &func); + virtual bool onFinishedRun(const std::function &func); + virtual bool onModInstalled(const std::function &func); + private: - MainWindow *m_Proxied; + + OrganizerCore *m_Proxied; + const QString &m_PluginName; }; diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp new file mode 100644 index 00000000..bd96828e --- /dev/null +++ b/src/plugincontainer.cpp @@ -0,0 +1,329 @@ +#include "plugincontainer.h" +#include "organizerproxy.h" +#include "report.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace MOBase; +using namespace MOShared; + +namespace bf = boost::fusion; + + +PluginContainer::PluginContainer(OrganizerCore *organizer) + : m_Organizer(organizer) +{ +} + + +void PluginContainer::setUserInterface(IUserInterface *userInterface, QWidget *widget) +{ + for (IPluginProxy *proxy : bf::at_key(m_Plugins)) { + proxy->setParentWidget(widget); + } + m_UserInterface = userInterface; +} + + +QStringList PluginContainer::pluginFileNames() const +{ + QStringList result; + for (QPluginLoader *loader : m_PluginLoaders) { + result.append(loader->fileName()); + } + return result; +} + + +bool PluginContainer::verifyPlugin(IPlugin *plugin) +{ + if (plugin == NULL) { + return false; + } else if (!plugin->init(new OrganizerProxy(m_Organizer, plugin->name()))) { + qWarning("plugin failed to initialize"); + return false; + } + return true; +} + + +void PluginContainer::registerGame(IPluginGame *game) +{ + m_SupportedGames.insert({ game->gameName(), game }); +} + + +bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) +{ + { // generic treatment for all plugins + IPlugin *pluginObj = qobject_cast(plugin); + if (pluginObj == NULL) { + qDebug("not an IPlugin"); + return false; + } + plugin->setProperty("filename", fileName); + m_Organizer->settings().registerPlugin(pluginObj); + } + + { // diagnosis plugins + IPluginDiagnose *diagnose = qobject_cast(plugin); + if (diagnose != NULL) { + bf::at_key(m_Plugins).push_back(diagnose); + m_DiagnosisConnections.push_back( + diagnose->onInvalidated([&] () { emit diagnosisUpdate(); }) + ); + } + } + { // mod page plugin + IPluginModPage *modPage = qobject_cast(plugin); + if (verifyPlugin(modPage)) { + bf::at_key(m_Plugins).push_back(modPage); + registerModPage(modPage); + return true; + } + } + { // game plugin + IPluginGame *game = qobject_cast(plugin); + if (verifyPlugin(game)) { + bf::at_key(m_Plugins).push_back(game); + registerGame(game); + return true; + } + } + { // tool plugins + IPluginTool *tool = qobject_cast(plugin); + if (verifyPlugin(tool)) { + bf::at_key(m_Plugins).push_back(tool); + registerPluginTool(tool); + return true; + } + } + { // installer plugins + IPluginInstaller *installer = qobject_cast(plugin); + if (verifyPlugin(installer)) { + bf::at_key(m_Plugins).push_back(installer); + m_Organizer->installationManager()->registerInstaller(installer); + return true; + } + } + { // preview plugins + IPluginPreview *preview = qobject_cast(plugin); + if (verifyPlugin(preview)) { + bf::at_key(m_Plugins).push_back(preview); + m_PreviewGenerator.registerPlugin(preview); + return true; + } + } + { // proxy plugins + IPluginProxy *proxy = qobject_cast(plugin); + if (verifyPlugin(proxy)) { + bf::at_key(m_Plugins).push_back(proxy); + QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath())); + foreach (const QString &pluginName, pluginNames) { + try { + QObject *proxiedPlugin = proxy->instantiate(pluginName); + if (proxiedPlugin != NULL) { + if (registerPlugin(proxiedPlugin, pluginName)) { + qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); + } else { + qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); + } + } + } catch (const std::exception &e) { + reportError(QObject::tr("failed to init plugin %1: %2").arg(pluginName).arg(e.what())); + } + } + return true; + } + } + + { // dummy plugins + // only initialize these, no processing otherwise + IPlugin *dummy = qobject_cast(plugin); + if (verifyPlugin(dummy)) { + bf::at_key(m_Plugins).push_back(dummy); + return true; + } + } + + qDebug("no matching plugin interface"); + + return false; +} + +struct clearPlugins +{ + template + void operator()(T& t) const + { + t.second.clear(); + } +}; + +void PluginContainer::unloadPlugins() +{ + if (m_UserInterface != nullptr) { + m_UserInterface->disconnectPlugins(); + } + + // disconnect all slots before unloading plugins so plugins don't have to take care of that + m_Organizer->disconnectPlugins(); + + bf::for_each(m_Plugins, clearPlugins()); + + foreach (const boost::signals2::connection &connection, m_DiagnosisConnections) { + connection.disconnect(); + } + m_DiagnosisConnections.clear(); + + while (!m_PluginLoaders.empty()) { + QPluginLoader *loader = m_PluginLoaders.back(); + m_PluginLoaders.pop_back(); + if (!loader->unload()) { + qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString())); + } + delete loader; + } +} + +IPluginGame *PluginContainer::managedGame(const QString &name) const +{ + auto iter = m_SupportedGames.find(name); + if (iter != m_SupportedGames.end()) { + return iter->second; + } else { + return nullptr; + } +} + +const PreviewGenerator &PluginContainer::previewGenerator() const +{ + return m_PreviewGenerator; +} + +void PluginContainer::loadPlugins() +{ + unloadPlugins(); + + foreach (QObject *plugin, QPluginLoader::staticInstances()) { + registerPlugin(plugin, ""); + } + + QFile loadCheck(qApp->property("dataPath").toString() + "/plugin_loadcheck.tmp"); + if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) { + // oh, there was a failed plugin load last time. Find out which plugin was loaded last + QString fileName; + while (!loadCheck.atEnd()) { + fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed(); + } + if (QMessageBox::question(nullptr, QObject::tr("Plugin error"), + QObject::tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n" + "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. " + "The plugin may be able to recover from the problem)").arg(fileName), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { + m_Organizer->settings().addBlacklistPlugin(fileName); + } + loadCheck.close(); + } + + loadCheck.open(QIODevice::WriteOnly); + + QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); + qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData()); + QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot); + + while (iter.hasNext()) { + iter.next(); + if (m_Organizer->settings().pluginBlacklisted(iter.fileName())) { + qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName())); + continue; + } + loadCheck.write(iter.fileName().toUtf8()); + loadCheck.write("\n"); + loadCheck.flush(); + QString pluginName = iter.filePath(); + if (QLibrary::isLibrary(pluginName)) { + QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this); + if (pluginLoader->instance() == NULL) { + m_FailedPlugins.push_back(pluginName); + qCritical("failed to load plugin %s: %s", + qPrintable(pluginName), qPrintable(pluginLoader->errorString())); + } else { + if (registerPlugin(pluginLoader->instance(), pluginName)) { + qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); + m_PluginLoaders.push_back(pluginLoader); + } else { + m_FailedPlugins.push_back(pluginName); + qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); + } + } + } + } + + // remove the load check file on success + loadCheck.remove(); + + bf::at_key(m_Plugins).push_back(this); + + m_Organizer->connectPlugins(this); +} + + +std::vector PluginContainer::activeProblems() const +{ + std::vector problems; + if (m_FailedPlugins.size()) { + problems.push_back(PROBLEM_PLUGINSNOTLOADED); + } + return problems; +} + +QString PluginContainer::shortDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_PLUGINSNOTLOADED: { + return tr("Some plugins could not be loaded"); + } break; + default: { + return tr("Description missing"); + } break; + } +} + +QString PluginContainer::fullDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_PLUGINSNOTLOADED: { + QString result = tr("The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:") + "
            "; + for (const QString &plugin : m_FailedPlugins) { + result += "
          • " + plugin + "
          • "; + } + result += "
              "; + return result; + } break; + default: { + return tr("Description missing"); + } break; + } +} + +bool PluginContainer::hasGuidedFix(unsigned int) const +{ + return false; +} + +void PluginContainer::startGuidedFix(unsigned int) const +{ +} diff --git a/src/plugincontainer.h b/src/plugincontainer.h new file mode 100644 index 00000000..213b4154 --- /dev/null +++ b/src/plugincontainer.h @@ -0,0 +1,102 @@ +#ifndef PLUGINCONTAINER_H +#define PLUGINCONTAINER_H + + +#include "organizercore.h" +#include "previewgenerator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef Q_MOC_RUN +#include +#endif // Q_MOC_RUN +#include + + +class PluginContainer : public QObject, public MOBase::IPluginDiagnose +{ + + Q_OBJECT + Q_INTERFACES(MOBase::IPluginDiagnose) + +public: + + PluginContainer(OrganizerCore *organizer); + + void setUserInterface(IUserInterface *userInterface, QWidget *widget); + + void loadPlugins(); + void unloadPlugins(); + + MOBase::IPluginGame *managedGame(const QString &name) const; + + template + std::vector plugins() const { + return boost::fusion::at_key(m_Plugins); + } + + const PreviewGenerator &previewGenerator() const; + + QStringList pluginFileNames() const; + +public: // IPluginDiagnose interface + + virtual std::vector activeProblems() const; + virtual QString shortDescription(unsigned int key) const; + virtual QString fullDescription(unsigned int key) const; + virtual bool hasGuidedFix(unsigned int key) const; + virtual void startGuidedFix(unsigned int key) const; + +signals: + + void diagnosisUpdate(); + +private: + + bool verifyPlugin(MOBase::IPlugin *plugin); + void registerPluginTool(MOBase::IPluginTool *tool); + void registerModPage(MOBase::IPluginModPage *modPage); + void registerGame(MOBase::IPluginGame *game); + 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; + + IUserInterface *m_UserInterface; + + PluginMap m_Plugins; + + std::map m_SupportedGames; + std::vector m_DiagnosisConnections; + QStringList m_FailedPlugins; + std::vector m_PluginLoaders; + + PreviewGenerator m_PreviewGenerator; + + QFile m_PluginsCheck; +}; + +#endif // PLUGINCONTAINER_H diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp index 6037422c..803b2cfa 100644 --- a/src/selfupdater.cpp +++ b/src/selfupdater.cpp @@ -55,9 +55,9 @@ template T resolveFunction(QLibrary &lib, const char *name) } -SelfUpdater::SelfUpdater(NexusInterface *nexusInterface, QWidget *parent) - : QObject(parent), m_Parent(parent), m_Interface(nexusInterface), m_UpdateRequestID(-1), - m_Reply(NULL), m_Progress(parent), m_Attempts(3) +SelfUpdater::SelfUpdater(NexusInterface *nexusInterface) + : m_Parent(nullptr), m_Interface(nexusInterface), m_UpdateRequestID(-1), + m_Reply(NULL), m_Progress(nullptr), m_Attempts(3) { m_Progress.setMaximum(100); @@ -88,6 +88,11 @@ SelfUpdater::~SelfUpdater() delete m_CurrentArchive; } +void SelfUpdater::setUserInterface(QWidget *widget) +{ + m_Progress.setParent(widget); + m_Parent = widget; +} void SelfUpdater::testForUpdate() { diff --git a/src/selfupdater.h b/src/selfupdater.h index 75b0ff45..3490b58a 100644 --- a/src/selfupdater.h +++ b/src/selfupdater.h @@ -64,10 +64,12 @@ public: * @param parent parent widget * @todo passing the nexus interface is unneccessary **/ - SelfUpdater(NexusInterface *nexusInterface, QWidget *parent); + SelfUpdater(NexusInterface *nexusInterface); virtual ~SelfUpdater(); + void setUserInterface(QWidget *widget); + /** * @brief start the update process * @note this should not be called if there is no update available diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp index 22db91ac..82b285b7 100644 --- a/src/shared/fallout3info.cpp +++ b/src/shared/fallout3info.cpp @@ -267,7 +267,7 @@ bool Fallout3Info::rerouteToProfile(const wchar_t *fileName, const wchar_t*) } -std::vector Fallout3Info::getExecutables() +/*std::vector Fallout3Info::getExecutables() { std::vector result; result.push_back(ExecutableInfo(L"FOSE", L"fose_loader.exe", L"", L"", DEFAULT_CLOSE)); @@ -278,5 +278,5 @@ std::vector Fallout3Info::getExecutables() result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE)); return result; -} +}*/ } // namespace MOShared diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index d1356de1..7e39cce4 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -87,7 +87,7 @@ public: // 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::vector getExecutables(); virtual std::wstring archiveListKey() { return L"SArchiveList"; } diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp index 0dde4db1..178ce8b4 100644 --- a/src/shared/falloutnvinfo.cpp +++ b/src/shared/falloutnvinfo.cpp @@ -257,7 +257,7 @@ bool FalloutNVInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t*) return false; } - +/* std::vector FalloutNVInfo::getExecutables() { std::vector result; @@ -269,5 +269,5 @@ std::vector FalloutNVInfo::getExecutables() result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE)); return result; -} +}*/ } // namespace MOShared diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h index 50a0d00d..231311de 100644 --- a/src/shared/falloutnvinfo.h +++ b/src/shared/falloutnvinfo.h @@ -88,7 +88,7 @@ public: // 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::vector getExecutables(); virtual std::wstring archiveListKey() { return L"SArchiveList"; } diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h index d719a073..c11679f3 100644 --- a/src/shared/gameinfo.h +++ b/src/shared/gameinfo.h @@ -28,7 +28,7 @@ along with Mod Organizer. If not, see . #include namespace MOShared { - +/* enum CloseMOStyle { DEFAULT_CLOSE, DEFAULT_STAY, @@ -53,7 +53,7 @@ struct ExecutableInfo { CloseMOStyle closeMO; std::wstring steamAppID; }; - +*/ /** Class to manage information that depends on the used game type. The intention is to keep @@ -160,13 +160,9 @@ public: virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath) = 0; - // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to - // the game directory. the boolean says whether omo should be closed when the executable is started - virtual std::vector getExecutables() = 0; - public: - // initialise with the path to the omo directory (needs to be where hook.dll is stored). This + // 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 &moDataDirectory, const std::wstring &gamePath = L""); diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp index 790fcdb0..89a795a5 100644 --- a/src/shared/oblivioninfo.cpp +++ b/src/shared/oblivioninfo.cpp @@ -273,7 +273,7 @@ std::wstring OblivionInfo::getSteamAPPId(int) const return L"22330"; } - +/* std::vector OblivionInfo::getExecutables() { std::vector result; @@ -286,5 +286,5 @@ std::vector OblivionInfo::getExecutables() result.push_back(ExecutableInfo(L"BOSS (old)", L"Data/BOSS.exe", L"", L"", NEVER_CLOSE)); return result; -} +}*/ } // namespace MOShared diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h index e64ae37b..cb506c01 100644 --- a/src/shared/oblivioninfo.h +++ b/src/shared/oblivioninfo.h @@ -84,7 +84,7 @@ public: // 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::vector getExecutables(); virtual std::wstring archiveListKey() { return L"SArchiveList"; } diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index 319e58d5..1203e3ed 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -306,7 +306,7 @@ bool SkyrimInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPa } -std::vector SkyrimInfo::getExecutables() +/*std::vector SkyrimInfo::getExecutables() { std::vector result; result.push_back(ExecutableInfo(L"SKSE", L"skse_loader.exe", L"", L"", DEFAULT_CLOSE)); @@ -317,6 +317,6 @@ std::vector SkyrimInfo::getExecutables() result.push_back(ExecutableInfo(L"Creation Kit", L"CreationKit.exe", L"", L"", DEFAULT_STAY, L"202480")); return result; -} +}*/ } // namespace MOShared diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index a7aff8dc..ad6ab95d 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -94,7 +94,7 @@ public: // 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::vector getExecutables(); virtual std::wstring archiveListKey() { return L"SResourceArchiveList"; } -- cgit v1.3.1