summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrian Munro <brian.alexander.munro@gmail.com>2018-05-08 12:47:54 +0200
committerGitHub <noreply@github.com>2018-05-08 12:47:54 +0200
commit0da6af17b2d6a6965849aa0effd5a1a876f447c4 (patch)
tree306056296c7a35504e85825ec6965b5193c74b24 /src
parentbc75009169ecbf378fa90891dc8183a8cb3ef499 (diff)
parent44111d12c181ff062d7936480fdc380e33232e0e (diff)
Merge pull request #336 from Modorganizer2/Develop
Release 2.1.3
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt42
-rw-r--r--src/aboutdialog.cpp5
-rw-r--r--src/aboutdialog.h5
-rw-r--r--src/aboutdialog.ui52
-rw-r--r--src/browserdialog.cpp4
-rw-r--r--src/downloadlistwidget.cpp8
-rw-r--r--src/downloadlistwidgetcompact.cpp7
-rw-r--r--src/downloadmanager.cpp251
-rw-r--r--src/downloadmanager.h44
-rw-r--r--src/installationmanager.cpp80
-rw-r--r--src/installationmanager.h9
-rw-r--r--src/loadmechanism.cpp4
-rw-r--r--src/main.cpp10
-rw-r--r--src/mainwindow.cpp235
-rw-r--r--src/mainwindow.h20
-rw-r--r--src/modflagicondelegate.cpp1
-rw-r--r--src/modidlineedit.cpp19
-rw-r--r--src/modidlineedit.h22
-rw-r--r--src/modinfo.cpp76
-rw-r--r--src/modinfo.h41
-rw-r--r--src/modinfobackup.cpp4
-rw-r--r--src/modinfobackup.h3
-rw-r--r--src/modinfodialog.cpp97
-rw-r--r--src/modinfodialog.h11
-rw-r--r--src/modinfodialog.ui98
-rw-r--r--src/modinfoforeign.cpp5
-rw-r--r--src/modinfoforeign.h4
-rw-r--r--src/modinfooverwrite.cpp2
-rw-r--r--src/modinfooverwrite.h4
-rw-r--r--src/modinforegular.cpp65
-rw-r--r--src/modinforegular.h35
-rw-r--r--src/modinfowithconflictinfo.cpp4
-rw-r--r--src/modinfowithconflictinfo.h2
-rw-r--r--src/modlist.cpp36
-rw-r--r--src/modlist.h7
-rw-r--r--src/nexusinterface.cpp202
-rw-r--r--src/nexusinterface.h116
-rw-r--r--src/nxmaccessmanager.cpp2
-rw-r--r--src/organizer_en.ts6695
-rw-r--r--src/organizercore.cpp75
-rw-r--r--src/organizercore.h3
-rw-r--r--src/organizerproxy.cpp11
-rw-r--r--src/organizerproxy.h5
-rw-r--r--src/overwriteinfodialog.cpp34
-rw-r--r--src/overwriteinfodialog.h2
-rw-r--r--src/plugincontainer.cpp29
-rw-r--r--src/plugincontainer.h6
-rw-r--r--src/pluginlist.cpp49
-rw-r--r--src/pluginlist.h7
-rw-r--r--src/pluginlistsortproxy.cpp4
-rw-r--r--src/profile.cpp1
-rw-r--r--src/resources.qrc2
-rw-r--r--src/resources/game-warning-16.pngbin0 -> 780 bytes
-rw-r--r--src/resources/game-warning.pngbin0 -> 2528 bytes
-rw-r--r--src/selfupdater.cpp12
-rw-r--r--src/selfupdater.h3
-rw-r--r--src/settings.cpp16
-rw-r--r--src/settings.h3
-rw-r--r--src/settingsdialog.cpp13
-rw-r--r--src/settingsdialog.h8
-rw-r--r--src/settingsdialog.ui3
-rw-r--r--src/version.rc8
62 files changed, 8049 insertions, 572 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fef640b3..77ee4dfc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -30,6 +30,7 @@ SET(organizer_SRCS
motddialog.cpp
modlistsortproxy.cpp
modlist.cpp
+ modidlineedit.cpp
modinfodialog.cpp
modinfo.cpp
modinfobackup.cpp
@@ -120,6 +121,7 @@ SET(organizer_HDRS
motddialog.h
modlistsortproxy.h
modlist.h
+ modidlineedit.h
modinfodialog.h
modinfo.h
modinfobackup.h
@@ -238,6 +240,13 @@ SOURCE_GROUP(Source FILES ${organizer_SRCS})
SOURCE_GROUP(Headers FILES ${organizer_HDRS})
SOURCE_GROUP(UI FILES ${organizer_UIS})
+# MO projects
+SET(default_project_path "${CMAKE_SOURCE_DIR}/..")
+GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH)
+
+SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects")
+#TODO this should not be a hardcoded path
+SET(lib_path "${project_path}/../../install/libs")
# Qt5
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -249,12 +258,12 @@ FIND_PACKAGE(Qt5Quick REQUIRED)
FIND_PACKAGE(Qt5Network REQUIRED)
FIND_PACKAGE(Qt5WinExtras REQUIRED)
FIND_PACKAGE(Qt5WebEngineWidgets REQUIRED)
-FIND_PACKAGE(Qt5Script REQUIRED)
FIND_PACKAGE(Qt5Qml REQUIRED)
FIND_PACKAGE(Qt5LinguistTools)
QT5_WRAP_UI(organizer_UIHDRS ${organizer_UIS})
QT5_ADD_RESOURCES(organizer_RCCPPS ${organizer_QRCS})
-QT5_CREATE_TRANSLATION(organizer_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/organizer_en.ts)
+SET(mo_translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/uibase/src)
+QT5_CREATE_TRANSLATION(organizer_translations_qm ${mo_translation_sources} ${CMAKE_SOURCE_DIR}/src/organizer_en.ts)
ADD_CUSTOM_TARGET(translations DEPENDS ${organizer_translations_qm})
INCLUDE_DIRECTORIES(${Qt5Declarative_INCLUDES})
@@ -274,16 +283,6 @@ LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
FIND_PACKAGE(zlib REQUIRED)
# TODO FindZlib doesn't find the static zlib library
-
-# MO projects
-SET(default_project_path "${CMAKE_SOURCE_DIR}/..")
-GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH)
-
-SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects")
-#TODO this should not be a hardcoded path
-SET(lib_path "${project_path}/../../install/libs")
-
-
INCLUDE_DIRECTORIES(${project_path}/uibase/src
${project_path}/bsatk/src
${project_path}/esptk/src
@@ -316,18 +315,27 @@ ENDIF()
ADD_EXECUTABLE(ModOrganizer WIN32 ${organizer_HDRS} ${organizer_SRCS} ${organizer_UIHDRS} ${organizer_RCS} ${organizer_RCCPPS} ${organizer_translations_qm})
TARGET_LINK_LIBRARIES(ModOrganizer
Qt5::Widgets Qt5::WinExtras Qt5::WebEngineWidgets Qt5::Quick
- Qt5::Script Qt5::Qml Qt5::QuickWidgets Qt5::Network
+ Qt5::Qml Qt5::QuickWidgets Qt5::Network
${Boost_LIBRARIES}
zlibstatic
uibase esptk bsatk githubpp
${usvfs_name}
Dbghelp advapi32 Version Shlwapi liblz4)
+
+IF (MSVC)
+ SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES COMPILE_FLAGS "/std:c++latest")
+ENDIF()
+IF (MSVC AND "${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
+ # 32 bits
+ SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE")
+ENDIF()
+
IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "")
- SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO
- ${OPTIMIZE_COMPILE_FLAGS})
+ SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS})
+ENDIF()
+IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "")
+ SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS})
ENDIF()
-SET_TARGET_PROPERTIES(ModOrganizer PROPERTIES LINK_FLAGS_RELWITHDEBINFO
- "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}")
###############
diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp
index a350036f..9d68fe2b 100644
--- a/src/aboutdialog.cpp
+++ b/src/aboutdialog.cpp
@@ -114,3 +114,8 @@ void AboutDialog::on_creditsList_currentItemChanged(QListWidgetItem *current, QL
ui->licenseText->setText(tr("No license"));
}
}
+
+void AboutDialog::on_copyrightText_linkActivated(const QString &link)
+{
+ emit linkClicked(link);
+} \ No newline at end of file
diff --git a/src/aboutdialog.h b/src/aboutdialog.h
index 3ae3237b..285d0066 100644
--- a/src/aboutdialog.h
+++ b/src/aboutdialog.h
@@ -40,6 +40,10 @@ public:
explicit AboutDialog(const QString &version, QWidget *parent = 0);
~AboutDialog();
+signals:
+
+ void linkClicked(QString link);
+
private:
enum Licenses {
@@ -70,6 +74,7 @@ private:
private slots:
void on_creditsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
+ void on_copyrightText_linkActivated(const QString &link);
private:
diff --git a/src/aboutdialog.ui b/src/aboutdialog.ui
index 69e52708..7e90ec32 100644
--- a/src/aboutdialog.ui
+++ b/src/aboutdialog.ui
@@ -125,7 +125,7 @@
</widget>
</item>
<item>
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="copyrightText">
<property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;/p&gt;&lt;p&gt;See the GNU General Public License for more details.&lt;/p&gt;&lt;p&gt;Source code can be found at &lt;a href=&quot;https://github.com/Modorganizer2/modorganizer&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;GitHub&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@@ -153,8 +153,8 @@
<attribute name="title">
<string>Thanks</string>
</attribute>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
+ <layout class="QGridLayout" name="gridLayout_0">
+ <item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Current Maintainers</string>
@@ -167,12 +167,12 @@
</property>
<item>
<property name="text">
- <string notr="true">LePresidente (Project Lead)</string>
+ <string>LePresidente (Project Lead)</string>
</property>
</item>
<item>
<property name="text">
- <string>AL12</string>
+ <string notr="true">AL12</string>
</property>
</item>
<item>
@@ -195,9 +195,30 @@
</layout>
</widget>
</item>
- <item>
+ <item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
+ <string>Major Contributors</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_7" stretch="0">
+ <item>
+ <widget class="QListWidget" name="listWidget_2">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::NoSelection</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">AnyOldName3 (Python Plugins)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="2">
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
<string>Translators</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
@@ -317,8 +338,8 @@
</layout>
</widget>
</item>
- <item>
- <widget class="QGroupBox" name="groupBox_3">
+ <item row="0" column="2" rowspan="2">
+ <widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Other Supporters &amp;&amp; Contributors</string>
</property>
@@ -330,11 +351,6 @@
</property>
<item>
<property name="text">
- <string notr="true">AnyOldName3</string>
- </property>
- </item>
- <item>
- <property name="text">
<string notr="true">blacksol</string>
</property>
</item>
@@ -370,6 +386,11 @@
</item>
<item>
<property name="text">
+ <string notr="true">GrantSP</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string notr="true">GSDFan</string>
</property>
</item>
@@ -380,6 +401,11 @@
</item>
<item>
<property name="text">
+ <string notr="true">outdatedtv</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string notr="true">Schilduin</string>
</property>
</item>
diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp
index c2c65acc..e186ad63 100644
--- a/src/browserdialog.cpp
+++ b/src/browserdialog.cpp
@@ -173,13 +173,13 @@ void BrowserDialog::titleChanged(const QString &title)
QString BrowserDialog::guessFileName(const QString &url)
{
- QRegExp uploadsExp(QString("http://.+/uploads/([^/]+)$"));
+ QRegExp uploadsExp(QString("https://.+/uploads/([^/]+)$"));
if (uploadsExp.indexIn(url) != -1) {
// these seem to be premium downloads
return uploadsExp.cap(1);
}
- QRegExp filesExp(QString("http://.+\\?file=([^&]+)"));
+ QRegExp filesExp(QString("https://.+\\?file=([^&]+)"));
if (filesExp.indexIn(url) != -1) {
// a regular manual download?
return filesExp.cap(1);
diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp
index 9a8ef572..2af74cc2 100644
--- a/src/downloadlistwidget.cpp
+++ b/src/downloadlistwidget.cpp
@@ -53,6 +53,7 @@ DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager,
m_InstallLabel = m_ItemWidget->findChild<QLabel*>("installLabel");
m_InstallLabel->setVisible(false);
+ m_Progress->setTextVisible(true);
connect(manager, SIGNAL(stateChanged(int,DownloadManager::DownloadState)), this, SLOT(stateChanged(int,DownloadManager::DownloadState)));
connect(manager, SIGNAL(downloadRemoved(int)), this, SLOT(resetCache(int)));
@@ -88,8 +89,8 @@ void DownloadListWidgetDelegate::drawCache(QPainter *painter, const QStyleOption
void DownloadListWidgetDelegate::paintPendingDownload(int downloadIndex) const
{
- std::pair<int, int> nexusids = m_Manager->getPendingDownload(downloadIndex);
- m_NameLabel->setText(tr("< mod %1 file %2 >").arg(nexusids.first).arg(nexusids.second));
+ std::tuple<QString, int, int> nexusids = m_Manager->getPendingDownload(downloadIndex);
+ m_NameLabel->setText(tr("< game %1 mod %2 file %3 >").arg(std::get<0>(nexusids)).arg(std::get<1>(nexusids)).arg(std::get<2>(nexusids)));
m_SizeLabel->setText("???");
m_InstallLabel->setVisible(true);
m_InstallLabel->setText(tr("Pending"));
@@ -159,7 +160,8 @@ void DownloadListWidgetDelegate::paintRegularDownload(int downloadIndex) const
} else {
m_InstallLabel->setVisible(false);
m_Progress->setVisible(true);
- m_Progress->setValue(m_Manager->getProgress(downloadIndex));
+ m_Progress->setValue(m_Manager->getProgress(downloadIndex).first);
+ m_Progress->setFormat(m_Manager->getProgress(downloadIndex).second);
}
}
diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp
index f7975150..898d400a 100644
--- a/src/downloadlistwidgetcompact.cpp
+++ b/src/downloadlistwidgetcompact.cpp
@@ -88,8 +88,8 @@ void DownloadListWidgetCompactDelegate::drawCache(QPainter *painter, const QStyl
void DownloadListWidgetCompactDelegate::paintPendingDownload(int downloadIndex) const
{
- std::pair<int, int> nexusids = m_Manager->getPendingDownload(downloadIndex);
- m_NameLabel->setText(tr("< mod %1 file %2 >").arg(nexusids.first).arg(nexusids.second));
+ std::tuple<QString, int, int> nexusids = m_Manager->getPendingDownload(downloadIndex);
+ m_NameLabel->setText(tr("< game %1 mod %2 file %3 >").arg(std::get<0>(nexusids)).arg(std::get<1>(nexusids)).arg(std::get<2>(nexusids)));
if (m_SizeLabel != nullptr) {
m_SizeLabel->setText("???");
}
@@ -138,7 +138,8 @@ void DownloadListWidgetCompactDelegate::paintRegularDownload(int downloadIndex)
} else {
m_DoneLabel->setVisible(false);
m_Progress->setVisible(true);
- m_Progress->setValue(m_Manager->getProgress(downloadIndex));
+ m_Progress->setValue(m_Manager->getProgress(downloadIndex).first);
+ m_Progress->setFormat(m_Manager->getProgress(downloadIndex).second);
}
}
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index 569a7d31..2ab56fab 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "nexusinterface.h"
#include "nxmaccessmanager.h"
#include "iplugingame.h"
+#include "downloadmanager.h"
#include <nxmurl.h>
#include <taskprogressmanager.h>
#include "utility.h"
@@ -61,7 +62,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Mo
info->m_DownloadID = s_NextDownloadID++;
info->m_StartTime.start();
info->m_PreResumeSize = 0LL;
- info->m_Progress = 0;
+ info->m_Progress = std::make_pair<int, QString>(0, "0 bytes/sec");
info->m_ResumePos = 0;
info->m_FileInfo = new ModRepositoryFileInfo(*fileInfo);
info->m_Urls = URLs;
@@ -73,11 +74,13 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Mo
return info;
}
-DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(const QString &filePath, bool showHidden)
+DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(const QString &filePath, bool showHidden, const QString outputDirectory)
{
DownloadInfo *info = new DownloadInfo;
QString metaFileName = filePath + ".meta";
+ QFileInfo metaFileInfo(metaFileName);
+ if (QDir::fromNativeSeparators(metaFileInfo.path()).compare(QDir::fromNativeSeparators(outputDirectory), Qt::CaseInsensitive) != 0) return nullptr;
QSettings metaFile(metaFileName, QSettings::IniFormat);
if (!showHidden && metaFile.value("removed", false).toBool()) {
return nullptr;
@@ -113,15 +116,17 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con
info->m_Urls = metaFile.value("url", "").toString().split(";");
info->m_Tries = 0;
info->m_TaskProgressId = TaskProgressManager::instance().getId();
+ QString gameName = metaFile.value("gameName", "").toString();
int modID = metaFile.value("modID", 0).toInt();
int fileID = metaFile.value("fileID", 0).toInt();
- info->m_FileInfo = new ModRepositoryFileInfo(modID, fileID);
+ info->m_FileInfo = new ModRepositoryFileInfo(gameName, modID, fileID);
info->m_FileInfo->name = metaFile.value("name", "").toString();
if (info->m_FileInfo->name == "0") {
// bug in earlier version
info->m_FileInfo->name = "";
}
info->m_FileInfo->modName = metaFile.value("modName", "").toString();
+ info->m_FileInfo->gameName = gameName;
info->m_FileInfo->modID = modID;
info->m_FileInfo->fileID = fileID;
info->m_FileInfo->description = metaFile.value("description").toString();
@@ -140,8 +145,10 @@ void DownloadManager::DownloadInfo::setName(QString newName, bool renameFile)
QString oldMetaFileName = QString("%1.meta").arg(m_FileName);
m_FileName = QFileInfo(newName).fileName();
if ((m_State == DownloadManager::STATE_STARTED) ||
- (m_State == DownloadManager::STATE_DOWNLOADING)) {
+ (m_State == DownloadManager::STATE_DOWNLOADING) ||
+ (m_State == DownloadManager::STATE_PAUSED)) {
newName.append(UNFINISHED);
+ oldMetaFileName = QString("%1%2.meta").arg(m_FileName).arg(UNFINISHED);
}
if (renameFile) {
if ((newName != m_Output.fileName()) && !m_Output.rename(newName)) {
@@ -149,10 +156,9 @@ void DownloadManager::DownloadInfo::setName(QString newName, bool renameFile)
return;
}
- QFile metaFile(oldMetaFileName);
- if (metaFile.exists()) {
+ QFile metaFile(QFileInfo(newName).path() + "/" + oldMetaFileName);
+ if (metaFile.exists())
metaFile.rename(newName.mid(0).append(".meta"));
- }
}
if (!m_Output.isOpen()) {
// can't set file name if it's open
@@ -260,6 +266,11 @@ void DownloadManager::setShowHidden(bool showHidden)
refreshList();
}
+void DownloadManager::setPluginContainer(PluginContainer *pluginContainer)
+{
+ m_NexusInterface->setPluginContainer(pluginContainer);
+}
+
void DownloadManager::refreshList()
{
try {
@@ -313,7 +324,7 @@ void DownloadManager::refreshList()
QString fileName = QDir::fromNativeSeparators(m_OutputDirectory) + "/" + file;
- DownloadInfo *info = DownloadInfo::createFromMeta(fileName, m_ShowHidden);
+ DownloadInfo *info = DownloadInfo::createFromMeta(fileName, m_ShowHidden, m_OutputDirectory);
if (info != nullptr) {
m_ActiveDownloads.push_front(info);
}
@@ -329,7 +340,7 @@ void DownloadManager::refreshList()
}
-bool DownloadManager::addDownload(const QStringList &URLs,
+bool DownloadManager::addDownload(const QStringList &URLs, QString gameName,
int modID, int fileID, const ModRepositoryFileInfo *fileInfo)
{
QString fileName = QFileInfo(URLs.first()).fileName();
@@ -340,7 +351,7 @@ bool DownloadManager::addDownload(const QStringList &URLs,
QUrl preferredUrl = QUrl::fromEncoded(URLs.first().toLocal8Bit());
qDebug("selected download url: %s", qPrintable(preferredUrl.toString()));
QNetworkRequest request(preferredUrl);
- return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, fileInfo);
+ return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, gameName, modID, fileID, fileInfo);
}
@@ -351,12 +362,12 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const ModRepositoryFileI
fileName = "unknown";
}
- return addDownload(reply, QStringList(reply->url().toString()), fileName, fileInfo->modID, fileInfo->fileID, fileInfo);
+ return addDownload(reply, QStringList(reply->url().toString()), fileName, fileInfo->gameName, fileInfo->modID, fileInfo->fileID, fileInfo);
}
bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName,
- int modID, int fileID, const ModRepositoryFileInfo *fileInfo)
+ QString gameName, int modID, int fileID, const ModRepositoryFileInfo *fileInfo)
{
// download invoked from an already open network reply (i.e. download link in the browser)
DownloadInfo *newDownload = DownloadInfo::createNew(fileInfo, URLs);
@@ -371,14 +382,6 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs,
baseName = dispoName;
}
}
- if (QFile::exists(m_OutputDirectory + "/" + baseName) &&
- (QMessageBox::question(nullptr, tr("Download again?"), tr("A file with the same name has already been downloaded. "
- "Do you want to download it again? The new file will receive a different name."),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) {
- removePending(modID, fileID);
- delete newDownload;
- return false;
- }
newDownload->setName(getDownloadFileName(baseName), false);
startDownload(reply, newDownload, false);
@@ -387,12 +390,12 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs,
}
-void DownloadManager::removePending(int modID, int fileID)
+void DownloadManager::removePending(QString gameName, int modID, int fileID)
{
emit aboutToUpdate();
- for (auto iter = m_PendingDownloads.begin(); iter != m_PendingDownloads.end(); ++iter) {
- if ((iter->first == modID) && (iter->second == fileID)) {
- m_PendingDownloads.erase(iter);
+ for (auto iter : m_PendingDownloads) {
+ if (gameName.compare(std::get<0>(iter), Qt::CaseInsensitive) == 0 && (std::get<1>(iter) == modID) && (std::get<2>(iter) == fileID)) {
+ m_PendingDownloads.removeAt(m_PendingDownloads.indexOf(iter));
break;
}
}
@@ -424,14 +427,13 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl
}
connect(newDownload->m_Reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
- connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
connect(newDownload->m_Reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(newDownload->m_Reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
connect(newDownload->m_Reply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
if (!resume) {
newDownload->m_PreResumeSize = newDownload->m_Output.size();
- removePending(newDownload->m_FileInfo->modID, newDownload->m_FileInfo->fileID);
+ removePending(newDownload->m_FileInfo->gameName, newDownload->m_FileInfo->modID, newDownload->m_FileInfo->fileID);
emit aboutToUpdate();
m_ActiveDownloads.append(newDownload);
@@ -439,11 +441,35 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl
emit update(-1);
emit downloadAdded();
- if (reply->isFinished()) {
- // it's possible the download has already finished before this function ran
- downloadFinished();
+ if (QFile::exists(m_OutputDirectory + "/" + newDownload->m_FileName)) {
+ setState(newDownload, STATE_PAUSING);
+ QCoreApplication::processEvents();
+ if (QMessageBox::question(nullptr, tr("Download again?"), tr("A file with the same name has already been downloaded. "
+ "Do you want to download it again? The new file will receive a different name."),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
+ if (reply->isFinished())
+ setState(newDownload, STATE_CANCELED);
+ else
+ setState(newDownload, STATE_CANCELING);
+ } else {
+ newDownload->setName(getDownloadFileName(newDownload->m_FileName, true), true);
+ if (newDownload->m_State == STATE_PAUSED)
+ resumeDownload(indexByName(newDownload->m_FileName));
+ else
+ setState(newDownload, STATE_DOWNLOADING);
+ }
+ } else
+ connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
+
+
+ QCoreApplication::processEvents();
+
+ if (newDownload->m_State != STATE_DOWNLOADING && reply->isFinished()) {
+ downloadFinished(indexByName(newDownload->m_FileName));
+ return;
}
- }
+ } else
+ connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
@@ -451,17 +477,19 @@ void DownloadManager::addNXMDownload(const QString &url)
{
NXMUrl nxmInfo(url);
- QString managedGame = m_ManagedGame->gameShortName();
+ QStringList validGames;
+ validGames.append(m_ManagedGame->gameShortName());
+ validGames.append(m_ManagedGame->validShortNames());
qDebug("add nxm download: %s", qPrintable(url));
- if (nxmInfo.game().compare(managedGame, Qt::CaseInsensitive) != 0) {
- qDebug("download requested for wrong game (game: %s, url: %s)", qPrintable(managedGame), qPrintable(nxmInfo.game()));
+ if (!validGames.contains(nxmInfo.game(), Qt::CaseInsensitive)) {
+ qDebug("download requested for wrong game (game: %s, url: %s)", qPrintable(m_ManagedGame->gameShortName()), qPrintable(nxmInfo.game()));
QMessageBox::information(nullptr, tr("Wrong Game"), tr("The download link is for a mod for \"%1\" but this instance of MO "
- "has been set up for \"%2\".").arg(nxmInfo.game()).arg(managedGame), QMessageBox::Ok);
+ "has been set up for \"%2\".").arg(nxmInfo.game()).arg(m_ManagedGame->gameShortName()), QMessageBox::Ok);
return;
}
- for (auto pair : m_PendingDownloads) {
- if (pair.first == nxmInfo.modId() && pair.second == nxmInfo.fileId()) {
+ for (auto tuple : m_PendingDownloads) {
+ if (std::get<0>(tuple).compare(nxmInfo.game(), Qt::CaseInsensitive) == 0, std::get<1>(tuple) == nxmInfo.modId() && std::get<2>(tuple) == nxmInfo.fileId()) {
qDebug("download requested is already started (mod id: %s, file id: %s)", qPrintable(QString(nxmInfo.modId())), qPrintable(QString(nxmInfo.fileId())));
QMessageBox::information(nullptr, tr("Already Started"), tr("A download for this mod file has already been queued."), QMessageBox::Ok);
return;
@@ -471,11 +499,11 @@ void DownloadManager::addNXMDownload(const QString &url)
for (DownloadInfo *download : m_ActiveDownloads) {
if (download->m_FileInfo->modID == nxmInfo.modId() && download->m_FileInfo->fileID == nxmInfo.fileId()) {
if (download->m_State == STATE_DOWNLOADING || download->m_State == STATE_PAUSED || download->m_State == STATE_STARTED) {
- qDebug("download requested is already started (mod: %s, file: %s)", qPrintable(download->m_FileInfo->modName),
+ qDebug("download requested is already started (mod: %s, file: %s)", qPrintable(download->m_FileInfo->modID),
qPrintable(download->m_FileInfo->fileName));
- QMessageBox::information(nullptr, tr("Already Started"), tr("There is already a download started for this file (%2).")
- .arg(download->m_FileInfo->modName).arg(download->m_FileInfo->name), QMessageBox::Ok);
+ QMessageBox::information(nullptr, tr("Already Started"), tr("There is already a download started for this file (mod: %1, file: %2).")
+ .arg(download->m_FileInfo->modName).arg(download->m_FileInfo->fileName), QMessageBox::Ok);
return;
}
}
@@ -483,11 +511,11 @@ void DownloadManager::addNXMDownload(const QString &url)
emit aboutToUpdate();
- m_PendingDownloads.append(std::make_pair(nxmInfo.modId(), nxmInfo.fileId()));
+ m_PendingDownloads.append(std::make_tuple(nxmInfo.game(), nxmInfo.modId(), nxmInfo.fileId()));
emit update(-1);
emit downloadAdded();
- m_RequestIDs.insert(m_NexusInterface->requestFileInfo(nxmInfo.modId(), nxmInfo.fileId(), this, nxmInfo.fileId(), ""));
+ m_RequestIDs.insert(m_NexusInterface->requestFileInfo(nxmInfo.game(), nxmInfo.modId(), nxmInfo.fileId(), this, nxmInfo.fileId(), ""));
}
@@ -674,6 +702,11 @@ void DownloadManager::resumeDownloadInt(int index)
qDebug("request resume from url %s", qPrintable(info->currentURL()));
QNetworkRequest request(QUrl::fromEncoded(info->currentURL().toLocal8Bit()));
info->m_ResumePos = info->m_Output.size();
+ std::get<0>(info->m_SpeedDiff) = 0;
+ std::get<1>(info->m_SpeedDiff) = 0;
+ std::get<2>(info->m_SpeedDiff) = 0;
+ std::get<3>(info->m_SpeedDiff) = 0;
+ std::get<4>(info->m_SpeedDiff) = 0;
qDebug("resume at %lld bytes", info->m_ResumePos);
QByteArray rangeHeader = "bytes=" + QByteArray::number(info->m_ResumePos) + "-";
request.setRawHeader("Range", rangeHeader);
@@ -728,6 +761,20 @@ void DownloadManager::queryInfo(int index)
return;
}
}
+
+ if (info->m_FileInfo->gameName.size() == 0) {
+ SelectionDialog selection(tr("Please select the source game code for %1").arg(getFileName(index)));
+
+ std::vector<std::pair<QString, QString>> choices = m_NexusInterface->getGameChoices(m_ManagedGame);
+ for (auto choice : choices) {
+ selection.addChoice(choice.first, choice.second, choice.first);
+ }
+ if (selection.exec() == QDialog::Accepted) {
+ info->m_FileInfo->gameName = selection.getChoiceData().toString();
+ } else {
+ info->m_FileInfo->gameName = m_ManagedGame->gameShortName();
+ }
+ }
info->m_ReQueried = true;
setState(info, STATE_FETCHINGMODINFO);
}
@@ -743,7 +790,7 @@ int DownloadManager::numPendingDownloads() const
return m_PendingDownloads.size();
}
-std::pair<int, int> DownloadManager::getPendingDownload(int index)
+std::tuple<QString, int, int> DownloadManager::getPendingDownload(int index)
{
if ((index < 0) || (index >= m_PendingDownloads.size())) {
throw MyException(tr("get pending: invalid download index %1").arg(index));
@@ -826,7 +873,7 @@ qint64 DownloadManager::getFileSize(int index) const
}
-int DownloadManager::getProgress(int index) const
+std::pair<int, QString> DownloadManager::getProgress(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
throw MyException(tr("progress: invalid download index %1").arg(index));
@@ -869,6 +916,14 @@ int DownloadManager::getModID(int index) const
return m_ActiveDownloads.at(index)->m_FileInfo->modID;
}
+QString DownloadManager::getGameName(int index) const
+{
+ if ((index < 0) || (index >= m_ActiveDownloads.size())) {
+ throw MyException(tr("mod id: invalid download index %1").arg(index));
+ }
+ return m_ActiveDownloads.at(index)->m_FileInfo->gameName;
+}
+
bool DownloadManager::isHidden(int index) const
{
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
@@ -913,14 +968,14 @@ void DownloadManager::markInstalled(QString fileName)
QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat);
metaFile.setValue("installed", true);
metaFile.setValue("uninstalled", false);
+ delete info;
}
- delete info;
}
}
DownloadManager::DownloadInfo* DownloadManager::getDownloadInfo(QString fileName)
{
- return DownloadInfo::createFromMeta(fileName, true);
+ return DownloadInfo::createFromMeta(fileName, true, m_OutputDirectory);
}
void DownloadManager::markUninstalled(int index)
@@ -948,16 +1003,16 @@ void DownloadManager::markUninstalled(QString fileName)
if (info != nullptr) {
QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat);
metaFile.setValue("uninstalled", true);
+ delete info;
}
- delete info;
}
}
-QString DownloadManager::getDownloadFileName(const QString &baseName) const
+QString DownloadManager::getDownloadFileName(const QString &baseName, bool rename) const
{
QString fullPath = m_OutputDirectory + "/" + baseName;
- if (QFile::exists(fullPath)) {
+ if (QFile::exists(fullPath) && rename) {
int i = 1;
while (QFile::exists(QString("%1/%2_%3").arg(m_OutputDirectory).arg(i).arg(baseName))) {
++i;
@@ -998,15 +1053,16 @@ void DownloadManager::setState(DownloadManager::DownloadInfo *info, DownloadMana
case STATE_PAUSED:
case STATE_ERROR: {
info->m_Reply->abort();
+ info->m_Output.close();
} break;
case STATE_CANCELED: {
info->m_Reply->abort();
} break;
case STATE_FETCHINGMODINFO: {
- m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_FileInfo->modID, this, info->m_DownloadID, QString()));
+ m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_FileInfo->gameName, info->m_FileInfo->modID, this, info->m_DownloadID, QString()));
} break;
case STATE_FETCHINGFILEINFO: {
- m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_FileInfo->modID, this, info->m_DownloadID, QString()));
+ m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_FileInfo->gameName, info->m_FileInfo->modID, this, info->m_DownloadID, QString()));
} break;
case STATE_READY: {
createMetaFile(info);
@@ -1046,16 +1102,43 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
setState(info, STATE_CANCELED);
} else if (info->m_State == STATE_PAUSING) {
setState(info, STATE_PAUSED);
- } else {
+ }
+ else {
if (bytesTotal > info->m_TotalSize) {
info->m_TotalSize = bytesTotal;
}
- int oldProgress = info->m_Progress;
- info->m_Progress = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal);
- TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal);
- if (oldProgress != info->m_Progress) {
- emit update(index);
+ int oldProgress = info->m_Progress.first;
+ info->m_Progress.first = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal);
+
+ int elapsed = info->m_StartTime.elapsed();
+ std::get<0>(info->m_SpeedDiff) = bytesReceived - std::get<2>(info->m_SpeedDiff);
+ std::get<1>(info->m_SpeedDiff) = elapsed - std::get<3>(info->m_SpeedDiff);
+ std::get<2>(info->m_SpeedDiff) = bytesReceived;
+ std::get<3>(info->m_SpeedDiff) = elapsed;
+
+ double calc = ((double)std::get<0>(info->m_SpeedDiff)) / (((double)(std::get<1>(info->m_SpeedDiff)) / 5000.0));
+ std::get<4>(info->m_SpeedDiff) = ((calc*0.5) + (std::get<4>(info->m_SpeedDiff)*1.5)) / 2;
+
+ // calculate the download speed
+ double speed = (std::get<4>(info->m_SpeedDiff) * 1000.0) / (5 * 1000);
+
+ QString unit;
+ if (speed < 1024) {
+ unit = "bytes/sec";
}
+ else if (speed < 1024 * 1024) {
+ speed /= 1024;
+ unit = "kB/s";
+ }
+ else {
+ speed /= 1024 * 1024;
+ unit = "MB/s";
+ }
+
+ info->m_Progress.second = QString::fromLatin1("%1% - %2 %3").arg(info->m_Progress.first).arg(speed, 3, 'f', 1).arg(unit);
+
+ TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal);
+ emit update(index);
}
}
} catch (const std::bad_alloc&) {
@@ -1080,6 +1163,7 @@ void DownloadManager::downloadReadyRead()
void DownloadManager::createMetaFile(DownloadInfo *info)
{
QSettings metaFile(QString("%1.meta").arg(info->m_Output.fileName()), QSettings::IniFormat);
+ metaFile.setValue("gameName", info->m_FileInfo->gameName);
metaFile.setValue("modID", info->m_FileInfo->modID);
metaFile.setValue("fileID", info->m_FileInfo->fileID);
metaFile.setValue("url", info->m_Urls.join(";"));
@@ -1108,7 +1192,7 @@ void DownloadManager::createMetaFile(DownloadInfo *info)
}
-void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant resultData, int requestID)
+void DownloadManager::nxmDescriptionAvailable(QString, int, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
if (idIter == m_RequestIDs.end()) {
@@ -1157,7 +1241,7 @@ static EFileCategory convertFileCategory(int id)
}
-void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultData, int requestID)
+void DownloadManager::nxmFilesAvailable(QString, int, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
if (idIter == m_RequestIDs.end()) {
@@ -1193,13 +1277,11 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
if (!info->m_FileInfo->version.isValid()) {
info->m_FileInfo->version = info->m_FileInfo->newestVersion;
}
- // we receive some names html-encoded. This is used to decode it
- QTextDocument doc;
- doc.setHtml(fileInfo["modName"].toString());
- info->m_FileInfo->modName = doc.toPlainText();
info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt());
info->m_FileInfo->fileTime = matchDate(fileInfo["date"].toString());
info->m_FileInfo->fileID = fileInfo["id"].toInt();
+ info->m_FileInfo->fileName = fileInfo["uri"].toString();
+ info->m_FileInfo->description = BBCode::convertToHTML(fileInfo["description"].toString());
found = true;
break;
}
@@ -1237,7 +1319,7 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
}
-void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
+void DownloadManager::nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
if (idIter == m_RequestIDs.end()) {
@@ -1260,11 +1342,12 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD
info->description = BBCode::convertToHTML(result["description"].toString());
info->repository = "Nexus";
+ info->gameName = gameName;
info->modID = modID;
info->fileID = fileID;
QObject *test = info;
- m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test), QString()));
+ m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(gameName, modID, fileID, this, qVariantFromValue(test), QString()));
}
static int evaluateFileInfoMap(const QVariantMap &map, const std::map<QString, int> &preferredServers)
@@ -1300,7 +1383,7 @@ bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferred
int DownloadManager::startDownloadURLs(const QStringList &urls)
{
ModRepositoryFileInfo info;
- addDownload(urls, -1, -1, &info);
+ addDownload(urls, "", -1, -1, &info);
return m_ActiveDownloads.size() - 1;
}
@@ -1326,7 +1409,7 @@ int DownloadManager::indexByName(const QString &fileName) const
return -1;
}
-void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
+void DownloadManager::nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
if (idIter == m_RequestIDs.end()) {
@@ -1338,7 +1421,7 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
ModRepositoryFileInfo *info = qobject_cast<ModRepositoryFileInfo*>(qvariant_cast<QObject*>(userData));
QVariantList resultList = resultData.toList();
if (resultList.length() == 0) {
- removePending(modID, fileID);
+ removePending(gameName, modID, fileID);
emit showMessage(tr("No download server available. Please try again later."));
return;
}
@@ -1352,11 +1435,11 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
foreach (const QVariant &server, resultList) {
URLs.append(server.toMap()["URI"].toString());
}
- addDownload(URLs, modID, fileID, info);
+ addDownload(URLs, gameName, modID, fileID, info);
}
-void DownloadManager::nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString)
+void DownloadManager::nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorString)
{
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
if (idIter == m_RequestIDs.end()) {
@@ -1381,16 +1464,19 @@ void DownloadManager::nxmRequestFailed(int modID, int fileID, QVariant userData,
}
}
- removePending(modID, fileID);
+ removePending(gameName, modID, fileID);
emit showMessage(tr("Failed to request file info from nexus: %1").arg(errorString));
}
-void DownloadManager::downloadFinished()
+void DownloadManager::downloadFinished(int index)
{
- int index = 0;
+ DownloadInfo *info;
+ if (index)
+ info = m_ActiveDownloads[index];
+ else
+ info = findDownload(this->sender(), &index);
- DownloadInfo *info = findDownload(this->sender(), &index);
if (info != nullptr) {
QNetworkReply *reply = info->m_Reply;
QByteArray data;
@@ -1405,15 +1491,16 @@ void DownloadManager::downloadFinished()
if ((info->m_State != STATE_CANCELING) &&
(info->m_State != STATE_PAUSING)) {
bool textData = reply->header(QNetworkRequest::ContentTypeHeader).toString().startsWith("text", Qt::CaseInsensitive);
+ if (textData)
+ emit showMessage(tr("Warning: Content type is: %1").arg(reply->header(QNetworkRequest::ContentTypeHeader).toString()));
if ((info->m_Output.size() == 0) ||
- ((reply->error() != QNetworkReply::NoError) && (reply->error() != QNetworkReply::OperationCanceledError)) ||
- textData) {
+ ((reply->error() != QNetworkReply::NoError)
+ && (reply->error() != QNetworkReply::OperationCanceledError)
+ && (reply->error() == QNetworkReply::UnknownContentError && (info->m_Output.size() != reply->header(QNetworkRequest::ContentLengthHeader).toLongLong())))) {
+ if (reply->error() == QNetworkReply::UnknownContentError)
+ emit showMessage(tr("Download header content length: %1 downloaded file size: %2").arg(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()).arg(info->m_Output.size()));
if (info->m_Tries == 0) {
- if (textData && (reply->error() == QNetworkReply::NoError)) {
- emit showMessage(tr("Download failed. Server reported: %1").arg(QString(data)));
- } else {
- emit showMessage(tr("Download failed: %1 (%2)").arg(reply->errorString()).arg(reply->error()));
- }
+ emit showMessage(tr("Download failed: %1 (%2)").arg(reply->errorString()).arg(reply->error()));
}
error = true;
setState(info, STATE_PAUSING);
@@ -1469,7 +1556,7 @@ void DownloadManager::downloadFinished()
QString newName = getFileNameFromNetworkReply(reply);
QString oldName = QFileInfo(info->m_Output).fileName();
- if (!newName.isEmpty() && (newName != oldName)) {
+ if (!newName.isEmpty() && (oldName.isEmpty())) {
info->setName(getDownloadFileName(newName), true);
} else {
info->setName(m_OutputDirectory + "/" + info->m_FileName, true); // don't rename but remove the ".unfinished" extension
@@ -1512,7 +1599,7 @@ void DownloadManager::metaDataChanged()
DownloadInfo *info = findDownload(this->sender(), &index);
if (info != nullptr) {
QString newName = getFileNameFromNetworkReply(info->m_Reply);
- if (!newName.isEmpty() && (newName != info->m_FileName)) {
+ if (!newName.isEmpty() && (info->m_FileName.isEmpty())) {
info->setName(getDownloadFileName(newName), true);
refreshAlphabeticalTranslation();
if (!info->m_Output.isOpen() && !info->m_Output.open(QIODevice::WriteOnly | QIODevice::Append)) {
diff --git a/src/downloadmanager.h b/src/downloadmanager.h
index a6d3b20c..98f5e468 100644
--- a/src/downloadmanager.h
+++ b/src/downloadmanager.h
@@ -38,6 +38,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
namespace MOBase { class IPluginGame; }
class NexusInterface;
+class PluginContainer;
/*!
* \brief manages downloading of files and provides progress information for gui elements
@@ -74,7 +75,8 @@ private:
QNetworkReply *m_Reply;
QTime m_StartTime;
qint64 m_PreResumeSize;
- int m_Progress;
+ std::pair<int, QString> m_Progress;
+ std::tuple<int, int, int, int, int> m_SpeedDiff;
DownloadState m_State;
int m_CurrentUrl;
QStringList m_Urls;
@@ -92,7 +94,7 @@ private:
bool m_Hidden;
static DownloadInfo *createNew(const MOBase::ModRepositoryFileInfo *fileInfo, const QStringList &URLs);
- static DownloadInfo *createFromMeta(const QString &filePath, bool showHidden);
+ static DownloadInfo *createFromMeta(const QString &filePath, bool showHidden, const QString outputDirectory);
/**
* @brief rename the file
@@ -112,7 +114,7 @@ private:
private:
static unsigned int s_NextDownloadID;
private:
- DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false) {}
+ DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false), m_SpeedDiff(std::tuple<int,int,int,int,int>(0,0,0,0,0)) {}
};
public:
@@ -162,6 +164,8 @@ public:
*/
void setShowHidden(bool showHidden);
+ void setPluginContainer(PluginContainer *pluginContainer);
+
/**
* @brief download from an already open network connection
*
@@ -179,7 +183,7 @@ public:
* @param fileInfo information previously retrieved from the nexus network
* @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again
**/
- bool addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, int modID, int fileID = 0, const MOBase::ModRepositoryFileInfo *fileInfo = new MOBase::ModRepositoryFileInfo());
+ bool addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, QString gameName, int modID, int fileID = 0, const MOBase::ModRepositoryFileInfo *fileInfo = new MOBase::ModRepositoryFileInfo());
/**
* @brief start a download using a nxm-link
@@ -209,7 +213,7 @@ public:
* @param index index of the pending download (index in the range [0, numPendingDownloads()[)
* @return pair of modid, fileid
*/
- std::pair<int, int> getPendingDownload(int index);
+ std::tuple<QString, int, int> getPendingDownload(int index);
/**
* @brief retrieve the full path to the download specified by index
@@ -256,7 +260,7 @@ public:
* @param index index of the file to look up
* @return progress of the download in percent (integer)
**/
- int getProgress(int index) const;
+ std::pair<int, QString> getProgress(int index) const;
/**
* @brief retrieve the current state of the download
@@ -286,6 +290,14 @@ public:
int getModID(int index) const;
/**
+ * @brief retrieve the game name of the downlaod specified by the index
+ *
+ * @param index index of the file to look up
+ * @return the game name
+ **/
+ QString getGameName(int index) const;
+
+ /**
* @brief determine if the specified file is supposed to be hidden
* @param index index of the file to look up
* @return true if the specified file is supposed to be hidden
@@ -411,15 +423,15 @@ public slots:
void queryInfo(int index);
- void nxmDescriptionAvailable(int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmFilesAvailable(int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
- void nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
- void nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
+ void nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
void managedGameChanged(MOBase::IPluginGame const *gamePlugin);
@@ -427,7 +439,7 @@ private slots:
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void downloadReadyRead();
- void downloadFinished();
+ void downloadFinished(int index = 0);
void downloadError(QNetworkReply::NetworkError error);
void metaDataChanged();
void directoryChanged(const QString &dirctory);
@@ -448,7 +460,7 @@ public:
*
* @return Unique(ish) name
*/
- QString getDownloadFileName(const QString &baseName) const;
+ QString getDownloadFileName(const QString &baseName, bool rename = false) const;
private:
@@ -462,7 +474,7 @@ private:
* @param fileInfo information previously retrieved from the mod page
* @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again
**/
- bool addDownload(const QStringList &URLs, int modID, int fileID, const MOBase::ModRepositoryFileInfo *fileInfo);
+ bool addDownload(const QStringList &URLs, QString gameName, int modID, int fileID, const MOBase::ModRepositoryFileInfo *fileInfo);
// important: the caller has to lock the list-mutex, otherwise the DownloadInfo-pointer might get invalidated at any time
DownloadInfo *findDownload(QObject *reply, int *index = nullptr) const;
@@ -481,7 +493,7 @@ private:
QDateTime matchDate(const QString &timeString);
- void removePending(int modID, int fileID);
+ void removePending(QString gameName, int modID, int fileID);
static QString getFileTypeString(int fileType);
@@ -493,7 +505,7 @@ private:
NexusInterface *m_NexusInterface;
- QVector<std::pair<int, int> > m_PendingDownloads;
+ QVector<std::tuple<QString, int, int>> m_PendingDownloads;
QVector<DownloadInfo*> m_ActiveDownloads;
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index 9a70f8bd..d1922cf9 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -49,6 +49,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QDirIterator>
#include <QDebug>
#include <QTextDocument>
+#include <QtConcurrent/QtConcurrentRun>
#include <Shellapi.h>
@@ -190,10 +191,22 @@ bool InstallationManager::unpackSingleFile(const QString &fileName)
m_InstallationProgress->setFixedSize(600, 100);
m_InstallationProgress->show();
- bool res = m_ArchiveHandler->extract(QDir::tempPath(),
- new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
- nullptr,
- new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError));
+ QFuture<bool> future = QtConcurrent::run([&]() -> bool {
+ return m_ArchiveHandler->extract(
+ QDir::tempPath(),
+ new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
+ nullptr,
+ new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError)
+ );
+ });
+ do {
+ if (m_Progress != m_InstallationProgress->value())
+ m_InstallationProgress->setValue(m_Progress);
+ if (m_ProgressFile != m_InstallationProgress->labelText())
+ m_InstallationProgress->setLabelText(m_ProgressFile);
+ QCoreApplication::processEvents();
+ } while (!future.isFinished() || m_InstallationProgress->isVisible());
+ bool res = future.result();
return res;
}
@@ -279,10 +292,22 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool
m_InstallationProgress->show();
// unpack only the files we need for the installer
- if (!m_ArchiveHandler->extract(QDir::tempPath(),
- new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
- nullptr,
- new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError))) {
+ QFuture<bool> future = QtConcurrent::run([&]() -> bool {
+ return m_ArchiveHandler->extract(
+ QDir::tempPath(),
+ new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
+ nullptr,
+ new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError)
+ );
+ });
+ do {
+ if (m_Progress != m_InstallationProgress->value())
+ m_InstallationProgress->setValue(m_Progress);
+ if (m_ProgressFile != m_InstallationProgress->labelText())
+ m_InstallationProgress->setLabelText(m_ProgressFile);
+ QCoreApplication::processEvents();
+ } while (!future.isFinished() || m_InstallationProgress->isVisible());
+ if (!future.result()) {
throw MyException(QString("extracting failed (%1)").arg(m_ArchiveHandler->getLastError()));
}
@@ -410,7 +435,8 @@ DirectoryTree::Node *InstallationManager::getSimpleArchiveBase(DirectoryTree *da
void InstallationManager::updateProgress(float percentage)
{
if (m_InstallationProgress != nullptr) {
- m_InstallationProgress->setValue(static_cast<int>(percentage * 100.0));
+ m_Progress = static_cast<int>(percentage * 100.0);
+
if (m_InstallationProgress->wasCanceled()) {
m_ArchiveHandler->cancel();
m_InstallationProgress->reset();
@@ -421,10 +447,7 @@ void InstallationManager::updateProgress(float percentage)
void InstallationManager::updateProgressFile(QString const &fileName)
{
- if (m_InstallationProgress != nullptr) {
- m_InstallationProgress->setLabelText(fileName);
- QCoreApplication::processEvents();
- }
+ m_ProgressFile = fileName;
}
@@ -537,7 +560,7 @@ bool InstallationManager::ensureValidModName(GuessedValue<QString> &name) const
return true;
}
-bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
+bool InstallationManager::doInstall(GuessedValue<QString> &modName, QString gameName, int modID,
const QString &version, const QString &newestVersion,
int categoryID, const QString &repository)
{
@@ -568,10 +591,22 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
m_InstallationProgress->setWindowModality(Qt::WindowModal);
m_InstallationProgress->setFixedSize(600, 100);
m_InstallationProgress->show();
- if (!m_ArchiveHandler->extract(targetDirectory,
- new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
- new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::updateProgressFile),
- new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError))) {
+ QFuture<bool> future = QtConcurrent::run([&]() -> bool {
+ return m_ArchiveHandler->extract(
+ targetDirectory,
+ new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
+ new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::updateProgressFile),
+ new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError)
+ );
+ });
+ do {
+ if (m_Progress != m_InstallationProgress->value())
+ m_InstallationProgress->setValue(m_Progress);
+ if (m_ProgressFile != m_InstallationProgress->labelText())
+ m_InstallationProgress->setLabelText(m_ProgressFile);
+ QCoreApplication::processEvents();
+ } while (!future.isFinished());
+ if (!future.result()) {
if (m_ArchiveHandler->getLastError() == Archive::ERROR_EXTRACT_CANCELLED) {
return false;
} else {
@@ -582,6 +617,9 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
QSettings settingsFile(targetDirectory + "/meta.ini", QSettings::IniFormat);
// overwrite settings only if they are actually are available or haven't been set before
+ if ((gameName != "") || !settingsFile.contains("gameName")) {
+ settingsFile.setValue("gameName", gameName);
+ }
if ((modID != 0) || !settingsFile.contains("modid")) {
settingsFile.setValue("modid", modID);
}
@@ -662,6 +700,7 @@ bool InstallationManager::install(const QString &fileName,
modName.update(QFileInfo(fileName).completeBaseName(), GUESS_FALLBACK);
// read out meta information from the download if available
+ QString gameName = "";
int modID = 0;
QString version = "";
QString newestVersion = "";
@@ -671,6 +710,7 @@ bool InstallationManager::install(const QString &fileName,
QString metaName = fileName + ".meta";
if (QFile(metaName).exists()) {
QSettings metaFile(metaName, QSettings::IniFormat);
+ gameName = metaFile.value("gameName", "").toString();
modID = metaFile.value("modID", 0).toInt();
QTextDocument doc;
doc.setHtml(metaFile.value("name", "").toString());
@@ -759,7 +799,7 @@ bool InstallationManager::install(const QString &fileName,
mapToArchive(filesTree.data());
// the simple installer only prepares the installation, the rest
// works the same for all installers
- if (!doInstall(modName, modID, version, newestVersion, categoryID,
+ if (!doInstall(modName, gameName, modID, version, newestVersion, categoryID,
repository)) {
installResult = IPluginInstaller::RESULT_FAILED;
}
@@ -779,7 +819,7 @@ bool InstallationManager::install(const QString &fileName,
= installerCustom->supportedExtensions();
if (installerExt.find(fileInfo.suffix()) != installerExt.end()) {
installResult
- = installerCustom->install(modName, fileName, version, modID);
+ = installerCustom->install(modName, gameName, fileName, version, modID);
unsigned int idx = ModInfo::getIndex(modName);
if (idx != UINT_MAX) {
ModInfo::Ptr info = ModInfo::getByIndex(idx);
diff --git a/src/installationmanager.h b/src/installationmanager.h
index e1ebb519..e17aee17 100644
--- a/src/installationmanager.h
+++ b/src/installationmanager.h
@@ -168,7 +168,7 @@ private:
bool isSimpleArchiveTopLayer(const MOBase::DirectoryTree::Node *node, bool bainStyle);
MOBase::DirectoryTree::Node *getSimpleArchiveBase(MOBase::DirectoryTree *dataTree);
- bool doInstall(MOBase::GuessedValue<QString> &modName,
+ bool doInstall(MOBase::GuessedValue<QString> &modName, QString gameName,
int modID, const QString &version, const QString &newestVersion, int categoryID, const QString &repository);
QString generateBackupName(const QString &directoryName) const;
@@ -177,6 +177,11 @@ private:
void postInstallCleanup();
+signals:
+
+ void progressUpdate(float percentage);
+ void progressUpdate(QString const fileName);
+
private:
struct ByPriority {
@@ -207,6 +212,8 @@ private:
QString m_CurrentFile;
QProgressDialog *m_InstallationProgress { nullptr };
+ int m_Progress;
+ QString m_ProgressFile;
std::set<QString> m_TempFilesToDelete;
diff --git a/src/loadmechanism.cpp b/src/loadmechanism.cpp
index 7ad36ac7..ebbb5de3 100644
--- a/src/loadmechanism.cpp
+++ b/src/loadmechanism.cpp
@@ -126,7 +126,7 @@ void LoadMechanism::deactivateScriptExtender()
IPluginGame const *game = qApp->property("managed_game").value<IPluginGame*>();
ScriptExtender *extender = game->feature<ScriptExtender>();
if (extender == nullptr) {
- throw MyException(QObject::tr("game doesn't support a script extender"));
+ return;
}
QDir pluginsDir(game->gameDirectory().absolutePath() + "/data/" + extender->PluginPath());
@@ -193,7 +193,7 @@ void LoadMechanism::activateScriptExtender()
IPluginGame const *game = qApp->property("managed_game").value<IPluginGame *>();
ScriptExtender *extender = game->feature<ScriptExtender>();
if (extender == nullptr) {
- throw MyException(QObject::tr("game doesn't support a script extender"));
+ return;
}
QDir pluginsDir(game->gameDirectory().absolutePath() + "/data/" + extender->PluginPath());
diff --git a/src/main.cpp b/src/main.cpp
index fc332fe7..9c30a1c6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -46,6 +46,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "nxmaccessmanager.h"
#include "instancemanager.h"
#include "moshortcut.h"
+#include "organizercore.h"
#include <eh.h>
#include <windows_error.h>
@@ -71,6 +72,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QDesktopServices>
#include <QLibraryInfo>
#include <QSslSocket>
+#include <QtPlatformHeaders/QWindowsWindowFunctions>
#include <boost/scoped_array.hpp>
@@ -480,6 +482,8 @@ int runApplication(MOApplication &application, SingleInstance &instance,
return 1;
}
+ QWindowsWindowFunctions::setWindowActivationBehavior(QWindowsWindowFunctions::AlwaysActivateWindow);
+
QStringList arguments = application.arguments();
try {
@@ -538,6 +542,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
"start the game correctly if this is set "
"incorrectly!)"),
nullptr);
+ selection.setWindowFlag(Qt::WindowStaysOnTopHint, true);
int index = 0;
for (const QString &edition : editions) {
selection.addChoice(edition, "", index++);
@@ -601,8 +606,9 @@ int runApplication(MOApplication &application, SingleInstance &instance,
QPixmap pixmap(splashPath);
QSplashScreen splash(pixmap);
splash.show();
+ splash.activateWindow();
- NexusInterface::instance()->getAccessManager()->startLoginCheck();
+ NexusInterface::instance(&pluginContainer)->getAccessManager()->startLoginCheck();
qDebug("initializing tutorials");
TutorialManager::init(
@@ -625,10 +631,12 @@ int runApplication(MOApplication &application, SingleInstance &instance,
QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer,
SLOT(externalMessage(QString)));
+ mainWindow.processUpdates();
mainWindow.readSettings();
qDebug("displaying main window");
mainWindow.show();
+ mainWindow.activateWindow();
splash.finish(&mainWindow);
return application.exec();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index abcb5312..2830c776 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -98,6 +98,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QCursor>
#include <QDebug>
#include <QDesktopWidget>
+#include <QDesktopServices>
#include <QDialog>
#include <QDirIterator>
#include <QDragEnterEvent>
@@ -147,9 +148,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QTreeWidgetItemIterator>
#include <QUrl>
#include <QVariantList>
+#include <QVersionNumber>
#include <QWhatsThis>
#include <QWidgetAction>
#include <QWebEngineProfile>
+#include <QShortcut>
#include <QDebug>
#include <QtGlobal>
@@ -266,6 +269,7 @@ MainWindow::MainWindow(QSettings &initSettings
// hide these columns by default
ui->modList->header()->setSectionHidden(ModList::COL_CONTENT, true);
ui->modList->header()->setSectionHidden(ModList::COL_MODID, true);
+ ui->modList->header()->setSectionHidden(ModList::COL_GAME, true);
ui->modList->header()->setSectionHidden(ModList::COL_INSTALLTIME, true);
}
@@ -317,6 +321,11 @@ MainWindow::MainWindow(QSettings &initSettings
ui->groupCombo->installEventFilter(noWheel);
ui->profileBox->installEventFilter(noWheel);
+ if (organizerCore.managedGame()->sortMechanism() == MOBase::IPluginGame::SortMechanism::NONE) {
+ ui->bossButton->setDisabled(true);
+ ui->bossButton->setToolTip(tr("There is no supported sort mechanism for this game. You will probably have to use a third-party tool."));
+ }
+
connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*)));
connect(ui->modList, SIGNAL(dropModeUpdate(bool)), m_OrganizerCore.modList(), SLOT(dropModeUpdate(bool)));
@@ -343,11 +352,11 @@ MainWindow::MainWindow(QSettings &initSettings
connect(m_OrganizerCore.updater(), SIGNAL(updateAvailable()), this, SLOT(updateAvailable()));
connect(m_OrganizerCore.updater(), SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString)));
- connect(NexusInterface::instance(), SIGNAL(requestNXMDownload(QString)), &m_OrganizerCore, 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()), &m_OrganizerCore, SLOT(nexusLogin()));
- connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
- connect(NexusInterface::instance()->getAccessManager(), SIGNAL(credentialsReceived(const QString&, bool)),
+ connect(NexusInterface::instance(&pluginContainer), SIGNAL(requestNXMDownload(QString)), &m_OrganizerCore, SLOT(downloadRequestedNXM(QString)));
+ connect(NexusInterface::instance(&pluginContainer), SIGNAL(nxmDownloadURLsAvailable(QString,int,int,QVariant,QVariant,int)), this, SLOT(nxmDownloadURLs(QString,int,int,QVariant,QVariant,int)));
+ connect(NexusInterface::instance(&pluginContainer), SIGNAL(needLogin()), &m_OrganizerCore, SLOT(nexusLogin()));
+ connect(NexusInterface::instance(&pluginContainer)->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
+ connect(NexusInterface::instance(&pluginContainer)->getAccessManager(), SIGNAL(credentialsReceived(const QString&, bool)),
this, SLOT(updateWindowTitle(const QString&, bool)));
connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString)));
@@ -368,6 +377,12 @@ MainWindow::MainWindow(QSettings &initSettings
connect(ui->espList->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(esplistSelectionsChanged(QItemSelection)));
connect(ui->modList->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(modlistSelectionsChanged(QItemSelection)));
+ new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Enter), this, SLOT(openExplorer_activated()));
+ new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(openExplorer_activated()));
+
+ new QShortcut(QKeySequence::Refresh, this, SLOT(refreshProfile_activated()));
+
+
m_UpdateProblemsTimer.setSingleShot(true);
connect(&m_UpdateProblemsTimer, SIGNAL(timeout()), this, SLOT(updateProblemsButton()));
@@ -659,6 +674,7 @@ size_t MainWindow::checkForProblems()
void MainWindow::about()
{
AboutDialog dialog(m_OrganizerCore.getVersion().displayString(), this);
+ connect(&dialog, SIGNAL(linkClicked(QString)), this, SLOT(linkClicked(QString)));
dialog.exec();
}
@@ -1000,8 +1016,7 @@ void MainWindow::modPagePluginInvoke()
m_IntegratedBrowser.setWindowTitle(plugin->displayName());
m_IntegratedBrowser.openUrl(plugin->pageURL());
} else {
- ::ShellExecuteW(nullptr, L"open", ToWString(plugin->pageURL().toString()).c_str(),
- nullptr, nullptr, SW_SHOWNORMAL);
+ QDesktopServices::openUrl(QUrl(plugin->pageURL()));
}
}
}
@@ -1651,6 +1666,29 @@ void MainWindow::readSettings()
}
}
+void MainWindow::processUpdates() {
+ QSettings settings(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat);
+ QVersionNumber lastVersion = QVersionNumber::fromString(settings.value("version", "2.1.2").toString()).normalized();
+ QVersionNumber currentVersion = QVersionNumber::fromString(m_OrganizerCore.getVersion().displayString()).normalized();
+ if (!m_OrganizerCore.settings().directInterface().value("first_start", true).toBool()) {
+ if (lastVersion < QVersionNumber(2, 1, 3)) {
+ bool lastHidden = true;
+ for (int i = ModList::COL_GAME; i < ui->modList->model()->columnCount(); ++i) {
+ bool hidden = ui->modList->header()->isSectionHidden(i);
+ ui->modList->header()->setSectionHidden(i, lastHidden);
+ lastHidden = hidden;
+ }
+ }
+ }
+
+ if (currentVersion > lastVersion)
+ settings.setValue("version", currentVersion.toString());
+ else if (currentVersion < lastVersion)
+ qWarning() << tr("Notice: Your current MO version (%1) is lower than the previous version (%2).<br>"
+ "The GUI may not downgrade gracefully, so you may experience oddities.<br>"
+ "However, there should be no serious issues.").arg(lastVersion.toString()).arg(currentVersion.toString()).toStdWString();
+}
+
void MainWindow::storeSettings(QSettings &settings) {
settings.setValue("group_state", ui->groupCombo->currentIndex());
@@ -1886,12 +1924,12 @@ void MainWindow::helpTriggered()
void MainWindow::wikiTriggered()
{
- ::ShellExecuteW(nullptr, L"open", L"http://wiki.step-project.com/Guide:Mod_Organizer", nullptr, nullptr, SW_SHOWNORMAL);
+ QDesktopServices::openUrl(QUrl("http://wiki.step-project.com/Guide:Mod_Organizer"));
}
void MainWindow::issueTriggered()
{
- ::ShellExecuteW(nullptr, L"open", L"http://github.com/Modorganizer2/modorganizer/issues", nullptr, nullptr, SW_SHOWNORMAL);
+ QDesktopServices::openUrl(QUrl("https://github.com/Modorganizer2/modorganizer/issues"));
}
void MainWindow::tutorialTriggered()
@@ -2347,7 +2385,7 @@ void MainWindow::reinstallMod_clicked()
void MainWindow::resumeDownload(int downloadIndex)
{
- if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
+ if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->loggedIn()) {
m_OrganizerCore.downloadManager()->resumeDownload(downloadIndex);
} else {
QString username, password;
@@ -2355,7 +2393,7 @@ void MainWindow::resumeDownload(int downloadIndex)
m_OrganizerCore.doAfterLogin([this, downloadIndex] () {
this->resumeDownload(downloadIndex);
});
- NexusInterface::instance()->getAccessManager()->login(username, password);
+ NexusInterface::instance(&m_PluginContainer)->getAccessManager()->login(username, password);
} else {
MessageDialog::showMessage(tr("You need to be logged in with Nexus to resume a download"), this);
}
@@ -2365,13 +2403,13 @@ void MainWindow::resumeDownload(int downloadIndex)
void MainWindow::endorseMod(ModInfo::Ptr mod)
{
- if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
+ if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->loggedIn()) {
mod->endorse(true);
} else {
QString username, password;
if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
m_OrganizerCore.doAfterLogin(boost::bind(&MainWindow::endorseMod, this, mod));
- NexusInterface::instance()->getAccessManager()->login(username, password);
+ NexusInterface::instance(&m_PluginContainer)->getAccessManager()->login(username, password);
} else {
MessageDialog::showMessage(tr("You need to be logged in with Nexus to endorse"), this);
}
@@ -2393,12 +2431,12 @@ void MainWindow::dontendorse_clicked()
void MainWindow::unendorse_clicked()
{
QString username, password;
- if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
+ if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->loggedIn()) {
ModInfo::getByIndex(m_ContextRow)->endorse(false);
} else {
if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
m_OrganizerCore.doAfterLogin([this] () { this->unendorse_clicked(); });
- NexusInterface::instance()->getAccessManager()->login(username, password);
+ NexusInterface::instance(&m_PluginContainer)->getAccessManager()->login(username, password);
} else {
MessageDialog::showMessage(tr("You need to be logged in with Nexus to endorse"), this);
}
@@ -2453,16 +2491,31 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index,
} else {
modInfo->saveMeta();
ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), &m_OrganizerCore, &m_PluginContainer,this);
- connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString)));
+ connect(&dialog, SIGNAL(linkActivated(QString)), this, SLOT(linkClicked(QString)));
connect(&dialog, SIGNAL(downloadRequest(QString)), &m_OrganizerCore, SLOT(downloadRequestedNXM(QString)));
connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection);
- connect(&dialog, SIGNAL(modOpenNext()), this, SLOT(modOpenNext()), Qt::QueuedConnection);
- connect(&dialog, SIGNAL(modOpenPrev()), this, SLOT(modOpenPrev()), Qt::QueuedConnection);
+ connect(&dialog, SIGNAL(modOpenNext(int)), this, SLOT(modOpenNext(int)), Qt::QueuedConnection);
+ connect(&dialog, SIGNAL(modOpenPrev(int)), this, SLOT(modOpenPrev(int)), Qt::QueuedConnection);
connect(&dialog, SIGNAL(originModified(int)), this, SLOT(originModified(int)));
connect(&dialog, SIGNAL(endorseMod(ModInfo::Ptr)), this, SLOT(endorseMod(ModInfo::Ptr)));
+
+ //Open the tab first if we want to use the standard indexes of the tabs.
+ if (tab != -1) {
+ dialog.openTab(tab);
+ }
- dialog.openTab(tab);
dialog.restoreTabState(m_OrganizerCore.settings().directInterface().value("mod_info_tabs").toByteArray());
+
+ //If no tab was specified use the first tab from the left based on the user order.
+ if (tab == -1) {
+ for (int i = 0; i < dialog.findChild<QTabWidget*>("tabWidget")->count(); ++i) {
+ if (dialog.findChild<QTabWidget*>("tabWidget")->isTabEnabled(i)) {
+ dialog.findChild<QTabWidget*>("tabWidget")->setCurrentIndex(i);
+ break;
+ }
+ }
+ }
+
dialog.exec();
m_OrganizerCore.settings().directInterface().setValue("mod_info_tabs", dialog.saveTabState());
@@ -2503,7 +2556,7 @@ void MainWindow::setWindowEnabled(bool enabled)
}
-void MainWindow::modOpenNext()
+void MainWindow::modOpenNext(int tab)
{
QModelIndex index = m_ModListSortProxy->mapFromSource(m_OrganizerCore.modList()->index(m_ContextRow, 0));
index = m_ModListSortProxy->index((index.row() + 1) % m_ModListSortProxy->rowCount(), 0);
@@ -2514,13 +2567,13 @@ void MainWindow::modOpenNext()
if ((std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) ||
(std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end())) {
// skip overwrite and backups
- modOpenNext();
+ modOpenNext(tab);
} else {
- displayModInformation(m_ContextRow);
+ displayModInformation(m_ContextRow,tab);
}
}
-void MainWindow::modOpenPrev()
+void MainWindow::modOpenPrev(int tab)
{
QModelIndex index = m_ModListSortProxy->mapFromSource(m_OrganizerCore.modList()->index(m_ContextRow, 0));
int row = index.row() - 1;
@@ -2534,9 +2587,9 @@ void MainWindow::modOpenPrev()
if ((std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) ||
(std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end())) {
// skip overwrite and backups
- modOpenPrev();
+ modOpenPrev(tab);
} else {
- displayModInformation(m_ContextRow);
+ displayModInformation(m_ContextRow,tab);
}
}
@@ -2570,12 +2623,21 @@ void MainWindow::ignoreMissingData_clicked()
emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
}
+void MainWindow::markConverted_clicked()
+{
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ info->markConverted(true);
+ connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex)));
+ emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
+}
+
void MainWindow::visitOnNexus_clicked()
{
int modID = m_OrganizerCore.modList()->data(m_OrganizerCore.modList()->index(m_ContextRow, 0), Qt::UserRole).toInt();
+ QString gameName = m_OrganizerCore.modList()->data(m_OrganizerCore.modList()->index(m_ContextRow, 0), Qt::UserRole + 4).toString();
if (modID > 0) {
- nexusLinkActivated(NexusInterface::instance()->getModURL(modID));
+ linkClicked(NexusInterface::instance(&m_PluginContainer)->getModURL(modID, gameName));
} else {
MessageDialog::showMessage(tr("Nexus ID for this Mod is unknown"), this);
}
@@ -2598,6 +2660,49 @@ void MainWindow::openExplorer_clicked()
::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
}
+void MainWindow::openExplorer_activated()
+{
+ if (ui->modList->hasFocus()) {
+ QItemSelectionModel *selection = ui->modList->selectionModel();
+ if (selection->hasSelection() && selection->selectedRows().count() == 1 ) {
+
+ QModelIndex idx = selection->currentIndex();
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt());
+ std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
+
+ if (modInfo->isRegular() || (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end())) {
+ ::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+ }
+
+ }
+ }
+
+ if (ui->espList->hasFocus()) {
+ QItemSelectionModel *selection = ui->espList->selectionModel();
+
+ if (selection->hasSelection() && selection->selectedRows().count() == 1) {
+
+ QModelIndex idx = selection->currentIndex();
+ QString fileName = idx.data().toString();
+
+
+
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName)));
+ std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
+
+ if (modInfo->isRegular() || (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end())) {
+ ::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+ }
+
+ }
+ }
+}
+
+void MainWindow::refreshProfile_activated()
+{
+ m_OrganizerCore.profileRefresh();
+}
+
void MainWindow::information_clicked()
{
try {
@@ -2921,18 +3026,18 @@ void MainWindow::saveArchiveList()
void MainWindow::checkModsForUpdates()
{
statusBar()->show();
- if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
- m_ModsToUpdate = ModInfo::checkAllForUpdate(this);
+ if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->loggedIn()) {
+ m_ModsToUpdate = ModInfo::checkAllForUpdate(&m_PluginContainer, this);
m_RefreshProgress->setRange(0, m_ModsToUpdate);
} else {
QString username, password;
if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
m_OrganizerCore.doAfterLogin([this] () { this->checkModsForUpdates(); });
- NexusInterface::instance()->getAccessManager()->login(username, password);
+ NexusInterface::instance(&m_PluginContainer)->getAccessManager()->login(username, password);
} else { // otherwise there will be no endorsement info
MessageDialog::showMessage(tr("Not logged in, endorsement information will be wrong"),
this, true);
- m_ModsToUpdate = ModInfo::checkAllForUpdate(this);
+ m_ModsToUpdate = ModInfo::checkAllForUpdate(&m_PluginContainer, this);
}
}
}
@@ -3207,7 +3312,7 @@ void MainWindow::exportModListCSV()
if (nexus_ID->isChecked())
builder.setRowField("#Nexus_ID", info->getNexusID());
if (mod_Nexus_URL->isChecked())
- builder.setRowField("#Mod_Nexus_URL",(info->getNexusID()>0)? NexusInterface::instance()->getModURL(info->getNexusID()) : "");
+ builder.setRowField("#Mod_Nexus_URL",(info->getNexusID()>0)? NexusInterface::instance(&m_PluginContainer)->getModURL(info->getNexusID(), info->getGameName()) : "");
if (mod_Version->isChecked())
builder.setRowField("#Mod_Version", info->getVersion().canonicalString());
if (install_Date->isChecked())
@@ -3390,6 +3495,10 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
menu->addAction(tr("Ignore missing data"), this, SLOT(ignoreMissingData_clicked()));
}
+ if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_ALTERNATE_GAME) != flags.end()) {
+ menu->addAction(tr("Mark as converted/working"), this, SLOT(markConverted_clicked()));
+ }
+
if (info->getNexusID() > 0) {
menu->addAction(tr("Visit on Nexus"), this, SLOT(visitOnNexus_clicked()));
} else if ((info->getURL() != "")) {
@@ -3472,6 +3581,7 @@ void MainWindow::deleteSavegame_clicked()
} else {
ISaveGame const *save = info->getSaveGameInfo(name);
deleteFiles += save->allFiles();
+ delete save;
}
}
@@ -3629,7 +3739,7 @@ void MainWindow::on_actionSettings_triggered()
bool oldDisplayForeign(settings.displayForeign());
bool proxy = settings.useProxy();
- settings.query(this);
+ settings.query(&m_PluginContainer, this);
InstallationManager *instManager = m_OrganizerCore.installationManager();
instManager->setModsDirectory(settings.getModDirectory());
@@ -3661,14 +3771,14 @@ void MainWindow::on_actionSettings_triggered()
}
if (settings.getCacheDirectory() != oldCacheDirectory) {
- NexusInterface::instance()->setCacheDirectory(settings.getCacheDirectory());
+ NexusInterface::instance(&m_PluginContainer)->setCacheDirectory(settings.getCacheDirectory());
}
if (proxy != settings.useProxy()) {
activateProxy(settings.useProxy());
}
- NexusInterface::instance()->setNMMVersion(settings.getNMMVersion());
+ NexusInterface::instance(&m_PluginContainer)->setNMMVersion(settings.getNMMVersion());
updateDownloadListDelegate();
@@ -3679,22 +3789,13 @@ void MainWindow::on_actionSettings_triggered()
void MainWindow::on_actionNexus_triggered()
{
- ::ShellExecuteW(nullptr, L"open",
- NexusInterface::instance()->getGameURL().toStdWString().c_str(),
- nullptr, nullptr, SW_SHOWNORMAL);
-}
-
-
-void MainWindow::nexusLinkActivated(const QString &link)
-{
- ::ShellExecuteW(nullptr, L"open", ToWString(link).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
- ui->tabWidget->setCurrentIndex(4);
+ QDesktopServices::openUrl(QUrl(NexusInterface::instance(&m_PluginContainer)->getGameURL(m_OrganizerCore.managedGame()->gameShortName())));
}
void MainWindow::linkClicked(const QString &url)
{
- ::ShellExecuteW(nullptr, L"open", ToWString(url).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+ QDesktopServices::openUrl(QUrl(url));
}
@@ -3725,7 +3826,11 @@ void MainWindow::languageChange(const QString &newLanguage)
m_CurrentLanguage = newLanguage;
installTranslator("qt");
+ installTranslator("qtbase");
installTranslator(ToQString(AppConfig::translationPrefix()));
+ for (const QString &fileName : m_PluginContainer.pluginFileNames()) {
+ installTranslator(QFileInfo(fileName).baseName());
+ }
ui->retranslateUi(this);
qDebug("loaded language %s", qPrintable(newLanguage));
@@ -4096,10 +4201,10 @@ void MainWindow::on_actionEndorseMO_triggered()
{
if (QMessageBox::question(this, tr("Endorse Mod Organizer"),
tr("Do you want to endorse Mod Organizer on %1 now?").arg(
- NexusInterface::instance()->getGameURL()),
+ NexusInterface::instance(&m_PluginContainer)->getGameURL(m_OrganizerCore.managedGame()->gameShortName())),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- NexusInterface::instance()->requestToggleEndorsement(
- m_OrganizerCore.managedGame()->nexusModOrganizerID(), true, this, QVariant(), QString());
+ NexusInterface::instance(&m_PluginContainer)->requestToggleEndorsement(
+ m_OrganizerCore.managedGame()->gameShortName(), m_OrganizerCore.managedGame()->nexusModOrganizerID(), true, this, QVariant(), QString());
}
}
@@ -4162,16 +4267,32 @@ void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant us
QVariantList resultList = resultData.toList();
for (auto iter = resultList.begin(); iter != resultList.end(); ++iter) {
QVariantMap result = iter->toMap();
- if (result["id"].toInt() == m_OrganizerCore.managedGame()->nexusModOrganizerID()) {
+ if (result["id"].toInt() == m_OrganizerCore.managedGame()->nexusModOrganizerID()
+ && result["game_id"].toInt() == m_OrganizerCore.managedGame()->nexusGameID()) {
if (!result["voted_by_user"].toBool()) {
ui->actionEndorseMO->setVisible(true);
}
} else {
- std::vector<ModInfo::Ptr> info = ModInfo::getByModID(result["id"].toInt());
+ QString gameName = m_OrganizerCore.managedGame()->gameShortName();
+ bool sameNexus = false;
+ for (IPluginGame *game : m_PluginContainer.plugins<IPluginGame>()) {
+ if (game->nexusGameID() == result["game_id"].toInt()) {
+ gameName = game->gameShortName();
+ if (game->nexusGameID() == m_OrganizerCore.managedGame()->nexusGameID())
+ sameNexus = true;
+ break;
+ }
+ }
+ std::vector<ModInfo::Ptr> info = ModInfo::getByModID(gameName, result["id"].toInt());
+ if (sameNexus) {
+ std::vector<ModInfo::Ptr> mainInfo = ModInfo::getByModID(m_OrganizerCore.managedGame()->gameShortName(), result["id"].toInt());
+ info.reserve(info.size() + mainInfo.size());
+ info.insert(info.end(), mainInfo.begin(), mainInfo.end());
+ }
for (auto iter = info.begin(); iter != info.end(); ++iter) {
(*iter)->setNewestVersion(result["version"].toString());
(*iter)->setNexusDescription(result["description"].toString());
- if (NexusInterface::instance()->getAccessManager()->loggedIn() &&
+ if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->loggedIn() &&
result.contains("voted_by_user")) {
// don't use endorsement info if we're not logged in or if the response doesn't contain it
(*iter)->setIsEndorsed(result["voted_by_user"].toBool());
@@ -4194,20 +4315,20 @@ void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant us
}
}
-void MainWindow::nxmEndorsementToggled(int, QVariant, QVariant resultData, int)
+void MainWindow::nxmEndorsementToggled(QString, int, QVariant, QVariant resultData, int)
{
if (resultData.toBool()) {
ui->actionEndorseMO->setVisible(false);
QMessageBox::question(this, tr("Thank you!"), tr("Thank you for your endorsement!"));
}
- if (!disconnect(sender(), SIGNAL(nxmEndorsementToggled(int, QVariant, QVariant, int)),
- this, SLOT(nxmEndorsementToggled(int, QVariant, QVariant, int)))) {
+ if (!disconnect(sender(), SIGNAL(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)),
+ this, SLOT(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)))) {
qCritical("failed to disconnect endorsement slot");
}
}
-void MainWindow::nxmDownloadURLs(int, int, QVariant, QVariant resultData, int)
+void MainWindow::nxmDownloadURLs(QString, int, int, QVariant, QVariant resultData, int)
{
QVariantList serverList = resultData.toList();
@@ -4226,7 +4347,7 @@ void MainWindow::nxmDownloadURLs(int, int, QVariant, QVariant resultData, int)
}
-void MainWindow::nxmRequestFailed(int modID, int, QVariant, int, const QString &errorString)
+void MainWindow::nxmRequestFailed(QString, int modID, int, QVariant, int, const QString &errorString)
{
if (modID == -1) {
// must be the update-check that failed
@@ -4516,7 +4637,7 @@ void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos)
menu.addAction(tr("Unlock load order"), this, SLOT(unlockESPIndex()));
}
if (hasUnlocked) {
- menu.addAction(tr("Lock load order"), this, SLOT(lockESPIndex()));
+ menu.addAction(tr("Lock load order"), this, SLOT(f()));
}
try {
diff --git a/src/mainwindow.h b/src/mainwindow.h
index ef6eb262..bbff0d93 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -116,6 +116,7 @@ public:
void storeSettings(QSettings &settings) override;
void readSettings();
+ void processUpdates();
virtual ILockedWaitingForProcess* lock() override;
virtual void unlock() override;
@@ -217,7 +218,7 @@ private:
QList<MOBase::IOrganizer::FileInfo> findFileInfos(const QString &path, const std::function<bool (const MOBase::IOrganizer::FileInfo &)> &filter) const;
bool modifyExecutablesDialog();
- void displayModInformation(int row, int tab = 0);
+ void displayModInformation(int row, int tab = -1);
void testExtractBSA(int modIndex);
void writeDataToFile(QFile &file, const QString &directory, const MOShared::DirectoryEntry &directoryEntry);
@@ -386,6 +387,7 @@ private slots:
void showMessage(const QString &message);
void showError(const QString &message);
+
// main window actions
void helpTriggered();
void issueTriggered();
@@ -393,6 +395,10 @@ private slots:
void tutorialTriggered();
void extractBSATriggered();
+ //modlist shortcuts
+ void openExplorer_activated();
+ void refreshProfile_activated();
+
// modlist context menu
void installMod_clicked();
void createEmptyMod_clicked();
@@ -404,6 +410,7 @@ private slots:
void dontendorse_clicked();
void unendorse_clicked();
void ignoreMissingData_clicked();
+ void markConverted_clicked();
void visitOnNexus_clicked();
void visitWebPage_clicked();
void openExplorer_clicked();
@@ -438,7 +445,6 @@ private slots:
// nexus related
void checkModsForUpdates();
- void nexusLinkActivated(const QString &link);
void loginFailed(const QString &message);
@@ -461,16 +467,16 @@ private slots:
void modInstalled(const QString &modName);
void nxmUpdatesAvailable(const std::vector<int> &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);
- void nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
+ void nxmEndorsementToggled(QString, int, QVariant, QVariant resultData, int);
+ void nxmDownloadURLs(QString, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmRequestFailed(QString, int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
void editCategories();
void deselectFilters();
void displayModInformation(const QString &modName, int tab);
- void modOpenNext();
- void modOpenPrev();
+ void modOpenNext(int tab=-1);
+ void modOpenPrev(int tab=-1);
void modRenamed(const QString &oldName, const QString &newName);
void modRemoved(const QString &fileName);
diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp
index 61df0a0d..1995964b 100644
--- a/src/modflagicondelegate.cpp
+++ b/src/modflagicondelegate.cpp
@@ -48,6 +48,7 @@ QString ModFlagIconDelegate::getFlagIcon(ModInfo::EFlag flag) const
case ModInfo::FLAG_CONFLICT_OVERWRITTEN: return ":/MO/gui/emblem_conflict_overwritten";
case ModInfo::FLAG_CONFLICT_MIXED: return ":/MO/gui/emblem_conflict_mixed";
case ModInfo::FLAG_CONFLICT_REDUNDANT: return ":MO/gui/emblem_conflict_redundant";
+ case ModInfo::FLAG_ALTERNATE_GAME: return ":MO/gui/alternate_game";
default: return QString();
}
}
diff --git a/src/modidlineedit.cpp b/src/modidlineedit.cpp
new file mode 100644
index 00000000..7d1f0c38
--- /dev/null
+++ b/src/modidlineedit.cpp
@@ -0,0 +1,19 @@
+#include "modidlineedit.h"
+#include <QWhatsThis>
+
+#include <QEvent>
+#include <QWhatsThisClickedEvent>
+
+ModIDLineEdit::ModIDLineEdit(QWidget *parent) : QLineEdit(parent) {}
+ModIDLineEdit::ModIDLineEdit(const QString &text, QWidget *parent) : QLineEdit(text, parent) {}
+
+bool ModIDLineEdit::event(QEvent *event)
+{
+ if (event->type() == QEvent::WhatsThisClicked)
+ {
+ QWhatsThisClickedEvent *wtcEvent = static_cast<QWhatsThisClickedEvent*>(event);
+ emit linkClicked(wtcEvent->href().trimmed());
+ }
+
+ return QLineEdit::event(event);
+} \ No newline at end of file
diff --git a/src/modidlineedit.h b/src/modidlineedit.h
new file mode 100644
index 00000000..2a3db36c
--- /dev/null
+++ b/src/modidlineedit.h
@@ -0,0 +1,22 @@
+#ifndef MODIDLINEEDIT_H
+#define MODIDLINEEDIT_H
+
+#include <QLineEdit>
+
+class ModIDLineEdit : public QLineEdit
+{
+ Q_OBJECT
+
+public:
+ explicit ModIDLineEdit(QWidget *parent = 0);
+ explicit ModIDLineEdit(const QString &text, QWidget *parent = 0);
+
+public:
+ virtual bool event(QEvent* event) override;
+
+signals:
+ void linkClicked(QString);
+
+};
+
+#endif //MODIDLINEEDIT_H \ No newline at end of file
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index d80c636b..bd4c1254 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -48,7 +48,7 @@ using namespace MOShared;
std::vector<ModInfo::Ptr> ModInfo::s_Collection;
std::map<QString, unsigned int> ModInfo::s_ModsByName;
-std::map<int, std::vector<unsigned int> > ModInfo::s_ModsByModID;
+std::map<std::pair<QString, int>, std::vector<unsigned int>> ModInfo::s_ModsByModID;
int ModInfo::s_NextID;
QMutex ModInfo::s_Mutex(QMutex::Recursive);
@@ -61,16 +61,16 @@ bool ModInfo::ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS)
}
-ModInfo::Ptr ModInfo::createFrom(const QDir &dir, DirectoryEntry **directoryStructure)
+ModInfo::Ptr ModInfo::createFrom(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &dir, DirectoryEntry **directoryStructure)
{
QMutexLocker locker(&s_Mutex);
// int id = s_NextID++;
static QRegExp backupExp(".*backup[0-9]*");
ModInfo::Ptr result;
if (backupExp.exactMatch(dir.dirName())) {
- result = ModInfo::Ptr(new ModInfoBackup(dir, directoryStructure));
+ result = ModInfo::Ptr(new ModInfoBackup(pluginContainer, game, dir, directoryStructure));
} else {
- result = ModInfo::Ptr(new ModInfoRegular(dir, directoryStructure));
+ result = ModInfo::Ptr(new ModInfoRegular(pluginContainer, game, dir, directoryStructure));
}
s_Collection.push_back(result);
return result;
@@ -80,10 +80,11 @@ ModInfo::Ptr ModInfo::createFromPlugin(const QString &modName,
const QString &espName,
const QStringList &bsaNames,
ModInfo::EModType modType,
- DirectoryEntry **directoryStructure) {
+ DirectoryEntry **directoryStructure,
+ PluginContainer *pluginContainer) {
QMutexLocker locker(&s_Mutex);
ModInfo::Ptr result = ModInfo::Ptr(
- new ModInfoForeign(modName, espName, bsaNames, modType, directoryStructure));
+ new ModInfoForeign(modName, espName, bsaNames, modType, directoryStructure, pluginContainer));
s_Collection.push_back(result);
return result;
}
@@ -105,11 +106,11 @@ QString ModInfo::getContentTypeName(int contentType)
}
}
-void ModInfo::createFromOverwrite()
+void ModInfo::createFromOverwrite(PluginContainer *pluginContainer)
{
QMutexLocker locker(&s_Mutex);
- s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite));
+ s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite(pluginContainer)));
}
unsigned int ModInfo::getNumMods()
@@ -131,11 +132,11 @@ ModInfo::Ptr ModInfo::getByIndex(unsigned int index)
}
-std::vector<ModInfo::Ptr> ModInfo::getByModID(int modID)
+std::vector<ModInfo::Ptr> ModInfo::getByModID(QString game, int modID)
{
QMutexLocker locker(&s_Mutex);
- auto iter = s_ModsByModID.find(modID);
+ auto iter = s_ModsByModID.find(std::pair<QString, int>(game, modID));
if (iter == s_ModsByModID.end()) {
return std::vector<ModInfo::Ptr>();
}
@@ -160,11 +161,11 @@ bool ModInfo::removeMod(unsigned int index)
ModInfo::Ptr modInfo = s_Collection[index];
s_ModsByName.erase(s_ModsByName.find(modInfo->name()));
- auto iter = s_ModsByModID.find(modInfo->getNexusID());
+ auto iter = s_ModsByModID.find(std::pair<QString, int>(modInfo->getGameName(), modInfo->getNexusID()));
if (iter != s_ModsByModID.end()) {
std::vector<unsigned int> indices = iter->second;
indices.erase(std::remove(indices.begin(), indices.end(), index), indices.end());
- s_ModsByModID[modInfo->getNexusID()] = indices;
+ s_ModsByModID[std::pair<QString, int>(modInfo->getGameName(), modInfo->getNexusID())] = indices;
}
// physically remove the mod directory
@@ -207,6 +208,7 @@ unsigned int ModInfo::findMod(const boost::function<bool (ModInfo::Ptr)> &filter
void ModInfo::updateFromDisc(const QString &modDirectory,
DirectoryEntry **directoryStructure,
+ PluginContainer *pluginContainer,
bool displayForeign,
MOBase::IPluginGame const *game)
{
@@ -219,7 +221,7 @@ void ModInfo::updateFromDisc(const QString &modDirectory,
mods.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
QDirIterator modIter(mods);
while (modIter.hasNext()) {
- createFrom(QDir(modIter.next()), directoryStructure);
+ createFrom(pluginContainer, game, QDir(modIter.next()), directoryStructure);
}
}
@@ -233,11 +235,12 @@ void ModInfo::updateFromDisc(const QString &modDirectory,
unmanaged->referenceFile(modName).absoluteFilePath(),
unmanaged->secondaryFiles(modName),
modType,
- directoryStructure);
+ directoryStructure,
+ pluginContainer);
}
}
- createFromOverwrite();
+ createFromOverwrite(pluginContainer);
std::sort(s_Collection.begin(), s_Collection.end(), ModInfo::ByName);
@@ -252,28 +255,29 @@ void ModInfo::updateIndices()
for (unsigned int i = 0; i < s_Collection.size(); ++i) {
QString modName = s_Collection[i]->internalName();
+ QString game = s_Collection[i]->getGameName();
int modID = s_Collection[i]->getNexusID();
s_ModsByName[modName] = i;
- s_ModsByModID[modID].push_back(i);
+ s_ModsByModID[std::pair<QString, int>(game, modID)].push_back(i);
}
}
-ModInfo::ModInfo()
+ModInfo::ModInfo(PluginContainer *pluginContainer)
: m_Valid(false), m_PrimaryCategory(-1)
{
}
-void ModInfo::checkChunkForUpdate(const std::vector<int> &modIDs, QObject *receiver)
+void ModInfo::checkChunkForUpdate(PluginContainer *pluginContainer, const std::vector<int> &modIDs, QObject *receiver, QString gameName)
{
if (modIDs.size() != 0) {
- NexusInterface::instance()->requestUpdates(modIDs, receiver, QVariant(), QString());
+ NexusInterface::instance(pluginContainer)->requestUpdates(modIDs, receiver, QVariant(), gameName, QString());
}
}
-int ModInfo::checkAllForUpdate(QObject *receiver)
+int ModInfo::checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiver)
{
// technically this should be 255 but those requests can take nexus fairly long, produce
// large output and may have been the cause of issue #1166
@@ -284,20 +288,36 @@ int ModInfo::checkAllForUpdate(QObject *receiver)
//I ought to store this, it's used elsewhere
IPluginGame const *game = qApp->property("managed_game").value<IPluginGame *>();
+ if (game->nexusModOrganizerID()) {
+ modIDs.push_back(game->nexusModOrganizerID());
+ checkChunkForUpdate(pluginContainer, modIDs, receiver, game->gameShortName());
+ modIDs.clear();
+ }
- modIDs.push_back(game->nexusModOrganizerID());
-
- for (const ModInfo::Ptr &mod : s_Collection) {
+ std::multimap<QString, QSharedPointer<ModInfo>> organizedGames;
+ for (auto mod : s_Collection) {
if (mod->canBeUpdated()) {
- modIDs.push_back(mod->getNexusID());
- if (modIDs.size() >= chunkSize) {
- checkChunkForUpdate(modIDs, receiver);
+ organizedGames.insert(std::pair<QString, QSharedPointer<ModInfo>>(mod->getGameName(), mod));
+ }
+ }
+
+ QString currentGame = "";
+ for (auto game : organizedGames) {
+ if (currentGame != game.first) {
+ if (currentGame != "") {
+ checkChunkForUpdate(pluginContainer, modIDs, receiver, currentGame);
modIDs.clear();
}
+ currentGame = game.first;
+ }
+ modIDs.push_back(game.second->getNexusID());
+ if (modIDs.size() >= chunkSize) {
+ checkChunkForUpdate(pluginContainer, modIDs, receiver, currentGame);
+ modIDs.clear();
}
}
- checkChunkForUpdate(modIDs, receiver);
+ checkChunkForUpdate(pluginContainer, modIDs, receiver, currentGame);
return result;
}
@@ -394,4 +414,4 @@ void ModInfo::testValid()
while (dirIter.hasNext()) {
dirIter.next();
}
-}
+} \ No newline at end of file
diff --git a/src/modinfo.h b/src/modinfo.h
index 1ceb8e1f..001a78dc 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -23,6 +23,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "imodinterface.h"
#include "versioninfo.h"
+class PluginContainer;
+
class QDateTime;
class QDir;
#include <QMutex>
@@ -68,7 +70,8 @@ public:
FLAG_CONFLICT_OVERWRITTEN,
FLAG_CONFLICT_MIXED,
FLAG_CONFLICT_REDUNDANT,
- FLAG_PLUGIN_SELECTED
+ FLAG_PLUGIN_SELECTED,
+ FLAG_ALTERNATE_GAME
};
enum EContent {
@@ -115,6 +118,7 @@ public:
**/
static void updateFromDisc(const QString &modDirectory,
MOShared::DirectoryEntry **directoryStructure,
+ PluginContainer *pluginContainer,
bool displayForeign,
MOBase::IPluginGame const *game);
@@ -144,7 +148,7 @@ public:
* @todo in its current form, this function is broken! There may be multiple mods with the same nexus id,
* this function will return only one of them
**/
- static std::vector<ModInfo::Ptr> getByModID(int modID);
+ static std::vector<ModInfo::Ptr> getByModID(QString game, int modID);
/**
* @brief remove a mod by index
@@ -176,19 +180,19 @@ public:
* @param modIDs list of mods (Nexus Mod IDs) to check for updates
* @return
*/
- static void checkChunkForUpdate(const std::vector<int> &modIDs, QObject *receiver);
+ static void checkChunkForUpdate(PluginContainer *pluginContainer, const std::vector<int> &modIDs, QObject *receiver, QString gameName);
/**
* @brief query nexus information for every mod and update the "newest version" information
**/
- static int checkAllForUpdate(QObject *receiver);
+ static int checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiver);
/**
* @brief create a new mod from the specified directory and add it to the collection
* @param dir directory to create from
* @return pointer to the info-structure of the newly created/added mod
*/
- static ModInfo::Ptr createFrom(const QDir &dir, MOShared::DirectoryEntry **directoryStructure);
+ static ModInfo::Ptr createFrom(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &dir, MOShared::DirectoryEntry **directoryStructure);
/**
* @brief create a new "foreign-managed" mod from a tuple of plugin and archives
@@ -196,7 +200,7 @@ public:
* @param bsaNames names of archives
* @return a new mod
*/
- static ModInfo::Ptr createFromPlugin(const QString &modName, const QString &espName, const QStringList &bsaNames, ModInfo::EModType modType, MOShared::DirectoryEntry **directoryStructure);
+ static ModInfo::Ptr createFromPlugin(const QString &modName, const QString &espName, const QStringList &bsaNames, ModInfo::EModType modType, MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer);
/**
* @brief retieve a name for one of the CONTENT_ enums
@@ -265,6 +269,13 @@ public:
virtual void setNotes(const QString &notes) = 0;
/**
+ * @brief set/change the source game of this mod
+ *
+ * @param gameName the source game shortName
+ */
+ virtual void setGameName(QString gameName) = 0;
+
+ /**
* @brief set/change the nexus mod id of this mod
*
* @param modID the nexus mod id
@@ -411,6 +422,13 @@ public:
virtual int getNexusID() const = 0;
/**
+ * @brief getter for the source game repository
+ *
+ * @return the source game repository. should default to the active game.
+ **/
+ virtual QString getGameName() const = 0;
+
+ /**
* @return the fixed priority of mods of this type or INT_MIN if the priority of mods
* needs to be user-modifiable. Can be < 0 to force a priority below user-modifable mods
* or INT_MAX to force priority above all user-modifiables
@@ -551,6 +569,11 @@ public:
void testValid();
/**
+ * @brief updates the mod to flag it as converted in order to ignore the alternate game warning
+ */
+ virtual void markConverted(bool converted) {}
+
+ /**
* @brief reads meta information from disk
*/
virtual void readMeta() {}
@@ -596,14 +619,14 @@ signals:
protected:
- ModInfo();
+ ModInfo(PluginContainer *pluginContainer);
static void updateIndices();
static bool ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS);
private:
- static void createFromOverwrite();
+ static void createFromOverwrite(PluginContainer *pluginContainer);
protected:
@@ -620,7 +643,7 @@ protected:
private:
static QMutex s_Mutex;
- static std::map<int, std::vector<unsigned int> > s_ModsByModID;
+ static std::map<std::pair<QString, int>, std::vector<unsigned int> > s_ModsByModID;
static int s_NextID;
bool m_Valid;
diff --git a/src/modinfobackup.cpp b/src/modinfobackup.cpp
index a57b84fe..6e307103 100644
--- a/src/modinfobackup.cpp
+++ b/src/modinfobackup.cpp
@@ -14,7 +14,7 @@ QString ModInfoBackup::getDescription() const
}
-ModInfoBackup::ModInfoBackup(const QDir &path, MOShared::DirectoryEntry **directoryStructure)
- : ModInfoRegular(path, directoryStructure)
+ModInfoBackup::ModInfoBackup(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &path, MOShared::DirectoryEntry **directoryStructure)
+ : ModInfoRegular(pluginContainer, game, path, directoryStructure)
{
}
diff --git a/src/modinfobackup.h b/src/modinfobackup.h
index adbac783..da1fcd4a 100644
--- a/src/modinfobackup.h
+++ b/src/modinfobackup.h
@@ -14,6 +14,7 @@ public:
virtual bool updateIgnored() const { return false; }
virtual bool downgradeAvailable() const { return false; }
virtual bool updateNXMInfo() { return false; }
+ virtual void setGameName(QString) {}
virtual void setNexusID(int) {}
virtual void endorse(bool) {}
virtual int getFixedPriority() const { return -1; }
@@ -32,7 +33,7 @@ public:
private:
- ModInfoBackup(const QDir &path, MOShared::DirectoryEntry **directoryStructure);
+ ModInfoBackup(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &path, MOShared::DirectoryEntry **directoryStructure);
};
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index 6a53d915..12654755 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -22,6 +22,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "descriptionpage.h"
#include "mainwindow.h"
+#include "modidlineedit.h"
#include "iplugingame.h"
#include "nexusinterface.h"
#include "report.h"
@@ -46,6 +47,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QInputDialog>
#include <QPointer>
#include <QFileDialog>
+#include <QShortcut>
#include <Shlwapi.h>
@@ -92,6 +94,24 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
ui->modIDEdit->setValidator(new QIntValidator(modIDEdit));
ui->modIDEdit->setText(QString("%1").arg(modInfo->getNexusID()));
+ connect(ui->modIDEdit, SIGNAL(linkClicked(QString)), this, SLOT(linkClicked(QString)));
+
+ QString gameName = modInfo->getGameName();
+ ui->sourceGameEdit->addItem(organizerCore->managedGame()->gameName(), organizerCore->managedGame()->gameShortName());
+ if (organizerCore->managedGame()->validShortNames().size() == 0) {
+ ui->sourceGameEdit->setDisabled(true);
+ } else {
+ for (auto game : pluginContainer->plugins<IPluginGame>()) {
+ for (QString gameName : organizerCore->managedGame()->validShortNames()) {
+ if (game->gameShortName().compare(gameName, Qt::CaseInsensitive) == 0) {
+ ui->sourceGameEdit->addItem(game->gameName(), game->gameShortName());
+ break;
+ }
+ }
+ }
+ }
+ ui->sourceGameEdit->setCurrentIndex(ui->sourceGameEdit->findData(gameName));
+
ui->notesEdit->setText(modInfo->notes());
ui->descriptionView->setPage(new DescriptionPage);
@@ -103,6 +123,8 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
//TODO: No easy way to delegate links
//ui->descriptionView->page()->acceptNavigationRequest(QWebEnginePage::DelegateAllLinks);
+ new QShortcut(QKeySequence::Delete, this, SLOT(delete_activated()));
+
if (directory->originExists(ToWString(modInfo->name()))) {
m_Origin = &directory->getOriginByName(ToWString(modInfo->name()));
if (m_Origin->isDisabled()) {
@@ -706,22 +728,26 @@ void ModInfoDialog::on_deactivateESP_clicked()
void ModInfoDialog::on_visitNexusLabel_linkActivated(const QString &link)
{
- this->close();
- emit nexusLinkActivated(link);
+ emit linkActivated(link);
}
void ModInfoDialog::linkClicked(const QUrl &url)
{
//Ideally we'd ask the mod for the game and the web service then pass the game
//and URL to the web service
- if (NexusInterface::instance()->isURLGameRelated(url)) {
- this->close();
- emit nexusLinkActivated(url.toString());
+ if (NexusInterface::instance(m_PluginContainer)->isURLGameRelated(url)) {
+
+ emit linkActivated(url.toString());
} else {
::ShellExecuteW(nullptr, L"open", ToWString(url.toString()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
}
}
+void ModInfoDialog::linkClicked(QString url)
+{
+ emit linkActivated(url);
+}
+
void ModInfoDialog::refreshNexusData(int modID)
{
@@ -860,7 +886,7 @@ void ModInfoDialog::activateNexusTab()
QLineEdit *modIDEdit = findChild<QLineEdit*>("modIDEdit");
int modID = modIDEdit->text().toInt();
if (modID != 0) {
- QString nexusLink = NexusInterface::instance()->getModURL(modID);
+ QString nexusLink = NexusInterface::instance(m_PluginContainer)->getModURL(modID, m_ModInfo->getGameName());
QLabel *visitNexusLabel = findChild<QLabel*>("visitNexusLabel");
visitNexusLabel->setText(tr("<a href=\"%1\">Visit on Nexus</a>").arg(nexusLink));
visitNexusLabel->setToolTip(nexusLink);
@@ -901,6 +927,16 @@ void ModInfoDialog::on_modIDEdit_editingFinished()
}
}
+void ModInfoDialog::on_sourceGameEdit_currentIndexChanged(int)
+{
+ for (auto game : m_PluginContainer->plugins<IPluginGame>()) {
+ if (game->gameName() == ui->sourceGameEdit->currentText()) {
+ m_ModInfo->setGameName(game->gameShortName());
+ return;
+ }
+ }
+}
+
void ModInfoDialog::on_versionEdit_editingFinished()
{
VersionInfo version(ui->versionEdit->text());
@@ -933,6 +969,11 @@ bool ModInfoDialog::recursiveDelete(const QModelIndex &index)
}
+void ModInfoDialog::on_openInExplorerButton_clicked()
+{
+ ::ShellExecuteW(nullptr, L"explore", ToWString(m_ModInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+}
+
void ModInfoDialog::deleteFile(const QModelIndex &index)
{
@@ -944,6 +985,36 @@ void ModInfoDialog::deleteFile(const QModelIndex &index)
}
}
+void ModInfoDialog::delete_activated()
+{
+ if (ui->fileTree->hasFocus()) {
+ QItemSelectionModel *selection = ui->fileTree->selectionModel();
+
+ if (selection->hasSelection() && selection->selectedRows().count() >= 1) {
+
+ if (selection->selectedRows().count() == 0) {
+ return;
+ }
+ else if (selection->selectedRows().count() == 1) {
+ QString fileName = m_FileSystemModel->fileName(selection->selectedRows().at(0));
+ if (QMessageBox::question(this, tr("Confirm"), tr("Are sure you want to delete \"%1\"?").arg(fileName),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return;
+ }
+ }
+ else {
+ if (QMessageBox::question(this, tr("Confirm"), tr("Are sure you want to delete the selected files?"),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return;
+ }
+ }
+
+ foreach(QModelIndex index, selection->selectedRows()) {
+ deleteFile(index);
+ }
+ }
+ }
+}
void ModInfoDialog::deleteTriggered()
{
@@ -1419,14 +1490,20 @@ void ModInfoDialog::on_endorseBtn_clicked()
void ModInfoDialog::on_nextButton_clicked()
{
- emit modOpenNext();
- this->accept();
+ int currentTab = ui->tabWidget->currentIndex();
+ int tab = m_RealTabPos[currentTab];
+
+ emit modOpenNext(tab);
+ this->accept();
}
void ModInfoDialog::on_prevButton_clicked()
{
- emit modOpenPrev();
- this->accept();
+ int currentTab = ui->tabWidget->currentIndex();
+ int tab = m_RealTabPos[currentTab];
+
+ emit modOpenPrev(tab);
+ this->accept();
}
diff --git a/src/modinfodialog.h b/src/modinfodialog.h
index 9eb17be5..f3bc48b4 100644
--- a/src/modinfodialog.h
+++ b/src/modinfodialog.h
@@ -109,11 +109,11 @@ public:
signals:
void thumbnailClickedSignal(const QString &filename);
- void nexusLinkActivated(const QString &link);
+ void linkActivated(const QString &link);
void downloadRequest(const QString &link);
void modOpen(const QString &modName, int tab);
- void modOpenNext();
- void modOpenPrev();
+ void modOpenNext(int tab=-1);
+ void modOpenPrev(int tab=-1);
void originModified(int originID);
void endorseMod(ModInfo::Ptr nexusID);
@@ -164,6 +164,9 @@ private slots:
void thumbnailClicked(const QString &fileName);
void linkClicked(const QUrl &url);
+ void linkClicked(QString url);
+
+ void delete_activated();
void deleteTriggered();
void renameTriggered();
@@ -172,6 +175,7 @@ private slots:
void hideTriggered();
void unhideTriggered();
+ void on_openInExplorerButton_clicked();
void on_closeButton_clicked();
void on_saveButton_clicked();
void on_activateESP_clicked();
@@ -179,6 +183,7 @@ private slots:
void on_saveTXTButton_clicked();
void on_visitNexusLabel_linkActivated(const QString &link);
void on_modIDEdit_editingFinished();
+ void on_sourceGameEdit_currentIndexChanged(int);
void on_versionEdit_editingFinished();
void on_iniFileView_textChanged();
void on_textFileView_textChanged();
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui
index 05415445..de9fe5ed 100644
--- a/src/modinfodialog.ui
+++ b/src/modinfodialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>720</width>
- <height>648</height>
+ <width>790</width>
+ <height>534</height>
</rect>
</property>
<property name="windowTitle">
@@ -20,7 +20,7 @@
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
- <number>0</number>
+ <number>8</number>
</property>
<property name="movable">
<bool>true</bool>
@@ -110,19 +110,19 @@
</item>
<item>
<widget class="QLabel" name="label_5">
- <property name="enabled">
+ <property name="enabled">
<bool>false</bool>
- </property>
+ </property>
<property name="text">
- <string>Ini Tweaks *This feature is non-functional*</string>
+ <string>Ini Tweaks *This feature is non-functional*</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="iniTweaksList">
- <property name="enabled">
+ <property name="enabled">
<bool>false</bool>
- </property>
+ </property>
<property name="maximumSize">
<size>
<width>228</width>
@@ -490,7 +490,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<item>
<widget class="QTreeWidget" name="overwrittenTree">
<property name="contextMenuPolicy">
- <enum>Qt::CustomContextMenu</enum>
+ <enum>Qt::CustomContextMenu</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
@@ -502,7 +502,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<bool>true</bool>
</property>
<property name="columnCount">
- <number>2</number>
+ <number>2</number>
</property>
<attribute name="headerDefaultSectionSize">
<number>365</number>
@@ -600,7 +600,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
</widget>
</item>
<item>
- <widget class="QLineEdit" name="modIDEdit">
+ <widget class="ModIDLineEdit" name="modIDEdit">
<property name="toolTip">
<string>Mod ID for this mod on Nexus.</string>
</property>
@@ -608,8 +608,41 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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: &lt;/span&gt;&lt;a href=&quot; http://www.skyrimnexus.com/downloads/file.php?id=1334&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;http://skyrim.nexusmods.com/downloads/file.php?id=1334&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;http://www.skyrimnexus.com/downloads/file.php?id=1334&quot;&gt;&lt;span style=&quot; font-size:8pt; color:#000000;&quot;&gt;. 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?&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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: &lt;a href=&quot; https://www.nexusmods.com/skyrimspecialedition/mods/6194&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.nexusmods.com/skyrimspecialedition/mods/6194&lt;/span&gt;&lt;/a&gt;. In this example, 6194 is the id you're looking for. Besides: The above is the link to Mod Organizer2 on Nexus. Why not go there now and endorse us?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Source Game</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="sourceGameEdit">
+ <property name="toolTip">
+ <string>Source game for this mod.</string>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Source game for this mod. This determines where the mod was downloaded from and decides where to fetch info, version updates, and send endorsements. Changing this will likely require you to enter a new Mod ID.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -747,6 +780,36 @@ p, li { white-space: pre-wrap; }
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
+ <layout class="QHBoxLayout" name="horizontalLayout_13">
+ <item>
+ <widget class="QPushButton" name="openInExplorerButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Open Mod in Explorer</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
<widget class="QTreeView" name="fileTree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
@@ -819,9 +882,14 @@ p, li { white-space: pre-wrap; }
</widget>
<customwidgets>
<customwidget>
- <class>QQuickWidget</class>
+ <class>QWebEngineView</class>
<extends>QWidget</extends>
- <header>QtQuickWidgets/QQuickWidget</header>
+ <header location="global">QtWebEngineWidgets/QWebEngineView</header>
+ </customwidget>
+ <customwidget>
+ <class>ModIDLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>modidlineedit.h</header>
</customwidget>
</customwidgets>
<resources>
diff --git a/src/modinfoforeign.cpp b/src/modinfoforeign.cpp
index 6ac66c67..b599d4eb 100644
--- a/src/modinfoforeign.cpp
+++ b/src/modinfoforeign.cpp
@@ -51,8 +51,9 @@ ModInfoForeign::ModInfoForeign(const QString &modName,
const QString &referenceFile,
const QStringList &archives,
ModInfo::EModType modType,
- DirectoryEntry **directoryStructure)
- : ModInfoWithConflictInfo(directoryStructure),
+ DirectoryEntry **directoryStructure,
+ PluginContainer *pluginContainer)
+ : ModInfoWithConflictInfo(pluginContainer, directoryStructure),
m_ReferenceFile(referenceFile), m_Archives(archives) {
m_CreationTime = QFileInfo(referenceFile).created();
switch (modType) {
diff --git a/src/modinfoforeign.h b/src/modinfoforeign.h
index d60064f0..0d7b3847 100644
--- a/src/modinfoforeign.h
+++ b/src/modinfoforeign.h
@@ -19,6 +19,7 @@ public:
virtual void setCategory(int, bool) {}
virtual bool setName(const QString&) { return false; }
virtual void setNotes(const QString&) {}
+ virtual void setGameName(QString) {}
virtual void setNexusID(int) {}
virtual void setNewestVersion(const MOBase::VersionInfo&) {}
virtual void ignoreUpdate(bool) {}
@@ -37,6 +38,7 @@ public:
virtual QString absolutePath() const;
virtual MOBase::VersionInfo getNewestVersion() const { return QString(); }
virtual QString getInstallationFile() const { return ""; }
+ virtual QString getGameName() const { return ""; }
virtual int getNexusID() const { return -1; }
virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
virtual std::vector<ModInfo::EFlag> getFlags() const;
@@ -53,7 +55,7 @@ public:
protected:
ModInfoForeign(const QString &modName, const QString &referenceFile,
const QStringList &archives, ModInfo::EModType modType,
- MOShared::DirectoryEntry **directoryStructure);
+ MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer);
private:
QString m_Name;
diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp
index 360212c0..742ae384 100644
--- a/src/modinfooverwrite.cpp
+++ b/src/modinfooverwrite.cpp
@@ -6,7 +6,7 @@
#include <QApplication>
#include <QDirIterator>
-ModInfoOverwrite::ModInfoOverwrite()
+ModInfoOverwrite::ModInfoOverwrite(PluginContainer *pluginContainer) : ModInfo(pluginContainer)
{
testValid();
}
diff --git a/src/modinfooverwrite.h b/src/modinfooverwrite.h
index b6cdfb43..5681dc6f 100644
--- a/src/modinfooverwrite.h
+++ b/src/modinfooverwrite.h
@@ -21,6 +21,7 @@ public:
virtual void setCategory(int, bool) {}
virtual bool setName(const QString&) { return false; }
virtual void setNotes(const QString&) {}
+ virtual void setGameName(QString) {}
virtual void setNexusID(int) {}
virtual void setNewestVersion(const MOBase::VersionInfo&) {}
virtual void ignoreUpdate(bool) {}
@@ -40,6 +41,7 @@ public:
virtual MOBase::VersionInfo getNewestVersion() const { return QString(); }
virtual QString getInstallationFile() const { return ""; }
virtual int getFixedPriority() const { return INT_MAX; }
+ virtual QString getGameName() const { return ""; }
virtual int getNexusID() const { return -1; }
virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
virtual std::vector<ModInfo::EFlag> getFlags() const;
@@ -52,7 +54,7 @@ public:
private:
- ModInfoOverwrite();
+ ModInfoOverwrite(PluginContainer *pluginContainer);
};
diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp
index 4572f5bf..c19294f1 100644
--- a/src/modinforegular.cpp
+++ b/src/modinforegular.cpp
@@ -1,7 +1,6 @@
#include "modinforegular.h"
#include "categories.h"
-#include "iplugingame.h"
#include "messagedialog.h"
#include "report.h"
#include "scriptextender.h"
@@ -24,26 +23,32 @@ namespace {
}
}
-ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStructure)
- : ModInfoWithConflictInfo(directoryStructure)
+ModInfoRegular::ModInfoRegular(PluginContainer *pluginContainer, const IPluginGame *game, const QDir &path, DirectoryEntry **directoryStructure)
+ : ModInfoWithConflictInfo(pluginContainer, directoryStructure)
, m_Name(path.dirName())
, m_Path(path.absolutePath())
, m_Repository()
+ , m_GameName(game->gameShortName())
+ , m_IsAlternate(false)
+ , m_Converted(false)
, m_MetaInfoChanged(false)
, m_EndorsedState(ENDORSED_UNKNOWN)
- , m_NexusBridge()
+ , m_NexusBridge(pluginContainer)
{
testValid();
m_CreationTime = QFileInfo(path.absolutePath()).created();
// read out the meta-file for information
readMeta();
+ if (m_GameName.compare(game->gameShortName(), Qt::CaseInsensitive) != 0)
+ if (!game->primarySources().contains(m_GameName, Qt::CaseInsensitive))
+ m_IsAlternate = true;
- connect(&m_NexusBridge, SIGNAL(descriptionAvailable(int,QVariant,QVariant))
- , this, SLOT(nxmDescriptionAvailable(int,QVariant,QVariant)));
- connect(&m_NexusBridge, SIGNAL(endorsementToggled(int,QVariant,QVariant))
- , this, SLOT(nxmEndorsementToggled(int,QVariant,QVariant)));
- connect(&m_NexusBridge, SIGNAL(requestFailed(int,int,QVariant,QString))
- , this, SLOT(nxmRequestFailed(int,int,QVariant,QString)));
+ connect(&m_NexusBridge, SIGNAL(descriptionAvailable(QString,int,QVariant,QVariant))
+ , this, SLOT(nxmDescriptionAvailable(QString,int,QVariant,QVariant)));
+ connect(&m_NexusBridge, SIGNAL(endorsementToggled(QString,int,QVariant,QVariant))
+ , this, SLOT(nxmEndorsementToggled(QString,int,QVariant,QVariant)));
+ connect(&m_NexusBridge, SIGNAL(requestFailed(QString,int,int,QVariant,QString))
+ , this, SLOT(nxmRequestFailed(QString,int,int,QVariant,QString)));
}
@@ -71,15 +76,18 @@ void ModInfoRegular::readMeta()
{
QSettings metaFile(m_Path + "/meta.ini", QSettings::IniFormat);
m_Notes = metaFile.value("notes", "").toString();
+ QString tempGameName = metaFile.value("gameName", m_GameName).toString();
+ if (tempGameName.size()) m_GameName = tempGameName;
m_NexusID = metaFile.value("modid", -1).toInt();
m_Version.parse(metaFile.value("version", "").toString());
m_NewestVersion = metaFile.value("newestVersion", "").toString();
m_IgnoredVersion = metaFile.value("ignoredVersion", "").toString();
m_InstallationFile = metaFile.value("installationFile", "").toString();
m_NexusDescription = metaFile.value("nexusDescription", "").toString();
- m_Repository = metaFile.value("repository", "Nexus").toString();
- m_URL = metaFile.value("url", "").toString();
- m_LastNexusQuery = QDateTime::fromString(metaFile.value("lastNexusQuery", "").toString(), Qt::ISODate);
+ m_Repository = metaFile.value("repository", "Nexus").toString();
+ m_Converted = metaFile.value("converted", false).toBool();
+ m_URL = metaFile.value("url", "").toString();
+ m_LastNexusQuery = QDateTime::fromString(metaFile.value("lastNexusQuery", "").toString(), Qt::ISODate);
if (metaFile.contains("endorsed")) {
if (metaFile.value("endorsed").canConvert<int>()) {
switch (metaFile.value("endorsed").toInt()) {
@@ -135,11 +143,13 @@ void ModInfoRegular::saveMeta()
metaFile.setValue("version", m_Version.canonicalString());
metaFile.setValue("installationFile", m_InstallationFile);
metaFile.setValue("repository", m_Repository);
+ metaFile.setValue("gameName", m_GameName);
metaFile.setValue("modid", m_NexusID);
metaFile.setValue("notes", m_Notes);
metaFile.setValue("nexusDescription", m_NexusDescription);
metaFile.setValue("url", m_URL);
metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate));
+ metaFile.setValue("converted", m_Converted);
if (m_EndorsedState != ENDORSED_UNKNOWN) {
metaFile.setValue("endorsed", m_EndorsedState);
}
@@ -185,7 +195,7 @@ bool ModInfoRegular::downgradeAvailable() const
}
-void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData)
+void ModInfoRegular::nxmDescriptionAvailable(QString, int, QVariant, QVariant resultData)
{
QVariantMap result = resultData.toMap();
setNewestVersion(VersionInfo(result["version"].toString()));
@@ -201,7 +211,7 @@ void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData)
}
-void ModInfoRegular::nxmEndorsementToggled(int, QVariant, QVariant resultData)
+void ModInfoRegular::nxmEndorsementToggled(QString, int, QVariant, QVariant resultData)
{
m_EndorsedState = resultData.toBool() ? ENDORSED_TRUE : ENDORSED_FALSE;
m_MetaInfoChanged = true;
@@ -210,7 +220,7 @@ void ModInfoRegular::nxmEndorsementToggled(int, QVariant, QVariant resultData)
}
-void ModInfoRegular::nxmRequestFailed(int, int, QVariant userData, const QString &errorMessage)
+void ModInfoRegular::nxmRequestFailed(QString, int, int, QVariant userData, const QString &errorMessage)
{
QString fullMessage = errorMessage;
if (userData.canConvert<int>() && (userData.toInt() == 1)) {
@@ -226,7 +236,7 @@ void ModInfoRegular::nxmRequestFailed(int, int, QVariant userData, const QString
bool ModInfoRegular::updateNXMInfo()
{
if (m_NexusID > 0) {
- m_NexusBridge.requestDescription(m_NexusID, QVariant());
+ m_NexusBridge.requestDescription(m_GameName, m_NexusID, QVariant());
return true;
}
return false;
@@ -315,6 +325,12 @@ void ModInfoRegular::setNotes(const QString &notes)
m_MetaInfoChanged = true;
}
+void ModInfoRegular::setGameName(QString gameName)
+{
+ m_GameName = gameName;
+ m_MetaInfoChanged = true;
+}
+
void ModInfoRegular::setNexusID(int modID)
{
m_NexusID = modID;
@@ -387,10 +403,18 @@ bool ModInfoRegular::remove()
void ModInfoRegular::endorse(bool doEndorse)
{
if (doEndorse != (m_EndorsedState == ENDORSED_TRUE)) {
- m_NexusBridge.requestToggleEndorsement(getNexusID(), doEndorse, QVariant(1));
+ m_NexusBridge.requestToggleEndorsement(m_GameName, getNexusID(), doEndorse, QVariant(1));
}
}
+void ModInfoRegular::markConverted(bool converted)
+{
+ m_Converted = converted;
+ m_MetaInfoChanged = true;
+ saveMeta();
+ emit modDetailsUpdated(true);
+}
+
QString ModInfoRegular::absolutePath() const
{
@@ -423,6 +447,9 @@ std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const
if (m_PluginSelected) {
result.push_back(ModInfo::FLAG_PLUGIN_SELECTED);
}
+ if (m_IsAlternate && !m_Converted) {
+ result.push_back(ModInfo::FLAG_ALTERNATE_GAME);
+ }
return result;
}
@@ -449,7 +476,7 @@ std::vector<ModInfo::EContent> ModInfoRegular::getContents() const
if (dir.exists(sePluginPath))
m_CachedContent.push_back(CONTENT_SKSE);
}
- if (dir.exists("textures"))
+ if (dir.exists("textures") || dir.exists("icons") || dir.exists("bookart"))
m_CachedContent.push_back(CONTENT_TEXTURE);
if (dir.exists("meshes"))
m_CachedContent.push_back(CONTENT_MESH);
diff --git a/src/modinforegular.h b/src/modinforegular.h
index a94d0363..3abaded4 100644
--- a/src/modinforegular.h
+++ b/src/modinforegular.h
@@ -2,7 +2,6 @@
#define MODINFOREGULAR_H
#include "modinfowithconflictinfo.h"
-
#include "nexusinterface.h"
/**
@@ -27,6 +26,9 @@ public:
virtual bool isEmpty() const;
+ bool isAlternate() { return m_IsAlternate; }
+ bool isConverted() { return m_Converted; }
+
/**
* @brief test if there is a newer version of the mod
*
@@ -94,6 +96,13 @@ public:
void setNotes(const QString &notes);
/**
+ * @brief set/change the source game of this mod
+ *
+ * @param gameName the source game shortName
+ */
+ void setGameName(QString gameName);
+
+ /**
* @brief set/change the nexus mod id of this mod
*
* @param modID the nexus mod id
@@ -175,6 +184,11 @@ public:
virtual void endorse(bool doEndorse);
/**
+ * @brief updates the mod to flag it as converted in order to ignore the alternate game warning
+ */
+ virtual void markConverted(bool converted) override;
+
+ /**
* @brief getter for the mod name
*
* @return the mod name
@@ -206,6 +220,14 @@ public:
* @return file used to install this mod from
*/
virtual QString getInstallationFile() const { return m_InstallationFile; }
+
+ /**
+ * @brief getter for the source game repository
+ *
+ * @return the source game repository. should default to the active game.
+ **/
+ QString getGameName() const { return m_GameName; }
+
/**
* @brief getter for the nexus mod id
*
@@ -308,13 +330,13 @@ private:
private slots:
- void nxmDescriptionAvailable(int modID, QVariant userData, QVariant resultData);
- void nxmEndorsementToggled(int, QVariant userData, QVariant resultData);
- void nxmRequestFailed(int modID, int fileID, QVariant userData, const QString &errorMessage);
+ void nxmDescriptionAvailable(QString, int modID, QVariant userData, QVariant resultData);
+ void nxmEndorsementToggled(QString, int, QVariant userData, QVariant resultData);
+ void nxmRequestFailed(QString, int modID, int fileID, QVariant userData, const QString &errorMessage);
protected:
- ModInfoRegular(const QDir &path, MOShared::DirectoryEntry **directoryStructure);
+ ModInfoRegular(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &path, MOShared::DirectoryEntry **directoryStructure);
private:
@@ -325,6 +347,7 @@ private:
QString m_NexusDescription;
QString m_Repository;
QString m_URL;
+ QString m_GameName;
QDateTime m_CreationTime;
QDateTime m_LastNexusQuery;
@@ -333,6 +356,8 @@ private:
std::set<std::pair<int, int>> m_InstalledFileIDs;
bool m_MetaInfoChanged;
+ bool m_IsAlternate;
+ bool m_Converted;
MOBase::VersionInfo m_NewestVersion;
MOBase::VersionInfo m_IgnoredVersion;
diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp
index b8ece783..e88ba29d 100644
--- a/src/modinfowithconflictinfo.cpp
+++ b/src/modinfowithconflictinfo.cpp
@@ -6,8 +6,8 @@
using namespace MOBase;
using namespace MOShared;
-ModInfoWithConflictInfo::ModInfoWithConflictInfo(DirectoryEntry **directoryStructure)
- : m_DirectoryStructure(directoryStructure) {}
+ModInfoWithConflictInfo::ModInfoWithConflictInfo(PluginContainer *pluginContainer, DirectoryEntry **directoryStructure)
+ : ModInfo(pluginContainer), m_DirectoryStructure(directoryStructure) {}
void ModInfoWithConflictInfo::clearCaches()
{
diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h
index be31f20f..6c1591c5 100644
--- a/src/modinfowithconflictinfo.h
+++ b/src/modinfowithconflictinfo.h
@@ -10,7 +10,7 @@ class ModInfoWithConflictInfo : public ModInfo
public:
- ModInfoWithConflictInfo(MOShared::DirectoryEntry **directoryStructure);
+ ModInfoWithConflictInfo(PluginContainer *pluginContainer, MOShared::DirectoryEntry **directoryStructure);
std::vector<ModInfo::EFlag> getFlags() const;
diff --git a/src/modlist.cpp b/src/modlist.cpp
index 7b2ad1f9..2d58081d 100644
--- a/src/modlist.cpp
+++ b/src/modlist.cpp
@@ -25,6 +25,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "viewmarkingscrollbar.h"
#include "modlistsortproxy.h"
#include "settings.h"
+#include "modinforegular.h"
#include <appconfig.h>
#include <utility.h>
#include <report.h>
@@ -53,13 +54,14 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
-ModList::ModList(QObject *parent)
+ModList::ModList(PluginContainer *pluginContainer, QObject *parent)
: QAbstractItemModel(parent)
, m_Profile(nullptr)
, m_NexusInterface(nullptr)
, m_Modified(false)
, m_FontMetrics(QFont())
, m_DropOnItems(false)
+ , m_PluginContainer(pluginContainer)
{
m_ContentIcons[ModInfo::CONTENT_PLUGIN] = std::make_tuple(":/MO/gui/content/plugin", tr("Game Plugins (ESP/ESM/ESL)"));
m_ContentIcons[ModInfo::CONTENT_INTERFACE] = std::make_tuple(":/MO/gui/content/interface", tr("Interface"));
@@ -148,6 +150,7 @@ QString ModList::getFlagText(ModInfo::EFlag flag, ModInfo::Ptr modInfo) const
case ModInfo::FLAG_CONFLICT_OVERWRITTEN: return tr("Overwritten files");
case ModInfo::FLAG_CONFLICT_MIXED: return tr("Overwrites & Overwritten");
case ModInfo::FLAG_CONFLICT_REDUNDANT: return tr("Redundant");
+ case ModInfo::FLAG_ALTERNATE_GAME: return tr("Alternate game source");
default: return "";
}
}
@@ -219,9 +222,18 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
int modID = modInfo->getNexusID();
if (modID >= 0) {
return modID;
- } else {
+ }
+ else {
return QVariant();
}
+ } else if (column == COL_GAME) {
+ if (m_PluginContainer != nullptr) {
+ for (auto game : m_PluginContainer->plugins<IPluginGame>()) {
+ if (game->gameShortName() == modInfo->getGameName())
+ return game->gameName();
+ }
+ }
+ return modInfo->getGameName();
} else if (column == COL_CATEGORY) {
if (modInfo->hasFlag(ModInfo::FLAG_FOREIGN)) {
return tr("Non-MO");
@@ -309,6 +321,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
}
} else if (role == Qt::UserRole + 3) {
return contentsToIcons(modInfo->getContents());
+ } else if (role == Qt::UserRole + 4) {
+ return modInfo->getGameName();
} else if (role == Qt::FontRole) {
QFont result;
if (column == COL_NAME) {
@@ -424,14 +438,14 @@ bool ModList::renameMod(int index, const QString &newName)
return false;
}
- if (ModList::allMods().contains(newName,Qt::CaseInsensitive)) {
+ if (ModList::allMods().contains(nameFixed, Qt::CaseInsensitive) && nameFixed.toLower()!=ModInfo::getByIndex(index)->name().toLower() ) {
MessageDialog::showMessage(tr("Name is already in use by another mod"), nullptr);
return false;
}
ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
QString oldName = modInfo->name();
- if (newName != oldName) {
+ if (nameFixed != oldName) {
// before we rename, ensure there is no scheduled asynchronous to rewrite
m_Profile->cancelModlistWrite();
@@ -659,6 +673,11 @@ void ModList::setOverwriteMarkers(const std::set<unsigned int> &overwrite, const
notifyChange(0, rowCount() - 1);
}
+void ModList::setPluginContainer(PluginContainer *pluginContianer)
+{
+ m_PluginContainer = pluginContianer;
+}
+
bool ModList::modInfoAboutToChange(ModInfo::Ptr info)
{
if (m_ChangeInfo.name.isEmpty()) {
@@ -707,7 +726,6 @@ void ModList::highlightMods(const QItemSelection &selected, const MOShared::Dire
const MOShared::FileEntry::Ptr fileEntry = directoryEntry.findFile(modName.toStdWString());
if (fileEntry.get() != nullptr) {
- QString fileName;
bool archive = false;
std::vector<std::pair<int, std::wstring>> origins;
{
@@ -743,6 +761,11 @@ IModList::ModStates ModList::state(unsigned int modIndex) const
if (modInfo->isValid()) {
result |= IModList::STATE_VALID;
}
+ if (modInfo->isRegular()) {
+ QSharedPointer<ModInfoRegular> modInfoRegular = modInfo.staticCast<ModInfoRegular>();
+ if (modInfoRegular->isAlternate() && !modInfoRegular->isConverted())
+ result |= IModList::STATE_ALTERNATE;
+ }
if (modInfo->canBeEnabled()) {
if (m_Profile->modEnabled(modIndex)) {
result |= IModList::STATE_ACTIVE;
@@ -1051,6 +1074,7 @@ QString ModList::getColumnName(int column)
case COL_VERSION: return tr("Version");
case COL_PRIORITY: return tr("Priority");
case COL_CATEGORY: return tr("Category");
+ case COL_GAME: return tr("Source Game");
case COL_MODID: return tr("Nexus ID");
case COL_INSTALLTIME: return tr("Installation");
default: return tr("unknown");
@@ -1066,6 +1090,7 @@ QString ModList::getColumnToolTip(int column)
case COL_PRIORITY: return tr("Installation priority of your mod. The higher, the more \"important\" it is and thus "
"overwrites files from mods with lower priority.");
case COL_CATEGORY: return tr("Category of the mod.");
+ case COL_GAME: return tr("The source game which was the origin of this mod.");
case COL_MODID: return tr("Id of the mod as used on Nexus.");
case COL_FLAGS: return tr("Emblemes to highlight things that might require attention.");
case COL_CONTENT: return tr("Depicts the content of the mod:<br>"
@@ -1193,4 +1218,3 @@ bool ModList::eventFilter(QObject *obj, QEvent *event)
}
return QAbstractItemModel::eventFilter(obj, event);
}
-
diff --git a/src/modlist.h b/src/modlist.h
index bd715107..b5f18e98 100644
--- a/src/modlist.h
+++ b/src/modlist.h
@@ -42,6 +42,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
class QSortFilterProxyModel;
+class PluginContainer;
/**
* Model presenting an overview of the installed mod
@@ -60,6 +61,7 @@ public:
COL_CONTENT,
COL_CATEGORY,
COL_MODID,
+ COL_GAME,
COL_VERSION,
COL_INSTALLTIME,
COL_PRIORITY,
@@ -76,7 +78,7 @@ public:
* @brief constructor
* @todo ensure this view works without a profile set, otherwise there are intransparent dependencies on the initialisation order
**/
- ModList(QObject *parent = nullptr);
+ ModList(PluginContainer *pluginContainer, QObject *parent = nullptr);
~ModList();
@@ -106,6 +108,7 @@ public:
void changeModPriority(int sourceIndex, int newPriority);
void setOverwriteMarkers(const std::set<unsigned int> &overwrite, const std::set<unsigned int> &overwritten);
+ void setPluginContainer(PluginContainer *pluginContainer);
bool modInfoAboutToChange(ModInfo::Ptr info);
void modInfoChanged(ModInfo::Ptr info);
@@ -329,6 +332,8 @@ private:
QTime m_LastCheck;
+ PluginContainer *m_PluginContainer;
+
};
#endif // MODLIST_H
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index 97186e8b..d2a52c7b 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -36,48 +36,48 @@ using namespace MOBase;
using namespace MOShared;
-NexusBridge::NexusBridge(const QString &subModule)
- : m_Interface(NexusInterface::instance())
+NexusBridge::NexusBridge(PluginContainer *pluginContainer, const QString &subModule)
+ : m_Interface(NexusInterface::instance(pluginContainer))
, m_SubModule(subModule)
{
}
-void NexusBridge::requestDescription(int modID, QVariant userData)
+void NexusBridge::requestDescription(QString gameName, int modID, QVariant userData)
{
- m_RequestIDs.insert(m_Interface->requestDescription(modID, this, userData, m_SubModule));
+ m_RequestIDs.insert(m_Interface->requestDescription(gameName, modID, this, userData, m_SubModule));
}
-void NexusBridge::requestFiles(int modID, QVariant userData)
+void NexusBridge::requestFiles(QString gameName, int modID, QVariant userData)
{
- m_RequestIDs.insert(m_Interface->requestFiles(modID, this, userData, m_SubModule));
+ m_RequestIDs.insert(m_Interface->requestFiles(gameName, modID, this, userData, m_SubModule));
}
-void NexusBridge::requestFileInfo(int modID, int fileID, QVariant userData)
+void NexusBridge::requestFileInfo(QString gameName, int modID, int fileID, QVariant userData)
{
- m_RequestIDs.insert(m_Interface->requestFileInfo(modID, fileID, this, userData, m_SubModule));
+ m_RequestIDs.insert(m_Interface->requestFileInfo(gameName, modID, fileID, this, userData, m_SubModule));
}
-void NexusBridge::requestDownloadURL(int modID, int fileID, QVariant userData)
+void NexusBridge::requestDownloadURL(QString gameName, int modID, int fileID, QVariant userData)
{
- m_RequestIDs.insert(m_Interface->requestDownloadURL(modID, fileID, this, userData, m_SubModule));
+ m_RequestIDs.insert(m_Interface->requestDownloadURL(gameName, modID, fileID, this, userData, m_SubModule));
}
-void NexusBridge::requestToggleEndorsement(int modID, bool endorse, QVariant userData)
+void NexusBridge::requestToggleEndorsement(QString gameName, int modID, bool endorse, QVariant userData)
{
- m_RequestIDs.insert(m_Interface->requestToggleEndorsement(modID, endorse, this, userData, m_SubModule));
+ m_RequestIDs.insert(m_Interface->requestToggleEndorsement(gameName, modID, endorse, this, userData, m_SubModule));
}
-void NexusBridge::nxmDescriptionAvailable(int modID, QVariant userData, QVariant resultData, int requestID)
+void NexusBridge::nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
m_RequestIDs.erase(iter);
- emit descriptionAvailable(modID, userData, resultData);
+ emit descriptionAvailable(gameName, modID, userData, resultData);
}
}
-void NexusBridge::nxmFilesAvailable(int modID, QVariant userData, QVariant resultData, int requestID)
+void NexusBridge::nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
@@ -100,43 +100,43 @@ void NexusBridge::nxmFilesAvailable(int modID, QVariant userData, QVariant resul
fileInfoList.append(temp);
}
- emit filesAvailable(modID, userData, fileInfoList);
+ emit filesAvailable(gameName, modID, userData, fileInfoList);
}
}
-void NexusBridge::nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
+void NexusBridge::nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
m_RequestIDs.erase(iter);
- emit fileInfoAvailable(modID, fileID, userData, resultData);
+ emit fileInfoAvailable(gameName, modID, fileID, userData, resultData);
}
}
-void NexusBridge::nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
+void NexusBridge::nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
m_RequestIDs.erase(iter);
- emit downloadURLsAvailable(modID, fileID, userData, resultData);
+ emit downloadURLsAvailable(gameName, modID, fileID, userData, resultData);
}
}
-void NexusBridge::nxmEndorsementToggled(int modID, QVariant userData, QVariant resultData, int requestID)
+void NexusBridge::nxmEndorsementToggled(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
m_RequestIDs.erase(iter);
- emit endorsementToggled(modID, userData, resultData);
+ emit endorsementToggled(gameName, modID, userData, resultData);
}
}
-void NexusBridge::nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorMessage)
+void NexusBridge::nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorMessage)
{
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
m_RequestIDs.erase(iter);
- emit requestFailed(modID, fileID, userData, errorMessage);
+ emit requestFailed(gameName, modID, fileID, userData, errorMessage);
}
}
@@ -144,8 +144,8 @@ void NexusBridge::nxmRequestFailed(int modID, int fileID, QVariant userData, int
QAtomicInt NexusInterface::NXMRequestInfo::s_NextID(0);
-NexusInterface::NexusInterface()
- : m_NMMVersion()
+NexusInterface::NexusInterface(PluginContainer *pluginContainer)
+ : m_NMMVersion(), m_PluginContainer(pluginContainer)
{
VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath()));
m_MOVersion = VersionInfo(version.dwFileVersionMS >> 16,
@@ -167,9 +167,9 @@ NexusInterface::~NexusInterface()
cleanup();
}
-NexusInterface *NexusInterface::instance()
+NexusInterface *NexusInterface::instance(PluginContainer *pluginContainer)
{
- static NexusInterface s_Instance;
+ static NexusInterface s_Instance(pluginContainer);
return &s_Instance;
}
@@ -246,24 +246,41 @@ void NexusInterface::interpretNexusFileName(const QString &fileName, QString &mo
bool NexusInterface::isURLGameRelated(const QUrl &url) const
{
QString const name(url.toString());
- return name.startsWith(getGameURL() + "/") ||
- name.startsWith(getOldModsURL() + "/");
+ return name.startsWith(getGameURL("") + "/") ||
+ name.startsWith(getOldModsURL("") + "/");
}
-QString NexusInterface::getGameURL() const
+QString NexusInterface::getGameURL(QString gameName) const
{
- return "http://www.nexusmods.com/" + m_Game->gameNexusName().toLower();
+ IPluginGame *game = getGame(gameName);
+ return "https://www.nexusmods.com/" + game->gameNexusName().toLower();
}
-QString NexusInterface::getOldModsURL() const
+QString NexusInterface::getOldModsURL(QString gameName) const
{
- return "http://" + m_Game->gameNexusName().toLower() + ".nexusmods.com/mods";
+ IPluginGame *game = getGame(gameName);
+ return "https://" + game->gameNexusName().toLower() + ".nexusmods.com/mods";
}
-QString NexusInterface::getModURL(int modID) const
+QString NexusInterface::getModURL(int modID, QString gameName = "") const
{
- return QString("%1/mods/%2").arg(getGameURL()).arg(modID);
+ return QString("%1/mods/%2").arg(getGameURL(gameName)).arg(modID);
+}
+
+std::vector<std::pair<QString, QString>> NexusInterface::getGameChoices(const MOBase::IPluginGame *game)
+{
+ std::vector<std::pair<QString, QString>> choices;
+ choices.push_back(std::pair<QString, QString>(game->gameShortName(), game->gameName()));
+ for (QString gameName : game->validShortNames()) {
+ for (auto gamePlugin : m_PluginContainer->plugins<IPluginGame>()) {
+ if (gamePlugin->gameShortName().compare(gameName, Qt::CaseInsensitive) == 0) {
+ choices.push_back(std::pair<QString, QString>(gamePlugin->gameShortName(), gamePlugin->gameName()));
+ break;
+ }
+ }
+ }
+ return choices;
}
bool NexusInterface::isModURL(int modID, const QString &url) const
@@ -272,21 +289,26 @@ bool NexusInterface::isModURL(int modID, const QString &url) const
return true;
}
//Try the alternate (old style) mod name
- QString alt = QString("%1/%2").arg(getOldModsURL()).arg(modID);
+ QString alt = QString("%1/%2").arg(getOldModsURL("")).arg(modID);
return QUrl(alt) == QUrl(url);
}
-int NexusInterface::requestDescription(int modID, QObject *receiver, QVariant userData,
+void NexusInterface::setPluginContainer(PluginContainer *pluginContainer)
+{
+ m_PluginContainer = pluginContainer;
+}
+
+int NexusInterface::requestDescription(QString gameName, int modID, QObject *receiver, QVariant userData,
const QString &subModule, MOBase::IPluginGame const *game)
{
NXMRequestInfo requestInfo(modID, NXMRequestInfo::TYPE_DESCRIPTION, userData, subModule, game);
m_RequestQueue.enqueue(requestInfo);
- connect(this, SIGNAL(nxmDescriptionAvailable(int,QVariant,QVariant,int)),
- receiver, SLOT(nxmDescriptionAvailable(int,QVariant,QVariant,int)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmDescriptionAvailable(QString, int, QVariant, QVariant, int)),
+ receiver, SLOT(nxmDescriptionAvailable(QString, int, QVariant, QVariant, int)), Qt::UniqueConnection);
- connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
- receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)),
+ receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection);
nextRequest();
return requestInfo.m_ID;
@@ -294,16 +316,17 @@ int NexusInterface::requestDescription(int modID, QObject *receiver, QVariant us
int NexusInterface::requestUpdates(const std::vector<int> &modIDs, QObject *receiver, QVariant userData,
- const QString &subModule, MOBase::IPluginGame const *game)
+ QString gameName, const QString &subModule)
{
+ IPluginGame *game = getGame(gameName);
NXMRequestInfo requestInfo(modIDs, NXMRequestInfo::TYPE_GETUPDATES, userData, subModule, game);
m_RequestQueue.enqueue(requestInfo);
- connect(this, SIGNAL(nxmUpdatesAvailable(std::vector<int>,QVariant,QVariant,int)),
- receiver, SLOT(nxmUpdatesAvailable(std::vector<int>,QVariant,QVariant,int)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmUpdatesAvailable(std::vector<int>, QVariant, QVariant, int)),
+ receiver, SLOT(nxmUpdatesAvailable(std::vector<int>, QVariant, QVariant, int)), Qt::UniqueConnection);
- connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
- receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)),
+ receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection);
nextRequest();
return requestInfo.m_ID;
@@ -325,72 +348,72 @@ void NexusInterface::fakeFiles()
fileMap["size"] = "512";
result.append(fileMap);
- emit nxmFilesAvailable(1234, "fake", result, id++);
+ emit nxmFilesAvailable("fakeGame", 1234, "fake", result, id++);
}
-int NexusInterface::requestFiles(int modID, QObject *receiver, QVariant userData,
+int NexusInterface::requestFiles(QString gameName, int modID, QObject *receiver, QVariant userData,
const QString &subModule, MOBase::IPluginGame const *game)
{
NXMRequestInfo requestInfo(modID, NXMRequestInfo::TYPE_FILES, userData, subModule, game);
m_RequestQueue.enqueue(requestInfo);
- connect(this, SIGNAL(nxmFilesAvailable(int,QVariant,QVariant,int)),
- receiver, SLOT(nxmFilesAvailable(int,QVariant,QVariant,int)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmFilesAvailable(QString, int, QVariant, QVariant, int)),
+ receiver, SLOT(nxmFilesAvailable(QString, int, QVariant, QVariant, int)), Qt::UniqueConnection);
- connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
- receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)),
+ receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection);
nextRequest();
return requestInfo.m_ID;
}
-int NexusInterface::requestFileInfo(int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule,
- MOBase::IPluginGame const *game)
+int NexusInterface::requestFileInfo(QString gameName, int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule)
{
- NXMRequestInfo requestInfo(modID, fileID, NXMRequestInfo::TYPE_FILEINFO, userData, subModule, game);
+ IPluginGame *gamePlugin = getGame(gameName);
+ NXMRequestInfo requestInfo(modID, fileID, NXMRequestInfo::TYPE_FILEINFO, userData, subModule, gamePlugin);
m_RequestQueue.enqueue(requestInfo);
- connect(this, SIGNAL(nxmFileInfoAvailable(int,int,QVariant,QVariant,int)),
- receiver, SLOT(nxmFileInfoAvailable(int,int,QVariant,QVariant,int)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmFileInfoAvailable(QString, int, int, QVariant, QVariant, int)),
+ receiver, SLOT(nxmFileInfoAvailable(QString, int, int, QVariant, QVariant, int)), Qt::UniqueConnection);
- connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
- receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)),
+ receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection);
nextRequest();
return requestInfo.m_ID;
}
-int NexusInterface::requestDownloadURL(int modID, int fileID, QObject *receiver, QVariant userData,
+int NexusInterface::requestDownloadURL(QString gameName, int modID, int fileID, QObject *receiver, QVariant userData,
const QString &subModule, MOBase::IPluginGame const *game)
{
NXMRequestInfo requestInfo(modID, fileID, NXMRequestInfo::TYPE_DOWNLOADURL, userData, subModule, game);
m_RequestQueue.enqueue(requestInfo);
- connect(this, SIGNAL(nxmDownloadURLsAvailable(int,int,QVariant,QVariant,int)),
- receiver, SLOT(nxmDownloadURLsAvailable(int,int,QVariant,QVariant,int)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmDownloadURLsAvailable(QString,int,int,QVariant,QVariant,int)),
+ receiver, SLOT(nxmDownloadURLsAvailable(QString,int,int,QVariant,QVariant,int)), Qt::UniqueConnection);
- connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
- receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmRequestFailed(QString,int,int,QVariant,int,QString)),
+ receiver, SLOT(nxmRequestFailed(QString,int,int,QVariant,int,QString)), Qt::UniqueConnection);
nextRequest();
return requestInfo.m_ID;
}
-int NexusInterface::requestToggleEndorsement(int modID, bool endorse, QObject *receiver, QVariant userData,
+int NexusInterface::requestToggleEndorsement(QString gameName, int modID, bool endorse, QObject *receiver, QVariant userData,
const QString &subModule, MOBase::IPluginGame const *game)
{
NXMRequestInfo requestInfo(modID, NXMRequestInfo::TYPE_TOGGLEENDORSEMENT, userData, subModule, game);
requestInfo.m_Endorse = endorse;
m_RequestQueue.enqueue(requestInfo);
- connect(this, SIGNAL(nxmEndorsementToggled(int,QVariant,QVariant,int)),
- receiver, SLOT(nxmEndorsementToggled(int,QVariant,QVariant,int)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)),
+ receiver, SLOT(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)), Qt::UniqueConnection);
- connect(this, SIGNAL(nxmRequestFailed(int,int,QVariant,int,QString)),
- receiver, SLOT(nxmRequestFailed(int,int,QVariant,int,QString)), Qt::UniqueConnection);
+ connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)),
+ receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection);
nextRequest();
return requestInfo.m_ID;
@@ -402,6 +425,19 @@ bool NexusInterface::requiresLogin(const NXMRequestInfo &info)
|| (info.m_Type == NXMRequestInfo::TYPE_DOWNLOADURL);
}
+IPluginGame* NexusInterface::getGame(QString gameName) const
+{
+ auto gamePlugins = m_PluginContainer->plugins<IPluginGame>();
+ IPluginGame *gamePlugin = qApp->property("managed_game").value<IPluginGame*>();
+ for (auto plugin : gamePlugins) {
+ if (plugin->gameShortName().compare(gameName, Qt::CaseInsensitive) == 0) {
+ gamePlugin = plugin;
+ break;
+ }
+ }
+ return gamePlugin;
+}
+
void NexusInterface::cleanup()
{
// delete m_AccessManager;
@@ -492,7 +528,7 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter)
if (reply->error() != QNetworkReply::NoError) {
qWarning("request failed: %s", reply->errorString().toUtf8().constData());
- emit nxmRequestFailed(iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, reply->errorString());
+ emit nxmRequestFailed(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, reply->errorString());
} else {
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode == 301) {
@@ -510,33 +546,33 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter)
nexusError = tr("empty response");
}
qDebug("nexus error: %s", qPrintable(nexusError));
- emit nxmRequestFailed(iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, nexusError);
+ emit nxmRequestFailed(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, nexusError);
} else {
bool ok;
QVariant result = QtJson::parse(data, ok);
if (result.isValid() && ok) {
switch (iter->m_Type) {
case NXMRequestInfo::TYPE_DESCRIPTION: {
- emit nxmDescriptionAvailable(iter->m_ModID, iter->m_UserData, result, iter->m_ID);
+ emit nxmDescriptionAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID);
} break;
case NXMRequestInfo::TYPE_FILES: {
- emit nxmFilesAvailable(iter->m_ModID, iter->m_UserData, result, iter->m_ID);
+ emit nxmFilesAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID);
} break;
case NXMRequestInfo::TYPE_FILEINFO: {
- emit nxmFileInfoAvailable(iter->m_ModID, iter->m_FileID, iter->m_UserData, result, iter->m_ID);
+ emit nxmFileInfoAvailable(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, result, iter->m_ID);
} break;
case NXMRequestInfo::TYPE_DOWNLOADURL: {
- emit nxmDownloadURLsAvailable(iter->m_ModID, iter->m_FileID, iter->m_UserData, result, iter->m_ID);
+ emit nxmDownloadURLsAvailable(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, result, iter->m_ID);
} break;
case NXMRequestInfo::TYPE_GETUPDATES: {
emit nxmUpdatesAvailable(iter->m_ModIDList, iter->m_UserData, result, iter->m_ID);
} break;
case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: {
- emit nxmEndorsementToggled(iter->m_ModID, iter->m_UserData, result, iter->m_ID);
+ emit nxmEndorsementToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID);
} break;
}
} else {
- emit nxmRequestFailed(iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, tr("invalid response"));
+ emit nxmRequestFailed(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, tr("invalid response"));
}
}
}
@@ -591,15 +627,10 @@ void NexusInterface::requestTimeout()
}
}
-void NexusInterface::managedGameChanged(IPluginGame const *game)
-{
- m_Game = game;
-}
-
namespace {
QString get_management_url(MOBase::IPluginGame const *game)
{
- return "http://nmm.nexusmods.com/" + game->gameNexusName().toLower();
+ return "https://legacy-api.nexusmods.com/" + game->gameNexusName().toLower();
}
}
@@ -620,6 +651,7 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID
, m_URL(get_management_url(game))
, m_SubModule(subModule)
, m_NexusGameID(game->nexusGameID())
+ , m_GameName(game->gameShortName())
, m_Endorse(false)
{}
@@ -641,6 +673,7 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(std::vector<int> modIDList
, m_URL(get_management_url(game))
, m_SubModule(subModule)
, m_NexusGameID(game->nexusGameID())
+ , m_GameName(game->gameShortName())
, m_Endorse(false)
{}
@@ -662,5 +695,6 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID
, m_URL(get_management_url(game))
, m_SubModule(subModule)
, m_NexusGameID(game->nexusGameID())
+ , m_GameName(game->gameShortName())
, m_Endorse(false)
{}
diff --git a/src/nexusinterface.h b/src/nexusinterface.h
index 9e7f3642..defb370f 100644
--- a/src/nexusinterface.h
+++ b/src/nexusinterface.h
@@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <utility.h>
#include <versioninfo.h>
#include <imodrepositorybridge.h>
+#include <plugincontainer.h>
#include <QNetworkReply>
#include <QNetworkDiskCache>
@@ -53,7 +54,7 @@ class NexusBridge : public MOBase::IModRepositoryBridge
public:
- NexusBridge(const QString &subModule = "");
+ NexusBridge(PluginContainer *pluginContainer, const QString &subModule = "");
/**
* @brief request description for a mod
@@ -62,7 +63,7 @@ public:
* @param userData user data to be returned with the result
* @param url the url to request from
**/
- virtual void requestDescription(int modID, QVariant userData);
+ virtual void requestDescription(QString gameName, int modID, QVariant userData);
/**
* @brief request a list of the files belonging to a mod
@@ -70,7 +71,7 @@ public:
* @param modID id of the mod caller is interested in
* @param userData user data to be returned with the result
**/
- virtual void requestFiles(int modID, QVariant userData);
+ virtual void requestFiles(QString gameName, int modID, QVariant userData);
/**
* @brief request info about a single file of a mod
@@ -79,7 +80,7 @@ public:
* @param fileID id of the file the caller is interested in
* @param userData user data to be returned with the result
**/
- virtual void requestFileInfo(int modID, int fileID, QVariant userData);
+ virtual void requestFileInfo(QString gameName, int modID, int fileID, QVariant userData);
/**
* @brief request the download url of a file
@@ -88,23 +89,23 @@ public:
* @param fileID id of the file the caller is interested in
* @param userData user data to be returned with the result
**/
- virtual void requestDownloadURL(int modID, int fileID, QVariant userData);
+ virtual void requestDownloadURL(QString gameName, int modID, int fileID, QVariant userData);
/**
* @brief requestToggleEndorsement
* @param modID id of the mod caller is interested in
* @param userData user data to be returned with the result
*/
- virtual void requestToggleEndorsement(int modID, bool endorse, QVariant userData);
+ virtual void requestToggleEndorsement(QString gameName, int modID, bool endorse, QVariant userData);
public slots:
- void nxmDescriptionAvailable(int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmFilesAvailable(int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
- void nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
- void nxmEndorsementToggled(int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorMessage);
+ void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmEndorsementToggled(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorMessage);
private:
@@ -130,7 +131,7 @@ public:
~NexusInterface();
- static NexusInterface *instance();
+ static NexusInterface *instance(PluginContainer *pluginContainer);
/**
* @return the access manager object used to connect to nexus
@@ -155,9 +156,9 @@ public:
* @param userData user data to be returned with the result
* @return int an id to identify the request
**/
- int requestDescription(int modID, QObject *receiver, QVariant userData, const QString &subModule)
+ int requestDescription(QString gameName, int modID, QObject *receiver, QVariant userData, const QString &subModule)
{
- return requestDescription(modID, receiver, userData, subModule, m_Game);
+ return requestDescription(gameName, modID, receiver, userData, subModule, getGame(gameName));
}
/**
@@ -169,31 +170,18 @@ public:
* @param game Game with which the mod is associated
* @return int an id to identify the request
**/
- int requestDescription(int modID, QObject *receiver, QVariant userData, const QString &subModule,
+ int requestDescription(QString gameName, int modID, QObject *receiver, QVariant userData, const QString &subModule,
MOBase::IPluginGame const *game);
/**
* @brief request nexus descriptions for multiple mods at once
- * @param modIDs a list of ids of mods the caller is interested in (assumed to be for the current game)
- * @param receiver the object to receive the result asynchronously via a signal (nxmDescriptionAvailable)
- * @param userData user data to be returned with the result
- * @return int an id to identify the request
- */
- int requestUpdates(const std::vector<int> &modIDs, QObject *receiver, QVariant userData, const QString &subModule)
- {
- return requestUpdates(modIDs, receiver, userData, subModule, m_Game);
- }
-
- /**
- * @brief request nexus descriptions for multiple mods at once
* @param modIDs a list of ids of mods the caller is interested in
* @param receiver the object to receive the result asynchronously via a signal (nxmDescriptionAvailable)
* @param userData user data to be returned with the result
* @param game the game with which the mods are associated
* @return int an id to identify the request
*/
- int requestUpdates(const std::vector<int> &modIDs, QObject *receiver, QVariant userData, const QString &subModule,
- MOBase::IPluginGame const *game);
+ int requestUpdates(const std::vector<int> &modIDs, QObject *receiver, QVariant userData, QString gameName, const QString &subModule);
/**
* @brief request a list of the files belonging to a mod
@@ -203,9 +191,9 @@ public:
* @param userData user data to be returned with the result
* @return int an id to identify the request
**/
- int requestFiles(int modID, QObject *receiver, QVariant userData, const QString &subModule)
+ int requestFiles(QString gameName, int modID, QObject *receiver, QVariant userData, const QString &subModule)
{
- return requestFiles(modID, receiver, userData, subModule, m_Game);
+ return requestFiles(gameName, modID, receiver, userData, subModule, getGame(gameName));
}
@@ -218,35 +206,20 @@ public:
* @param game the game with which the mods are associated
* @return int an id to identify the request
**/
- int requestFiles(int modID, QObject *receiver, QVariant userData, const QString &subModule,
+ int requestFiles(QString gameName, int modID, QObject *receiver, QVariant userData, const QString &subModule,
MOBase::IPluginGame const *game);
/**
* @brief request info about a single file of a mod
*
+ * @param game name of the game short name to request the download from
* @param modID id of the mod caller is interested in (assumed to be for the current game)
* @param fileID id of the file the caller is interested in
* @param receiver the object to receive the result asynchronously via a signal (nxmFilesAvailable)
* @param userData user data to be returned with the result
* @return int an id to identify the request
**/
- int requestFileInfo(int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule)
- {
- return requestFileInfo(modID, fileID, receiver, userData, subModule, m_Game);
- }
-
- /**
- * @brief request info about a single file of a mod
- *
- * @param modID id of the mod caller is interested in (assumed to be for the current game)
- * @param fileID id of the file the caller is interested in
- * @param receiver the object to receive the result asynchronously via a signal (nxmFilesAvailable)
- * @param userData user data to be returned with the result
- * @param game the game with which the mods are associated
- * @return int an id to identify the request
- **/
- int requestFileInfo(int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule,
- MOBase::IPluginGame const *game);
+ int requestFileInfo(QString gameName, int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule);
/**
* @brief request the download url of a file
@@ -257,9 +230,9 @@ public:
* @param userData user data to be returned with the result
* @return int an id to identify the request
**/
- int requestDownloadURL(int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule)
+ int requestDownloadURL(QString gameName, int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule)
{
- return requestDownloadURL(modID, fileID, receiver, userData, subModule, m_Game);
+ return requestDownloadURL(gameName, modID, fileID, receiver, userData, subModule, getGame(gameName));
}
/**
@@ -272,7 +245,7 @@ public:
* @param game the game with which the mods are associated
* @return int an id to identify the request
**/
- int requestDownloadURL(int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule, MOBase::IPluginGame const *game);
+ int requestDownloadURL(QString gameName, int modID, int fileID, QObject *receiver, QVariant userData, const QString &subModule, MOBase::IPluginGame const *game);
/**
* @brief toggle endorsement state of the mod
@@ -282,9 +255,9 @@ public:
* @param userData user data to be returned with the result
* @return int an id to identify the request
*/
- int requestToggleEndorsement(int modID, bool endorse, QObject *receiver, QVariant userData, const QString &subModule)
+ int requestToggleEndorsement(QString gameName, int modID, bool endorse, QObject *receiver, QVariant userData, const QString &subModule)
{
- return requestToggleEndorsement(modID, endorse, receiver, userData, subModule, m_Game);
+ return requestToggleEndorsement(gameName, modID, endorse, receiver, userData, subModule, getGame(gameName));
}
/**
@@ -296,7 +269,7 @@ public:
* @param game the game with which the mods are associated
* @return int an id to identify the request
*/
- int requestToggleEndorsement(int modID, bool endorse, QObject *receiver, QVariant userData, const QString &subModule,
+ int requestToggleEndorsement(QString gameName, int modID, bool endorse, QObject *receiver, QVariant userData, const QString &subModule,
MOBase::IPluginGame const *game);
/**
@@ -315,6 +288,8 @@ public:
*/
void loginCompleted();
+ std::vector<std::pair<QString, QString>> getGameChoices(const MOBase::IPluginGame *game);
+
public:
/**
@@ -342,13 +317,13 @@ public:
*
* Arguably, this should optionally take a gameplugin pointer
*/
- QString getGameURL() const;
+ QString getGameURL(QString gameName) const;
/**
* @brief Get the URL for the mod web page
* @param modID
*/
- QString getModURL(int modID) const;
+ QString getModURL(int modID, QString gameName) const;
/**
* @brief Checks if the specified URL might correspond to a nexus mod
@@ -358,22 +333,21 @@ public:
*/
bool isModURL(int modID, QString const &url) const;
+ void setPluginContainer(PluginContainer *pluginContainer);
+
signals:
void requestNXMDownload(const QString &url);
void needLogin();
- void nxmDescriptionAvailable(int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
void nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant userData, QVariant resultData, int requestID);
- void nxmFilesAvailable(int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
- void nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
- void nxmEndorsementToggled(int modID, QVariant userData, QVariant resultData, int requestID);
- void nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
-
-public slots:
- void managedGameChanged(MOBase::IPluginGame const *game);
+ void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
+ void nxmEndorsementToggled(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
+ void nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
private slots:
@@ -404,6 +378,7 @@ private:
QTimer *m_Timeout;
QString m_URL;
QString m_SubModule;
+ QString m_GameName;
int m_NexusGameID;
bool m_Reroute;
int m_ID;
@@ -421,11 +396,12 @@ private:
private:
- NexusInterface();
+ NexusInterface(PluginContainer *pluginContainer);
void nextRequest();
void requestFinished(std::list<NXMRequestInfo>::iterator iter);
bool requiresLogin(const NXMRequestInfo &info);
- QString getOldModsURL() const;
+ MOBase::IPluginGame *getGame(QString gameName) const;
+ QString getOldModsURL(QString gameName) const;
private:
@@ -439,7 +415,7 @@ private:
MOBase::VersionInfo m_MOVersion;
QString m_NMMVersion;
- MOBase::IPluginGame const *m_Game;
+ PluginContainer *m_PluginContainer;
};
diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp
index 17c50e35..05016e8f 100644
--- a/src/nxmaccessmanager.cpp
+++ b/src/nxmaccessmanager.cpp
@@ -42,7 +42,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
namespace {
- QString const Nexus_Management_URL("http://nmm.nexusmods.com");
+ QString const Nexus_Management_URL("https://legacy-api.nexusmods.com");
}
// unfortunately Nexus doesn't seem to document these states, all I know is all these listed
diff --git a/src/organizer_en.ts b/src/organizer_en.ts
new file mode 100644
index 00000000..09c100cf
--- /dev/null
+++ b/src/organizer_en.ts
@@ -0,0 +1,6695 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="en_US">
+<context>
+ <name>AboutDialog</name>
+ <message>
+ <location filename="aboutdialog.ui" line="14"/>
+ <location filename="aboutdialog.ui" line="90"/>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="103"/>
+ <source>Revision:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="141"/>
+ <source>Used Software</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="154"/>
+ <source>Thanks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="160"/>
+ <source>Current Maintainers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="170"/>
+ <source>LePresidente (Project Lead)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="201"/>
+ <source>Major Contributors</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="222"/>
+ <source>Translators</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="247"/>
+ <source>Cyb3r (Dutch)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="257"/>
+ <source>fruttyx (French)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="272"/>
+ <source>Yoplala (French)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="277"/>
+ <source>Faron (German)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="287"/>
+ <source>Mordan (Greek)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="300"/>
+ <source>Yoosk (Polish)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="305"/>
+ <source>Brgodfx (Portuguese)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="325"/>
+ <source>Jax (Swedish)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="330"/>
+ <source>...and all other Transifex contributors!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="344"/>
+ <source>Other Supporters &amp;&amp; Contributors</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.ui" line="466"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="aboutdialog.cpp" line="114"/>
+ <source>No license</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ActivateModsDialog</name>
+ <message>
+ <location filename="activatemodsdialog.ui" line="14"/>
+ <source>Activate Mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="activatemodsdialog.ui" line="20"/>
+ <source>This is a list of esps, esms, and esls that were active when the save game was created.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="activatemodsdialog.ui" line="23"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This is a list of esps, esms, and esls that were active when the save game was created.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;If you hit Ok, all the mods selected in the right columns and all missing esps that have become available will be activated.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="activatemodsdialog.ui" line="37"/>
+ <source>Missing ESP</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="activatemodsdialog.ui" line="42"/>
+ <source>Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="activatemodsdialog.cpp" line="49"/>
+ <source>not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>BrowserDialog</name>
+ <message>
+ <location filename="browserdialog.ui" line="14"/>
+ <source>Some Page</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="browserdialog.ui" line="281"/>
+ <source>Search</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="browserdialog.cpp" line="94"/>
+ <source>new</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="browserdialog.cpp" line="207"/>
+ <source>failed to start download</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>CategoriesDialog</name>
+ <message>
+ <location filename="categoriesdialog.ui" line="14"/>
+ <source>Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="66"/>
+ <source>ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="69"/>
+ <source>Internal ID for the category.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="72"/>
+ <source>Internal ID for the category. The categories a mod belongs to are stored by this ID. It is recommended you use new IDs for categories you add instead of re-using existing ones.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="77"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="80"/>
+ <location filename="categoriesdialog.ui" line="83"/>
+ <source>Name of the Categorie used for display.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="88"/>
+ <source>Nexus IDs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="91"/>
+ <source>Comma-Separated list of Nexus IDs to be matched to the internal ID.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="94"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-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;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="105"/>
+ <source>Parent ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.ui" line="108"/>
+ <source>If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.cpp" line="239"/>
+ <source>Add</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categoriesdialog.cpp" line="240"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>CredentialsDialog</name>
+ <message>
+ <location filename="credentialsdialog.ui" line="14"/>
+ <source>Login</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="credentialsdialog.ui" line="20"/>
+ <source>This feature may not work unless you&apos;re logged in with Nexus</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="credentialsdialog.ui" line="32"/>
+ <source>Username</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="credentialsdialog.ui" line="42"/>
+ <source>Password</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="credentialsdialog.ui" line="60"/>
+ <source>Remember</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="credentialsdialog.ui" line="71"/>
+ <source>Never ask again</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DirectoryRefresher</name>
+ <message>
+ <location filename="directoryrefresher.cpp" line="94"/>
+ <source>failed to parse bsa %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="directoryrefresher.cpp" line="160"/>
+ <source>failed to read mod (%1): %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DownloadList</name>
+ <message>
+ <location filename="downloadlist.cpp" line="64"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlist.cpp" line="65"/>
+ <source>Filetime</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlist.cpp" line="66"/>
+ <source>Done</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlist.cpp" line="82"/>
+ <source>Information missing, please select &quot;Query Info&quot; from the context menu to re-retrieve.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlist.cpp" line="89"/>
+ <source>pending download</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DownloadListWidget</name>
+ <message>
+ <location filename="downloadlistwidget.ui" line="17"/>
+ <location filename="downloadlistwidget.ui" line="61"/>
+ <source>Placeholder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.ui" line="99"/>
+ <location filename="downloadlistwidget.cpp" line="150"/>
+ <location filename="downloadlistwidget.cpp" line="152"/>
+ <source>Done - Double Click to install</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="116"/>
+ <location filename="downloadlistwidget.cpp" line="118"/>
+ <source>Paused - Double Click to resume</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="136"/>
+ <location filename="downloadlistwidget.cpp" line="138"/>
+ <source>Installed - Double Click to re-install</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="143"/>
+ <location filename="downloadlistwidget.cpp" line="145"/>
+ <source>Uninstalled - Double Click to re-install</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DownloadListWidgetCompact</name>
+ <message>
+ <location filename="downloadlistwidgetcompact.ui" line="17"/>
+ <location filename="downloadlistwidgetcompact.ui" line="56"/>
+ <source>Placeholder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.ui" line="122"/>
+ <source>Done</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DownloadListWidgetCompactDelegate</name>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="92"/>
+ <source>&lt; game %1 mod %2 file %3 &gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="97"/>
+ <source>Pending</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="120"/>
+ <source>Paused</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="122"/>
+ <source>Fetching Info 1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="124"/>
+ <source>Fetching Info 2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="129"/>
+ <source>Installed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="131"/>
+ <source>Uninstalled</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="133"/>
+ <source>Done</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="242"/>
+ <location filename="downloadlistwidgetcompact.cpp" line="251"/>
+ <location filename="downloadlistwidgetcompact.cpp" line="260"/>
+ <location filename="downloadlistwidgetcompact.cpp" line="269"/>
+ <source>Are you sure?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="243"/>
+ <source>This will remove all finished downloads from this list and from disk.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="252"/>
+ <source>This will remove all installed downloads from this list and from disk.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="261"/>
+ <source>This will permanently remove all finished downloads from this list (but NOT from disk).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="270"/>
+ <source>This will permanently remove all installed downloads from this list (but NOT from disk).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="299"/>
+ <source>Install</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="301"/>
+ <source>Query Info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="303"/>
+ <source>Delete</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="305"/>
+ <source>Un-Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="307"/>
+ <source>Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="310"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="311"/>
+ <source>Pause</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="313"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="314"/>
+ <source>Resume</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="319"/>
+ <source>Delete Installed...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="320"/>
+ <source>Delete All...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="323"/>
+ <source>Hide Installed...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidgetcompact.cpp" line="324"/>
+ <source>Hide All...</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DownloadListWidgetDelegate</name>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="93"/>
+ <source>&lt; game %1 mod %2 file %3 &gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="96"/>
+ <source>Pending</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="123"/>
+ <source>Fetching Info 1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="126"/>
+ <source>Fetching Info 2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="259"/>
+ <location filename="downloadlistwidget.cpp" line="268"/>
+ <location filename="downloadlistwidget.cpp" line="277"/>
+ <location filename="downloadlistwidget.cpp" line="286"/>
+ <source>Are you sure?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="260"/>
+ <source>This will remove all finished downloads from this list and from disk.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="269"/>
+ <source>This will remove all installed downloads from this list and from disk.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="278"/>
+ <source>This will remove all finished downloads from this list (but NOT from disk).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="287"/>
+ <source>This will remove all installed downloads from this list (but NOT from disk).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="315"/>
+ <source>Install</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="317"/>
+ <source>Query Info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="319"/>
+ <source>Delete</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="321"/>
+ <source>Un-Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="323"/>
+ <source>Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="326"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="327"/>
+ <source>Pause</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="329"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="330"/>
+ <source>Resume</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="335"/>
+ <source>Delete Installed...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="336"/>
+ <source>Delete All...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="339"/>
+ <source>Hide Installed...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadlistwidget.cpp" line="340"/>
+ <source>Hide All...</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>DownloadManager</name>
+ <message>
+ <location filename="downloadmanager.cpp" line="155"/>
+ <source>failed to rename &quot;%1&quot; to &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="338"/>
+ <source>Memory allocation error (in refreshing directory).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="424"/>
+ <source>failed to download %1: could not open output file: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="447"/>
+ <source>Download again?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="447"/>
+ <source>A file with the same name has already been downloaded. Do you want to download it again? The new file will receive a different name.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="486"/>
+ <source>Wrong Game</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="486"/>
+ <source>The download link is for a mod for &quot;%1&quot; but this instance of MO has been set up for &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="494"/>
+ <location filename="downloadmanager.cpp" line="505"/>
+ <source>Already Started</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="494"/>
+ <source>A download for this mod file has already been queued.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="505"/>
+ <source>There is already a download started for this file (mod: %1, file: %2).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="525"/>
+ <location filename="downloadmanager.cpp" line="627"/>
+ <source>remove: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="543"/>
+ <source>failed to delete %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="549"/>
+ <source>failed to delete meta file for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="592"/>
+ <source>restore: invalid download index: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="645"/>
+ <source>cancel: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="658"/>
+ <source>pause: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="678"/>
+ <source>resume: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="689"/>
+ <source>resume (int): invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="696"/>
+ <source>No known download urls. Sorry, this download can&apos;t be resumed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="734"/>
+ <source>query: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="756"/>
+ <source>Please enter the nexus mod id</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="756"/>
+ <source>Mod ID:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="766"/>
+ <source>Please select the source game code for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="796"/>
+ <source>get pending: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="805"/>
+ <source>get path: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="814"/>
+ <source>Main</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="815"/>
+ <source>Update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="816"/>
+ <source>Optional</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="817"/>
+ <source>Old</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="818"/>
+ <source>Misc</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="819"/>
+ <source>Unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="826"/>
+ <source>display name: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="846"/>
+ <source>file name: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="855"/>
+ <source>file time: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="869"/>
+ <source>file size: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="879"/>
+ <source>progress: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="889"/>
+ <source>state: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="899"/>
+ <source>infocomplete: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="914"/>
+ <location filename="downloadmanager.cpp" line="922"/>
+ <source>mod id: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="930"/>
+ <source>ishidden: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="939"/>
+ <source>file info: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="949"/>
+ <source>mark installed: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="984"/>
+ <source>mark uninstalled: invalid download index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1145"/>
+ <source>Memory allocation error (in processing progress event).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1158"/>
+ <source>Memory allocation error (in processing downloaded data).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1292"/>
+ <source>Information updated</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1294"/>
+ <location filename="downloadmanager.cpp" line="1308"/>
+ <source>No matching file found on Nexus! Maybe this file is no longer available or it was renamed?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1296"/>
+ <source>No file on Nexus matches the selected file by name. Please manually choose the correct one.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1425"/>
+ <source>No download server available. Please try again later.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1468"/>
+ <source>Failed to request file info from nexus: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1495"/>
+ <source>Warning: Content type is: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1501"/>
+ <source>Download header content length: %1 downloaded file size: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1503"/>
+ <source>Download failed: %1 (%2)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="downloadmanager.cpp" line="1606"/>
+ <source>failed to re-open %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>EditExecutablesDialog</name>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="20"/>
+ <source>Modify Executables</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="26"/>
+ <source>List of configured executables</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="29"/>
+ <source>This is a list of your configured executables. Executables in grey are automatically recognised and can not be modified.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="47"/>
+ <source>Title</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="54"/>
+ <location filename="editexecutablesdialog.ui" line="57"/>
+ <source>Name of the executable. This is only for display purposes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="68"/>
+ <source>Binary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="75"/>
+ <location filename="editexecutablesdialog.ui" line="78"/>
+ <source>Binary to run</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="85"/>
+ <source>Browse filesystem</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="88"/>
+ <source>Browse filesystem for the executable to run.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="91"/>
+ <location filename="editexecutablesdialog.ui" line="112"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="102"/>
+ <source>Start in</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="123"/>
+ <source>Arguments</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="130"/>
+ <location filename="editexecutablesdialog.ui" line="133"/>
+ <source>Arguments to pass to the application</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="144"/>
+ <source>Allow the Steam AppID to be used for this executable to be changed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="147"/>
+ <source>Allow the Steam AppID to be used for this executable to be changed.
+Every game/tool distributed through Steam has a unique ID. MO needs to know this ID to start those programs directly, otherwise the program is started by steam and then MO will not work. By default, MO will use the AppID for the game.
+Right now the only case I know of where this needs to be overwritten is for the Skyrim Creation Kit which has its own AppID. This overwrite is already preconfigured.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="152"/>
+ <source>Overwrite Steam AppID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="162"/>
+ <source>Steam AppID to use for this executable that differs from the games AppID.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="165"/>
+ <source>Steam AppID to use for this executable that differs from the games AppID.
+Every game/tool distributed through Steam has a unique ID. MO needs to know this ID to start those programs directly, otherwise the program is started by steam and then MO will not work. By default, MO will use the AppID for the game (usually 72850).
+Right now the only case I know of where this needs to be overwritten is for the Skyrim Creation Kit which has its own AppID (usually 202480). This overwrite is already preconfigured.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="178"/>
+ <source>If this is enabled, new files are created in the specified mod instead of the &quot;Overwrite&quot; mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="181"/>
+ <source>Create Files in Mod instead of Overwrite (*)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="197"/>
+ <source>Use Application&apos;s Icon for shortcuts</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="204"/>
+ <source>(*) This setting is profile-specific</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="213"/>
+ <location filename="editexecutablesdialog.ui" line="216"/>
+ <source>Add an executable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="219"/>
+ <location filename="editexecutablesdialog.cpp" line="217"/>
+ <source>Add</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="230"/>
+ <location filename="editexecutablesdialog.ui" line="233"/>
+ <source>Remove the selected executable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="236"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.ui" line="264"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="146"/>
+ <source>Select a binary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="147"/>
+ <source>Executable (%1)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="172"/>
+ <source>Java (32-bit) required</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="173"/>
+ <source>MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe from that installation as the binary.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="189"/>
+ <source>Select a directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="196"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="196"/>
+ <source>Really remove &quot;%1&quot; from executables?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="221"/>
+ <source>Modify</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="267"/>
+ <location filename="editexecutablesdialog.cpp" line="287"/>
+ <source>Save Changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="editexecutablesdialog.cpp" line="268"/>
+ <location filename="editexecutablesdialog.cpp" line="288"/>
+ <source>You made changes to the current executable, do you want to save them?</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>FindDialog</name>
+ <message>
+ <location filename="../../uibase/src/finddialog.ui" line="14"/>
+ <location filename="finddialog.ui" line="14"/>
+ <source>Find</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/finddialog.ui" line="24"/>
+ <location filename="finddialog.ui" line="24"/>
+ <source>Find what:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/finddialog.ui" line="31"/>
+ <location filename="../../uibase/src/finddialog.ui" line="34"/>
+ <location filename="finddialog.ui" line="31"/>
+ <location filename="finddialog.ui" line="34"/>
+ <source>Search term</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/finddialog.ui" line="47"/>
+ <location filename="../../uibase/src/finddialog.ui" line="50"/>
+ <location filename="finddialog.ui" line="47"/>
+ <location filename="finddialog.ui" line="50"/>
+ <source>Find next occurence from current file position.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/finddialog.ui" line="53"/>
+ <location filename="finddialog.ui" line="53"/>
+ <source>&amp;Find Next</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/finddialog.ui" line="60"/>
+ <location filename="../../uibase/src/finddialog.ui" line="63"/>
+ <location filename="../../uibase/src/finddialog.ui" line="66"/>
+ <location filename="finddialog.ui" line="60"/>
+ <location filename="finddialog.ui" line="63"/>
+ <location filename="finddialog.ui" line="66"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>InstallDialog</name>
+ <message>
+ <location filename="installdialog.ui" line="20"/>
+ <source>Install Mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="32"/>
+ <source>New Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="46"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="53"/>
+ <source>Pick a name for the mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="56"/>
+ <source>Pick a name for the mod. This is also used as a directory name, so please don&apos;t use characters that are illegal in file names.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="65"/>
+ <source>Content</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="75"/>
+ <source>Content of the archive. You can change the directory structure by using drag&amp;drop. Hint: Also try right clicking...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="78"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This displays the content of the archive. &amp;lt;data&amp;gt; represents the base directory which will map to the game&apos;s data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;amp;drop&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="121"/>
+ <source>Placeholder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="141"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installdialog.ui" line="148"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>InstallationManager</name>
+ <message>
+ <location filename="installationmanager.cpp" line="119"/>
+ <source>Password required</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="120"/>
+ <source>Password</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="189"/>
+ <location filename="installationmanager.cpp" line="289"/>
+ <source>Extracting files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="490"/>
+ <source>failed to create backup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="499"/>
+ <source>Mod Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="499"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="552"/>
+ <source>Invalid name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="553"/>
+ <source>The name you entered is invalid, please enter a different one.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="694"/>
+ <source>File format &quot;%1&quot; not supported</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="857"/>
+ <source>None of the available installer plugins were able to handle that archive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="867"/>
+ <source>no error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="870"/>
+ <source>7z.dll not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="873"/>
+ <source>7z.dll isn&apos;t valid</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="876"/>
+ <source>archive not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="879"/>
+ <source>failed to open archive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="882"/>
+ <source>unsupported archive type</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="885"/>
+ <source>internal library error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="888"/>
+ <source>archive invalid</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="892"/>
+ <source>unknown archive error</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>LockedDialog</name>
+ <message>
+ <location filename="lockeddialog.ui" line="14"/>
+ <source>Running virtualized processes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="lockeddialog.ui" line="20"/>
+ <source>This dialog should disappear automatically if the application/game is done. Click unlock if it didn&apos;t.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="lockeddialog.ui" line="23"/>
+ <source>MO is locked while the executable is running.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="lockeddialog.ui" line="78"/>
+ <source>Unlock</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>LogBuffer</name>
+ <message>
+ <location filename="logbuffer.cpp" line="83"/>
+ <source>failed to write log to %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MOApplication</name>
+ <message>
+ <location filename="moapplication.cpp" line="119"/>
+ <source>an error occured: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="moapplication.cpp" line="124"/>
+ <source>an error occured</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MOBase::TextViewer</name>
+ <message>
+ <location filename="../../uibase/src/textviewer.cpp" line="58"/>
+ <source>Save changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/textviewer.cpp" line="59"/>
+ <source>Do you want to save changes to %1?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/textviewer.cpp" line="130"/>
+ <source>failed to write to %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/textviewer.cpp" line="161"/>
+ <source>file not found: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/textviewer.cpp" line="186"/>
+ <source>Save</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MOBase::TutorialControl</name>
+ <message>
+ <location filename="../../uibase/src/tutorialcontrol.cpp" line="145"/>
+ <source>Tutorial failed to start, please check &quot;mo_interface.log&quot; for details.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MOBase::TutorialManager</name>
+ <message>
+ <location filename="../../uibase/src/tutorialmanager.cpp" line="54"/>
+ <source>tutorial manager not set up yet</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <location filename="mainwindow.ui" line="46"/>
+ <location filename="mainwindow.ui" line="600"/>
+ <source>Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="115"/>
+ <source>Clear</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="134"/>
+ <source>If checked, only mods that match all selected categories are displayed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="137"/>
+ <source>And</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="147"/>
+ <source>If checked, all mods that match at least one of the selected categories are displayed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="150"/>
+ <source>Or</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="189"/>
+ <source>Profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="199"/>
+ <source>Pick a module collection</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="202"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Please note that right now your esp load order is not kept seperate for different profiles.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="233"/>
+ <source>Open list options...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="236"/>
+ <source>Refresh list. This is usually not necessary unless you modified data outside the program.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="256"/>
+ <source>Show Open Folders menu...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="280"/>
+ <location filename="mainwindow.ui" line="866"/>
+ <source>Restore Backup...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="294"/>
+ <location filename="mainwindow.ui" line="886"/>
+ <source>Create Backup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="410"/>
+ <source>List of available mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="413"/>
+ <source>This is a list of installed mods. Use the checkboxes to activate/deactivate mods and drag &amp; drop mods to change their &quot;installation&quot; orders.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="498"/>
+ <source>Filter</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="555"/>
+ <source>Clear all Filters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="595"/>
+ <source>No groups</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="605"/>
+ <source>Nexus IDs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="619"/>
+ <location filename="mainwindow.ui" line="1003"/>
+ <location filename="mainwindow.ui" line="1356"/>
+ <source>Namefilter</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="654"/>
+ <source>Pick a program to run.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="657"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;You can add new Tools to this list, but I can&apos;t promise tools I haven&apos;t tested will work.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="705"/>
+ <source>Run program</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="708"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Run the selected program with ModOrganizer enabled.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="718"/>
+ <source>Run</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="759"/>
+ <source>Create a shortcut in your start menu or on the desktop to the specified program</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="762"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This creates a start menu shortcut that directly starts the selected program with the MO active.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="769"/>
+ <source>Shortcut</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="819"/>
+ <source>Plugins</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="842"/>
+ <source>Sort</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="948"/>
+ <source>List of available esp/esm files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="951"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This list contains the esps, esms, and esls contained in the active mods. These require their own load order. Use drag&amp;amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.&lt;br /&gt;There is a great tool named &amp;quot;BOSS&amp;quot; to automatically sort these files.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1016"/>
+ <source>Archives</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1049"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;BSAs / BA2s are bundles of game assets (textures, scripts, etc.). By default, the engine loads these bundles in a separate step from loose files. &lt;p&gt;Their load order is specified by the priority of the corresponding plugin (right pane, plugins tab).&lt;/p&gt;&lt;p&gt;If there is a matching plugin, the game will load them no matter what.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1052"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Currently detected archives. (&lt;a href=&quot;#&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;What is an archive?&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1067"/>
+ <source>List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1070"/>
+ <source>BSA files are archives (comparable to .zip files) that contain data assets (meshes, textures, ...) to be used by the game. As such they &quot;compete&quot; with loose files in your data directory over which is loaded.
+ 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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1116"/>
+ <location filename="mainwindow.ui" line="1175"/>
+ <source>File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1125"/>
+ <source>Data</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1143"/>
+ <source>refresh data-directory overview</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1146"/>
+ <source>Refresh the overview. This may take a moment.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1149"/>
+ <location filename="mainwindow.cpp" line="3395"/>
+ <location filename="mainwindow.cpp" line="4183"/>
+ <source>Refresh</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1165"/>
+ <source>This is an overview of your data directory as visible to the game (and tools). </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1180"/>
+ <source>Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1190"/>
+ <location filename="mainwindow.ui" line="1193"/>
+ <source>Filter the above list so that only conflicts are displayed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1196"/>
+ <source>Show only conflicts</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1204"/>
+ <source>Saves</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1228"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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&apos;t active now.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-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;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;If you click &amp;quot;Fix Mods...&amp;quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1248"/>
+ <source>Downloads</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1283"/>
+ <source>This is a list of mods you downloaded from Nexus. Double click one to install it. You can also drag an archive into here.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1336"/>
+ <source>Show Hidden</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1398"/>
+ <source>Tool Bar</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1441"/>
+ <source>Install Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1444"/>
+ <source>Install &amp;Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1447"/>
+ <source>Install a new mod from an archive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1450"/>
+ <source>Ctrl+M</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1459"/>
+ <source>Profiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1462"/>
+ <source>&amp;Profiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1465"/>
+ <source>Configure Profiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1468"/>
+ <source>Ctrl+P</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1477"/>
+ <source>Executables</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1480"/>
+ <source>&amp;Executables</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1483"/>
+ <source>Configure the executables that can be started through Mod Organizer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1486"/>
+ <source>Ctrl+E</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1495"/>
+ <location filename="mainwindow.ui" line="1501"/>
+ <source>Tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1498"/>
+ <source>&amp;Tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1504"/>
+ <source>Ctrl+I</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1513"/>
+ <source>Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1516"/>
+ <source>&amp;Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1519"/>
+ <source>Configure settings and workarounds</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1522"/>
+ <source>Ctrl+S</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1531"/>
+ <source>Nexus</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1534"/>
+ <source>Search nexus network for more mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1537"/>
+ <source>Ctrl+N</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1549"/>
+ <location filename="mainwindow.cpp" line="4124"/>
+ <source>Update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1552"/>
+ <source>Mod Organizer is up-to-date</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1564"/>
+ <location filename="mainwindow.cpp" line="628"/>
+ <source>No Problems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1567"/>
+ <source>This button will be highlighted if MO discovered potential problems in your setup and provide tips on how to fix them.
+
+!Work in progress!
+Right now this has very limited functionality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1579"/>
+ <location filename="mainwindow.ui" line="1582"/>
+ <source>Help</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1585"/>
+ <source>Ctrl+H</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1594"/>
+ <source>Endorse MO</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1597"/>
+ <location filename="mainwindow.cpp" line="4202"/>
+ <source>Endorse Mod Organizer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1602"/>
+ <source>Copy Log to Clipboard</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1605"/>
+ <source>Ctrl+C</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1614"/>
+ <source>Change Game</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.ui" line="1617"/>
+ <source>Open the Instance selection dialog to manage a different Game</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="300"/>
+ <source>Toolbar</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="301"/>
+ <source>Desktop</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="302"/>
+ <source>Start Menu</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="326"/>
+ <source>There is no supported sort mechanism for this game. You will probably have to use a third-party tool.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="616"/>
+ <source>Problems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="617"/>
+ <source>There are potential problems with your setup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="629"/>
+ <source>Everything seems to be in order</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="691"/>
+ <source>Help on UI</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="695"/>
+ <source>Documentation Wiki</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="699"/>
+ <source>Report Issue</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="703"/>
+ <source>Tutorials</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="742"/>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="743"/>
+ <source>About Qt</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="795"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="796"/>
+ <source>Please enter a name for the new profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="804"/>
+ <source>failed to create profile: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="848"/>
+ <source>Show tutorial?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="849"/>
+ <source>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 &quot;Help&quot;-menu.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="885"/>
+ <source>Downloads in progress</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="886"/>
+ <source>There are still downloads in progress, do you really want to quit?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1003"/>
+ <source>Plugin &quot;%1&quot; failed: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1005"/>
+ <source>Plugin &quot;%1&quot; failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1041"/>
+ <source>Browse Mod Page</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1176"/>
+ <source>Also in: &lt;br&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1187"/>
+ <source>No conflict</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1299"/>
+ <source>&lt;Edit...&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1567"/>
+ <source>This bsa is enabled in the ini file so it may be required!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1629"/>
+ <source>Activating Network Proxy</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1687"/>
+ <source>Notice: Your current MO version (%1) is lower than the previous version (%2).&lt;br&gt;The GUI may not downgrade gracefully, so you may experience oddities.&lt;br&gt;However, there should be no serious issues.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1776"/>
+ <source>Choose Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1777"/>
+ <source>Mod Archive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1939"/>
+ <source>Start Tutorial?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1940"/>
+ <source>You&apos;re about to start a tutorial. For technical reasons it&apos;s not possible to end the tutorial early. Continue?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2076"/>
+ <source>failed to spawn notepad.exe: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2116"/>
+ <source>failed to change origin name: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2140"/>
+ <source>failed to move &quot;%1&quot; from mod &quot;%2&quot; to &quot;%3&quot;: %4</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2164"/>
+ <source>&lt;Contains %1&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2199"/>
+ <source>&lt;Checked&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2200"/>
+ <source>&lt;Unchecked&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2201"/>
+ <source>&lt;Update&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2202"/>
+ <source>&lt;Managed by MO&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2203"/>
+ <source>&lt;Managed outside MO&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2204"/>
+ <source>&lt;No category&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2205"/>
+ <source>&lt;Conflicted&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2206"/>
+ <source>&lt;Not Endorsed&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2252"/>
+ <source>failed to rename mod: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2265"/>
+ <source>Overwrite?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2266"/>
+ <source>This will replace the existing mod &quot;%1&quot;. Continue?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2269"/>
+ <source>failed to remove mod &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2273"/>
+ <location filename="mainwindow.cpp" line="4008"/>
+ <location filename="mainwindow.cpp" line="4032"/>
+ <source>failed to rename &quot;%1&quot; to &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2333"/>
+ <location filename="mainwindow.cpp" line="3126"/>
+ <location filename="mainwindow.cpp" line="3134"/>
+ <location filename="mainwindow.cpp" line="3592"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2334"/>
+ <source>Remove the following mods?&lt;br&gt;&lt;ul&gt;%1&lt;/ul&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2345"/>
+ <source>failed to remove mod: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2377"/>
+ <location filename="mainwindow.cpp" line="2380"/>
+ <source>Failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2377"/>
+ <source>Installation file no longer exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2381"/>
+ <source>Mods installed with old versions of MO can&apos;t be reinstalled in this way.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2398"/>
+ <source>You need to be logged in with Nexus to resume a download</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2414"/>
+ <location filename="mainwindow.cpp" line="2441"/>
+ <source>You need to be logged in with Nexus to endorse</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2489"/>
+ <source>Failed to display overwrite dialog: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2642"/>
+ <source>Nexus ID for this Mod is unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2652"/>
+ <source>Web page for this mod is unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2722"/>
+ <location filename="mainwindow.cpp" line="2751"/>
+ <location filename="mainwindow.cpp" line="3425"/>
+ <source>Create Mod...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2723"/>
+ <source>This will create an empty mod.
+Please enter a name:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2732"/>
+ <location filename="mainwindow.cpp" line="2761"/>
+ <source>A mod with this name already exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2752"/>
+ <source>This will move all files from overwrite into a new, regular mod.
+Please enter a name:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2793"/>
+ <location filename="mainwindow.cpp" line="4513"/>
+ <source>Are you sure?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="2794"/>
+ <source>About to recursively delete:
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3038"/>
+ <source>Not logged in, endorsement information will be wrong</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3046"/>
+ <source>Continue?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3047"/>
+ <source>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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3067"/>
+ <location filename="mainwindow.cpp" line="4092"/>
+ <source>Sorry</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3068"/>
+ <source>I don&apos;t know a versioning scheme where %1 is newer than %2.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3126"/>
+ <source>Really enable all visible mods?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3134"/>
+ <source>Really disable all visible mods?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3187"/>
+ <source>Export to csv</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3190"/>
+ <source>CSV (Comma Separated Values) is a format that can be imported in programs like Excel to create a spreadsheet.
+You can also use online editors and converters instead.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3193"/>
+ <source>Select what mods you want export:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3194"/>
+ <source>All installed mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3195"/>
+ <source>Only active (checked) mods from your current profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3196"/>
+ <source>All currently visible mods in the mod list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3217"/>
+ <source>Choose what Columns to export:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3220"/>
+ <source>Mod_Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3222"/>
+ <source>Mod_Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3224"/>
+ <source>Mod_Status</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3225"/>
+ <source>Primary_Category</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3226"/>
+ <source>Nexus_ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3227"/>
+ <source>Mod_Nexus_URL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3228"/>
+ <source>Mod_Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3229"/>
+ <source>Install_Date</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3230"/>
+ <source>Download_File_Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3332"/>
+ <source>export failed: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3351"/>
+ <source>Open Game folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3353"/>
+ <source>Open MyGames folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3357"/>
+ <source>Open Instance folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3359"/>
+ <source>Open Profile folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3361"/>
+ <source>Open Downloads folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3365"/>
+ <source>Open MO2 Install folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3367"/>
+ <source>Open MO2 Logs folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3384"/>
+ <source>Install Mod...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3386"/>
+ <source>Create empty mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3390"/>
+ <source>Enable all visible</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3391"/>
+ <source>Disable all visible</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3393"/>
+ <source>Check all for update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3397"/>
+ <source>Export to csv...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3418"/>
+ <source>All Mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3424"/>
+ <source>Sync to Mods...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3426"/>
+ <source>Clear Overwrite...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3428"/>
+ <location filename="mainwindow.cpp" line="3508"/>
+ <source>Open in explorer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3430"/>
+ <source>Restore Backup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3431"/>
+ <source>Remove Backup...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3435"/>
+ <source>Change Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3448"/>
+ <source>Primary Category</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3454"/>
+ <source>Change versioning scheme</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3458"/>
+ <source>Un-ignore update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3460"/>
+ <source>Ignore update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3465"/>
+ <source>Rename Mod...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3466"/>
+ <source>Reinstall Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3467"/>
+ <source>Remove Mod...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3474"/>
+ <source>Un-Endorse</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3477"/>
+ <location filename="mainwindow.cpp" line="3481"/>
+ <source>Endorse</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3478"/>
+ <source>Won&apos;t endorse</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3484"/>
+ <source>Endorsement state unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3495"/>
+ <source>Ignore missing data</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3499"/>
+ <source>Mark as converted/working</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3503"/>
+ <source>Visit on Nexus</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3505"/>
+ <source>Visit web page</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3512"/>
+ <source>Information...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3519"/>
+ <location filename="mainwindow.cpp" line="4646"/>
+ <source>Exception: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3521"/>
+ <location filename="mainwindow.cpp" line="4648"/>
+ <source>Unknown exception</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3552"/>
+ <source>&lt;All&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3554"/>
+ <source>&lt;Multiple&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3589"/>
+ <source>%1 more</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <location filename="mainwindow.cpp" line="3593"/>
+ <source>Are you sure you want to remove the following %n save(s)?&lt;br&gt;&lt;ul&gt;%1&lt;/ul&gt;&lt;br&gt;Removed saves will be sent to the Recycle Bin.</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3638"/>
+ <source>Enable Mods...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <location filename="mainwindow.cpp" line="3653"/>
+ <source>Delete %n save(s)</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3695"/>
+ <source>failed to remove %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3717"/>
+ <source>failed to create %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3759"/>
+ <source>Can&apos;t change download directory while downloads are in progress!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3880"/>
+ <source>failed to write to file %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3886"/>
+ <source>%1 written</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3927"/>
+ <source>Select binary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3927"/>
+ <source>Binary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3953"/>
+ <source>Enter Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3954"/>
+ <source>Please enter a name for the executable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3968"/>
+ <source>Not an executable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3968"/>
+ <source>This is not a recognized executable.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3993"/>
+ <location filename="mainwindow.cpp" line="4018"/>
+ <source>Replace file?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3993"/>
+ <source>There already is a hidden version of this file. Replace it?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3996"/>
+ <location filename="mainwindow.cpp" line="4021"/>
+ <source>File operation failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="3996"/>
+ <location filename="mainwindow.cpp" line="4021"/>
+ <source>Failed to remove &quot;%1&quot;. Maybe you lack the required file permissions?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4018"/>
+ <source>There already is a visible version of this file. Replace it?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4065"/>
+ <source>file not found: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4078"/>
+ <source>failed to generate preview for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4092"/>
+ <source>Sorry, can&apos;t preview anything. This function currently does not support extracting from bsas.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4126"/>
+ <source>Update available</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4163"/>
+ <source>Open/Execute</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4164"/>
+ <source>Add as Executable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4168"/>
+ <source>Preview</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4174"/>
+ <source>Un-Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4176"/>
+ <source>Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4182"/>
+ <source>Write To File...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4203"/>
+ <source>Do you want to endorse Mod Organizer on %1 now?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4322"/>
+ <source>Thank you!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4322"/>
+ <source>Thank you for your endorsement!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4357"/>
+ <source>Request to Nexus failed: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4372"/>
+ <location filename="mainwindow.cpp" line="4434"/>
+ <source>failed to read %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4384"/>
+ <location filename="mainwindow.cpp" line="4833"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4384"/>
+ <source>failed to extract %1 (errorcode %2)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4416"/>
+ <source>Extract BSA</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4445"/>
+ <source>This archive contains invalid hashes. Some files may be broken.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4491"/>
+ <source>Extract...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4514"/>
+ <source>This will restart MO, continue?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4554"/>
+ <source>Edit Categories...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4555"/>
+ <source>Deselect filter</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4606"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4617"/>
+ <source>Enable all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4618"/>
+ <source>Disable all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4637"/>
+ <source>Unlock load order</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4640"/>
+ <source>Lock load order</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4782"/>
+ <source>depends on missing &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4786"/>
+ <source>incompatible with &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4812"/>
+ <source>Please wait while LOOT is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4906"/>
+ <source>loot failed. Exit code was: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4928"/>
+ <source>failed to start loot</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4931"/>
+ <source>failed to run loot: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4935"/>
+ <source>Errors occured</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4982"/>
+ <source>Backup of load order created</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="4992"/>
+ <source>Choose backup to restore</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5005"/>
+ <source>No Backups</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5005"/>
+ <source>There are no backups to restore</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5026"/>
+ <location filename="mainwindow.cpp" line="5048"/>
+ <source>Restore failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5027"/>
+ <location filename="mainwindow.cpp" line="5049"/>
+ <source>Failed to restore the backup. Errorcode: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5038"/>
+ <source>Backup of modlist created</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5144"/>
+ <source>A file with the same name has already been downloaded. What would you like to do?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5146"/>
+ <source>Overwrite</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5147"/>
+ <source>Rename new file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="5148"/>
+ <source>Ignore file</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MessageDialog</name>
+ <message>
+ <location filename="messagedialog.ui" line="150"/>
+ <location filename="messagedialog.ui" line="180"/>
+ <source>Placeholder</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModInfo</name>
+ <message>
+ <location filename="modinfo.cpp" line="95"/>
+ <source>Plugins</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="96"/>
+ <source>Textures</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="97"/>
+ <source>Meshes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="98"/>
+ <source>Bethesda Archive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="99"/>
+ <source>UI Changes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="100"/>
+ <source>Sound Effects</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="101"/>
+ <source>Scripts</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="102"/>
+ <source>Script Extender</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="103"/>
+ <source>SkyProc Tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="104"/>
+ <source>MCM Data</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="105"/>
+ <source>invalid content type %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="128"/>
+ <source>invalid mod index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfo.cpp" line="158"/>
+ <source>remove: invalid mod index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModInfoBackup</name>
+ <message>
+ <location filename="modinfobackup.cpp" line="13"/>
+ <source>This is the backup of a mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModInfoDialog</name>
+ <message>
+ <location filename="modinfodialog.ui" line="14"/>
+ <source>Mod Info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="30"/>
+ <source>Textfiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="42"/>
+ <source>A list of text-files in the mod directory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="45"/>
+ <source>A list of text-files in the mod directory like readmes. </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="67"/>
+ <location filename="modinfodialog.ui" line="181"/>
+ <source>Save</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="77"/>
+ <source>INI-Files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="91"/>
+ <source>Ini Files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="104"/>
+ <source>This is a list of .ini files in the mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="107"/>
+ <source>This is a list of .ini files in the mod. These are usually used to configure the behaviour of mods if there are configurable parameters.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="117"/>
+ <source>Ini Tweaks *This feature is non-functional*</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="136"/>
+ <source>This is a list of ini tweaks (ini modifications that can be toggled).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="139"/>
+ <source>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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="175"/>
+ <source>Save changes to the file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="178"/>
+ <source>Save changes to the file. This overwrites the original. There is no automatic backup!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="191"/>
+ <source>Images</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="246"/>
+ <source>Images located in the mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="249"/>
+ <source>This lists all the images (.jpg and .png) in the mod directory, like screenshots and such. Click one to get a larger view.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="282"/>
+ <location filename="modinfodialog.ui" line="301"/>
+ <source>Optional ESPs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="288"/>
+ <source>List of esps, esms, and esls that can not be loaded by the game.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="291"/>
+ <source>List of esps, esms, and esls contained in this plugin that currently can not be loaded by the game. They will not even appear in the esp-list in the main MO-window.
+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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="316"/>
+ <source>Make the selected mod in the lower list unavailable.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="319"/>
+ <source>The selected esp (in the lower list) will be pushed into a subdirectory of the mod and will thus become &quot;invisible&quot; to the game. It can then no longer be activated.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="345"/>
+ <source>Move a file to the data directory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="348"/>
+ <source>This moves a esp to the esp directory so it can be enabled in the main window. Please note that the ESP merely becomes &quot;available&quot;, it will not necessarily be loaded! That is configured in the main window of omo.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="383"/>
+ <source>ESPs in the data directory and thus visible to the game.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="386"/>
+ <source>These are the mod files that are in the (virtual) data directory of your game and will thus be selecteable in the esp list in the main window.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="393"/>
+ <source>Available ESPs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="401"/>
+ <source>Conflicts</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="409"/>
+ <source>The following conflicted files are provided by this mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="459"/>
+ <location filename="modinfodialog.ui" line="515"/>
+ <source>File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="464"/>
+ <source>Overwritten Mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="474"/>
+ <source>The following conflicted files are provided by other mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="520"/>
+ <source>Providing Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="530"/>
+ <source>Non-Conflicted files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="550"/>
+ <source>Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="573"/>
+ <source>Primary Category</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="590"/>
+ <source>Nexus Info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="598"/>
+ <source>Mod ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="605"/>
+ <source>Mod ID for this mod on Nexus.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="608"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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: &lt;a href=&quot; https://www.nexusmods.com/skyrimspecialedition/mods/6194&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.nexusmods.com/skyrimspecialedition/mods/6194&lt;/span&gt;&lt;/a&gt;. In this example, 6194 is the id you&apos;re looking for. Besides: The above is the link to Mod Organizer2 on Nexus. Why not go there now and endorse us?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="635"/>
+ <source>Source Game</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="642"/>
+ <source>Source game for this mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="645"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Source game for this mod. This determines where the mod was downloaded from and decides where to fetch info, version updates, and send endorsements. Changing this will likely require you to enter a new Mod ID.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="665"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="672"/>
+ <source>Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="702"/>
+ <source>Refresh</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="705"/>
+ <source>Refresh all information from Nexus.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="719"/>
+ <source>Description</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="729"/>
+ <source>about:blank</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="755"/>
+ <source>Endorse</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="769"/>
+ <source>Notes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="779"/>
+ <source>Filetree</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="793"/>
+ <source>Open Mod in Explorer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="818"/>
+ <source>A directory view of this mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="821"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This is a modifiable directory view of the mod directory. You can move around files using drag &amp;amp; drop and rename them (double click).&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Changes happen immediately on disc, so do&lt;/span&gt;&lt;span style=&quot; font-size:8pt; font-weight:600;&quot;&gt; be careful&lt;/span&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="848"/>
+ <source>Previous</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="855"/>
+ <source>Next</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.ui" line="875"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="211"/>
+ <source>&amp;Delete</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="212"/>
+ <source>&amp;Rename</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="213"/>
+ <source>&amp;Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="214"/>
+ <source>&amp;Unhide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="215"/>
+ <source>&amp;Open</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="216"/>
+ <source>&amp;New Folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="468"/>
+ <location filename="modinfodialog.cpp" line="483"/>
+ <source>Save changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="468"/>
+ <location filename="modinfodialog.cpp" line="483"/>
+ <source>Save changes to &quot;%1&quot;?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="673"/>
+ <source>File Exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="673"/>
+ <source>A file with that name exists, please enter a new one</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="690"/>
+ <source>failed to move file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="715"/>
+ <source>failed to create directory &quot;optional&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="759"/>
+ <location filename="modinfodialog.cpp" line="1483"/>
+ <source>Info requested, please wait</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="813"/>
+ <source>Main</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="814"/>
+ <source>Update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="815"/>
+ <source>Optional</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="816"/>
+ <source>Old</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="817"/>
+ <source>Misc</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="818"/>
+ <source>Unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="829"/>
+ <source>Current Version: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="833"/>
+ <source>No update available</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="876"/>
+ <source>(description incomplete, please visit nexus)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="891"/>
+ <source>&lt;a href=&quot;%1&quot;&gt;Visit on Nexus&lt;/a&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="984"/>
+ <source>Failed to delete %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1000"/>
+ <location filename="modinfodialog.cpp" line="1006"/>
+ <location filename="modinfodialog.cpp" line="1025"/>
+ <location filename="modinfodialog.cpp" line="1030"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1000"/>
+ <location filename="modinfodialog.cpp" line="1025"/>
+ <source>Are sure you want to delete &quot;%1&quot;?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1006"/>
+ <location filename="modinfodialog.cpp" line="1030"/>
+ <source>Are sure you want to delete the selected files?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1104"/>
+ <location filename="modinfodialog.cpp" line="1110"/>
+ <source>New Folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1116"/>
+ <source>Failed to create &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1220"/>
+ <location filename="modinfodialog.cpp" line="1244"/>
+ <source>Replace file?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1220"/>
+ <source>There already is a hidden version of this file. Replace it?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1223"/>
+ <location filename="modinfodialog.cpp" line="1247"/>
+ <source>File operation failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1223"/>
+ <location filename="modinfodialog.cpp" line="1247"/>
+ <source>Failed to remove &quot;%1&quot;. Maybe you lack the required file permissions?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1234"/>
+ <location filename="modinfodialog.cpp" line="1257"/>
+ <source>failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1244"/>
+ <source>There already is a visible version of this file. Replace it?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1320"/>
+ <source>Select binary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1320"/>
+ <source>Binary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1392"/>
+ <source>file not found: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1405"/>
+ <source>failed to generate preview for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1421"/>
+ <source>Sorry</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1421"/>
+ <source>Sorry, can&apos;t preview anything. This function currently does not support extracting from bsas.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1435"/>
+ <source>Un-Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1437"/>
+ <source>Hide</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1440"/>
+ <location filename="modinfodialog.cpp" line="1460"/>
+ <source>Open/Execute</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1444"/>
+ <location filename="modinfodialog.cpp" line="1464"/>
+ <source>Preview</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1512"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1512"/>
+ <source>Please enter a name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1516"/>
+ <location filename="modinfodialog.cpp" line="1519"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1516"/>
+ <source>Invalid name. Must be a valid file name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1519"/>
+ <source>A tweak by that name exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfodialog.cpp" line="1533"/>
+ <source>Create Tweak</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModInfoForeign</name>
+ <message>
+ <location filename="modinfoforeign.cpp" line="47"/>
+ <source>This pseudo mod represents content managed outside MO. It isn&apos;t modified by MO.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfoforeign.cpp" line="61"/>
+ <source>DLC: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfoforeign.cpp" line="64"/>
+ <source>Creation Club: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinfoforeign.cpp" line="67"/>
+ <source>Unmanaged: </source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModInfoOverwrite</name>
+ <message>
+ <location filename="modinfooverwrite.cpp" line="48"/>
+ <source>This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit)</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModInfoRegular</name>
+ <message>
+ <location filename="modinforegular.cpp" line="171"/>
+ <location filename="modinforegular.cpp" line="174"/>
+ <source>failed to write %1/meta.ini: error %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinforegular.cpp" line="516"/>
+ <source>%1 contains no esp/esm/esl and no asset (textures, meshes, interface, ...) directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modinforegular.cpp" line="520"/>
+ <source>Categories: &lt;br&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModList</name>
+ <message>
+ <location filename="modlist.cpp" line="66"/>
+ <source>Game Plugins (ESP/ESM/ESL)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="67"/>
+ <source>Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="68"/>
+ <source>Meshes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="69"/>
+ <source>Bethesda Archive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="70"/>
+ <source>Scripts (Papyrus)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="71"/>
+ <source>Script Extender Plugin</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="72"/>
+ <source>SkyProc Patcher</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="73"/>
+ <source>Sound or Music</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="74"/>
+ <source>Textures</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="75"/>
+ <source>MCM Configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="136"/>
+ <source>This entry contains files that have been created inside the virtual data tree (i.e. by the construction kit)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="145"/>
+ <source>Backup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="146"/>
+ <source>No valid game data</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="147"/>
+ <source>Not endorsed yet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="149"/>
+ <source>Overwrites files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="150"/>
+ <source>Overwritten files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="151"/>
+ <source>Overwrites &amp; Overwritten</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="152"/>
+ <source>Redundant</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="153"/>
+ <source>Alternate game source</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="239"/>
+ <source>Non-MO</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="269"/>
+ <source>invalid</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="398"/>
+ <source>installed version: &quot;%1&quot;, newest version: &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="400"/>
+ <source>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 &quot;upgrade&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="408"/>
+ <source>Categories: &lt;br&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="437"/>
+ <source>Invalid name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="442"/>
+ <source>Name is already in use by another mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="937"/>
+ <source>drag&amp;drop failed: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1007"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1008"/>
+ <source>Are you sure you want to remove &quot;%1&quot;?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1071"/>
+ <source>Flags</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1072"/>
+ <source>Content</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1073"/>
+ <source>Mod Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1074"/>
+ <source>Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1075"/>
+ <source>Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1076"/>
+ <source>Category</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1077"/>
+ <source>Source Game</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1078"/>
+ <source>Nexus ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1079"/>
+ <source>Installation</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1080"/>
+ <location filename="modlist.cpp" line="1112"/>
+ <source>unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1088"/>
+ <source>Name of your mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1089"/>
+ <source>Version of the mod (if available)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1090"/>
+ <source>Installation priority of your mod. The higher, the more &quot;important&quot; it is and thus overwrites files from mods with lower priority.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1092"/>
+ <source>Category of the mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1093"/>
+ <source>The source game which was the origin of this mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1094"/>
+ <source>Id of the mod as used on Nexus.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1095"/>
+ <source>Emblemes to highlight things that might require attention.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1096"/>
+ <source>Depicts the content of the mod:&lt;br&gt;&lt;table cellspacing=7&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/plugin&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Game plugins (esp/esm/esl)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/interface&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Interface&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/mesh&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Meshes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/bsa&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;BSA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/texture&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Textures&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/sound&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Sounds&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/music&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Music&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/string&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Strings&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/script&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Scripts (Papyrus)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/skse&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Script Extender plugins&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/skyproc&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;SkyProc Patcher&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;:/MO/gui/content/menu&quot; width=32/&gt;&lt;/td&gt;&lt;td&gt;Mod Configuration Menu&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="modlist.cpp" line="1111"/>
+ <source>Time this mod was installed</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ModListSortProxy</name>
+ <message>
+ <location filename="modlistsortproxy.cpp" line="383"/>
+ <source>Drag&amp;Drop is only supported when sorting by priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MotDDialog</name>
+ <message>
+ <location filename="motddialog.ui" line="14"/>
+ <source>Message of the Day</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="motddialog.ui" line="42"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MyFileSystemModel</name>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="48"/>
+ <source>Overwrites</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="60"/>
+ <source>not implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>NXMAccessManager</name>
+ <message>
+ <location filename="nxmaccessmanager.cpp" line="177"/>
+ <source>Verifying Nexus login</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="nxmaccessmanager.cpp" line="254"/>
+ <source>Logging into Nexus</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="nxmaccessmanager.cpp" line="277"/>
+ <source>timeout</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="nxmaccessmanager.cpp" line="297"/>
+ <source>Unknown error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="nxmaccessmanager.cpp" line="333"/>
+ <source>Please check your password</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>NXMUrl</name>
+ <message>
+ <location filename="../../uibase/src/nxmurl.cpp" line="30"/>
+ <source>invalid nxm-link: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>NexusInterface</name>
+ <message>
+ <location filename="nexusinterface.cpp" line="212"/>
+ <source>Failed to guess mod id for &quot;%1&quot;, please pick the correct one</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="nexusinterface.cpp" line="546"/>
+ <source>empty response</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="nexusinterface.cpp" line="575"/>
+ <source>invalid response</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>OrganizerCore</name>
+ <message>
+ <location filename="organizercore.cpp" line="332"/>
+ <location filename="organizercore.cpp" line="359"/>
+ <source>Failed to write settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="333"/>
+ <source>An error occured trying to update MO settings to %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="354"/>
+ <source>File is write protected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="356"/>
+ <source>Invalid file format (probably a bug)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="357"/>
+ <source>Unknown error %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="360"/>
+ <source>An error occured trying to write back MO settings to %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="613"/>
+ <location filename="organizercore.cpp" line="624"/>
+ <source>Download started</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="627"/>
+ <source>Download failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="884"/>
+ <location filename="organizercore.cpp" line="942"/>
+ <source>Installation successful</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="892"/>
+ <location filename="organizercore.cpp" line="952"/>
+ <source>Configure Mod</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="893"/>
+ <location filename="organizercore.cpp" line="953"/>
+ <source>This mod contains ini tweaks. Do you want to configure them now?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="905"/>
+ <location filename="organizercore.cpp" line="963"/>
+ <source>mod &quot;%1&quot; not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="908"/>
+ <location filename="organizercore.cpp" line="970"/>
+ <source>Installation cancelled</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="909"/>
+ <location filename="organizercore.cpp" line="971"/>
+ <source>The mod was not installed completely.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1173"/>
+ <source>Executable &quot;%1&quot; not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1199"/>
+ <source>Start Steam?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1200"/>
+ <source>Steam is required to be running already to correctly start the game. Should MO try to start steam now?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1223"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1306"/>
+ <source>No profile set</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1592"/>
+ <source>Failed to refresh list of esps: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1676"/>
+ <source>Multiple esps/esls activated, please check that they don&apos;t conflict.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1751"/>
+ <source>Download?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1752"/>
+ <source>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?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1886"/>
+ <source>failed to update mod list: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1893"/>
+ <location filename="organizercore.cpp" line="1910"/>
+ <source>login successful</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1917"/>
+ <source>Login failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1918"/>
+ <source>Login failed, try again?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1927"/>
+ <source>login failed: %1. Download will not be associated with an account</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1935"/>
+ <source>login failed: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1945"/>
+ <source>login failed: %1. You need to log-in with Nexus to update MO.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="1998"/>
+ <source>MO1 &quot;Script Extender&quot; load mechanism has left hook.dll in your game folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="2001"/>
+ <location filename="organizercore.cpp" line="2017"/>
+ <source>Description missing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="2010"/>
+ <source>&lt;a href=&quot;%1&quot;&gt;hook.dll&lt;/a&gt; has been found in your game folder (right click to copy the full path). This is most likely a leftover of setting the ModOrganizer 1 load mechanism to &quot;Script Extender&quot;, in which case you must remove this file either by changing the load mechanism in ModOrganizer 1 or manually removing the file, otherwise the game is likely to crash and burn.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="2044"/>
+ <source>failed to save load order: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="2116"/>
+ <source>The designated write target &quot;%1&quot; is not enabled.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>OverwriteInfoDialog</name>
+ <message>
+ <location filename="overwriteinfodialog.ui" line="14"/>
+ <source>Overwrite</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.ui" line="42"/>
+ <source>You can use drag&amp;drop to move files and directories to regular mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="89"/>
+ <source>&amp;Delete</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="90"/>
+ <source>&amp;Rename</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="91"/>
+ <source>&amp;Open</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="92"/>
+ <source>&amp;New Folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="113"/>
+ <source>%1 not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="148"/>
+ <source>Failed to delete &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="164"/>
+ <location filename="overwriteinfodialog.cpp" line="170"/>
+ <location filename="overwriteinfodialog.cpp" line="189"/>
+ <location filename="overwriteinfodialog.cpp" line="194"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="164"/>
+ <location filename="overwriteinfodialog.cpp" line="189"/>
+ <source>Are sure you want to delete &quot;%1&quot;?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="170"/>
+ <location filename="overwriteinfodialog.cpp" line="194"/>
+ <source>Are sure you want to delete the selected files?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="244"/>
+ <location filename="overwriteinfodialog.cpp" line="250"/>
+ <source>New Folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="overwriteinfodialog.cpp" line="256"/>
+ <source>Failed to create &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>PluginContainer</name>
+ <message>
+ <location filename="plugincontainer.cpp" line="326"/>
+ <source>Some plugins could not be loaded</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="plugincontainer.cpp" line="329"/>
+ <location filename="plugincontainer.cpp" line="347"/>
+ <source>Description missing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="plugincontainer.cpp" line="338"/>
+ <source>The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>PluginList</name>
+ <message>
+ <location filename="pluginlist.cpp" line="92"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="93"/>
+ <source>Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="94"/>
+ <source>Mod Index</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="95"/>
+ <source>Flags</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="96"/>
+ <location filename="pluginlist.cpp" line="108"/>
+ <source>unknown</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="104"/>
+ <source>Name of your mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="105"/>
+ <source>Load priority of your mod. The higher, the more &quot;important&quot; it is and thus overwrites data from plugins with lower priority.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="107"/>
+ <source>The modindex determines the formids of objects originating from this mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="197"/>
+ <source>failed to update esp info for file %1 (source id: %2), error: %3</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="270"/>
+ <source>esp not found: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="277"/>
+ <location filename="pluginlist.cpp" line="289"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="277"/>
+ <source>Really enable all plugins?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="289"/>
+ <source>Really disable all plugins?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="379"/>
+ <source>The file containing locked plugin indices is broken</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="870"/>
+ <location filename="pluginlist.cpp" line="874"/>
+ <source>&lt;b&gt;Origin&lt;/b&gt;: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="871"/>
+ <source>&lt;br&gt;&lt;b&gt;&lt;i&gt;This plugin can&apos;t be disabled (enforced by the game).&lt;/i&gt;&lt;/b&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="876"/>
+ <source>Author</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="879"/>
+ <source>Description</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="882"/>
+ <source>Missing Masters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="889"/>
+ <source>Enabled Masters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="892"/>
+ <source>There is an ini file connected to this esp. Its settings will be added to your game settings, overwriting in case of conflicts.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="896"/>
+ <source>This ESP is flagged as an ESL. It will adhere to the ESP load order but the records will be loaded in ESL space.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="1067"/>
+ <source>failed to restore load order for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>PluginListSortProxy</name>
+ <message>
+ <location filename="pluginlistsortproxy.cpp" line="120"/>
+ <source>Drag&amp;Drop is only supported when sorting by priority or mod index</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>PreviewDialog</name>
+ <message>
+ <location filename="previewdialog.ui" line="14"/>
+ <source>Preview</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="previewdialog.ui" line="78"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ProblemsDialog</name>
+ <message>
+ <location filename="problemsdialog.ui" line="14"/>
+ <source>Problems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="problemsdialog.ui" line="49"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-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:7.8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="problemsdialog.ui" line="75"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="problemsdialog.cpp" line="42"/>
+ <location filename="problemsdialog.cpp" line="43"/>
+ <source>Fix</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="problemsdialog.cpp" line="49"/>
+ <source>No guided fix</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>Profile</name>
+ <message>
+ <location filename="profile.cpp" line="81"/>
+ <source>invalid profile name %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="85"/>
+ <source>failed to create %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="211"/>
+ <source>failed to write mod list: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="222"/>
+ <source>failed to update tweaked ini file, wrong settings may be used: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="242"/>
+ <source>failed to create tweaked ini: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="267"/>
+ <source>failed to open %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="326"/>
+ <source>&quot;%1&quot; is missing or inaccessible</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="371"/>
+ <location filename="profile.cpp" line="410"/>
+ <location filename="profile.cpp" line="512"/>
+ <location filename="profile.cpp" line="531"/>
+ <location filename="profile.cpp" line="541"/>
+ <source>invalid index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="493"/>
+ <source>Overwrite directory couldn&apos;t be parsed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="502"/>
+ <source>invalid priority %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="725"/>
+ <source>Delete savegames?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profile.cpp" line="726"/>
+ <source>Do you want to delete local savegames? (If you select &quot;No&quot;, the save games will show up again if you re-enable local savegames)</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ProfileInputDialog</name>
+ <message>
+ <location filename="profileinputdialog.ui" line="14"/>
+ <source>Dialog</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profileinputdialog.ui" line="20"/>
+ <source>Please enter a name for the new profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profileinputdialog.ui" line="30"/>
+ <source>If checked, the new profile will use the default game settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profileinputdialog.ui" line="33"/>
+ <source>If checked, the new profile will use the default game settings instead of the &quot;global&quot; settings. Global settings are the settings you configure when running the game launcher directly, without MO.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profileinputdialog.ui" line="36"/>
+ <source>Default Game Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ProfilesDialog</name>
+ <message>
+ <location filename="profilesdialog.ui" line="14"/>
+ <source>Profiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="22"/>
+ <source>List of Profiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="25"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note&lt;/span&gt; For technical reasons it&apos;s currently not possible to have seperate load-orders for esps. This means you can&apos;t load moda.esp before modb.esp in one profile and the other way around in another.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="38"/>
+ <location filename="profilesdialog.ui" line="41"/>
+ <source>If checked, savegames are local to this profile and will not appear when starting with a different profile.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="44"/>
+ <source>Local Savegames</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="51"/>
+ <source>Local Game Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="61"/>
+ <source>This ensures data files from mods are actually used. You want to enable this unless you use a different tool for Archive Invalidation.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="64"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;The Mod Organizer uses a workaround called &amp;quot;BSA redirection&amp;quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-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;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;With Skyrim this bug seems to be fixed to a degree but whether a mod becomes active still depends on file dates. Therefore, it still makes sense to activate this.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="74"/>
+ <source>Automatic Archive Invalidation</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="85"/>
+ <location filename="profilesdialog.ui" line="88"/>
+ <source>Create a new profile from scratch</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="91"/>
+ <source>Create</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="101"/>
+ <source>Clone the selected profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="104"/>
+ <source>This creates a new profile with the same settings and active mods as the selected one.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="107"/>
+ <source>Copy</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="117"/>
+ <location filename="profilesdialog.ui" line="120"/>
+ <source>Delete the selected Profile. This can not be un-done!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="123"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="133"/>
+ <source>Rename</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="143"/>
+ <location filename="profilesdialog.ui" line="146"/>
+ <source>Transfer save games to the selected profile.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="149"/>
+ <source>Transfer Saves</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.ui" line="172"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="75"/>
+ <source>Archive invalidation isn&apos;t required for this game.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="113"/>
+ <location filename="profilesdialog.cpp" line="154"/>
+ <source>failed to create profile: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="163"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="163"/>
+ <source>Please enter a name for the new profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="174"/>
+ <source>failed to copy profile: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="177"/>
+ <source>Invalid name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="178"/>
+ <source>Invalid profile name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="185"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="185"/>
+ <source>Are you sure you want to remove this profile (including local savegames if any)?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="194"/>
+ <source>Profile broken</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="195"/>
+ <source>This profile you&apos;re about to delete seems to be broken or the path is invalid. I&apos;m about to delete the following folder: &quot;%1&quot;. Proceed?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="227"/>
+ <source>Rename Profile</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="227"/>
+ <source>New Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="262"/>
+ <source>failed to change archive invalidation state: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="296"/>
+ <source>failed to determine if invalidation is active: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../../uibase/src/report.cpp" line="34"/>
+ <location filename="../../uibase/src/report.cpp" line="37"/>
+ <location filename="main.cpp" line="98"/>
+ <location filename="organizercore.cpp" line="651"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/safewritefile.cpp" line="33"/>
+ <source>failed to open temporary file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/utility.cpp" line="86"/>
+ <source>removal of &quot;%1&quot; failed: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/utility.cpp" line="93"/>
+ <source>removal of &quot;%1&quot; failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/utility.cpp" line="97"/>
+ <source>&quot;%1&quot; doesn&apos;t exist (remove)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/utility.cpp" line="278"/>
+ <location filename="../../uibase/src/utility.cpp" line="303"/>
+ <source>failed to create directory &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/utility.cpp" line="287"/>
+ <location filename="../../uibase/src/utility.cpp" line="310"/>
+ <source>failed to copy &quot;%1&quot; to &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categories.cpp" line="149"/>
+ <source>Failed to save custom categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categories.cpp" line="271"/>
+ <location filename="categories.cpp" line="306"/>
+ <location filename="categories.cpp" line="316"/>
+ <location filename="categories.cpp" line="326"/>
+ <source>invalid index %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="categories.cpp" line="337"/>
+ <source>invalid category id %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="70"/>
+ <source>invalid field name &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="76"/>
+ <source>invalid type for &quot;%1&quot; (should be integer)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="81"/>
+ <source>invalid type for &quot;%1&quot; (should be string)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="86"/>
+ <source>invalid type for &quot;%1&quot; (should be float)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="103"/>
+ <source>no fields set up yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="140"/>
+ <source>field not set &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="237"/>
+ <source>invalid character in field &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="csvbuilder.cpp" line="240"/>
+ <source>empty field name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="gameinfoimpl.cpp" line="43"/>
+ <source>invalid game type %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="helper.cpp" line="55"/>
+ <source>helper failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="helper.cpp" line="71"/>
+ <source>failed to determine account name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="73"/>
+ <location filename="selfupdater.cpp" line="81"/>
+ <source>invalid 7-zip32.dll: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="installationmanager.cpp" line="87"/>
+ <source>archive.dll not loaded: &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="81"/>
+ <source>Deleting folder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="82"/>
+ <source>I&apos;m about to delete the following folder: &quot;%1&quot;. Proceed?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="103"/>
+ <source>Choose Instance to Delete</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="104"/>
+ <source>Be Carefull! Deleting an Instance will remove all your files for that Instance (mods, downloads, profiles, configuration, ...). Custom paths outside of the instance folder for downloads, mods, etc. will be left untoched.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="117"/>
+ <source>Are you sure?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="118"/>
+ <source>Are you really sure you want to delete the Instance &quot;%1&quot; with all its files?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="122"/>
+ <source>Failed to delete Instance</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="123"/>
+ <source>Could not delete Instance &quot;%1&quot;.
+If the folder was still in use, restart MO and try again.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="137"/>
+ <source>Enter a Name for the new Instance</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="138"/>
+ <source>Enter a new name or select one from the sugested list (only letters and numbers allowed):</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="147"/>
+ <location filename="instancemanager.cpp" line="208"/>
+ <source>Canceled</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="159"/>
+ <source>The instance &quot;%1&quot; already exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="160"/>
+ <source>Please choose a different instance name, like: &quot;%1 1&quot; .</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="179"/>
+ <source>Choose Instance</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="180"/>
+ <source>Each Instance is a full set of MO data files (mods, downloads, profiles, configuration, ...). You can use multiple instances for different games. Instances are stored in Appdata and can be accessed by all MO installations. If your MO folder is writable, you can also store a single instance locally (called a Portable install, and all the MO data files will be inside the installation folder).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="192"/>
+ <source>New</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="193"/>
+ <source>Create a new instance.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="197"/>
+ <source>Portable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="198"/>
+ <source>Use MO folder for data.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="202"/>
+ <source>Manage Instances</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="203"/>
+ <source>Delete an Instance.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="254"/>
+ <location filename="profile.cpp" line="66"/>
+ <source>failed to create %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="257"/>
+ <source>Data directory created</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="instancemanager.cpp" line="258"/>
+ <source>New data directory created at %1. If you don&apos;t want to store a lot of data there, reconfigure the storage directories via settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="52"/>
+ <source>failed to open %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="103"/>
+ <location filename="loadmechanism.cpp" line="112"/>
+ <source>%1 not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="129"/>
+ <location filename="loadmechanism.cpp" line="196"/>
+ <source>game doesn&apos;t support a script extender</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="149"/>
+ <source>Failed to delete %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="156"/>
+ <source>Failed to deactivate script extender loading</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="176"/>
+ <source>Failed to remove %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="178"/>
+ <location filename="loadmechanism.cpp" line="283"/>
+ <source>Failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="185"/>
+ <source>Failed to deactivate proxy-dll loading</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="233"/>
+ <location filename="loadmechanism.cpp" line="267"/>
+ <location filename="loadmechanism.cpp" line="286"/>
+ <source>Failed to copy %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="239"/>
+ <source>Failed to set up script extender loading</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="264"/>
+ <source>Failed to delete old proxy-dll %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="279"/>
+ <source>Failed to overwrite %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="loadmechanism.cpp" line="291"/>
+ <source>Failed to set up proxy-dll loading</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="99"/>
+ <location filename="organizercore.cpp" line="652"/>
+ <source>Failed to create &quot;%1&quot;. Your user account probably lacks permission.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="296"/>
+ <source>Plugin to handle %1 no longer installed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="353"/>
+ <source>Could not use configuration settings for game &quot;%1&quot;, path &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="357"/>
+ <location filename="main.cpp" line="375"/>
+ <source>Please select the game to manage</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="385"/>
+ <source>No game identified in &quot;%1&quot;. The directory is required to contain the game binary and its launcher.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="541"/>
+ <source>Please select the game edition you have (MO can&apos;t start the game correctly if this is set incorrectly!)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="578"/>
+ <source>failed to start shortcut: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="600"/>
+ <source>failed to start application: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="686"/>
+ <location filename="settings.cpp" line="967"/>
+ <source>Mod Organizer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="687"/>
+ <source>An instance of Mod Organizer is already running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.cpp" line="702"/>
+ <source>Failed to set up instance</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="861"/>
+ <source>Please use &quot;Help&quot; from the toolbar to get usage instructions to all elements</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1263"/>
+ <location filename="mainwindow.cpp" line="3837"/>
+ <source>&lt;Manage...&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="mainwindow.cpp" line="1275"/>
+ <source>failed to parse profile %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="170"/>
+ <source>Failed to start &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="173"/>
+ <source>Waiting</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="organizercore.cpp" line="174"/>
+ <source>Please press OK once you&apos;re logged into steam.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="plugincontainer.cpp" line="173"/>
+ <source>failed to initialize plugin %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="plugincontainer.cpp" line="259"/>
+ <source>Plugin error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="plugincontainer.cpp" line="260"/>
+ <source>It appears the plugin &quot;%1&quot; 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)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="455"/>
+ <source>failed to access %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="pluginlist.cpp" line="469"/>
+ <source>failed to set file time %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="profilesdialog.cpp" line="94"/>
+ <source>Before you can use ModOrganizer, you need to create at least one profile. ATTENTION: Run the game at least once before creating a profile!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settings.cpp" line="974"/>
+ <source>Script Extender</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settings.cpp" line="981"/>
+ <source>Proxy DLL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="spawn.cpp" line="143"/>
+ <source>failed to spawn &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="spawn.cpp" line="150"/>
+ <source>Elevation required</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="spawn.cpp" line="151"/>
+ <source>This process requires elevation to run.
+This is a potential security risk so I highly advice you to investigate if
+&quot;%1&quot;
+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)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="spawn.cpp" line="166"/>
+ <source>failed to spawn &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QueryOverwriteDialog</name>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="14"/>
+ <source>Mod Exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="45"/>
+ <source>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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="63"/>
+ <source>Keep Backup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="70"/>
+ <source>Merge</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="77"/>
+ <source>Replace</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="84"/>
+ <source>Rename</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="queryoverwritedialog.ui" line="91"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QuestionBoxMemory</name>
+ <message>
+ <location filename="../../uibase/src/questionboxmemory.ui" line="88"/>
+ <source>Remember selection</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/questionboxmemory.ui" line="95"/>
+ <source>Remember selection only for</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SaveTextAsDialog</name>
+ <message>
+ <location filename="savetextasdialog.ui" line="14"/>
+ <source>Dialog</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="savetextasdialog.ui" line="32"/>
+ <source>Copy To Clipboard</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="savetextasdialog.ui" line="39"/>
+ <source>Save As...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="savetextasdialog.ui" line="59"/>
+ <source>Close</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="savetextasdialog.cpp" line="40"/>
+ <source>Save CSV</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="savetextasdialog.cpp" line="40"/>
+ <source>Text Files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="savetextasdialog.cpp" line="44"/>
+ <source>failed to open &quot;%1&quot; for writing</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SelectionDialog</name>
+ <message>
+ <location filename="selectiondialog.ui" line="14"/>
+ <source>Select</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selectiondialog.ui" line="23"/>
+ <source>Placeholder</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selectiondialog.ui" line="77"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SelfUpdater</name>
+ <message>
+ <location filename="selfupdater.cpp" line="95"/>
+ <source>archive.dll not loaded: &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="178"/>
+ <source>New update available (%1)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="179"/>
+ <source>Do you want to install update? All your mods and setup will be left untouched.
+Select Show Details option to see the full change-log.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="183"/>
+ <source>Install</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="200"/>
+ <source>Download failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="201"/>
+ <source>Failed to find correct download, please try again later.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="216"/>
+ <source>Update</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="217"/>
+ <source>Download in progress</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="308"/>
+ <source>Download failed: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="319"/>
+ <source>Failed to install update: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="342"/>
+ <source>Failed to start %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="selfupdater.cpp" line="352"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>Settings</name>
+ <message>
+ <location filename="settings.cpp" line="143"/>
+ <source>Failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settings.cpp" line="144"/>
+ <source>Sorry, failed to start the helper application</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settings.cpp" line="435"/>
+ <location filename="settings.cpp" line="454"/>
+ <source>attempt to store setting for unknown plugin &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settings.cpp" line="757"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settings.cpp" line="758"/>
+ <source>Failed to create &quot;%1&quot;, you may not have the necessary permission. path remains unchanged.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SettingsDialog</name>
+ <message>
+ <location filename="settingsdialog.ui" line="14"/>
+ <source>Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="24"/>
+ <source>General</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="32"/>
+ <source>Language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="39"/>
+ <source>The display language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="42"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;The display language. This will only displaye languages for which you have a translation installed.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="57"/>
+ <source>Style</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="64"/>
+ <source>graphical style</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="67"/>
+ <source>graphical style of the MO user interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="76"/>
+ <source>Update to non-stable releases.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="79"/>
+ <source>If this is enabled, the integrated update mechanism will notify of all releases, including pre-releases (alphas, betas).
+
+Please use this only if you&apos;re sufficiently tech-savvy to investigate issues, look for known problems in the issue tracker and create meaningful reports.
+
+If you use pre-releases, never contact me directly by e-mail or via private messages!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="86"/>
+ <source>Install Pre-releases (Betas)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="93"/>
+ <source>User interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="99"/>
+ <source>If checked, the download interface will be more compact.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="102"/>
+ <source>Compact Download Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="109"/>
+ <source>If checked, the download list will display meta information instead of file names.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="112"/>
+ <source>Download Meta Information</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="125"/>
+ <source>Reset stored information from dialogs.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="128"/>
+ <source>This will make all dialogs show up again where you checked the &quot;Remember selection&quot;-box.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="131"/>
+ <source>Reset Dialogs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="151"/>
+ <location filename="settingsdialog.ui" line="154"/>
+ <source>Modify the categories available to arrange your mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="157"/>
+ <source>Configure Mod Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="168"/>
+ <source>Paths</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="176"/>
+ <source>Base Directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="183"/>
+ <location filename="settingsdialog.ui" line="196"/>
+ <location filename="settingsdialog.ui" line="281"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="203"/>
+ <source>Overwrite</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="210"/>
+ <source>Caches</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="227"/>
+ <source>Downloads</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="241"/>
+ <source>Directory where mods are stored.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="244"/>
+ <source>Directory where mods are stored. Please note that changing this will break all associations of profiles with mods that don&apos;t exist in the new location (with the same name).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="264"/>
+ <location filename="settingsdialog.ui" line="267"/>
+ <source>Directory where downloads are stored.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="274"/>
+ <source>Mods</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="291"/>
+ <source>Profiles</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="313"/>
+ <source>Use %BASE_DIR% to refer to the Base Directory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="333"/>
+ <source>Important: All directories have to be writeable!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="341"/>
+ <location filename="settingsdialog.ui" line="357"/>
+ <source>Nexus</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="347"/>
+ <source>Allows automatic log-in when the Nexus-Page for the game is clicked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="350"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;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&apos;re worried someone might steal your password, don&apos;t store it here.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="366"/>
+ <source>If checked and if correct credentials are entered below, log-in to Nexus (for browsing and downloading) is automatic.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="369"/>
+ <source>Automatically Log-In to Nexus</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="378"/>
+ <location filename="settingsdialog.ui" line="564"/>
+ <source>Username</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="392"/>
+ <location filename="settingsdialog.ui" line="574"/>
+ <source>Password</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="413"/>
+ <source>Remove cache and cookies. Forces a new login.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="416"/>
+ <source>Clear Cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="445"/>
+ <source>Disable automatic internet features</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="448"/>
+ <source>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)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="451"/>
+ <source>Offline Mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="458"/>
+ <source>Use a proxy for network connections.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="461"/>
+ <source>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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="464"/>
+ <source>Use HTTP Proxy (Uses System Settings)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="473"/>
+ <source>Associate with &quot;Download with manager&quot; links</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="502"/>
+ <source>Known Servers (updated on download)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="523"/>
+ <source>Preferred Servers (Drag &amp; Drop)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="558"/>
+ <source>Steam</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="604"/>
+ <source>If you save your steam user ID and password here, they will be used when logging into steam. Note, however, your password will be stored unencrypted, so make sure your computer is secure.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="631"/>
+ <source>Plugins</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="653"/>
+ <source>Author:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="667"/>
+ <source>Version:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="681"/>
+ <source>Description:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="719"/>
+ <source>Key</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="724"/>
+ <source>Value</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="736"/>
+ <source>Blacklisted Plugins (use &lt;del&gt; to remove):</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="747"/>
+ <source>Workarounds</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="755"/>
+ <source>Steam App ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="775"/>
+ <source>The Steam AppID for your game</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="778"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &amp;quot;Mod Organizer&amp;quot; load mechanism may not work properly.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;The preset for this is the App ID of the &amp;quot;regular&amp;quot; version so in most cases, you should be set.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;If you think you have a different version (GotY or something), follow these steps to get to the id:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;1. Navigate to the game library in steam&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;2. right-click on the game you need the id for and choose &lt;/span&gt;&lt;span style=&quot; font-size:8pt; font-weight:600;&quot;&gt;Create desktop shortcut&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;3. right-click on the newly created shortcut on your desktop and select &lt;/span&gt;&lt;span style=&quot; font-size:8pt; font-weight:600;&quot;&gt;Properties&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;4. in the URL-field you should see something like this: &lt;/span&gt;&lt;span style=&quot; font-size:8pt; font-style:italic;&quot;&gt;steam://rungameid/22380&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;22380 is the id you&apos;re looking for.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="809"/>
+ <source>Load Mechanism</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="829"/>
+ <source>Select loading mechanism. See help for details.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="832"/>
+ <source>Mod Organizer needs a dll to be injected into the game so all mods are visible to it.
+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&apos;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&apos;t work.
+
+If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use &quot;Script Extender&quot; 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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="849"/>
+ <source>NMM Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="869"/>
+ <source>The Version of Nexus Mod Manager to impersonate.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="872"/>
+ <source>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&apos;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&apos;s not lying about what it is. It is merely adding a &quot;compatible&quot; NMM version to the user agent.
+
+tl;dr-version: If Nexus-features don&apos;t work, insert the current version number of NMM here and try again.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="897"/>
+ <source>Enforces that inactive ESPs and ESMs are never loaded.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="900"/>
+ <source>It seems that the Games occasionally load ESP or ESM files even if they haven&apos;t been activated as plugins.
+I don&apos;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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="904"/>
+ <source>Hide inactive ESPs/ESMs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="911"/>
+ <source>If checked, files (i.e. esps, esms and bsas) belonging to the core game can not be disabled in the UI. (default: on)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="914"/>
+ <source>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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="918"/>
+ <source>Force-enable game files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="928"/>
+ <source>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.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="931"/>
+ <source>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&apos;t be resolved correctly.
+
+If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps, esms, and esls) displayed in the right pane are completely unaffected by this feature.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="937"/>
+ <source>Display mods installed outside MO</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="947"/>
+ <location filename="settingsdialog.ui" line="951"/>
+ <source>For Skyrim, this can be used instead of Archive Invalidation. It should make AI redundant for all Profiles.
+For the other games this is not a sufficient replacement for AI!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="955"/>
+ <source>Back-date BSAs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="979"/>
+ <source>These are workarounds for problems with Mod Organizer. Please make sure you read the help text before changing anything here.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="990"/>
+ <source>Diagnostics</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="998"/>
+ <source>Log Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1005"/>
+ <source>Decides the amount of data printed to &quot;ModOrganizer.log&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1008"/>
+ <source>
+ Decides the amount of data printed to &quot;ModOrganizer.log&quot;.
+ &quot;Debug&quot; 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 &quot;Info&quot; level for regluar use. On the &quot;Error&quot; level the log file usually remains empty.
+ </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1015"/>
+ <source>Debug</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1020"/>
+ <source>Info (recommended)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1025"/>
+ <source>Warning</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1030"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1055"/>
+ <source>Crash Dumps</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1062"/>
+ <source>Decides which type of crash dumps are collected when injected processes crash.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1065"/>
+ <source>
+ Decides which type of crash dumps are collected when injected processes crash.
+ &quot;None&quot; Disables the generation of crash dumps by MO.
+ &quot;Mini&quot; Default level which generates small dumps (only stack traces).
+ &quot;Data&quot; Much larger dumps with additional information which may be need (also data segments).
+ &quot;Full&quot; Even larger dumps with a full memory dump of the process.
+ </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1075"/>
+ <source>None</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1080"/>
+ <source>Mini (recommended)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1085"/>
+ <source>Data</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1090"/>
+ <source>Full</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1102"/>
+ <source>Max Dumps To Keep</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1122"/>
+ <source>Maximum number of crash dumps to keep on disk. Use 0 for unlimited.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1125"/>
+ <source>
+ Maximum number of crash dumps to keep on disk. Use 0 for unlimited.
+ Set &quot;Crash Dumps&quot; above to None to disable crash dump collection.
+ </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1137"/>
+ <source>
+ Logs and crash dumps are stored under your current instance in the &lt;a href=&quot;LOGS_FULL_PATH&quot;&gt;LOGS_DIR&lt;/a&gt;
+ and &lt;a href=&quot;DUMPS_FULL_PATH&quot;&gt;DUMPS_DIR&lt;/a&gt; folders.
+ Sending logs and/or crash dumps to the developers can help investigate issues.
+ It is recommended to compress large log and dmp files before sending.
+ </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.ui" line="1148"/>
+ <source>Hint: right click link and copy link location</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="70"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="71"/>
+ <source>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?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="119"/>
+ <source>Select base directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="130"/>
+ <source>Select download directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="141"/>
+ <source>Select mod directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="152"/>
+ <source>Select cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="163"/>
+ <source>Select profiles directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="174"/>
+ <source>Select overwrite directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="182"/>
+ <source>Confirm?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="settingsdialog.cpp" line="183"/>
+ <source>This will make all dialogs show up again where you checked the &quot;Remember selection&quot;-box. Continue?</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SimpleInstallDialog</name>
+ <message>
+ <location filename="simpleinstalldialog.ui" line="14"/>
+ <source>Quick Install</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="simpleinstalldialog.ui" line="22"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="simpleinstalldialog.ui" line="49"/>
+ <location filename="simpleinstalldialog.ui" line="52"/>
+ <source>Opens a Dialog that allows custom modifications.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="simpleinstalldialog.ui" line="55"/>
+ <source>Manual</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="simpleinstalldialog.ui" line="62"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="simpleinstalldialog.ui" line="72"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SingleInstance</name>
+ <message>
+ <location filename="singleinstance.cpp" line="51"/>
+ <source>SHM error: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="singleinstance.cpp" line="85"/>
+ <source>failed to connect to running instance: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="singleinstance.cpp" line="91"/>
+ <source>failed to communicate with running instance: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="singleinstance.cpp" line="103"/>
+ <source>failed to receive data from secondary instance: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SyncOverwriteDialog</name>
+ <message>
+ <location filename="syncoverwritedialog.ui" line="14"/>
+ <source>Sync Overwrite</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="syncoverwritedialog.ui" line="27"/>
+ <source>Name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="syncoverwritedialog.ui" line="32"/>
+ <source>Sync To</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="syncoverwritedialog.cpp" line="96"/>
+ <source>&lt;don&apos;t sync&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="syncoverwritedialog.cpp" line="148"/>
+ <source>failed to remove %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="syncoverwritedialog.cpp" line="150"/>
+ <source>failed to move %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TextViewer</name>
+ <message>
+ <location filename="../../uibase/src/textviewer.ui" line="14"/>
+ <source>Log Viewer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../uibase/src/textviewer.ui" line="20"/>
+ <source>Placeholder</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TransferSavesDialog</name>
+ <message>
+ <location filename="transfersavesdialog.ui" line="14"/>
+ <source>Transfer Savegames</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="22"/>
+ <source>Global Characters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="29"/>
+ <source>This is a list of characters in the global location.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="32"/>
+ <source>This is a list of characters in the global location.
+
+On Windows Vista/Windows 7:
+ C:\Users\[UserName]\Documents\My Games\Skyrim\Saves
+
+On Windows XP:
+ C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="46"/>
+ <source>This is a list of save games for the selected character in the global location.
+
+On Windows Vista/Windows 7:
+ C:\Users\[UserName]\Documents\My Games\Skyrim\Saves
+
+On Windows XP:
+ C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves
+
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="87"/>
+ <source>Move -&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="97"/>
+ <source>Copy -&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="123"/>
+ <source>&lt;- Move</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="133"/>
+ <source>&lt;- Copy</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="156"/>
+ <source>Done</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.ui" line="167"/>
+ <source>Profile Characters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.cpp" line="119"/>
+ <source>Characters for profile %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.cpp" line="159"/>
+ <source>Overwrite</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.cpp" line="160"/>
+ <source>Overwrite the file &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="transfersavesdialog.cpp" line="319"/>
+ <source>Confirm</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UsvfsConnector</name>
+ <message>
+ <location filename="usvfsconnector.cpp" line="157"/>
+ <source>Preparing vfs</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>WaitingOnCloseDialog</name>
+ <message>
+ <location filename="waitingonclosedialog.ui" line="14"/>
+ <source>Waiting for virtualized processes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="waitingonclosedialog.ui" line="20"/>
+ <source>This dialog should disappear automatically if the application/game is done.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="waitingonclosedialog.ui" line="23"/>
+ <source>Virtualized processes are still running, it is prefered to keep MO running until they are finished.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="waitingonclosedialog.ui" line="77"/>
+ <source>Close Now</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="waitingonclosedialog.ui" line="97"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_conflictresolution_main</name>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="5"/>
+ <source>There are multiple types of conflicts you may encounter when dealing with Mods. This tutorial will try to cover and explain how to deal with all of them.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="10"/>
+ <source>First up are file conflicts. These occur when two mods contain the same file. Most commonly this happens when several mods replace the same standard asset from the game, like the texture of an armor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="16"/>
+ <source>As an example, say you install &quot;ModA&quot; which contains stylish new iron and leather armor. Then you install &quot;ModB&quot; which contains sexy ebony and leather armor. Obviously there is a conflict now: which leather armor to use?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="22"/>
+ <source>If you were to install the mods manually, when installing &quot;ModB&quot; you would be asked if you want to overwrite conflicting files. If you choose yes, you get the leather armor from &quot;ModB&quot; otherwise you keep the one from &quot;ModA&quot;. If you later decide you made the wrong choice, you have to reinstall one of the mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="29"/>
+ <source>With MO, both ModA and ModB get installed completely (no overwrite dialog) and by default &quot;ModB&quot; gets to provide the leather armor because it&apos;s automatically assigned the higher priority.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="34"/>
+ <source>However, you can change the mod priority at any time using drag&amp;drop on this list. If you assign &quot;ModA&quot; a higher priority, it provides the leather armor, no re-installation required. Since the priorities of mods in this list are treated as if the mods were installed in that order, I tend to talk about &quot;installation order&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="42"/>
+ <source>If the &quot;Flags&quot;-column is enabled in the mod list, it will show you which mods are involved in a conflict and how...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="47"/>
+ <source>&lt;img src=&quot;qrc:///MO/gui/emblem_conflict_overwrite&quot; /&gt; indicates that the mod overwrites files that are also available in another mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="51"/>
+ <source>&lt;img src=&quot;qrc:///MO/gui/emblem_conflict_overwritten&quot; /&gt; indicates that the mod is &lt;b&gt;partially&lt;/b&gt; overwritten by another.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="55"/>
+ <source>&lt;img src=&quot;qrc:///MO/gui/emblem_conflict_mixed&quot; /&gt; indicates that both of the above is true.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="59"/>
+ <source>&lt;img src=&quot;qrc:///MO/gui/emblem_conflict_redundant&quot; /&gt; indicates that the mod is completely overwrtten by another. You could as well disable it.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="63"/>
+ <source>There are two ways to see the individual files involved in a conflict:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="67"/>
+ <source>Option A: Switch to the &quot;Data&quot;-tab if necessary</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="76"/>
+ <source>... here, if you mark the highlighted control, the tree will only display files in conflict. In the right column, it says which mod currently provides the mod (because it has highest priority) and if you hover your mouse over that info, it will list which other mods contains it.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="83"/>
+ <source>Option B: Open the &lt;i&gt;Information&lt;/i&gt;-Dialog of an &lt;b&gt;enabled&lt;/b&gt; mod you&apos;re interested in by either double-clicking it or selecting &lt;i&gt;Information...&lt;/i&gt; from the right-click menu</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="91"/>
+ <source>This was everything to know about file conflicts. The second type of conflict we have to deal with are &quot;record conflicts&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="96"/>
+ <source>I told you in the &quot;First Steps&quot; tutorial how the esp/esm/esl plugins contain changes to the game world like modifications to the terrain or existing NPCs. Each change like this is stored in a record, hence the name &quot;record conflict&quot;. For example when two mods try to change the same location, only one change can become active.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="102"/>
+ <source>As with file conflicts you can&apos;t really fix these conflicts, you have to choose which change you want. This time around however, if you choose wrong, your game may become unstable because there may be dependencies between the records of a mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="108"/>
+ <source>Please open the &quot;Plugins&quot;-tab...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="115"/>
+ <source>Again you can use drag&amp;drop to change priorities of plugins, thus deciding which plugin takes precedence in regards to conflicts. This is commonly called the &quot;load order&quot;. But how do you know how to order the plugins?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="122"/>
+ <source>Unlike with file conflicts, MO does not provide help on finding conflicts. The good news is, there already is a perfect tool for that called LOOT. LOOT is available on the Nexus and integrates neatly with MO. Basically, if you don&apos;t have LOOT yet, install it once this tutorial is over.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="128"/>
+ <source>After you installed LOOT in the default location (follow its instructions), start MO again and LOOT should automatically appear as an Executable...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="133"/>
+ <source>When you run LOOT, it will automatically re-organize plugins for best compatibility (overwriting your manual changes). It will also open a report in your browser that warns about incompatibilities. You should read the report, at least for new mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="140"/>
+ <source>The final type of conflicts are also &quot;record conflicts&quot;. Like the previous type. It&apos;s confusing, so I&apos;ll just call them &quot;lists conflicts&quot; instead. The difference is the types of records in conflict. The ones in question here can be merged so you may be able to get all modifications in your game.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="146"/>
+ <source>One common example of such records are leveled lists that contain all the items that may spawn at a specific character level. Traditionally, if multiple mods add items to such a list, only one is in effect...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="151"/>
+ <source>... but there are tools to merge those mods so you can have the effects of all of them. Again, this functionality is not integrated with MO because there are already great tools. For Oblivion and Skyrim look for wrye bash, for fallout 3/nv it&apos;s wrye flash. For Skyrim there is also &quot;SkyBash&quot;. All of these can create a so-called &quot;bashed patch&quot; which is a plugin that contains the combined mergeable records from all your mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_main.js" line="159"/>
+ <source>This completes the tutorial.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_conflictresolution_modinfo</name>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_modinfo.js" line="4"/>
+ <source>Please switch to the &quot;Conflicts&quot;-Tab.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_modinfo.js" line="11"/>
+ <source>Here you can see a list of files in this mod that out-prioritize others in a file conflict and one with files where this mod is overridden.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_conflictresolution_modinfo.js" line="16"/>
+ <source>Please close the information dialog again.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_firststeps_browser</name>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_browser.js" line="5"/>
+ <source>This is a fully featured browser that is set up to open the correct nexus page for your game. You can download any mod using the &quot;DOWNLOAD WITH MANAGER&quot;-button or the &quot;manual&quot;-link and it will be downloaded by MO.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_firststeps_main</name>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="6"/>
+ <source>Welcome to the ModOrganizer Tutorial! This will guide you through the most common features of MO.
+Please go along with the tutorial because some things can&apos;t be demonstrated if you skip something.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="12"/>
+ <source>Before we continue with the step-by-step tutorial, I&apos;d like to tell you about the other ways you can receive help on ModOrganizer.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="17"/>
+ <source>The highlighted button provides hints on solving problems MO recognized automatically.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="19"/>
+ <source>
+There IS a problem now but you may want to hold off on fixing it until after completing the tutorial.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="29"/>
+ <source>This button provides multiple sources of information and further tutorials.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="39"/>
+ <source>Finally there are tooltips on almost every part of Mod Organizer. If there is a control in MO you don&apos;t understand, please try hovering over it to get a short description or use &quot;Help on UI&quot; from the help menu to get a longer explanation</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="46"/>
+ <source>This list displays all mods installed through MO. It also displays installed DLCs and some mods installed outside MO but you have limited control over those in MO.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="53"/>
+ <source>Before we start installing mods, let&apos;s have a quick look at the settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="65"/>
+ <source>Now it&apos;s time to install a few mods!Please go along with this because we need a few mods installed to demonstrate other features</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="71"/>
+ <source>There are a few ways to get mods into ModOrganizer. If you associated MO with NXM links in the settings you can now use your regular browser to send downloads from Nexus to MO. Click on &quot;Nexus&quot; to open nexus, find a mod and click the green download buttons on Nexus saying &quot;Download with Manager&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="83"/>
+ <source>You can also install mods from disk using the &quot;Install Mod&quot; button.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="89"/>
+ <source>Downloads will appear on the &quot;Downloads&quot;-tab here. You have to download and install at least one mod to proceed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="97"/>
+ <source>Great, you just installed your first mod. Please note that the installation procedure may differ based on how a mod was packaged.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="103"/>
+ <source>Now you know all about downloading and installing mods but they are not enabled yet...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="108"/>
+ <source>Install a few more mods if you want, then enable mods by checking them in the left pane. Mods that aren&apos;t enabled have no effect on the game whatsoever. </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="117"/>
+ <source>For some mods, enabling it on the left pane is all you have to do...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="122"/>
+ <source>...but most contain plugins. These are plugins for the game and are required to add stuff to the game (new weapons, armors, quests, areas, ...). Please open the &quot;Plugins&quot;-tab to get a list of plugins.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="133"/>
+ <source>You will notice some plugins are grayed out. These are part of the main game and can&apos;t be disabled.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="139"/>
+ <source>A single mod may contain zero, one or multiple esps. Some or all may be optional. If in doubt, please consult the documentation of the indiviual mod. To do so, right-click the mod and select &quot;Information&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="148"/>
+ <source>Now you know how to download, install and enable mods.
+It&apos;s important you always start the game from inside MO, otherwise the mods you installed here won&apos;t work.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="156"/>
+ <source>This combobox lets you choose &lt;i&gt;what&lt;/i&gt; to start. This way you can start the game, Launcher, Script Extender, the Creation Kit or other tools. If you miss a tool you can also configure this list but that is an advanced topic.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_main.js" line="164"/>
+ <source>This completes the basic tutorial. As homework go play a bit! After you have installed more mods you may want to read the tutorial on conflict resolution.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_firststeps_modinfo</name>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_modinfo.js" line="5"/>
+ <source>This dialog tries to expose as much information about a mod as possible. Depending on the mod this may include readmes, screenshots, optional plugins and so on. If a certain type of information was not found in a mod, the corresponding tab is grayed out.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_modinfo.js" line="13"/>
+ <source>If you installed the mod from Nexus, the corresponding tab should give you direct access to the mod page.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_modinfo.js" line="19"/>
+ <source>We may re-visit this screen in later tutorials.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_firststeps_settings</name>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_settings.js" line="6"/>
+ <source>You can use your regular browser to download from Nexus.
+Please open the &quot;Nexus&quot;-tab</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_settings.js" line="12"/>
+ <source>Click this button so that &quot;DOWNLOAD WITH MANAGER&quot;-buttons are download with Mod Organizer.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_firststeps_settings.js" line="19"/>
+ <source>You can also store your Nexus-credentials here for automatic login. The password is stored unencrypted on your disk!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_primer_main</name>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="71"/>
+ <source>This window shows all the mods that are installed. The column headers can be used for sorting. Only checked mods are active in the current profile.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="72"/>
+ <source>Each profile is a separate set of enabled mods and ini settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="73"/>
+ <source>The dropdown allows various ways of grouping the mods shown in the mod list.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="74"/>
+ <source>Show/hide the category pane.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="75"/>
+ <source>Quickly filter the mod list as you type.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="76"/>
+ <source>Switch between information views.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="77"/>
+ <source>This shows mod categories and some meta categories (in angle-brackets). Select some to filter the mod list. For example select &quot;&lt;Checked&gt;&quot; to show only active mods.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="78"/>
+ <source>Customizable list for choosing the program to run.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="79"/>
+ <source>When this button is clicked, Mod Organizer creates a virtual directory structure then runs the program selected to the left.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="80"/>
+ <source>Will create a shortcut for quick access. The shortcut can be placed in the toolbar at the top, in the Start Menu or on the Windows Desktop.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="81"/>
+ <source>Log messages produced by MO. Please note that messages with a light bulb usually don&apos;t require your attention.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="83"/>
+ <source>Configure Mod Organizer.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="84"/>
+ <source>Reports potential Problems about the current setup.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="85"/>
+ <source>Activates if there is an update for MO. Please note that if, for any reason, MO can&apos;t communicate with NMM, this will not work either.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="89"/>
+ <source>Plugins (esp/esm/esl files) of the mods in the current profile. They need to be checked to be loaded.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="90"/>
+ <source>Automatically sort plugins using the bundled LOOT application.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="91"/>
+ <source>Quickly filter plugin list as you type.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="97"/>
+ <source>The directory tree and all files that the program will see.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="100"/>
+ <source>Save game browser. Shows all the saves for the current profile and whether or not the current mod-load status is correct.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="103"/>
+ <source>Shows the mods that have been downloaded and if they’ve been installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_primer_main.js" line="111"/>
+ <source>Click to quit</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>tutorial_window_installer</name>
+ <message>
+ <location filename="tutorials/tutorial_window_installer.js" line="6"/>
+ <source>This mod has been packaged in a way that Mod Organizer did not automatically recognize...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_window_installer.js" line="11"/>
+ <source>You can use drag&amp;drop on this list to fix the structure of the mod.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_window_installer.js" line="16"/>
+ <source>The correct structure replicates the data-directory of the game. That means esps, the &quot;meshes&quot;- or &quot;textures&quot;-directory and so on should be directly below &quot;&lt;data&gt;&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_window_installer.js" line="22"/>
+ <source>You can also disable files and directories that you don&apos;t want to unpack.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_window_installer.js" line="26"/>
+ <source>From the context menu (right-click) you can open textfiles, in case you want to access a readme.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="tutorials/tutorial_window_installer.js" line="31"/>
+ <source>This text will turn green if MO thinks the structure looks good.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 999c7732..35486f98 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -192,15 +192,15 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings)
, m_GameName()
, m_CurrentProfile(nullptr)
, m_Settings(initSettings)
- , m_Updater(NexusInterface::instance())
+ , m_Updater(NexusInterface::instance(m_PluginContainer))
, m_AboutToRun()
, m_FinishedRun()
, m_ModInstalled()
- , m_ModList(this)
+ , m_ModList(m_PluginContainer, this)
, m_PluginList(this)
, m_DirectoryRefresher()
, m_DirectoryStructure(new DirectoryEntry(L"data", nullptr, 0))
- , m_DownloadManager(NexusInterface::instance(), this)
+ , m_DownloadManager(NexusInterface::instance(m_PluginContainer), this)
, m_InstallationManager()
, m_RefresherThread()
, m_AskForNexusPW(false)
@@ -211,8 +211,8 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings)
m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory());
m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers());
- NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory());
- NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion());
+ NexusInterface::instance(m_PluginContainer)->setCacheDirectory(m_Settings.getCacheDirectory());
+ NexusInterface::instance(m_PluginContainer)->setNMMVersion(m_Settings.getNMMVersion());
MOBase::QuestionBoxMemory::init(initSettings.fileName());
@@ -227,9 +227,9 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings)
connect(&m_ModList, SIGNAL(removeOrigin(QString)), this,
SLOT(removeOrigin(QString)));
- connect(NexusInterface::instance()->getAccessManager(),
+ connect(NexusInterface::instance(m_PluginContainer)->getAccessManager(),
SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
- connect(NexusInterface::instance()->getAccessManager(),
+ connect(NexusInterface::instance(m_PluginContainer)->getAccessManager(),
SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
// This seems awfully imperative
@@ -240,9 +240,6 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings)
SLOT(managedGameChanged(MOBase::IPluginGame const *)));
connect(this, SIGNAL(managedGameChanged(MOBase::IPluginGame const *)),
&m_PluginList, SLOT(managedGameChanged(MOBase::IPluginGame const *)));
- connect(this, SIGNAL(managedGameChanged(MOBase::IPluginGame const *)),
- NexusInterface::instance(),
- SLOT(managedGameChanged(MOBase::IPluginGame const *)));
connect(&m_PluginList, &PluginList::writePluginsList, &m_PluginListsWriter,
&DelayedFileWriterBase::write);
@@ -454,7 +451,7 @@ void OrganizerCore::updateExecutablesList(QSettings &settings)
// TODO this has nothing to do with executables list move to an appropriate
// function!
ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure,
- m_Settings.displayForeign(), managedGame());
+ m_PluginContainer, m_Settings.displayForeign(), managedGame());
}
void OrganizerCore::setUserInterface(IUserInterface *userInterface,
@@ -504,6 +501,9 @@ void OrganizerCore::connectPlugins(PluginContainer *container)
m_DownloadManager.setSupportedExtensions(
m_InstallationManager.getSupportedExtensions());
m_PluginContainer = container;
+ m_Updater.setPluginContainer(m_PluginContainer);
+ m_DownloadManager.setPluginContainer(m_PluginContainer);
+ m_ModList.setPluginContainer(m_PluginContainer);
if (!m_GameName.isEmpty()) {
m_GamePlugin = m_PluginContainer->managedGame(m_GameName);
@@ -518,6 +518,9 @@ void OrganizerCore::disconnectPlugins()
m_ModInstalled.disconnect_all_slots();
m_ModList.disconnectSlots();
m_PluginList.disconnectSlots();
+ m_Updater.setPluginContainer(nullptr);
+ m_DownloadManager.setPluginContainer(nullptr);
+ m_ModList.setPluginContainer(nullptr);
m_Settings.clearPlugins();
m_GamePlugin = nullptr;
@@ -540,7 +543,7 @@ Settings &OrganizerCore::settings()
bool OrganizerCore::nexusLogin(bool retry)
{
NXMAccessManager *accessManager
- = NexusInterface::instance()->getAccessManager();
+ = NexusInterface::instance(m_PluginContainer)->getAccessManager();
if ((accessManager->loginAttempted() || accessManager->loggedIn())
&& !retry) {
@@ -612,12 +615,12 @@ void OrganizerCore::externalMessage(const QString &message)
}
}
-void OrganizerCore::downloadRequested(QNetworkReply *reply, int modID,
+void OrganizerCore::downloadRequested(QNetworkReply *reply, QString gameName, int modID,
const QString &fileName)
{
try {
- if (m_DownloadManager.addDownload(reply, QStringList(), fileName, modID, 0,
- new ModRepositoryFileInfo(modID))) {
+ if (m_DownloadManager.addDownload(reply, QStringList(), fileName, gameName, modID, 0,
+ new ModRepositoryFileInfo(gameName, modID))) {
MessageDialog::showMessage(tr("Download started"), qApp->activeWindow());
}
} catch (const std::exception &e) {
@@ -739,7 +742,7 @@ void OrganizerCore::setCurrentProfile(const QString &profileName)
MOBase::IModRepositoryBridge *OrganizerCore::createNexusBridge() const
{
- return new NexusBridge();
+ return new NexusBridge(m_PluginContainer);
}
QString OrganizerCore::profileName() const
@@ -786,6 +789,15 @@ MOBase::IModInterface *OrganizerCore::getMod(const QString &name) const
return index == UINT_MAX ? nullptr : ModInfo::getByIndex(index).data();
}
+MOBase::IPluginGame *OrganizerCore::getGame(const QString &name) const
+{
+ for (IPluginGame *game : m_PluginContainer->plugins<IPluginGame>()) {
+ if (game->gameShortName().compare(name, Qt::CaseInsensitive) == 0)
+ return game;
+ }
+ return nullptr;
+}
+
MOBase::IModInterface *OrganizerCore::createMod(GuessedValue<QString> &name)
{
bool merge = false;
@@ -813,7 +825,7 @@ MOBase::IModInterface *OrganizerCore::createMod(GuessedValue<QString> &name)
settingsFile.endArray();
}
- return ModInfo::createFrom(QDir(targetDirectory), &m_DirectoryStructure)
+ return ModInfo::createFrom(m_PluginContainer, m_GamePlugin, QDir(targetDirectory), &m_DirectoryStructure)
.data();
}
@@ -913,13 +925,14 @@ void OrganizerCore::installDownload(int index)
{
try {
QString fileName = m_DownloadManager.getFilePath(index);
+ QString gameName = m_DownloadManager.getGameName(index);
int modID = m_DownloadManager.getModID(index);
int fileID = m_DownloadManager.getFileInfo(index)->fileID;
GuessedValue<QString> modName;
// see if there already are mods with the specified mod id
if (modID != 0) {
- std::vector<ModInfo::Ptr> modInfo = ModInfo::getByModID(modID);
+ std::vector<ModInfo::Ptr> modInfo = ModInfo::getByModID(gameName, modID);
for (auto iter = modInfo.begin(); iter != modInfo.end(); ++iter) {
std::vector<ModInfo::EFlag> flags = (*iter)->getFlags();
if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP)
@@ -1232,12 +1245,19 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary,
if (virtualizedCwd || virtualizedBin) {
if (virtualizedCwd) {
int cwdOffset = cwdPath.indexOf('/', modsPath.length() + 1);
- cwdPath = m_GamePlugin->dataDirectory().absolutePath() + cwdPath.mid(cwdOffset, -1);
+ QString adjustedCwd = cwdPath.mid(cwdOffset, -1);
+ cwdPath = m_GamePlugin->dataDirectory().absolutePath();
+ if (cwdOffset >= 0)
+ cwdPath += adjustedCwd;
+
}
if (virtualizedBin) {
int binOffset = binPath.indexOf('/', modsPath.length() + 1);
- binPath = m_GamePlugin->dataDirectory().absolutePath() + binPath.mid(binOffset, -1);
+ QString adjustedBin = binPath.mid(binOffset, -1);
+ binPath = m_GamePlugin->dataDirectory().absolutePath();
+ if (binOffset >= 0)
+ binPath += adjustedBin;
}
QString cmdline
@@ -1552,7 +1572,7 @@ void OrganizerCore::refreshModList(bool saveChanges)
m_CurrentProfile->writeModlistNow(true);
}
ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure,
- m_Settings.displayForeign(), managedGame());
+ m_PluginContainer, m_Settings.displayForeign(), managedGame());
m_CurrentProfile->refreshModStatus();
@@ -1719,8 +1739,13 @@ void OrganizerCore::requestDownload(const QUrl &url, QNetworkReply *reply)
// no mod found that could handle the download. Is it a nexus mod?
if (url.host() == "www.nexusmods.com") {
+ QString gameName = "";
int modID = 0;
int fileID = 0;
+ QRegExp nameExp("www\.nexusmods\.com/(\\a+)/");
+ if (nameExp.indexIn(url.toString()) != -1) {
+ gameName = nameExp.cap(1);
+ }
QRegExp modExp("mods/(\\d+)");
if (modExp.indexIn(url.toString()) != -1) {
modID = modExp.cap(1).toInt();
@@ -1730,7 +1755,7 @@ void OrganizerCore::requestDownload(const QUrl &url, QNetworkReply *reply)
fileID = fileExp.cap(1).toInt();
}
m_DownloadManager.addDownload(reply,
- new ModRepositoryFileInfo(modID, fileID));
+ new ModRepositoryFileInfo(gameName, modID, fileID));
} else {
if (QMessageBox::question(qApp->activeWindow(), tr("Download?"),
tr("A download has been started but no installed "
@@ -1827,7 +1852,7 @@ 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(), managedGame());
+ m_PluginContainer, m_Settings.displayForeign(), managedGame());
m_CurrentProfile->refreshModStatus();
refreshModList();
@@ -1885,7 +1910,7 @@ void OrganizerCore::loginSuccessful(bool necessary)
}
m_PostLoginTasks.clear();
- NexusInterface::instance()->loginCompleted();
+ NexusInterface::instance(m_PluginContainer)->loginCompleted();
}
void OrganizerCore::loginSuccessfulUpdate(bool necessary)
@@ -1920,7 +1945,7 @@ void OrganizerCore::loginFailed(const QString &message)
qApp->activeWindow());
m_PostLoginTasks.clear();
}
- NexusInterface::instance()->loginCompleted();
+ NexusInterface::instance(m_PluginContainer)->loginCompleted();
}
void OrganizerCore::loginFailedUpdate(const QString &message)
diff --git a/src/organizercore.h b/src/organizercore.h
index 54d9dd6d..28ecef48 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -184,6 +184,7 @@ public:
QString basePath() const;
MOBase::VersionInfo appVersion() const;
MOBase::IModInterface *getMod(const QString &name) const;
+ MOBase::IPluginGame *getGame(const QString &gameName) const;
MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name);
bool removeMod(MOBase::IModInterface *mod);
void modDataChanged(MOBase::IModInterface *mod);
@@ -285,7 +286,7 @@ private:
private slots:
void directory_refreshed();
- void downloadRequested(QNetworkReply *reply, int modID, const QString &fileName);
+ void downloadRequested(QNetworkReply *reply, QString gameName, int modID, const QString &fileName);
void removeOrigin(const QString &name);
void downloadSpeed(const QString &serverName, int bytesPerSecond);
void loginSuccessful(bool necessary);
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp
index cf2e29e3..8e0bc95b 100644
--- a/src/organizerproxy.cpp
+++ b/src/organizerproxy.cpp
@@ -2,6 +2,7 @@
#include "appconfig.h"
#include "organizercore.h"
+#include "plugincontainer.h"
#include <QApplication>
@@ -9,15 +10,16 @@ using namespace MOBase;
using namespace MOShared;
-OrganizerProxy::OrganizerProxy(OrganizerCore *organizer, const QString &pluginName)
+OrganizerProxy::OrganizerProxy(OrganizerCore *organizer, PluginContainer *pluginContainer, const QString &pluginName)
: m_Proxied(organizer)
+ , m_PluginContainer(pluginContainer)
, m_PluginName(pluginName)
{
}
IModRepositoryBridge *OrganizerProxy::createNexusBridge() const
{
- return new NexusBridge(m_PluginName);
+ return new NexusBridge(m_PluginContainer, m_PluginName);
}
QString OrganizerProxy::profileName() const
@@ -58,6 +60,11 @@ IModInterface *OrganizerProxy::getMod(const QString &name) const
return m_Proxied->getMod(name);
}
+IPluginGame *OrganizerProxy::getGame(const QString &gameName) const
+{
+ return m_Proxied->getGame(gameName);
+}
+
IModInterface *OrganizerProxy::createMod(MOBase::GuessedValue<QString> &name)
{
return m_Proxied->createMod(name);
diff --git a/src/organizerproxy.h b/src/organizerproxy.h
index 7004db14..b8eb9b82 100644
--- a/src/organizerproxy.h
+++ b/src/organizerproxy.h
@@ -5,13 +5,14 @@
#include <imoinfo.h>
class OrganizerCore;
+class PluginContainer;
class OrganizerProxy : public MOBase::IOrganizer
{
public:
- OrganizerProxy(OrganizerCore *organizer, const QString &pluginName);
+ OrganizerProxy(OrganizerCore *organizer, PluginContainer *pluginContainer, const QString &pluginName);
virtual MOBase::IModRepositoryBridge *createNexusBridge() const;
virtual QString profileName() const;
@@ -21,6 +22,7 @@ public:
virtual QString basePath() const;
virtual MOBase::VersionInfo appVersion() const;
virtual MOBase::IModInterface *getMod(const QString &name) const;
+ virtual MOBase::IPluginGame *getGame(const QString &gameName) const;
virtual MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name);
virtual bool removeMod(MOBase::IModInterface *mod);
virtual void modDataChanged(MOBase::IModInterface *mod);
@@ -55,6 +57,7 @@ public:
private:
OrganizerCore *m_Proxied;
+ PluginContainer *m_PluginContainer;
const QString &m_PluginName;
diff --git a/src/overwriteinfodialog.cpp b/src/overwriteinfodialog.cpp
index e956b025..3bb67354 100644
--- a/src/overwriteinfodialog.cpp
+++ b/src/overwriteinfodialog.cpp
@@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "utility.h"
#include <QMessageBox>
#include <QMenu>
+#include <QShortcut>
#include <Shlwapi.h>
@@ -89,6 +90,9 @@ OverwriteInfoDialog::OverwriteInfoDialog(ModInfo::Ptr modInfo, QWidget *parent)
m_RenameAction = new QAction(tr("&Rename"), ui->filesView);
m_OpenAction = new QAction(tr("&Open"), ui->filesView);
m_NewFolderAction = new QAction(tr("&New Folder"), ui->filesView);
+
+ new QShortcut(QKeySequence::Delete, this, SLOT(delete_activated()));
+
QObject::connect(m_DeleteAction, SIGNAL(triggered()), this, SLOT(deleteTriggered()));
QObject::connect(m_RenameAction, SIGNAL(triggered()), this, SLOT(renameTriggered()));
QObject::connect(m_OpenAction, SIGNAL(triggered()), this, SLOT(openTriggered()));
@@ -145,6 +149,36 @@ void OverwriteInfoDialog::deleteFile(const QModelIndex &index)
}
}
+void OverwriteInfoDialog::delete_activated()
+{
+ if (ui->filesView->hasFocus()) {
+ QItemSelectionModel *selection = ui->filesView->selectionModel();
+
+ if (selection->hasSelection() && selection->selectedRows().count() >= 1) {
+
+ if (selection->selectedRows().count() == 0) {
+ return;
+ }
+ else if (selection->selectedRows().count() == 1) {
+ QString fileName = m_FileSystemModel->fileName(selection->selectedRows().at(0));
+ if (QMessageBox::question(this, tr("Confirm"), tr("Are sure you want to delete \"%1\"?").arg(fileName),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return;
+ }
+ }
+ else {
+ if (QMessageBox::question(this, tr("Confirm"), tr("Are sure you want to delete the selected files?"),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return;
+ }
+ }
+
+ foreach(QModelIndex index, selection->selectedRows()) {
+ deleteFile(index);
+ }
+ }
+ }
+}
void OverwriteInfoDialog::deleteTriggered()
{
diff --git a/src/overwriteinfodialog.h b/src/overwriteinfodialog.h
index eb182292..7d44c9e8 100644
--- a/src/overwriteinfodialog.h
+++ b/src/overwriteinfodialog.h
@@ -49,6 +49,8 @@ private:
private slots:
+ void delete_activated();
+
void deleteTriggered();
void renameTriggered();
void openTriggered();
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp
index c980c0a1..8935c472 100644
--- a/src/plugincontainer.cpp
+++ b/src/plugincontainer.cpp
@@ -1,4 +1,5 @@
#include "plugincontainer.h"
+#include "organizercore.h"
#include "organizerproxy.h"
#include "report.h"
#include <ipluginproxy.h>
@@ -53,6 +54,12 @@ QStringList PluginContainer::pluginFileNames() const
for (QPluginLoader *loader : m_PluginLoaders) {
result.append(loader->fileName());
}
+ std::vector<IPluginProxy *> proxyList = bf::at_key<IPluginProxy>(m_Plugins);
+ for (IPluginProxy *proxy : proxyList) {
+ QStringList proxiedPlugins = proxy->pluginList(
+ QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
+ result.append(proxiedPlugins);
+ }
return result;
}
@@ -61,7 +68,7 @@ bool PluginContainer::verifyPlugin(IPlugin *plugin)
{
if (plugin == nullptr) {
return false;
- } else if (!plugin->init(new OrganizerProxy(m_Organizer, plugin->name()))) {
+ } else if (!plugin->init(new OrganizerProxy(m_Organizer, this, plugin->name()))) {
qWarning("plugin failed to initialize");
return false;
}
@@ -148,14 +155,18 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName)
QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
for (const QString &pluginName : pluginNames) {
try {
- QObject *proxiedPlugin = proxy->instantiate(pluginName);
- if (proxiedPlugin != nullptr) {
- if (registerPlugin(proxiedPlugin, pluginName)) {
- qDebug("loaded plugin \"%s\"", qPrintable(QFileInfo(pluginName).fileName()));
- } else {
- qWarning("plugin \"%s\" failed to load. If this plugin is for an older version of MO "
- "you have to update it or delete it if no update exists.",
- qPrintable(pluginName));
+ // we get a list of matching plugins as proxies don't necessarily have a good way of supporting multiple inheritance
+ QList<QObject*> matchingPlugins = proxy->instantiate(pluginName);
+ for (QObject *proxiedPlugin : matchingPlugins) {
+ if (proxiedPlugin != nullptr) {
+ if (registerPlugin(proxiedPlugin, pluginName)) {
+ qDebug("loaded plugin \"%s\"", qPrintable(QFileInfo(pluginName).fileName()));
+ }
+ else {
+ qWarning("plugin \"%s\" failed to load. If this plugin is for an older version of MO "
+ "you have to update it or delete it if no update exists.",
+ qPrintable(pluginName));
+ }
}
}
} catch (const std::exception &e) {
diff --git a/src/plugincontainer.h b/src/plugincontainer.h
index 70392d0b..172dbd09 100644
--- a/src/plugincontainer.h
+++ b/src/plugincontainer.h
@@ -1,9 +1,11 @@
#ifndef PLUGINCONTAINER_H
#define PLUGINCONTAINER_H
-
-#include "organizercore.h"
#include "previewgenerator.h"
+
+class OrganizerCore;
+class IUserInterface;
+
#include <iplugindiagnose.h>
#include <ipluginmodpage.h>
#include <iplugingame.h>
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index bd863f52..a6ae8fa7 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -76,6 +76,7 @@ PluginList::PluginList(QObject *parent)
: QAbstractItemModel(parent)
, m_FontMetrics(QFont())
{
+ connect(this, SIGNAL(writePluginsList()), this, SLOT(generatePluginIndexes()));
}
PluginList::~PluginList()
@@ -485,6 +486,11 @@ int PluginList::enabledCount() const
return enabled;
}
+QString PluginList::getIndexPriority(int index) const
+{
+ return m_ESPs[index].m_Index;
+}
+
bool PluginList::isESPLocked(int index) const
{
return m_LockedOrder.find(m_ESPs.at(index).m_Name.toLower()) != m_LockedOrder.end();
@@ -732,6 +738,29 @@ void PluginList::updateIndices()
m_ESPsByName[m_ESPs[i].m_Name.toLower()] = i;
m_ESPsByPriority.at(static_cast<size_t>(m_ESPs[i].m_Priority)) = i;
}
+
+ generatePluginIndexes();
+}
+
+void PluginList::generatePluginIndexes()
+{
+ int numESLs = 0;
+ int numSkipped = 0;
+ for (int l = 0; l < m_ESPs.size(); ++l) {
+ int i = m_ESPsByPriority.at(l);
+ if (!m_ESPs[i].m_Enabled) {
+ m_ESPs[i].m_Index = QString();
+ ++numSkipped;
+ continue;
+ }
+ if (m_ESPs[i].m_IsLight || m_ESPs[i].m_IsLightFlagged) {
+ int ESLpos = 254 + ((numESLs + 1) / 4096);
+ m_ESPs[i].m_Index = QString("%1:%2").arg(ESLpos, 2, 16, QChar('0')).arg((numESLs) % 4096, 3, 16, QChar('0')).toUpper();
+ ++numESLs;
+ } else {
+ m_ESPs[i].m_Index = QString("%1").arg(l - numESLs - numSkipped, 2, 16, QChar('0')).toUpper();
+ }
+ }
}
@@ -789,25 +818,7 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
return m_ESPs[index].m_Priority;
} break;
case COL_MODINDEX: {
- if (m_ESPs[index].m_LoadOrder == -1) {
- return QString();
- } else {
- int numESLs = 0;
- std::vector<ESPInfo> sortESPs(m_ESPs);
- std::sort(sortESPs.begin(), sortESPs.end());
- for (auto sortedESP: sortESPs) {
- if (sortedESP.m_LoadOrder == m_ESPs[index].m_LoadOrder)
- break;
- if ((sortedESP.m_IsLight || sortedESP.m_IsLightFlagged) && sortedESP.m_LoadOrder != -1)
- ++numESLs;
- }
- if (m_ESPs[index].m_IsLight || m_ESPs[index].m_IsLightFlagged) {
- int ESLpos = 254 + ((numESLs+1) / 4096);
- return QString("%1:%2").arg(ESLpos, 2, 16, QChar('0')).arg((numESLs)%4096).toUpper();
- } else {
- return QString("%1").arg(m_ESPs[index].m_LoadOrder - numESLs, 2, 16, QChar('0')).toUpper();
- }
- }
+ return m_ESPs[index].m_Index;
} break;
default: {
return QVariant();
diff --git a/src/pluginlist.h b/src/pluginlist.h
index f9173810..f6745aa8 100644
--- a/src/pluginlist.h
+++ b/src/pluginlist.h
@@ -194,6 +194,7 @@ public:
QString getName(int index) const { return m_ESPs.at(index).m_Name; }
int getPriority(int index) const { return m_ESPs.at(index).m_Priority; }
+ QString getIndexPriority(int index) const;
bool isESPLocked(int index) const;
void lockESPIndex(int index, bool lock);
@@ -256,6 +257,11 @@ public slots:
*/
void managedGameChanged(MOBase::IPluginGame const *gamePlugin);
+ /**
+ * @brief Generate the plugin indexes because something was changed
+ **/
+ void generatePluginIndexes();
+
signals:
/**
@@ -277,6 +283,7 @@ private:
bool m_Enabled;
bool m_ForceEnabled;
int m_Priority;
+ QString m_Index;
int m_LoadOrder;
FILETIME m_Time;
QString m_OriginName;
diff --git a/src/pluginlistsortproxy.cpp b/src/pluginlistsortproxy.cpp
index 342b3744..e09e64a5 100644
--- a/src/pluginlistsortproxy.cpp
+++ b/src/pluginlistsortproxy.cpp
@@ -100,8 +100,8 @@ bool PluginListSortProxy::lessThan(const QModelIndex &left,
}
} break;
case PluginList::COL_MODINDEX: {
- int leftVal = plugins->isEnabled(left.row()) ? plugins->getPriority(left.row()) : -1;
- int rightVal = plugins->isEnabled(right.row()) ? plugins->getPriority(right.row()) : -1;
+ QString leftVal = plugins->getIndexPriority(left.row());
+ QString rightVal = plugins->getIndexPriority(right.row());
return leftVal < rightVal;
} break;
default: {
diff --git a/src/profile.cpp b/src/profile.cpp
index bbb5b814..7f10bd02 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -753,6 +753,7 @@ bool Profile::enableLocalSettings(bool enable)
QString backupFile = getIniFileName() + "_";
if (enable) {
if (m_Directory.exists(backupFile)) {
+
shellRename(backupFile, getIniFileName());
} else {
IPluginGame *game = qApp->property("managed_game").value<IPluginGame *>();
diff --git a/src/resources.qrc b/src/resources.qrc
index 14c8e533..a18baf45 100644
--- a/src/resources.qrc
+++ b/src/resources.qrc
@@ -77,6 +77,8 @@
<file alias="archive_conflict_mixed">resources/archive-conflict-mixed.png</file>
<file alias="archive_conflict_neutral">resources/archive-conflict-neutral.png</file>
<file alias="archive_conflict_winner">resources/archive-conflict-winner.png</file>
+ <file alias="alternate_game_alt">resources/game-warning.png</file>
+ <file alias="alternate_game">resources/game-warning-16.png</file>
</qresource>
<qresource prefix="/MO/gui/content">
<file alias="plugin">resources/contents/jigsaw-piece.png</file>
diff --git a/src/resources/game-warning-16.png b/src/resources/game-warning-16.png
new file mode 100644
index 00000000..0c421b17
--- /dev/null
+++ b/src/resources/game-warning-16.png
Binary files differ
diff --git a/src/resources/game-warning.png b/src/resources/game-warning.png
new file mode 100644
index 00000000..d54a5a36
--- /dev/null
+++ b/src/resources/game-warning.png
Binary files differ
diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp
index 8f962ba4..d671bafc 100644
--- a/src/selfupdater.cpp
+++ b/src/selfupdater.cpp
@@ -30,6 +30,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "nxmaccessmanager.h"
#include "settings.h"
#include "bbcode.h"
+#include "plugincontainer.h"
#include <versioninfo.h>
#include <report.h>
#include <util.h>
@@ -120,6 +121,11 @@ void SelfUpdater::setUserInterface(QWidget *widget)
m_Parent = widget;
}
+void SelfUpdater::setPluginContainer(PluginContainer *pluginContainer)
+{
+ m_Interface->setPluginContainer(pluginContainer);
+}
+
void SelfUpdater::testForUpdate()
{
// TODO: if prereleases are disabled we could just request the latest release
@@ -170,10 +176,10 @@ void SelfUpdater::startUpdate()
QMessageBox query(QMessageBox::Question,
tr("New update available (%1)")
- .arg(m_UpdateCandidate["tag_name"].toString()),
- BBCode::convertToHTML(m_UpdateCandidate["body"].toString()),
+ .arg(m_UpdateCandidate["tag_name"].toString()), tr("Do you want to install update? All your mods and setup will be left untouched.\nSelect Show Details option to see the full change-log."),
QMessageBox::Yes | QMessageBox::Cancel, m_Parent);
-
+
+ query.setDetailedText(m_UpdateCandidate["body"].toString());
query.button(QMessageBox::Yes)->setText(tr("Install"));
int res = query.exec();
diff --git a/src/selfupdater.h b/src/selfupdater.h
index 4743f6a4..bce49495 100644
--- a/src/selfupdater.h
+++ b/src/selfupdater.h
@@ -26,6 +26,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
class Archive;
class NexusInterface;
+class PluginContainer;
namespace MOBase { class IPluginGame; }
#include <QFile>
@@ -77,6 +78,8 @@ public:
void setUserInterface(QWidget *widget);
+ void setPluginContainer(PluginContainer *pluginContainer);
+
/**
* @brief start the update process
* @note this should not be called if there is no update available
diff --git a/src/settings.cpp b/src/settings.cpp
index d1130e05..2bcf2d02 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -133,7 +133,11 @@ void Settings::registerAsNXMHandler(bool force)
std::wstring nxmPath = ToWString(QCoreApplication::applicationDirPath() + "/nxmhandler.exe");
std::wstring executable = ToWString(QCoreApplication::applicationFilePath());
std::wstring mode = force ? L"forcereg" : L"reg";
- std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString() + L" \"" + executable + L"\"";
+ std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString();
+ for (QString altGame : m_GamePlugin->validShortNames()) {
+ parameters += L"," + altGame.toStdWString();
+ }
+ parameters += L" \"" + executable + L"\"";
HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL);
if ((int)res <= 32) {
QMessageBox::critical(nullptr, tr("Failed"),
@@ -291,7 +295,7 @@ QString Settings::getOverwriteDirectory(bool resolve) const
QString Settings::getNMMVersion() const
{
- static const QString MIN_NMM_VERSION = "0.61.13";
+ static const QString MIN_NMM_VERSION = "0.65.2";
QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString();
if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) {
result = MIN_NMM_VERSION;
@@ -584,9 +588,9 @@ void Settings::resetDialogs()
}
-void Settings::query(QWidget *parent)
+void Settings::query(PluginContainer *pluginContainer, QWidget *parent)
{
- SettingsDialog dialog(parent);
+ SettingsDialog dialog(pluginContainer, parent);
connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs()));
@@ -904,12 +908,16 @@ Settings::PluginsTab::PluginsTab(Settings *m_parent, SettingsDialog &m_dialog)
, m_pluginBlacklistList(m_dialog.findChild<QListWidget *>("pluginBlacklist"))
{
// display plugin settings
+ QSet<QString> handledNames;
for (IPlugin *plugin : m_parent->m_Plugins) {
+ if (handledNames.contains(plugin->name()))
+ continue;
QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), m_pluginsList);
listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin));
listItem->setData(Qt::UserRole + 1, m_parent->m_PluginSettings[plugin->name()]);
listItem->setData(Qt::UserRole + 2, m_parent->m_PluginDescriptions[plugin->name()]);
m_pluginsList->addItem(listItem);
+ handledNames.insert(plugin->name());
}
// display plugin blacklist
diff --git a/src/settings.h b/src/settings.h
index ae38223f..76ab55da 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -51,6 +51,7 @@ namespace MOBase {
}
class SettingsDialog;
+class PluginContainer;
/**
* manages the settings for Mod Organizer. The settings are not cached
@@ -88,7 +89,7 @@ public:
* displays a SettingsDialog that allows the user to change settings. If the
* user accepts the changes, the settings are immediately written
**/
- void query(QWidget *parent);
+ void query(PluginContainer *pluginContainer, QWidget *parent);
/**
* set up the settings for the specified plugins
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index fb9433a6..44fc9b5e 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -27,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "settings.h"
#include "instancemanager.h"
#include "nexusinterface.h"
+#include "plugincontainer.h"
#include <QDirIterator>
#include <QFileDialog>
@@ -40,9 +41,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
-SettingsDialog::SettingsDialog(QWidget *parent)
+SettingsDialog::SettingsDialog(PluginContainer *pluginContainer, QWidget *parent)
: TutorableDialog("SettingsDialog", parent)
, ui(new Ui::SettingsDialog)
+ , m_PluginContainer(pluginContainer)
{
ui->setupUi(this);
@@ -56,13 +58,6 @@ SettingsDialog::~SettingsDialog()
delete ui;
}
-void SettingsDialog::addPlugins(const std::vector<IPlugin*> &plugins)
-{
- for (IPlugin *plugin : plugins) {
- ui->pluginsList->addItem(plugin->name());
- }
-}
-
void SettingsDialog::accept()
{
QString newModPath = ui->modDirEdit->text();
@@ -252,6 +247,6 @@ void SettingsDialog::on_associateButton_clicked()
void SettingsDialog::on_clearCacheButton_clicked()
{
QDir(Settings::instance().getCacheDirectory()).removeRecursively();
- NexusInterface::instance()->clearCache();
+ NexusInterface::instance(m_PluginContainer)->clearCache();
}
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
index e9d995d3..2e270131 100644
--- a/src/settingsdialog.h
+++ b/src/settingsdialog.h
@@ -25,6 +25,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QDialog>
#include <QListWidgetItem>
+class PluginContainer;
+
namespace Ui {
class SettingsDialog;
}
@@ -39,11 +41,9 @@ class SettingsDialog : public MOBase::TutorableDialog
Q_OBJECT
public:
- explicit SettingsDialog(QWidget *parent = 0);
+ explicit SettingsDialog(PluginContainer *pluginContainer, QWidget *parent = 0);
~SettingsDialog();
- void addPlugins(const std::vector<MOBase::IPlugin*> &plugins);
-
public slots:
virtual void accept();
@@ -87,7 +87,7 @@ private slots:
private:
Ui::SettingsDialog *ui;
-
+ PluginContainer *m_PluginContainer;
};
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 3c47d226..85688cb8 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -890,6 +890,9 @@ tl;dr-version: If Nexus-features don't work, insert the current version number o
</item>
<item>
<widget class="QCheckBox" name="hideUncheckedBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="toolTip">
<string>Enforces that inactive ESPs and ESMs are never loaded.</string>
</property>
diff --git a/src/version.rc b/src/version.rc
index 142065bf..083cbfb0 100644
--- a/src/version.rc
+++ b/src/version.rc
@@ -1,7 +1,7 @@
#include "Winver.h"
-#define VER_FILEVERSION 2,1,2
-#define VER_FILEVERSION_STR "2.1.2\0"
+#define VER_FILEVERSION 2,1,3
+#define VER_FILEVERSION_STR "2.1.3\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
@@ -18,9 +18,9 @@ BEGIN
BEGIN
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "CompanyName", "Mod Organizer 2 Team\0"
- VALUE "FileDescription", "Main Mod Oranizer 2 UI\0"
+ VALUE "FileDescription", "Mod Organizer 2 GUI\0"
VALUE "OriginalFilename", "ModOrganizer.exe\0"
- VALUE "InternalName", "ModOrganizer\0"
+ VALUE "InternalName", "ModOrganizer2\0"
VALUE "LegalCopyright", "Copyright 2011-2016 Sebastian Herbord\r\nCopyright 2016-2018 Mod Organizer 2 contributors\0"
VALUE "ProductName", "Mod Organizer 2\0"
VALUE "ProductVersion", VER_FILEVERSION_STR